From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- files/zh-cn/mozilla/accessibility/index.html | 13 + .../software_accessibility_today/index.html | 133 ++ .../mozilla/add-ons/add-on_guidelines/index.html | 9 + files/zh-cn/mozilla/add-ons/amo/index.html | 11 + .../mozilla/add-ons/amo/policy/contact/index.html | 28 + files/zh-cn/mozilla/add-ons/amo/policy/index.html | 23 + .../add-ons/code_snippets/canvas/index.html | 237 +++ .../zh-cn/mozilla/add-ons/code_snippets/index.html | 134 ++ .../add-ons/code_snippets/js_xpcom/index.html | 97 ++ .../add-ons/code_snippets/modules/index.html | 37 + .../add-ons/code_snippets/queryselector/index.html | 114 ++ .../add-ons/code_snippets/timers/index.html | 67 + .../index.html | 470 ++++++ .../index.html | 159 ++ .../index.html | 175 +++ .../index.html | 35 + .../mozilla/add-ons/extension_packaging/index.html | 38 + files/zh-cn/mozilla/add-ons/index.html | 87 ++ .../mozilla/add-ons/install_manifests/index.html | 363 +++++ .../mozilla/add-ons/legacy_add_ons/index.html | 19 + .../mozilla/add-ons/overlay_extensions/index.html | 61 + .../index.html | 91 ++ files/zh-cn/mozilla/add-ons/plugins/index.html | 116 ++ .../mozilla/add-ons/plugins/reference/index.html | 16 + .../plugins/samples_and_test_cases/index.html | 21 + .../index.html | 56 + files/zh-cn/mozilla/add-ons/sdk/builder/index.html | 13 + .../add-ons/sdk/guides/content_scripts/index.html | 486 ++++++ files/zh-cn/mozilla/add-ons/sdk/guides/index.html | 115 ++ .../multiprocess_firefox_and_the_sdk/index.html | 212 +++ .../sdk/guides/working_with_events/index.html | 122 ++ .../add-ons/sdk/high-level_apis/base64/index.html | 65 + .../sdk/high-level_apis/clipboard/index.html | 101 ++ .../mozilla/add-ons/sdk/high-level_apis/index.html | 12 + .../sdk/high-level_apis/notifications/index.html | 129 ++ .../add-ons/sdk/high-level_apis/panel/index.html | 899 +++++++++++ .../add-ons/sdk/high-level_apis/tabs/index.html | 669 ++++++++ .../add-ons/sdk/high-level_apis/url/index.html | 191 +++ .../add-ons/sdk/high-level_apis/widget/index.html | 839 ++++++++++ files/zh-cn/mozilla/add-ons/sdk/index.html | 104 ++ .../mozilla/add-ons/sdk/low-level_apis/index.html | 26 + .../sdk/low-level_apis/test_assert/index.html | 283 ++++ .../sdk/low-level_apis/ui_button_action/index.html | 526 +++++++ files/zh-cn/mozilla/add-ons/sdk/tools/index.html | 14 + .../zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html | 652 ++++++++ .../add-ons/sdk/tools/package_json/index.html | 312 ++++ .../add_a_menu_item_to_firefox/index.html | 92 ++ .../adding_a_button_to_the_toolbar/index.html | 83 + .../annotator/implementing_the_widget/index.html | 92 ++ .../add-ons/sdk/tutorials/annotator/index.html | 36 + .../sdk/tutorials/annotator/overview/index.html | 54 + .../sdk/tutorials/display_a_popup/index.html | 135 ++ .../sdk/tutorials/getting_started/index.html | 172 +++ .../sdk/tutorials/getting_started_(jpm)/index.html | 162 ++ .../zh-cn/mozilla/add-ons/sdk/tutorials/index.html | 144 ++ .../add-ons/sdk/tutorials/installation/index.html | 135 ++ .../mozilla/add-ons/sdk/tutorials/l10n/index.html | 381 +++++ .../sdk/tutorials/list_open_tabs/index.html | 72 + .../sdk/tutorials/listen_for_page_load/index.html | 42 + .../modifying_the_page_hosted_by_a_tab/index.html | 109 ++ .../modifying_web_pages_based_on_url/index.html | 210 +++ .../sdk/tutorials/open_a_web_page/index.html | 52 + .../sdk/tutorials/troubleshooting/index.html | 39 + .../add-ons/sdk/tutorials/unit_testing/index.html | 102 ++ .../tutorials/\346\227\245\345\277\227/index.html" | 62 + .../index.html" | 49 + .../index.html | 58 + .../add-ons/submitting_an_add-on_to_amo/index.html | 24 + files/zh-cn/mozilla/add-ons/themes/index.html | 65 + .../creating_a_skin_for_firefox/index.html | 28 + .../creating_a_skin_for_firefox/uuid/index.html | 6 + .../mozilla/add-ons/themes/obsolete/index.html | 10 + .../obsolete/theme_changes_in_firefox_3/index.html | 92 ++ .../add_a_button_to_the_toolbar/index.html | 220 +++ .../anatomy_of_a_webextension/index.html | 148 ++ .../webextensions/api/alarms/create/index.html | 127 ++ .../add-ons/webextensions/api/alarms/index.html | 58 + .../api/bookmarks/bookmarktreenode/index.html | 81 + .../webextensions/api/bookmarks/gettree/index.html | 120 ++ .../add-ons/webextensions/api/bookmarks/index.html | 128 ++ .../webextensions/api/bookmarks/remove/index.html | 106 ++ .../webextensions/api/browseraction/index.html | 116 ++ .../webextensions/api/captiveportal/index.html | 90 ++ .../api/captiveportal/onstatechanged/index.html | 94 ++ .../webextensions/api/contentscripts/index.html | 41 + .../webextensions/api/contextmenus/index.html | 191 +++ .../webextensions/api/cookies/cookie/index.html | 121 ++ .../add-ons/webextensions/api/cookies/index.html | 151 ++ .../api/devtools.inspectedwindow/index.html | 72 + .../api/downloads/download/index.html | 144 ++ .../api/downloads/downloaditem/index.html | 101 ++ .../add-ons/webextensions/api/downloads/index.html | 134 ++ .../add-ons/webextensions/api/find/index.html | 25 + .../add-ons/webextensions/api/history/index.html | 134 ++ .../api/history/ontitlechanged/index.html | 111 ++ .../add-ons/webextensions/api/i18n/index.html | 85 + .../add-ons/webextensions/api/idle/index.html | 97 ++ .../mozilla/add-ons/webextensions/api/index.html | 50 + .../api/permissions/contains/index.html | 94 ++ .../webextensions/api/permissions/index.html | 93 ++ .../add-ons/webextensions/api/proxy/index.html | 65 + .../api/runtime/connectnative/index.html | 114 ++ .../api/runtime/getmanifest/index.html | 79 + .../add-ons/webextensions/api/runtime/index.html | 181 +++ .../webextensions/api/runtime/onconnect/index.html | 228 +++ .../webextensions/api/runtime/onmessage/index.html | 307 ++++ .../api/runtime/openoptionspage/index.html | 92 ++ .../api/runtime/platformarch/index.html | 70 + .../api/runtime/platformos/index.html | 76 + .../api/runtime/sendmessage/index.html | 157 ++ .../api/runtime/sendnativemessage/index.html | 109 ++ .../add-ons/webextensions/api/search/index.html | 34 + .../webextensions/api/search/search/index.html | 93 ++ .../add-ons/webextensions/api/sessions/index.html | 136 ++ .../webextensions/api/sessions/session/index.html | 78 + .../add-ons/webextensions/api/storage/index.html | 103 ++ .../webextensions/api/tabs/create/index.html | 137 ++ .../webextensions/api/tabs/discard/index.html | 108 ++ .../api/tabs/executescript/index.html | 173 +++ .../add-ons/webextensions/api/tabs/index.html | 192 +++ .../webextensions/api/tabs/insertcss/index.html | 129 ++ .../webextensions/api/tabs/onactivated/index.html | 110 ++ .../webextensions/api/tabs/sendmessage/index.html | 129 ++ .../add-ons/webextensions/api/tabs/tab/index.html | 117 ++ .../api/tabs/\346\237\245\350\257\242/index.html" | 179 +++ .../api/types/browsersetting/index.html | 85 + .../api/types/browsersetting/set/index.html | 118 ++ .../add-ons/webextensions/api/types/index.html | 66 + .../webextensions/api/webnavigation/index.html | 155 ++ .../webnavigation/ondomcontentloaded/index.html | 137 ++ .../webextensions/api/webrequest/index.html | 186 +++ .../api/webrequest/requestfilter/index.html | 71 + .../webextensions/api/windows/create/index.html | 169 ++ .../add-ons/webextensions/api/windows/index.html | 116 ++ .../api/windows/windowstate/index.html | 66 + .../api/windows/windowtype/index.html | 65 + .../index.html" | 36 + .../setimagedata/index.html" | 79 + .../browser_support_for_javascript_apis/index.html | 17 + .../chrome_incompatibilities/index.html | 154 ++ .../webextensions/content_scripts/index.html | 575 +++++++ .../content_security_policy/index.html | 107 ++ .../embedded_webextensions/index.html | 205 +++ .../add-ons/webextensions/examples/index.html | 31 + .../extending_the_developer_tools/index.html | 164 ++ .../zh-cn/mozilla/add-ons/webextensions/index.html | 122 ++ .../interact_with_the_clipboard/index.html | 157 ++ .../intercept_http_requests/index.html | 158 ++ .../webextensions/internationalization/index.html | 394 +++++ .../webextensions/manifest.json/author/index.html | 40 + .../manifest.json/background/index.html | 88 ++ .../manifest.json/browser_action/index.html | 209 +++ .../browser_specific_settings/index.html | 66 + .../manifest.json/content_scripts/index.html | 216 +++ .../manifest.json/default_locale/index.html | 42 + .../manifest.json/description/index.html | 43 + .../manifest.json/developer/index.html | 48 + .../add-ons/webextensions/manifest.json/index.html | 140 ++ .../manifest.json/manifest_version/index.html | 45 + .../webextensions/manifest.json/name/index.html | 43 + .../manifest.json/permissions/index.html | 182 +++ .../manifest.json/short_name/index.html | 43 + .../webextensions/manifest.json/version/index.html | 49 + .../web_accessible_resources/index.html | 96 ++ .../index.html" | 42 + .../webextensions/match_patterns/index.html | 384 +++++ .../webextensions/modify_a_web_page/index.html | 239 +++ .../webextensions/native_manifests/index.html | 344 +++++ .../webextensions/native_messaging/index.html | 326 ++++ .../packaging_and_installation/index.html | 82 + .../porting_from_google_chrome/index.html | 22 + .../add-ons/webextensions/prerequisites/index.html | 21 + .../publishing_your_webextension/index.html | 98 ++ .../index.html | 102 ++ .../user_interface/browser_action/index.html | 50 + .../user_interface/browser_styles/index.html | 466 ++++++ .../user_interface/context_menu_items/index.html | 48 + .../user_interface/devtools_panels/index.html | 61 + .../webextensions/user_interface/index.html | 92 ++ .../user_interface/page_actions/index.html | 93 ++ .../index.html" | 53 + .../add-ons/webextensions/walkthrough/index.html | 488 ++++++ .../what_are_webextensions/index.html | 61 + .../add-ons/webextensions/what_next_/index.html | 58 + .../working_with_the_tabs_api/index.html | 634 ++++++++ .../your_first_webextension/index.html | 238 +++ .../index.html" | 203 +++ .../index.html" | 275 ++++ .../index.html" | 162 ++ .../working_with_multiprocess_firefox/index.html | 296 ++++ .../add-ons/\351\233\267\351\270\237/index.html" | 131 ++ files/zh-cn/mozilla/adding_a_new_event/index.html | 186 +++ files/zh-cn/mozilla/bugzilla/index.html | 58 + files/zh-cn/mozilla/bugzilla/testopia/index.html | 134 ++ files/zh-cn/mozilla/chrome_registration/index.html | 229 +++ .../zh-cn/mozilla/command_line_options/index.html | 407 +++++ files/zh-cn/mozilla/connect/index.html | 122 ++ .../mozilla/debugging/existing_tools/index.html | 36 + files/zh-cn/mozilla/debugging/index.html | 139 ++ .../adding_apis_to_the_navigator_object/index.html | 34 + .../developer_guide/customizing_firefox/index.html | 9 + files/zh-cn/mozilla/developer_guide/index.html | 106 ++ .../developer_guide/source_code/cvs/index.html | 192 +++ .../mozilla/developer_guide/source_code/index.html | 48 + .../source_code/latestpassingsource/index.html | 22 + .../firefox/australis_add-on_compat/index.html | 130 ++ .../mozilla/firefox/developer_edition/index.html | 57 + .../firefox/enterprise_deployment/index.html | 138 ++ .../firefox/experimental_features/index.html | 623 ++++++++ .../zh-cn/mozilla/firefox/headless_mode/index.html | 270 ++++ files/zh-cn/mozilla/firefox/index.html | 74 + .../cross_process_object_wrappers/index.html | 114 ++ .../debugging_frame_scripts/index.html | 53 + .../firefox/multiprocess_firefox/faq/index.html | 18 + .../firefox/multiprocess_firefox/index.html | 78 + .../limitations_of_chrome_scripts/index.html | 197 +++ .../limitations_of_frame_scripts/index.html | 101 ++ .../communicating_with_frame_scripts/index.html | 205 +++ .../frame_script_environment/index.html | 104 ++ .../frame_script_loading_and_lifetime/index.html | 124 ++ .../message_manager/index.html | 68 + .../message_manager_overview/index.html | 442 ++++++ .../message_manager/performance/index.html | 292 ++++ .../multiprocess_firefox/motivation/index.html | 44 + .../index.html | 21 + .../technical_overview/index.html | 164 ++ .../which_uris_load_where/index.html | 53 + files/zh-cn/mozilla/firefox/privacy/index.html | 22 + .../storage_access_policy/errors/index.html | 24 + .../index.html" | 39 + .../privacy/storage_access_policy/index.html | 261 ++++ .../firefox/privacy/tracking_protection/index.html | 87 ++ .../zh-cn/mozilla/firefox/releases/1.5/index.html | 123 ++ .../1.5/using_firefox_1.5_caching/index.html | 184 +++ files/zh-cn/mozilla/firefox/releases/12/index.html | 165 ++ files/zh-cn/mozilla/firefox/releases/14/index.html | 98 ++ files/zh-cn/mozilla/firefox/releases/15/index.html | 122 ++ files/zh-cn/mozilla/firefox/releases/16/index.html | 114 ++ files/zh-cn/mozilla/firefox/releases/17/index.html | 146 ++ files/zh-cn/mozilla/firefox/releases/18/index.html | 82 + files/zh-cn/mozilla/firefox/releases/19/index.html | 76 + files/zh-cn/mozilla/firefox/releases/20/index.html | 47 + files/zh-cn/mozilla/firefox/releases/21/index.html | 107 ++ files/zh-cn/mozilla/firefox/releases/22/index.html | 89 ++ files/zh-cn/mozilla/firefox/releases/23/index.html | 94 ++ files/zh-cn/mozilla/firefox/releases/24/index.html | 22 + files/zh-cn/mozilla/firefox/releases/25/index.html | 50 + .../releases/25/site_compatibility/index.html | 40 + files/zh-cn/mozilla/firefox/releases/26/index.html | 41 + .../releases/26/site_compatibility/index.html | 104 ++ files/zh-cn/mozilla/firefox/releases/27/index.html | 45 + files/zh-cn/mozilla/firefox/releases/28/index.html | 117 ++ .../releases/28/site_compatibility/index.html | 56 + .../zh-cn/mozilla/firefox/releases/3.6/index.html | 305 ++++ files/zh-cn/mozilla/firefox/releases/3/index.html | 310 ++++ .../releases/3/site_compatibility/index.html | 26 + files/zh-cn/mozilla/firefox/releases/31/index.html | 46 + files/zh-cn/mozilla/firefox/releases/32/index.html | 154 ++ files/zh-cn/mozilla/firefox/releases/33/index.html | 38 + files/zh-cn/mozilla/firefox/releases/35/index.html | 213 +++ files/zh-cn/mozilla/firefox/releases/41/index.html | 209 +++ files/zh-cn/mozilla/firefox/releases/43/index.html | 173 +++ files/zh-cn/mozilla/firefox/releases/44/index.html | 222 +++ files/zh-cn/mozilla/firefox/releases/45/index.html | 187 +++ files/zh-cn/mozilla/firefox/releases/49/index.html | 348 +++++ files/zh-cn/mozilla/firefox/releases/56/index.html | 129 ++ files/zh-cn/mozilla/firefox/releases/59/index.html | 130 ++ files/zh-cn/mozilla/firefox/releases/62/index.html | 187 +++ files/zh-cn/mozilla/firefox/releases/65/index.html | 128 ++ files/zh-cn/mozilla/firefox/releases/68/index.html | 240 +++ files/zh-cn/mozilla/firefox/releases/69/index.html | 185 +++ files/zh-cn/mozilla/firefox/releases/78/index.html | 116 ++ files/zh-cn/mozilla/firefox/releases/index.html | 12 + .../mozilla/firefox/the_about_protocol/index.html | 163 ++ files/zh-cn/mozilla/firefox_for_android/index.html | 65 + files/zh-cn/mozilla/gecko/index.html | 74 + files/zh-cn/mozilla/gecko/versions/index.html | 130 ++ .../\345\265\214\345\205\245mozilla/index.html" | 49 + .../how_mozilla_determines_mime_types/index.html | 94 ++ .../index.html | 48 + .../index.html | 76 + files/zh-cn/mozilla/index.html | 8 + files/zh-cn/mozilla/instantbird/index.html | 62 + .../introduction_to_layout_in_mozilla/index.html | 360 +++++ .../ipdl/creating_a_new_protocol/index.html | 32 + files/zh-cn/mozilla/ipdl/index.html | 33 + .../ipdl/\345\205\245\351\227\250/index.html" | 670 ++++++++ .../index.html | 145 ++ .../javascript_code_modules/assert.jsm/index.html | 448 ++++++ .../javascript_code_modules/dict.jsm/index.html | 344 +++++ .../downloads.jsm/download/index.html | 335 ++++ .../downloads.jsm/index.html | 306 ++++ .../geometry.jsm/index.html | 19 + .../geometry.jsm/services.jsm/index.html | 25 + .../javascript_code_modules/http.jsm/index.html | 74 + .../mozilla/javascript_code_modules/index.html | 84 + .../promise.jsm/deferred/index.html | 190 +++ .../javascript_code_modules/promise.jsm/index.html | 172 +++ .../promise.jsm/promise/index.html | 226 +++ .../javascript_code_modules/timer.jsm/index.html | 33 + .../javascript_code_modules/using/index.html | 194 +++ files/zh-cn/mozilla/javascript_tips/index.html | 112 ++ files/zh-cn/mozilla/js-ctypes/index.html | 53 + .../js-ctypes_reference/ctypes/index.html | 534 +++++++ .../js-ctypes/js-ctypes_reference/index.html | 96 ++ .../declaring_and_using_callbacks/index.html | 100 ++ .../mozilla/js-ctypes/using_js-ctypes/index.html | 210 +++ .../using_js-ctypes/memory_management/index.html | 88 ++ .../working_with_arraybuffers/index.html | 212 +++ files/zh-cn/mozilla/localization/faq/index.html | 17 + files/zh-cn/mozilla/localization/index.html | 20 + .../localization/l10n_style_guide/index.html | 482 ++++++ .../localizing_extension_descriptions/index.html | 60 + files/zh-cn/mozilla/mercurial/basics/index.html | 56 + files/zh-cn/mozilla/mercurial/index.html | 43 + .../mercurial/installing_mercurial/index.html | 145 ++ files/zh-cn/mozilla/mfbt/index.html | 48 + files/zh-cn/mozilla/mozilla_on_github/index.html | 121 ++ files/zh-cn/mozilla/mozilla_persona/index.html | 155 ++ .../index.html | 94 ++ .../performance/about_colon_memory/index.html | 144 ++ files/zh-cn/mozilla/performance/index.html | 138 ++ .../performance/scroll-linked_effects/index.html | 121 ++ .../persona/bootstrapping_persona/index.html | 29 + files/zh-cn/mozilla/persona/branding/index.html | 79 + .../persona/browser_compatibility/index.html | 89 ++ files/zh-cn/mozilla/persona/glossary/index.html | 61 + files/zh-cn/mozilla/persona/index.html | 138 ++ .../mozilla/persona/protocol_overview/index.html | 96 ++ files/zh-cn/mozilla/persona/quick_setup/index.html | 140 ++ .../persona/remote_verification_api/index.html | 120 ++ .../persona/security_considerations/index.html | 55 + files/zh-cn/mozilla/persona/why_persona/index.html | 30 + files/zh-cn/mozilla/preferences/index.html | 6 + .../mozilla_networking_preferences/index.html | 536 +++++++ .../browser.altclicksave/index.html | 12 + .../index.html | 31 + .../index.html | 14 + .../browser.urlbar.trimurls/index.html | 12 + .../dom.event.clipboardevents.enabled/index.html | 12 + .../preferences/preference_reference/index.html | 8 + .../javascript.options.strict/index.html | 13 + .../ui.alertnotificationorigin/index.html | 12 + .../ui.spellcheckerunderline/index.html | 12 + .../ui.spellcheckerunderlinestyle/index.html | 13 + .../ui.tooltipdelay/index.html | 13 + .../view_source.syntax_highlight/index.html | 6 + .../mozilla/projects/crash_reporting/index.html | 47 + files/zh-cn/mozilla/projects/emscripten/index.html | 37 + files/zh-cn/mozilla/projects/index.html | 14 + files/zh-cn/mozilla/projects/l20n/index.html | 127 ++ files/zh-cn/mozilla/projects/nspr/index.html | 60 + .../mozilla/projects/nspr/reference/index.html | 770 ++++++++++ .../memory_management_operations/index.html | 424 +++++ files/zh-cn/mozilla/projects/psm/index.html | 15 + files/zh-cn/mozilla/projects/rhino/bsf/index.html | 10 + .../mozilla/projects/rhino/community/index.html | 24 + .../mozilla/projects/rhino/debugger/index.html | 220 +++ .../projects/rhino/documentation/index.html | 81 + .../projects/rhino/download_rhino/index.html | 106 ++ .../projects/rhino/embedding_tutorial/index.html | 221 +++ .../mozilla/projects/rhino/examples/index.html | 35 + files/zh-cn/mozilla/projects/rhino/index.html | 22 + .../mozilla/projects/rhino/license/index.html | 47 + .../mozilla/projects/rhino/overview/index.html | 78 + .../rhino/requirements_and_limitations/index.html | 24 + .../projects/rhino/scripting_java/index.html | 397 +++++ .../zh-cn/mozilla/projects/rhino/shell/index.html | 179 +++ files/zh-cn/mozilla/projects/social_api/index.html | 97 ++ .../mozilla/projects/social_api/share/index.html | 86 ++ .../spidermonkey/build_documentation/index.html | 294 ++++ .../comparision_of_js_engines/index.html | 105 ++ .../zh-cn/mozilla/projects/spidermonkey/index.html | 132 ++ .../spidermonkey/internals/bytecodes/index.html | 30 + .../spidermonkey/internals/functions/index.html | 73 + .../projects/spidermonkey/internals/index.html | 292 ++++ .../index.html | 382 +++++ .../index.html" | 11 + .../jsapi_reference/boolean_to_jsval/index.html | 53 + .../spidermonkey/jsapi_reference/index.html | 646 ++++++++ .../js_defineconstdoubles/index.html | 59 + .../jsapi_reference/js_doublecolon_call/index.html | 92 ++ .../js_doublecolon_ordinarytoprimitive/index.html | 66 + .../jsapi_reference/js_evaluatescript/index.html | 69 + .../jsapi_reference/js_getversion/index.html | 29 + .../jsapi_reference/js_hasownproperty/index.html | 73 + .../jsapi_reference/js_newruntime/index.html | 33 + .../jsapi_reference/js_seterrorreporter/index.html | 61 + .../jsapi_reference/js_valuetostring/index.html | 45 + .../jsapi_reference/jsclass/index.html | 137 ++ .../jsapi_reference/jsconstdoublespec/index.html | 56 + .../jsapi_reference/jserrorreport/index.html | 6 + .../jsapi_reference/jsproperty/index.html | 29 + .../jspropertydescriptor/index.html | 69 + .../jsapi_reference/jsruntime/index.html | 29 + .../projects/spidermonkey/parser_api/index.html | 1625 ++++++++++++++++++++ .../projects/spidermonkey/releases/index.html | 42 + .../projects/spidermonkey/split_object/index.html | 72 + files/zh-cn/mozilla/rust/index.html | 40 + files/zh-cn/mozilla/tech/index.html | 7 + .../tech/toolkit_api/extisessionstorage/index.html | 48 + files/zh-cn/mozilla/tech/toolkit_api/index.html | 18 + .../index.html | 26 + files/zh-cn/mozilla/tech/xpcom/glue/index.html | 71 + .../mozilla/tech/xpcom/guide/arrays/index.html | 573 +++++++ .../an_overview_of_xpcom/index.html | 535 +++++++ .../building_the_weblock_ui/index.html | 297 ++++ .../component_internals/index.html | 217 +++ .../creating_the_component_code/index.html | 727 +++++++++ .../finishing_the_component/index.html | 337 ++++ .../xpcom/guide/creating_components/index.html | 278 ++++ .../packaging_weblock/index.html | 136 ++ .../guide/creating_components/preface/index.html | 83 + .../guide/creating_components/resources/index.html | 10 + .../setting_up_the_gecko_sdk/index.html | 204 +++ .../starting_weblock/index.html | 1104 +++++++++++++ .../using_xpcom_components/index.html | 311 ++++ .../index.html | 388 +++++ .../mozilla/tech/xpcom/guide/hashtables/index.html | 282 ++++ files/zh-cn/mozilla/tech/xpcom/guide/index.html | 15 + .../tech/xpcom/guide/internal_strings/index.html | 809 ++++++++++ files/zh-cn/mozilla/tech/xpcom/index.html | 44 + .../index.html | 141 ++ .../components.utils.cloneinto/index.html | 290 ++++ .../components.utils.getglobalforobject/index.html | 41 + .../tech/xpcom/language_bindings/index.html | 20 + .../xpcom/language_bindings/javaxpcom/index.html | 49 + .../index.html" | 65 + .../javaxpcom/\345\274\200\345\217\221/index.html" | 26 + .../xpcom/language_bindings/pyxpcom/index.html | 67 + .../xpcom/language_bindings/xpconnect/index.html | 67 + .../tech/xpcom/observer_notifications/index.html | 880 +++++++++++ .../tech/xpcom/reference/glue_classes/index.html | 16 + .../nscomptr/getting_started_guide/index.html | 478 ++++++ .../reference/glue_classes/nscomptr/index.html | 56 + .../zh-cn/mozilla/tech/xpcom/reference/index.html | 14 + .../tech/xpcom/reference/interface/index.html | 11 + .../interface/nsiaccessibleprovider/index.html | 45 + .../reference/interface/nsiclipboard/index.html | 91 ++ .../interface/nsiclipboardhelper/index.html | 65 + .../interface/nsiconsoleservice/index.html | 215 +++ .../nsidirectoryserviceprovider/index.html | 65 + .../interface/nsidomclientrect/index.html | 92 ++ .../xpcom/reference/interface/nsifile/index.html | 828 ++++++++++ .../reference/interface/nsifilepicker/index.html | 376 +++++ .../reference/interface/nsihttpchannel/index.html | 365 +++++ .../reference/interface/nsiidleservice/index.html | 119 ++ .../reference/interface/nsilocalfile/index.html | 478 ++++++ .../reference/interface/nsiprocess/index.html | 283 ++++ .../xpcom/reference/interface/nsiprompt/index.html | 55 + .../interface/nsipromptservice/index.html | 696 +++++++++ .../nsiscriptableunicodeconverter/index.html | 609 ++++++++ .../interface/nsisyncmessagesender/index.html | 65 + .../xpcom/reference/interface/nsitimer/index.html | 285 ++++ .../interface/nsitraceablechannel/index.html | 71 + .../xpcom/reference/interface/nsiuri/index.html | 407 +++++ .../interface/nsixmlhttprequest/index.html | 90 ++ .../xpcom/setting_http_request_headers/index.html | 261 ++++ files/zh-cn/mozilla/tech/xpidl/index.html | 502 ++++++ files/zh-cn/mozilla/tech/xpidl/syntax/index.html | 127 ++ files/zh-cn/mozilla/tech/xpidl/xpidl/index.html | 58 + .../tech/xul/attribute/acceltext/index.html | 23 + .../tech/xul/attribute/accesskey/index.html | 43 + .../xul/attribute/activetitlebarcolor/index.html | 19 + .../mozilla/tech/xul/attribute/align/index.html | 54 + .../tech/xul/attribute/allowevents/index.html | 30 + .../attribute/allownegativeassertions/index.html | 18 + .../tech/xul/attribute/autocheck/index.html | 24 + .../tech/xul/attribute/autoscroll/index.html | 12 + .../xul/attribute/buttonaccesskeyaccept/index.html | 20 + .../xul/attribute/buttonlabelextra1/index.html | 19 + .../xul/attribute/buttonlabelextra2/index.html | 19 + .../mozilla/tech/xul/attribute/buttons/index.html | 28 + .../mozilla/tech/xul/attribute/checked/index.html | 24 + .../mozilla/tech/xul/attribute/class/index.html | 23 + .../xul/attribute/coalesceduplicatearcs/index.html | 17 + .../tech/xul/attribute/collapsed/index.html | 27 + .../mozilla/tech/xul/attribute/command/index.html | 30 + .../tech/xul/attribute/container/index.html | 18 + .../mozilla/tech/xul/attribute/control/index.html | 23 + .../mozilla/tech/xul/attribute/crop/index.html | 37 + .../tech/xul/attribute/description/index.html | 23 + .../mozilla/tech/xul/attribute/dir/index.html | 39 + .../mozilla/tech/xul/attribute/disabled/index.html | 38 + .../mozilla/tech/xul/attribute/flex/index.html | 23 + .../mozilla/tech/xul/attribute/href/index.html | 24 + .../zh-cn/mozilla/tech/xul/attribute/id/index.html | 41 + .../tech/xul/attribute/image.onload/index.html | 12 + .../mozilla/tech/xul/attribute/image/index.html | 25 + .../tech/xul/attribute/increment/index.html | 15 + files/zh-cn/mozilla/tech/xul/attribute/index.html | 304 ++++ .../mozilla/tech/xul/attribute/label/index.html | 41 + .../mozilla/tech/xul/attribute/max/index.html | 20 + .../tech/xul/attribute/menuitem.key/index.html | 23 + .../tech/xul/attribute/menuitem.name/index.html | 38 + .../tech/xul/attribute/menuitem.type/index.html | 28 + .../mozilla/tech/xul/attribute/min/index.html | 16 + .../mozilla/tech/xul/attribute/name/index.html | 16 + .../tech/xul/attribute/onpopupshowing/index.html | 21 + .../tech/xul/attribute/onpopupshown/index.html | 21 + .../mozilla/tech/xul/attribute/orient/index.html | 16 + .../mozilla/tech/xul/attribute/pending/index.html | 15 + .../mozilla/tech/xul/attribute/persist/index.html | 24 + .../mozilla/tech/xul/attribute/selected/index.html | 28 + .../tech/xul/attribute/selectedindex/index.html | 15 + .../mozilla/tech/xul/attribute/tabindex/index.html | 18 + .../mozilla/tech/xul/attribute/validate/index.html | 27 + .../mozilla/tech/xul/attribute/value/index.html | 30 + .../zh-cn/mozilla/tech/xul/broadcaster/index.html | 91 ++ files/zh-cn/mozilla/tech/xul/browser/index.html | 409 +++++ files/zh-cn/mozilla/tech/xul/button/index.html | 528 +++++++ files/zh-cn/mozilla/tech/xul/checkbox/index.html | 329 ++++ files/zh-cn/mozilla/tech/xul/command/index.html | 105 ++ .../tech/xul/deprecated_defunct_markup/index.html | 50 + files/zh-cn/mozilla/tech/xul/dialog/index.html | 364 +++++ files/zh-cn/mozilla/tech/xul/events/index.html | 497 ++++++ files/zh-cn/mozilla/tech/xul/image/index.html | 145 ++ files/zh-cn/mozilla/tech/xul/index.html | 79 + files/zh-cn/mozilla/tech/xul/key/index.html | 166 ++ files/zh-cn/mozilla/tech/xul/label/index.html | 298 ++++ .../mozilla/tech/xul/list_of_commands/index.html | 196 +++ files/zh-cn/mozilla/tech/xul/listbox/index.html | 480 ++++++ files/zh-cn/mozilla/tech/xul/listheader/index.html | 180 +++ files/zh-cn/mozilla/tech/xul/menu/index.html | 370 +++++ files/zh-cn/mozilla/tech/xul/menubar/index.html | 113 ++ files/zh-cn/mozilla/tech/xul/menuitem/index.html | 575 +++++++ files/zh-cn/mozilla/tech/xul/menulist/index.html | 509 ++++++ files/zh-cn/mozilla/tech/xul/menupopup/index.html | 324 ++++ .../mozilla/tech/xul/menuseparator/index.html | 435 ++++++ .../mozilla/tech/xul/method/extra1/index.html | 15 + .../zh-cn/mozilla/tech/xul/method/focus/index.html | 15 + .../tech/xul/method/getbrowserfortab/index.html | 15 + .../mozilla/tech/xul/method/getbutton/index.html | 15 + .../mozilla/tech/xul/method/increase/index.html | 21 + files/zh-cn/mozilla/tech/xul/method/index.html | 170 ++ .../zh-cn/mozilla/tech/xul/method/reset/index.html | 15 + .../zh-cn/mozilla/tech/xul/method/stop/index.html | 15 + files/zh-cn/mozilla/tech/xul/namespaces/index.html | 73 + files/zh-cn/mozilla/tech/xul/popup/index.html | 23 + .../tech/xul/property/accessibletype/index.html | 183 +++ .../mozilla/tech/xul/property/accesskey/index.html | 21 + .../xul/property/browser.preferences/index.html | 15 + .../mozilla/tech/xul/property/buttons/index.html | 10 + .../mozilla/tech/xul/property/command/index.html | 21 + .../mozilla/tech/xul/property/crop/index.html | 21 + .../tech/xul/property/defaultvalue/index.html | 15 + .../mozilla/tech/xul/property/disabled/index.html | 21 + .../mozilla/tech/xul/property/image/index.html | 21 + files/zh-cn/mozilla/tech/xul/property/index.html | 266 ++++ .../mozilla/tech/xul/property/label/index.html | 21 + .../tech/xul/property/labelelement/index.html | 21 + .../xul/property/markupdocumentviewer/index.html | 15 + .../zh-cn/mozilla/tech/xul/property/max/index.html | 15 + .../tech/xul/property/menuitem.control/index.html | 21 + .../tech/xul/property/parentcontainer/index.html | 21 + .../mozilla/tech/xul/property/selected/index.html | 18 + .../tech/xul/property/selectedindex/index.html | 21 + .../tech/xul/property/selecteditem/index.html | 21 + .../tech/xul/property/selectionstart/index.html | 16 + .../tech/xul/property/spinbuttons/index.html | 15 + .../mozilla/tech/xul/property/tabindex/index.html | 21 + .../tech/xul/property/textbox.value/index.html | 15 + .../mozilla/tech/xul/property/value/index.html | 21 + files/zh-cn/mozilla/tech/xul/radio/index.html | 379 +++++ files/zh-cn/mozilla/tech/xul/radiogroup/index.html | 275 ++++ files/zh-cn/mozilla/tech/xul/script/index.html | 117 ++ files/zh-cn/mozilla/tech/xul/statusbar/index.html | 131 ++ files/zh-cn/mozilla/tech/xul/style/index.html | 6 + .../tech/xul/style/menuitem-iconic/index.html | 16 + .../tech/xul/style/menuitem-non-iconic/index.html | 16 + files/zh-cn/mozilla/tech/xul/tabbox/index.html | 156 ++ .../mozilla/tech/xul/template_guide/index.html | 68 + files/zh-cn/mozilla/tech/xul/textbox/index.html | 653 ++++++++ .../mozilla/tech/xul/toolbarpalette/index.html | 103 ++ .../toolbars/creating_toolbar_buttons/index.html | 183 +++ .../xul/toolbars/custom_toolbar_button/index.html | 332 ++++ files/zh-cn/mozilla/tech/xul/toolbars/index.html | 65 + files/zh-cn/mozilla/tech/xul/toolbox/index.html | 6 + files/zh-cn/mozilla/tech/xul/tree/index.html | 512 ++++++ .../tech/xul/tutorial/adding_buttons/index.html | 98 ++ .../xul/tutorial/adding_event_handlers/index.html | 161 ++ .../xul/tutorial/adding_html_elements/index.html | 113 ++ .../tutorial/adding_labels_and_images/index.html | 40 + .../xul/tutorial/adding_more_elements/index.html | 115 ++ .../xul/tutorial/adding_style_sheets/index.html | 10 + .../tech/xul/tutorial/anonymous_content/index.html | 166 ++ .../tech/xul/tutorial/box_model_details/index.html | 6 + .../tech/xul/tutorial/content_panels/index.html | 63 + .../tech/xul/tutorial/creating_a_skin/index.html | 177 +++ .../tech/xul/tutorial/creating_a_window/index.html | 116 ++ .../xul/tutorial/creating_an_installer/index.html | 98 ++ .../tech/xul/tutorial/creating_dialogs/index.html | 6 + .../xul/tutorial/document_object_model/index.html | 220 +++ .../xul/tutorial/element_positioning/index.html | 254 +++ .../xul/tutorial/features_of_a_window/index.html | 6 + .../mozilla/tech/xul/tutorial/grids/index.html | 175 +++ .../tech/xul/tutorial/groupboxes/index.html | 85 + files/zh-cn/mozilla/tech/xul/tutorial/index.html | 171 ++ .../tech/xul/tutorial/input_controls/index.html | 110 ++ .../tech/xul/tutorial/introduction/index.html | 70 + .../xul/tutorial/introduction_to_rdf/index.html | 109 ++ .../tech/xul/tutorial/list_controls/index.html | 133 ++ .../tech/xul/tutorial/localization/index.html | 296 ++++ .../tech/xul/tutorial/manifest_files/index.html | 113 ++ .../tutorial/modifying_a_xul_interface/index.html | 118 ++ .../tutorial/modifying_the_default_skin/index.html | 63 + .../xul/tutorial/more_button_features/index.html | 216 +++ .../xul/tutorial/more_event_handlers/index.html | 183 +++ .../xul/tutorial/more_menu_features/index.html | 108 ++ .../tech/xul/tutorial/more_wizards/index.html | 64 + .../tech/xul/tutorial/numeric_controls/index.html | 78 + .../tech/xul/tutorial/popup_menus/index.html | 6 + .../tech/xul/tutorial/progress_meters/index.html | 58 + .../tech/xul/tutorial/property_files/index.html | 97 ++ .../tech/xul/tutorial/rdf_datasources/index.html | 267 ++++ .../tech/xul/tutorial/scroll_bars/index.html | 9 + .../tech/xul/tutorial/scrolling_menus/index.html | 45 + .../tech/xul/tutorial/simple_menu_bars/index.html | 159 ++ .../mozilla/tech/xul/tutorial/splitters/index.html | 85 + .../tech/xul/tutorial/stack_positioning/index.html | 30 + .../tech/xul/tutorial/stacks_and_decks/index.html | 71 + .../tech/xul/tutorial/styling_a_tree/index.html | 12 + .../mozilla/tech/xul/tutorial/tabboxes/index.html | 125 ++ .../mozilla/tech/xul/tutorial/templates/index.html | 77 + .../tech/xul/tutorial/the_box_model/index.html | 39 + .../tech/xul/tutorial/the_chrome_url/index.html | 74 + .../mozilla/tech/xul/tutorial/toolbars/index.html | 101 ++ .../mozilla/tech/xul/tutorial/trees/index.html | 8 + .../tech/xul/tutorial/using_spacers/index.html | 111 ++ .../tutorial/using_xbl_from_stylesheets/index.html | 223 +++ .../xbl\344\273\213\347\273\215/index.html" | 104 ++ .../xpcom_\346\216\245\345\217\243/index.html" | 179 +++ .../tech/xul/tutorial/xul_structure/index.html | 43 + .../index.html" | 68 + files/zh-cn/mozilla/tech/xul/vbox/index.html | 130 ++ files/zh-cn/mozilla/tech/xul/window/index.html | 281 ++++ .../mozilla/tech/xul/xul_reference/index.html | 20 + files/zh-cn/mozilla/thunderbird/index.html | 75 + .../mail_client_architecture_overview/index.html | 94 ++ .../thunderbird/mailnews_protocols/index.html | 31 + .../mozilla/toolkit_version_format/index.html | 88 ++ files/zh-cn/mozilla/webidl_bindings/index.html | 920 +++++++++++ .../index.html | 19 + .../index.html" | 123 ++ .../mozilla/\346\227\245\345\216\206/index.html" | 75 + 645 files changed, 89007 insertions(+) create mode 100644 files/zh-cn/mozilla/accessibility/index.html create mode 100644 files/zh-cn/mozilla/accessibility/software_accessibility_today/index.html create mode 100644 files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html create mode 100644 files/zh-cn/mozilla/add-ons/amo/index.html create mode 100644 files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html create mode 100644 files/zh-cn/mozilla/add-ons/amo/policy/index.html create mode 100644 files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html create mode 100644 files/zh-cn/mozilla/add-ons/code_snippets/index.html create mode 100644 files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html create mode 100644 files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html create mode 100644 files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html create mode 100644 files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html create mode 100644 files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html create mode 100644 files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html create mode 100644 files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html create mode 100644 files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html create mode 100644 files/zh-cn/mozilla/add-ons/extension_packaging/index.html create mode 100644 files/zh-cn/mozilla/add-ons/index.html create mode 100644 files/zh-cn/mozilla/add-ons/install_manifests/index.html create mode 100644 files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html create mode 100644 files/zh-cn/mozilla/add-ons/overlay_extensions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/plugins/index.html create mode 100644 files/zh-cn/mozilla/add-ons/plugins/reference/index.html create mode 100644 files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html create mode 100644 files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/builder/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/guides/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tools/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html create mode 100644 files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html create mode 100644 "files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\227\245\345\277\227/index.html" create mode 100644 "files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\267\273\345\212\240\344\270\200\344\270\252\350\217\234\345\215\225\351\241\271/index.html" create mode 100644 files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html create mode 100644 files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html create mode 100644 files/zh-cn/mozilla/add-ons/themes/index.html create mode 100644 files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html create mode 100644 files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html create mode 100644 files/zh-cn/mozilla/add-ons/themes/obsolete/index.html create mode 100644 files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/add_a_button_to_the_toolbar/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/anatomy_of_a_webextension/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/alarms/create/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/alarms/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/bookmarktreenode/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/gettree/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/remove/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/browseraction/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/onstatechanged/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/contentscripts/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/contextmenus/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/cookies/cookie/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/cookies/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/devtools.inspectedwindow/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/downloads/download/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/downloads/downloaditem/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/downloads/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/find/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/history/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/history/ontitlechanged/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/i18n/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/idle/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/permissions/contains/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/permissions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/proxy/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/connectnative/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/getmanifest/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onconnect/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/openoptionspage/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformarch/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformos/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendmessage/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendnativemessage/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/search/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/search/search/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/sessions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/sessions/session/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/storage/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/create/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/discard/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/executescript/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/insertcss/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/onactivated/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/sendmessage/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/tabs/tab/index.html create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/api/tabs/\346\237\245\350\257\242/index.html" create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/set/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/types/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/ondomcontentloaded/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/requestfilter/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/windows/create/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/windows/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowstate/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowtype/index.html create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/index.html" create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/setimagedata/index.html" create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/browser_support_for_javascript_apis/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/chrome_incompatibilities/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/content_scripts/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/content_security_policy/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/examples/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/interact_with_the_clipboard/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/intercept_http_requests/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/internationalization/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/author/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/background/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_action/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_specific_settings/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/content_scripts/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/default_locale/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/description/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/developer/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/manifest_version/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/name/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/permissions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/short_name/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/version/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/manifest.json/web_accessible_resources/index.html create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/manifest.json/\344\270\273\351\241\265\345\234\260\345\235\200/index.html" create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/match_patterns/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/modify_a_web_page/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/native_manifests/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/native_messaging/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/packaging_and_installation/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/porting_from_google_chrome/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/prerequisites/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/publishing_your_webextension/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/safely_inserting_external_content_into_a_page/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_action/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_styles/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/user_interface/context_menu_items/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/user_interface/devtools_panels/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/user_interface/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/user_interface/page_actions/index.html create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/user_interface/\344\276\247\350\276\271\346\240\217/index.html" create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/walkthrough/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/what_are_webextensions/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/what_next_/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/working_with_the_tabs_api/index.html create mode 100644 files/zh-cn/mozilla/add-ons/webextensions/your_first_webextension/index.html create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/\345\256\236\347\216\260\344\270\200\344\270\252\350\256\276\347\275\256\351\241\265\351\235\242/index.html" create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/\346\236\204\345\273\272\344\270\200\344\270\252\350\267\250\346\265\217\350\247\210\345\231\250\347\232\204\346\211\251\345\261\225\346\217\222\344\273\266/index.html" create mode 100644 "files/zh-cn/mozilla/add-ons/webextensions/\347\224\250\346\210\267\347\225\214\351\235\242\345\205\203\347\264\240/index.html" create mode 100644 files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html create mode 100644 "files/zh-cn/mozilla/add-ons/\351\233\267\351\270\237/index.html" create mode 100644 files/zh-cn/mozilla/adding_a_new_event/index.html create mode 100644 files/zh-cn/mozilla/bugzilla/index.html create mode 100644 files/zh-cn/mozilla/bugzilla/testopia/index.html create mode 100644 files/zh-cn/mozilla/chrome_registration/index.html create mode 100644 files/zh-cn/mozilla/command_line_options/index.html create mode 100644 files/zh-cn/mozilla/connect/index.html create mode 100644 files/zh-cn/mozilla/debugging/existing_tools/index.html create mode 100644 files/zh-cn/mozilla/debugging/index.html create mode 100644 files/zh-cn/mozilla/developer_guide/adding_apis_to_the_navigator_object/index.html create mode 100644 files/zh-cn/mozilla/developer_guide/customizing_firefox/index.html create mode 100644 files/zh-cn/mozilla/developer_guide/index.html create mode 100644 files/zh-cn/mozilla/developer_guide/source_code/cvs/index.html create mode 100644 files/zh-cn/mozilla/developer_guide/source_code/index.html create mode 100644 files/zh-cn/mozilla/developer_guide/source_code/latestpassingsource/index.html create mode 100644 files/zh-cn/mozilla/firefox/australis_add-on_compat/index.html create mode 100644 files/zh-cn/mozilla/firefox/developer_edition/index.html create mode 100644 files/zh-cn/mozilla/firefox/enterprise_deployment/index.html create mode 100644 files/zh-cn/mozilla/firefox/experimental_features/index.html create mode 100644 files/zh-cn/mozilla/firefox/headless_mode/index.html create mode 100644 files/zh-cn/mozilla/firefox/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/cross_process_object_wrappers/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/debugging_frame_scripts/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/faq/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_chrome_scripts/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_frame_scripts/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/communicating_with_frame_scripts/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_environment/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_loading_and_lifetime/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/message_manager_overview/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/performance/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/motivation/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/tab_selection_in_multiprocess_firefox/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/technical_overview/index.html create mode 100644 files/zh-cn/mozilla/firefox/multiprocess_firefox/which_uris_load_where/index.html create mode 100644 files/zh-cn/mozilla/firefox/privacy/index.html create mode 100644 files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/index.html create mode 100644 "files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/\347\246\201\347\224\250\345\244\226\351\203\250cookie/index.html" create mode 100644 files/zh-cn/mozilla/firefox/privacy/storage_access_policy/index.html create mode 100644 files/zh-cn/mozilla/firefox/privacy/tracking_protection/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/1.5/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/1.5/using_firefox_1.5_caching/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/12/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/14/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/15/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/16/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/17/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/18/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/19/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/20/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/21/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/22/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/23/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/24/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/25/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/25/site_compatibility/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/26/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/26/site_compatibility/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/27/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/28/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/28/site_compatibility/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/3.6/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/3/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/3/site_compatibility/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/31/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/32/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/33/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/35/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/41/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/43/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/44/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/45/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/49/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/56/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/59/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/62/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/65/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/68/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/69/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/78/index.html create mode 100644 files/zh-cn/mozilla/firefox/releases/index.html create mode 100644 files/zh-cn/mozilla/firefox/the_about_protocol/index.html create mode 100644 files/zh-cn/mozilla/firefox_for_android/index.html create mode 100644 files/zh-cn/mozilla/gecko/index.html create mode 100644 files/zh-cn/mozilla/gecko/versions/index.html create mode 100644 "files/zh-cn/mozilla/gecko/\345\265\214\345\205\245mozilla/index.html" create mode 100644 files/zh-cn/mozilla/how_mozilla_determines_mime_types/index.html create mode 100644 files/zh-cn/mozilla/how_to_get_a_process_dump_with_windows_task_manager/index.html create mode 100644 files/zh-cn/mozilla/implementing_pontoon_in_a_mozilla_website/index.html create mode 100644 files/zh-cn/mozilla/index.html create mode 100644 files/zh-cn/mozilla/instantbird/index.html create mode 100644 files/zh-cn/mozilla/introduction_to_layout_in_mozilla/index.html create mode 100644 files/zh-cn/mozilla/ipdl/creating_a_new_protocol/index.html create mode 100644 files/zh-cn/mozilla/ipdl/index.html create mode 100644 "files/zh-cn/mozilla/ipdl/\345\205\245\351\227\250/index.html" create mode 100644 files/zh-cn/mozilla/javascript-dom_prototypes_in_mozilla/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/assert.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/dict.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/download/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/services.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/http.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/promise.jsm/deferred/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/promise.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/promise.jsm/promise/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/timer.jsm/index.html create mode 100644 files/zh-cn/mozilla/javascript_code_modules/using/index.html create mode 100644 files/zh-cn/mozilla/javascript_tips/index.html create mode 100644 files/zh-cn/mozilla/js-ctypes/index.html create mode 100644 files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/ctypes/index.html create mode 100644 files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/index.html create mode 100644 files/zh-cn/mozilla/js-ctypes/using_js-ctypes/declaring_and_using_callbacks/index.html create mode 100644 files/zh-cn/mozilla/js-ctypes/using_js-ctypes/index.html create mode 100644 files/zh-cn/mozilla/js-ctypes/using_js-ctypes/memory_management/index.html create mode 100644 files/zh-cn/mozilla/js-ctypes/using_js-ctypes/working_with_arraybuffers/index.html create mode 100644 files/zh-cn/mozilla/localization/faq/index.html create mode 100644 files/zh-cn/mozilla/localization/index.html create mode 100644 files/zh-cn/mozilla/localization/l10n_style_guide/index.html create mode 100644 files/zh-cn/mozilla/localization/localizing_extension_descriptions/index.html create mode 100644 files/zh-cn/mozilla/mercurial/basics/index.html create mode 100644 files/zh-cn/mozilla/mercurial/index.html create mode 100644 files/zh-cn/mozilla/mercurial/installing_mercurial/index.html create mode 100644 files/zh-cn/mozilla/mfbt/index.html create mode 100644 files/zh-cn/mozilla/mozilla_on_github/index.html create mode 100644 files/zh-cn/mozilla/mozilla_persona/index.html create mode 100644 files/zh-cn/mozilla/participating_in_the_mozilla_project/index.html create mode 100644 files/zh-cn/mozilla/performance/about_colon_memory/index.html create mode 100644 files/zh-cn/mozilla/performance/index.html create mode 100644 files/zh-cn/mozilla/performance/scroll-linked_effects/index.html create mode 100644 files/zh-cn/mozilla/persona/bootstrapping_persona/index.html create mode 100644 files/zh-cn/mozilla/persona/branding/index.html create mode 100644 files/zh-cn/mozilla/persona/browser_compatibility/index.html create mode 100644 files/zh-cn/mozilla/persona/glossary/index.html create mode 100644 files/zh-cn/mozilla/persona/index.html create mode 100644 files/zh-cn/mozilla/persona/protocol_overview/index.html create mode 100644 files/zh-cn/mozilla/persona/quick_setup/index.html create mode 100644 files/zh-cn/mozilla/persona/remote_verification_api/index.html create mode 100644 files/zh-cn/mozilla/persona/security_considerations/index.html create mode 100644 files/zh-cn/mozilla/persona/why_persona/index.html create mode 100644 files/zh-cn/mozilla/preferences/index.html create mode 100644 files/zh-cn/mozilla/preferences/mozilla_networking_preferences/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/browser.altclicksave/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/browser.download.lastdir.savepersite/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/browser.search.context.loadinbackground/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/browser.urlbar.trimurls/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/dom.event.clipboardevents.enabled/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/javascript.options.strict/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/ui.alertnotificationorigin/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderline/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderlinestyle/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/ui.tooltipdelay/index.html create mode 100644 files/zh-cn/mozilla/preferences/preference_reference/view_source.syntax_highlight/index.html create mode 100644 files/zh-cn/mozilla/projects/crash_reporting/index.html create mode 100644 files/zh-cn/mozilla/projects/emscripten/index.html create mode 100644 files/zh-cn/mozilla/projects/index.html create mode 100644 files/zh-cn/mozilla/projects/l20n/index.html create mode 100644 files/zh-cn/mozilla/projects/nspr/index.html create mode 100644 files/zh-cn/mozilla/projects/nspr/reference/index.html create mode 100644 files/zh-cn/mozilla/projects/nspr/reference/memory_management_operations/index.html create mode 100644 files/zh-cn/mozilla/projects/psm/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/bsf/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/community/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/debugger/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/documentation/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/download_rhino/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/examples/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/license/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/overview/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/requirements_and_limitations/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/scripting_java/index.html create mode 100644 files/zh-cn/mozilla/projects/rhino/shell/index.html create mode 100644 files/zh-cn/mozilla/projects/social_api/index.html create mode 100644 files/zh-cn/mozilla/projects/social_api/share/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/build_documentation/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/comparision_of_js_engines/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/internals/bytecodes/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/internals/functions/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/internals/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/introduction_to_the_javascript_shell/index.html create mode 100644 "files/zh-cn/mozilla/projects/spidermonkey/javascript-c\345\274\225\346\223\216\345\265\214\345\205\245\345\274\200\345\217\221\346\214\207\345\215\227/index.html" create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/boolean_to_jsval/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_defineconstdoubles/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_call/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_ordinarytoprimitive/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_evaluatescript/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_getversion/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_hasownproperty/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_newruntime/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_seterrorreporter/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_valuetostring/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsclass/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsconstdoublespec/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jserrorreport/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsproperty/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jspropertydescriptor/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsruntime/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/parser_api/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/releases/index.html create mode 100644 files/zh-cn/mozilla/projects/spidermonkey/split_object/index.html create mode 100644 files/zh-cn/mozilla/rust/index.html create mode 100644 files/zh-cn/mozilla/tech/index.html create mode 100644 files/zh-cn/mozilla/tech/toolkit_api/extisessionstorage/index.html create mode 100644 files/zh-cn/mozilla/tech/toolkit_api/index.html create mode 100644 files/zh-cn/mozilla/tech/viewing_and_searching_mozilla_source_code_online/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/glue/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/arrays/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/an_overview_of_xpcom/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/building_the_weblock_ui/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/component_internals/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/creating_the_component_code/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/finishing_the_component/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/packaging_weblock/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/preface/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/resources/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/setting_up_the_gecko_sdk/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/starting_weblock/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_components/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_utilities_to_make_things_easier/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/hashtables/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/guide/internal_strings/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/interfacing_with_the_xpcom_cycle_collector/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.cloneinto/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.getglobalforobject/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/language_bindings/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/index.html create mode 100644 "files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\344\275\277\347\224\250javaxpcom\345\234\250java\345\272\224\347\224\250\347\250\213\345\272\217\344\270\255\345\265\214\345\205\245mozilla/index.html" create mode 100644 "files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\345\274\200\345\217\221/index.html" create mode 100644 files/zh-cn/mozilla/tech/xpcom/language_bindings/pyxpcom/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/language_bindings/xpconnect/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/observer_notifications/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/getting_started_guide/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiaccessibleprovider/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboard/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboardhelper/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiconsoleservice/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidirectoryserviceprovider/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidomclientrect/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifile/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifilepicker/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsihttpchannel/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiidleservice/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsilocalfile/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprocess/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprompt/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsipromptservice/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiscriptableunicodeconverter/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsisyncmessagesender/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitimer/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitraceablechannel/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiuri/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/reference/interface/nsixmlhttprequest/index.html create mode 100644 files/zh-cn/mozilla/tech/xpcom/setting_http_request_headers/index.html create mode 100644 files/zh-cn/mozilla/tech/xpidl/index.html create mode 100644 files/zh-cn/mozilla/tech/xpidl/syntax/index.html create mode 100644 files/zh-cn/mozilla/tech/xpidl/xpidl/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/acceltext/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/accesskey/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/activetitlebarcolor/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/align/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/allowevents/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/allownegativeassertions/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/autocheck/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/autoscroll/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/buttonaccesskeyaccept/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra1/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra2/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/buttons/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/checked/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/class/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/coalesceduplicatearcs/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/collapsed/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/command/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/container/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/control/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/crop/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/description/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/dir/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/disabled/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/flex/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/href/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/id/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/image.onload/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/image/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/increment/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/label/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/max/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/menuitem.key/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/menuitem.name/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/menuitem.type/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/min/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/name/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/onpopupshowing/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/onpopupshown/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/orient/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/pending/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/persist/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/selected/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/selectedindex/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/tabindex/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/validate/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/attribute/value/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/broadcaster/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/browser/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/button/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/checkbox/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/command/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/deprecated_defunct_markup/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/dialog/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/events/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/image/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/key/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/label/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/list_of_commands/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/listbox/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/listheader/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/menu/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/menubar/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/menuitem/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/menulist/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/menupopup/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/menuseparator/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/extra1/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/focus/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/getbrowserfortab/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/getbutton/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/increase/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/reset/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/method/stop/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/namespaces/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/popup/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/accessibletype/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/accesskey/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/browser.preferences/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/buttons/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/command/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/crop/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/defaultvalue/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/disabled/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/image/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/label/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/labelelement/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/markupdocumentviewer/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/max/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/menuitem.control/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/parentcontainer/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/selected/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/selectedindex/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/selecteditem/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/selectionstart/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/spinbuttons/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/tabindex/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/textbox.value/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/property/value/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/radio/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/radiogroup/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/script/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/statusbar/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/style/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/style/menuitem-iconic/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/style/menuitem-non-iconic/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tabbox/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/template_guide/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/textbox/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/toolbarpalette/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/toolbars/creating_toolbar_buttons/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/toolbars/custom_toolbar_button/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/toolbars/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/toolbox/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tree/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/adding_buttons/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/adding_event_handlers/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/adding_html_elements/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/adding_labels_and_images/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/adding_more_elements/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/adding_style_sheets/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/anonymous_content/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/box_model_details/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/content_panels/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/creating_a_skin/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/creating_a_window/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/creating_an_installer/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/creating_dialogs/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/document_object_model/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/element_positioning/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/features_of_a_window/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/grids/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/groupboxes/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/input_controls/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/introduction/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/introduction_to_rdf/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/list_controls/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/localization/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/manifest_files/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/modifying_a_xul_interface/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/modifying_the_default_skin/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/more_button_features/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/more_event_handlers/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/more_menu_features/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/more_wizards/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/numeric_controls/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/popup_menus/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/progress_meters/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/property_files/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/rdf_datasources/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/scroll_bars/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/scrolling_menus/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/simple_menu_bars/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/splitters/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/stack_positioning/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/stacks_and_decks/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/styling_a_tree/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/tabboxes/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/templates/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/the_box_model/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/the_chrome_url/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/toolbars/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/trees/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/using_spacers/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/using_xbl_from_stylesheets/index.html create mode 100644 "files/zh-cn/mozilla/tech/xul/tutorial/xbl\344\273\213\347\273\215/index.html" create mode 100644 "files/zh-cn/mozilla/tech/xul/tutorial/xpcom_\346\216\245\345\217\243/index.html" create mode 100644 files/zh-cn/mozilla/tech/xul/tutorial/xul_structure/index.html create mode 100644 "files/zh-cn/mozilla/tech/xul/tutorial/\346\233\264\345\244\232\347\232\204\346\214\211\351\222\256\347\211\271\346\200\247/index.html" create mode 100644 files/zh-cn/mozilla/tech/xul/vbox/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/window/index.html create mode 100644 files/zh-cn/mozilla/tech/xul/xul_reference/index.html create mode 100644 files/zh-cn/mozilla/thunderbird/index.html create mode 100644 files/zh-cn/mozilla/thunderbird/mail_client_architecture_overview/index.html create mode 100644 files/zh-cn/mozilla/thunderbird/mailnews_protocols/index.html create mode 100644 files/zh-cn/mozilla/toolkit_version_format/index.html create mode 100644 files/zh-cn/mozilla/webidl_bindings/index.html create mode 100644 files/zh-cn/mozilla/xmlhttprequest_changes_for_gecko_1.8/index.html create mode 100644 "files/zh-cn/mozilla/\345\220\214\346\227\266\344\275\277\347\224\250\345\244\232\344\270\252\347\233\270\344\272\222\347\213\254\347\253\213\347\232\204\347\201\253\347\213\220\346\265\217\350\247\210\345\231\250/index.html" create mode 100644 "files/zh-cn/mozilla/\346\227\245\345\216\206/index.html" (limited to 'files/zh-cn/mozilla') diff --git a/files/zh-cn/mozilla/accessibility/index.html b/files/zh-cn/mozilla/accessibility/index.html new file mode 100644 index 0000000000..38f8dff03d --- /dev/null +++ b/files/zh-cn/mozilla/accessibility/index.html @@ -0,0 +1,13 @@ +--- +title: Accessibility and Mozilla +slug: Mozilla/Accessibility +tags: + - Accessibility + - Mozilla + - NeedsTranslation + - TopicStub +translation_of: Mozilla/Accessibility +--- +

La accesibilidad es la idea de que el software (entre otras cosas) debe estar diseñado para ser utilizable y, en la medida de lo posible, conveniente para las personas con discapacidad. Mozilla se esfuerza por hacer que su software sea accesible; los documentos a continuación cubren las formas en que lo hacemos . SO Estos artículos proporcionan detalles acerca de la accesibilidad Mozilla específico -.

+ +

{{LandingPageListSubpages}}=Mx

diff --git a/files/zh-cn/mozilla/accessibility/software_accessibility_today/index.html b/files/zh-cn/mozilla/accessibility/software_accessibility_today/index.html new file mode 100644 index 0000000000..8f6884cbd0 --- /dev/null +++ b/files/zh-cn/mozilla/accessibility/software_accessibility_today/index.html @@ -0,0 +1,133 @@ +--- +title: 软件无障碍:我们前进到哪里了? +slug: Mozilla/Accessibility/Software_accessibility_today +tags: + - Accessibility + - 可访问性 + - 无障碍 +translation_of: Mozilla/Accessibility/Software_accessibility_today +--- +

在过去的二十年内,计算机软件的无障碍辅助功能已经出现了大幅改善。本文综述了这一方面的发展进度和技术。

+ +

我们前进到哪里了?

+ +

到目前为止,桌面计算机环境背后最大的驱动力来自微软公司,首先,他们开发出了 MS DOS,随后是一代又一代的 Microsoft Windows。在设计时,这些操作系统并没有考虑到残疾人的需要。许多人,包括那些失明或有其他身体残疾的人,无法使用一些为微软操作系统编写的应用程序。这些应用程序假设计算机用户可以:

+ + + +

如果一个人不能做到完成上面列出的项目中的任何一条,他就会发现自己无法使用许多流行的计算机应用程序。以下是一些在执行这些任务时会遇到问题的人群:

+ + + +

我们还必须考虑到,有越来越多的上了年纪的 50 后、60 后,还有 70 后开始出现视觉、视力或者灵活性方面的问题。当您将所有可能的用户群体加在一起时,就会发现,无障碍功能其实有很多潜在的用户!

+ +

In answer to this problem, many small accessibility hardware and software vendors created products and software which helped people who could not perform one of the four basic tasks to use common computer applications. Some examples of these assistive devices and software include:

+ + + +

In fact, the entire adaptive technology industry has grown up around these issues. One great place to go and learn about this industry is the CSUN conference in Los Angeles, which takes place every year in mid-late March.

+ +

访问屏幕内容的替代方法

+ +

大多数计算机程序都是图形化的,对于有视力障碍的人来说,其中一些程序难以使用或者根本无法使用。好在,这种情况不一定就无法挽回。以下是一些现在的视力障碍读者使用桌面软件的方式:

+ +
+
Text-to-speech (TTS)
+
Makes the computer talk to the user: Those who can't read print at all usually use talking programs (text-to-speech). Talking programs are also useful for print disabilities other than visual impairments, such as dyslexia. Additionally, text-to-speech is used by those who cannot speak, in place of their own voice. Finally, this technology could be useful to mainstream users, on portable information appliances, or to access information when the eyes are busy elsewhere.
+
放大
+
Enlarges the screen's contents: For those with low vision, it may suffice to use a larger font, a built-in high contrast theme, or even just an an extra large screen. Otherwise, screen magnification programs may be used, which allow zooming in to portions of the screen, while following the mouse or the current focus. Screen magnifiers also have some built-in text-to-speech and the ability to filter text and images through various color palettes, such as black on yellow for high contrast, or green on blue for low contrast.
+
The Optacon
+
Provides access to printed words, graphics and on-screen information by means of an array vibrating pins the size of an index finger. The user uses one hand to read the vibrating pins, and the other hand moves a mini-camera over the material to be read. Unfortunately, the unit is not currently produced, although there is occasional talk of resurrecting this useful device.
+
Braille
+
A solution used for quiet reading, for detailed work, and by deaf-blind users. This can come in the form of hard copy braille printed on braille embossers, or from a refreshable braille display (see below). These technologies requires special drivers, braille formatting routines and software based text-to-braille translation. The importance of braille itself must be emphasized. For those that read it, braille can offer higher levels of employment and life fulfillment.
+
+ + + + + + + + + + + + +
Refreshable braille displays of various sizesA braille embosser
+ +

Audio- and braille- based user interfaces are concepts that software designers are historically untrained for. The basic concept is easy - dealing with information when you're blind is like seeing everything through a mail slot - sequentially and methodically. Only small pieces of sequential, non-graphical information can be conveyed - via text-to-speech or a refreshable braille display. Whatever the user does, the software needs to respond with small, bite sized pieces of information that are as short and to the point as possible. Ideally, intelligent decisions are made, so the user does not have to wade through as much non-relevant data.

+ +

操作计算机、输入数据的替代方法

+ +

Another problem is how people with disabilities get information into the computer. If you're physically disabled, you may not be able to type on a regular keyboard or use a mouse. Here are some of the alternative ways physically disabled people enter information:

+ +
+
粘滞键
+
Make entering key combinations easy. For example to make a capital letter, first press the shift key, release it, then press the letter to be capitalized. The sticky key technique is utilized by people who have only one usable hand, or who have no use of their hands and type using a stick in their mouth.
+
Single switch
+
Technologies enable persons with severe physical disabilities. Some, like Stephen Hawking, enter information by choosing among lists of options. They might press a switch down to begin moving a highlight bar through the list, and release the switch when the desired option is highlighted.
+
特种键盘
+
Exist to make data entry easier. However, any special features are generally handled in the keyboard itself, so that no special programming is required.
+
语音识别
+
Technology lets people talk to the computer. This technology has come a long way, but still needs to be more integrated into mainstream software.
+
Consistent keyboard support and hotkeys
+
Many people can't use a mouse. Extremely consistent keystroke support is a very important consideration. Blind testers have knack for finding ways to improve keystroke support in almost any given piece of software. Testing with people that have disabilities generally benefits everyone. Use the accessible toolkit checklist to make sure your UI controls adhere to standards.
+
+ +

一大主要限制——上下文缺失

+ +

这些无障碍软件厂商开发的解决方案大大增加了几十万残障人士的就业率和幸福指数,这些工作的重要性绝不能被轻视。然而,这些解决方案都没能为残障人士提供一个完全可访问、高度易用的工作环境。这是由于一个和上下文有关的简单问题——用户与计算机间的交互是由交互的上下文决定的。当用户在键盘上输入一些东西,或者一个应用程序在屏幕上显示了一些文本或图像,在不同的上下文中,这些交互行为的具体含义也可以是截然不同的。举个例子,一个应用程序可能在处理任务时显示一个电灯泡,而另一个程序可能是在完成任务后显示电灯泡。如果盲人不能得知显示是哪个程序显示了电灯泡,就无法理解这个电灯泡代表什么意思,只能靠猜。类似地,语音识别软件常常需要用户补充交互的上下文信息,来保证用户的语音输入作用到正确的上下文中。这个上下文的问题依然困扰着现代的辅助功能解决方案。

+ +

The most recent noteable attempt at solving this problem was put forth by Microsoft in 1997, and is called Microsoft Active Accessibility (MSAA). Realizing that complete accessibility was not possible without cooperation between applications and accessibility aids such as screen reading software or voice recognition software, Microsoft Active Accessibility defines a Windows-based standard by which applications can communicate context and other pertanent information to accessibility aids. This solution has seen only partial success, largely due to the fact that it requires significant changes to applications which are made accessible. Because most popular desktop and productivity applications are not open source, this forced disabled people to rely on the companies which produce this software to make it accessible. These companies were often reluctant for various reasons including the large amount of time required to do so. On a positive note, recent federal purchasing rules such as Section 508 have caused many companies to pay attention and implement MSAA support.

+ +

步入开源软件之门

+ +

Microsoft was on the right track with Microsoft Active Accessibility, but because the source code to most popular desktop applications which are used in large corporations is not publicly available, they were never made fully accessible. In open source, however, making the necessary modifications to make them accessible is very possible.

+ +

Open source software is an ideal way to the needs of disabled users, because accessibility can be fully integrated into the core designs, rather than tacked onto as an afterthought. It also gives disabled programmers a chance to control their own destiny, by giving them the opportunity and the right to directly fix the innaccessible software themselves.

+ +

Furthermore, any software solution that can enable equality should by all rights be free of charge - an integral part of society's infrastructure. If no special hardware is required, why should a disabled person pay extra money to use the same software as everyone else? That said, there is still an important role for adaptive technology vendors in creating special services and hardware, or even proprietary software on platforms where that is appropriate. . The ideal situation would be for adaptive technology professionals to make money on rehab, trainingand support - something there is currently not enough of. Each end user has a unique set problems, and in the open source world, providing highly customized solutions can be a business in itself.

+ +

Right now, GUI's on Linux are mostly not accessible. Microsoft Windows is still far more accesible. Gnome, KDE, StarOffice, KOffice, Mozilla and all other GUI software packages in Linux are unuseable by large numbers of disabled users. There has been some progress with the support of Gnome's ATK APIs in many of these packages, and the development of GOK (Gnome Onscreen Keyboard) and Gnopernicus (screenreader and magnifier). However, these solutions are not yet truly usable for real disabled end users.

+ +

我需要做什么?

+ +

Mozilla 开发者

+ + + +

其他开发者

+ +

无论您从事何种工作,可访问性的基础是要了解每一个用户都是不同的。在此之后,具体需要采用的技术可能会随工程环境的不同而变化。下面的{{anch("参见")}}含有分别适用于 Web 开发者和桌面应用程序开发者的各种信息与工具。

+ +

参见

+ + 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/' +--- +

REDIRECT https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/AMO/Policy/Reviews

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 +--- +

{{AddonSidebar}}

+ +

Content to be added.

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 +--- +

{{AddonSideBar}}

+ +

感谢您愿意与Mozilla 附加组件小组联络。 请仔细阅读此页面,以确保您的请求能到达正确的地方。

+ +

附加组件支持

+ +

如果您有关于特定附加组件的支持问题,例如“如何使用此附加组件?” 或“为什么不能正常工作?”,请通过附加组件列表页上列出的支持渠道联系该附加组件作者。

+ +

附加组件审查相关

+ +

如果您有关于附加组件审核希望报告违反政策的问题,请发送电子邮件至 amo-editors@mozilla.org。几乎所有的附加组件报告都属于这个类别。请务必包含相关附加组件的链接以及您的问题或评论的详细说明。

+ +

附加组件安全漏洞

+ +

如果您在附加程序中发现了安全漏洞,即使它不在此处托管,Mozilla也对您的发现感兴趣并将与附加开发人员一起尽快更正该问题。附加组件的安全问题可以直接报告Bugzillaconfidentially 或发邮件给 amo-admins@mozilla.org.

+ +

网站功能与发展

+ +

如果您发现本网站有问题 , 我们乐意修复。请在Github 上传BUG报告, 报告中包括问题的位置以及您如何遇到这个问题。

+ +

关于这些政策或您的插件如何与我们联系。

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 +--- +

{{AddonSidebar}}

+ +

Mozilla 致力于为我们的用户和开发人员确保极佳的附加体验,在提交您的附加组件之前,请查阅下列政策。

+ +
+
开发者协议
+
Effective January 5, 2016
审核处理
+
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.

+
精选的Add-ons
+
How up-and-coming add-ons become featured and what's involved in the process.

+ 联系我们 + +

How to get in touch with us regarding these policies or your add-on.

+ +
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 +--- +

{{LegacyAddonsNotice}}

+ +

关于使用<canvas>的一般信息,请参阅 canvas topic page.

+ +

网页中可以用到的代码

+ +

在画布中获取特定颜色的像素数量

+ +

下面的函数将返回画布上颜色(RGB格式)为r、g、b的像素数量。如果用户希望像这篇博客文章中在另一个区域绘画,那么这将非常有用。 

+ +
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 < all; i += 4) {
+    if (pixels.data[i] === r &&
+        pixels.data[i + 1] === g &&
+        pixels.data[i + 2] === b) {
+      amount++;
+    }
+  }
+  return amount;
+};
+
+ +

在画布中获取某一个像素的颜色

+ +

下面的代码片段返回一个对象,该对象在画布的x和y的位置上具有RGBA值。这可以用来确定鼠标光标是否在一个特定的形状中。

+ +
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]
+  };
+}
+
+ +

链式调用方法

+ +

这个类允许可以像jQuery那样链式地访问 2D 渲染上下文的方法和属性 。

+ +
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();
+
+ +

Code usable only from privileged code

+ +

These snippets are only useful from privileged code, such as extensions or privileged apps.

+ +

将canvas图片保存到文件中

+ +

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.

+ +
function saveCanvas(canvas, path, type, options) {
+    return Task.spawn(function *() {
+        var reader = new FileReader;
+        var blob = yield new Promise(accept => canvas.toBlob(accept, type, options));
+        reader.readAsArrayBuffer(blob);
+
+        yield new Promise(accept => { reader.onloadend = accept });
+
+        return yield OS.File.writeAtomic(path, new Uint8Array(reader.result),
+                                         { tmpPath: path + '.tmp' });
+    });
+}
+
+ +

将一个远程页面加载到canvas元素上

+ +

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.

+ +

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.

+ +
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();
+};
+
+ +

Usage:

+ +
var remoteCanvas = new RemoteCanvas();
+remoteCanvas.load();
+
+ +

将图像文件转换为base64字符串

+ +

下面代码加载远程图片,并把它的内容转化为 Data URI scheme

+ +
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) => {
+    image.onload = accept;
+    image.onerror = reject;
+  }).then(accept => {
+    canvas.width = this.width;
+    canvas.height = this.height;
+    ctxt.clearRect(0, 0, this.width, this.height);
+    ctxt.drawImage(this, 0, 0);
+    accept(canvas.toDataURL());
+  });
+}
+
+ +

Usage:

+ +
loadImageFile('myimage.jpg').then(string64 => { alert(string64); });
+
+ +

如果你想获取本地文件(使用文件选择input元素)的 base64 内容,你必须使用 FileReader 对象。

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 +--- +

{{LegacyAddonsNotice}}

+ +

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.

+ +

These examples demonstrate how to accomplish basic tasks that might not be immediately obvious.

+ +

General

+ +
+
Examples and demos from MDN articles
+
A collection of examples and demos from articles.
+
Window code
+
Opening and manipulating windows
+
Toolbar
+
Toolbar related code
+
Sidebar
+
Sidebar related code
+
Forms
+
Forms related code
+
XML
+
Code used to parse, write, manipulate, etc. XML
+
File I/O
+
Code used to read, write and process files
+
Drag & Drop
+
Code used to setup and handle drag and drop events
+
Dialogs
+
Code used to display and process dialog boxes
+
Alerts and Notifications
+
Modal and non-modal ways to notify users
+
Preferences
+
Code used to read, write, and modify preferences
+
JS XPCOM
+
Code used to define and call XPCOM components in JavaScript
+
Running applications
+
Code used to run other applications
+
<canvas> related
+
WHAT WG Canvas-related code
+
Signing a XPI
+
How to sign an XPI with PKI
+
Delayed Execution
+
Performing background operations.
+
Miscellaneous
+
Miscellaneous useful code fragments
+
HTML to DOM
+
Using a hidden browser element to parse HTML to a window's DOM
+
+ +

JavaScript libraries

+ +

Here are some JavaScript libraries that may come in handy.

+ +
+
StringView
+
A library that implements a StringView view for JavaScript typed arrays. This lets you access data in typed arrays using C-like string functions.
+
Rosetta
+
By default, the only possible standardized scripting language for HTML is ECMAScript. 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 typed arrays in ECMAScript allow us, in theory, to build full virtual machines 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.
+
+ +

Browser-oriented code

+ +
+
Tabbed browser code (Firefox/SeaMonkey)
+
Basic operations, such as page loading, with the tabbed browser, which is the heart of Mozilla's browser applications
+
Cookies
+
Reading, writing, modifying, and removing cookies
+
Page Loading
+
Code used to load pages, reload pages, and listen for page loads
+
Interaction between privileged and non-privileged code
+
How to communicate from extensions to websites and vice-versa.
+
Downloading Files
+
Code to download files, images, and to monitor download progress
+
Password Manager
+
Code used to read and write passwords to/from the integrated password manager
+
Bookmarks
+
Code used to read and write bookmarks
+
JavaScript Debugger Service
+
Code used to interact with the JavaScript Debugger Service
+
+ +

SVG

+ +
+
General
+
General information and utilities
+
SVG Animation
+
Animate SVG using JavaScript and SMIL
+
SVG Interacting with Script
+
Using JavaScript and DOM events to create interactive SVG
+
Embedding SVG in HTML and XUL
+
Using SVG to enhance HTML or XUL based markup
+
+ +

XUL Widgets

+ +
+
HTML in XUL for Rich Tooltips
+
Dynamically embed HTML into a XUL element to attain markup in a tooltip
+
Label and description
+
Special uses and line breaking examples
+
Tree
+
Setup and manipulation of trees using XUL and JS
+
Scrollbar
+
Changing style of scrollbars. Applies to scrollbars in browser and iframe as well.
+
Autocomplete
+
Code used to enable form autocomplete in a browser
+
Boxes
+
Tips and tricks when using boxes as containers
+
Tabbox
+
Removing and manipulating tabs in a tabbox
+
+ +

Windows-specific

+ +
+
Finding Window Handles (HWND) (Firefox)
+
How to use Windows API calls to find various kinds of Mozilla window handles. Window handles can be used for IPC and Accessibility purposes.
+
Using the Windows Registry with XPCOM
+
How to read, write, modify, delete, enumerate, and watch registry keys and values.
+
+ + + +

The content at MozillaZine Example Code is slowly being moved here, but you can still find useful examples there for now.

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 +--- +

{{LegacyAddonsNotice}}

+ +

这是一些解决XPCOM组件相关的有用的JavaScript代码。

+ +

Contract IDs

+ +

契约ID是XPCOM对象独一无二的名字。它们用于创建或者获得XPCOM中的对象。

+ +

Interfaces

+ +

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 nsIFile. Every XPCOM object must implement the nsISupports interface.

+ +

Accessing XPCOM components from JavaScript

+ +

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.

+ +

Creating an instance of a component

+ +

The preferred method of creating XPCOM instances is via the Components.Constructor helper. For example,

+ +
var nsFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile", "initWithPath");
+
+var file = new nsFile(filePath);
+
+ +

They can also be created and initialized manually:

+ +
var file = Components.classes["@mozilla.org/file/local;1"]
+                     .createInstance(Components.interfaces.nsIFile);
+file.initWithPath(filePath);
+
+ +

This creates a new instance of the object with contract ID @mozilla.org/file/local;1 and allows you to call methods from the nsIFile interface on it.

+ +

Getting an XPCOM service

+ +
var preferences = Components.classes["@mozilla.org/preferences-service;1"]
+                            .getService(Components.interfaces.nsIPrefService);
+
+ +

You can then call any methods in the nsIPrefService interface on the preferences object.

+ +

Getting a different interface for a component

+ +

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:

+ +
var preferences = preferences.QueryInterface(Components.interfaces.nsIPrefBranch2);
+
+ +

This allows you to use the methods in the nsIPrefBranch2 interface.

+ +

Determining which interfaces an XPCOM component supports

+ +

To display a list of all interfaces that an XPCOM component supports, do the following:

+ +
// |c| is the XPCOM component instance
+for each (i in Components.interfaces) { if (c instanceof i) { alert(i); } }
+
+ +

In this context, instanceof is the same as QueryInterface except that it returns false instead of throwing an exception when |c| doesn't support interface |i|. Another difference is that QueryInterface returns an object, where as instanceof returns a boolean.

+ +

XPCOMUtils - About protocol handler

+ +

{{ Fx_minversion_inline(3) }}This example implements a quick about protocol handler in JS using XPCOMUtils.jsm.

+ +
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]);
+}
+
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 +--- +

{{LegacyAddonsNotice}}

+ +

一些简单的代码将JavaScript模块转换为非Mozilla特定的代码(例如,如果移植到浏览器)。eval()的使用可能不会被关注,因为它仅在EXPORTED_SYMBOLS 数组上使用,而不依赖于用户输入。

+ +
函数importModule(thatObj){
+    thatObj = thatObj || 窗口;
+
+    var EXPORTED_SYMBOLS = [
+    //把符号放在这里
+    ]。
+
+    //你的代码在这里...
+
+    //在你的代码结尾处:(假设'i'和'thatObj'都没有被导出!)
+    for(var i = 0; i <EXPORTED_SYMBOLS.length; i ++){thatObj [EXPORTED_SYMBOLS [i]] = eval(EXPORTED_SYMBOLS [i]);}
+}
+
+ +

或一次性使用模块:

+ +
(function(thatObj){
+    thatObj = thatObj || 窗口;
+
+    var EXPORTED_SYMBOLS = [
+    //把符号放在这里
+    ]。
+
+    //你的代码在这里...
+
+    //在你的代码结尾处:(假设'i'和'thatObj'都没有被导出!)
+    for(var i = 0; i <EXPORTED_SYMBOLS.length; i ++){thatObj [EXPORTED_SYMBOLS [i]] = eval(EXPORTED_SYMBOLS [i]);}
+})(); //可以在这里放置一个对象参数
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 +--- +

 {{ fx_minversion_header(3.5) }}

+ +

沿着其他框架,如jQuery或Prototype, 缩短“querySelector”的名称可以很方便:

+ +
    HTMLDocument.prototype.$ = function (selector) {
+        // Only for HTML
+        return this.querySelector(selector);
+    };
+    $(`div`);
+    HTMLDocument.prototype.$$ = function (selector) {
+        // Only for HTML
+        return this.querySelectorAll(selector);
+    };
+    $$(`div`);
+ +
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);
+
+ +

(请注意,在使用火狐浏览器控制台时,上述功能可自动使用.)

+ +

 XUL 甚至 XML可以很简单的支持(有以下两种替代方法,添加ChromeWindow.prototype 或者 Window.prototype,访问 this.document.querySelector, 或者根据jQuery 风格的链接,即在每个原型的$()方法中返回的‘this'

+ +
HTMLDocument.prototype.$ = function (selector) { // 只用于HTML
+    return this.querySelector(selector);
+};
+
+Example:
+
+<h1>Test!</h1>
+<script>
+HTMLDocument.prototype.$ = function (selector) {
+    return this.querySelector(selector);
+};
+alert(document.$('h1')); // [object HTMLHeadingElement]
+</script>
+
+ +
XULDocument.prototype.$ = function (selector) { // 只用于XUL
+    return this.querySelector(selector);
+};
+
+Example:
+
+<label value="Test!"/>
+<script type="text/javascript"><![CDATA[
+XULDocument.prototype.$ = function (selector) { // 只用于XUL
+    return this.querySelector(selector);
+};
+
+alert(document.$('label')); // [object XULElement]
+]]></script>
+
+ +
Document.prototype.$ = function (selector) { // 只用于XML
+    return this.querySelector(selector);
+};
+var foo = document.implementation.createDocument('someNS', 'foo', null); // Create an XML document <foo xmlns="someNS"/>
+var bar = foo.createElementNS('someNS', 'bar'); // add <bar xmlns="someNS"/>
+foo.documentElement.appendChild(bar);
+alert(foo.$('bar').nodeName); // gives 'bar'
+
+ +
Element.prototype.$ = function (selector) { // 可用于HTML,XUL,XML
+    return this.querySelector(selector);
+};
+
+HTML 例子:
+<h1><a>Test!<a/></h1>
+<script>
+Element.prototype.$ = function (selector) {
+    return this.querySelector(selector);
+};
+alert(document.getElementsByTagName('h1')[0].$('a').nodeName); // 'A'
+
+XUL 例子:
+<hbox><vbox/></hbox>
+<script type="text/javascript"><![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
+]]></script>
+
+XML 例子:
+<foo xmlns="someNS"><bar/></foo> in document earlier
+var foo = document.getElementsByTagNameNS('someNS', 'foo')[0];
+alert(foo.$('bar'));
+
+
+ +

注意在XML中,  # 'id'选择器将不能体现为'id'属性(因此一个这样名字的属性不一定是XML的ID,尽管他在HTML 和XUL中是这样的), 也不会对 xml:id 起作用.

+ +

然而,它将工作于指向没有无前缀属性选择器 (例如'id',但是不是 xml:id: http://www.w3.org/TR/selectors-api/#resolving) (即使 CSS3 支持命名空间属性选择器: http://www.w3.org/TR/css3-selectors/#attrnmsp 以及可能将xml:id 当作 #: http://www.w3.org/TR/css3-selectors/#id-selectors ).

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 +--- +

{{LegacyAddonsNotice}}

+ +

 

+ +

JavaScript的代码块通常情况下是顺序执行的。不过有几个JavaScript内置函数(计时器),能够让我们推迟任意指令的执行:

+ + + +

The setTimeout() function is commonly used if you wish to have your function called once after the specified delay. The setInterval() function is commonly used to set a delay for functions that are executed again and again, such as animations. The setImmediate() function can be used instead of the setTimeout(fn, 0) method to execute heavy operations in IE. The requestAnimationFrame() 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.

+ +

Documentation

+ +
+
{{domxref("window.setTimeout","setTimeout()")}}
+
Calls a function or executes a code snippet after specified delay.
+
{{domxref("window.setInterval","setInterval()")}}
+
Calls a function or executes a code snippet repeatedly, with a fixed time delay between each call to that function.
+
{{domxref("window.setImmediate","setImmediate()")}}
+
Calls a function immediately after the browser has completed other operations, such as events and display updates.
+
{{domxref("window.clearTimeout","clearTimeout()")}}
+
Clears the delay set by setTimeout().
+
{{domxref("window.clearInterval","clearInterval()")}}
+
Cancels repeated action which was set up using setInterval().
+
{{domxref("window.clearImmediate","clearImmediate()")}}
+
Cancels the immediate actions, just like {{domxref("window.clearTimeout","clearTimeout()")}} for {{domxref("window.setTimeout","setTimeout()")}}.
+
Using JavaScript timers within animations (Javascript Daemons Management)
+
In Computer science a daemon 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 daemons 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.
+
{{domxref("window.requestAnimationFrame","requestAnimationFrame()")}}
+
requestAnimationFrame() 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.
+
{{domxref("performance.now","performance.now()")}}
+
+

performance.now() returns a timestamp, measured in milliseconds, accurate to one thousandth of a millisecond. This timestamp is equal to the number of milliseconds since the navigationStart attribute of the performance.timing interface.

+
+
Date.now()
+
Date.now() returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
+
Using JavaScript timers within workers
+
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.
+
Functions available to workers
+
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.
+
Basic animations
+
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.
+
Timer.jsm
+
The Timer.jsm JavaScript code module contains pure-JavaScript implementations of setTimeout and clearTimeout 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, JavaScript code modules or content frame scripts).
+
+ +

See also

+ + + +

<embed height="0" id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd" type="application/thunder_download_plugin" width="0">

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 +--- +
+ Note: 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.
+

There is a wealth of material on creating extensions for Firefox. All of these documents currently assume, however, that you are developing your extension using XUL and JavaScript 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:

+

有大量如何创建扩展的资料, 但是这些文档都假定仅仅使用XUL和Javascript开发扩展. 对于复杂的扩展, 可能需要C++开发相关的功能代码. 下列原因可能使你想要在扩展中包括C++组件(Components):

+ +

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.

+

I should also stress that you do not 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 XPCOM component or two, this is probably overkill, and you might want to take a look at this guide 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.

+

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.

+

Bambi Meets Mozilla(小鹿斑比遇见Mozilla)

+

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.

+

(小鹿斑比小时候很胆小)其实这些并不适合胆小者. 尤其是, 第一步编译Mozilla, 那是庞大的 -- 非常非常巨大的 -- 项目. 在初次编译Mozilla时, 许多聪明的开发者都快被逼疯了. 如果你不是资深的C++开发者, 就别烦恼了, 继续玩Javascript.

+

On Windows Platforms

+

The first time I built Mozilla I used this guide. 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 comprehensive looking guide 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.

+

On Other Platforms

+

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 here.

+

Structuring Your Project(构造您的项目)

+

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 extensions/ directory and so forth. So it behooves us to piggyback on this infrastructure to build our extension.

+

First of all, think of a catchy name for your extension and create a directory with that name under the /mozilla/extensions/ directory. Use only lowercase letters. You should see a bunch of other directories (inspector/, reporter/ and so forth) at the same level in the build tree.

+

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 Makefile.in. 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.

+

Anatomy of a Simple C++ Extension(分析一个简单的C++扩展)

+

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.

+

In the simplest case, a component will consist of a single main directory with two subdirectories, public/ and src/. The main directory and each subdirectory must contain a Makefile.in (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.

+

So here’s your basic, plain-vanilla top-level makefile (Makefile.in in the main extension directory):

+
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
+
+

A detailed description of the make process, describing the key features of this makefile, can be found here. MODULE and XPI_NAME 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). INSTALL_EXTENSION_ID 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 XPI_PKGNAME, but if you do an XPI file, suitable for distribution, is automatically created in the root of the XPI staging area (/mozilla/$(MOZ_OBJDIR)/dist/xpi-stage/).

+

Every extension must include an install.rdf file that tells Firefox how to install it. This file should be located in the main extension directory and look something like this:

+
<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>myextension@mycompany.com</em:id>
+    <em:version>0.1</em:version>
+
+    <em:targetApplication>
+      <!-- Firefox -->
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>1.0+</em:minVersion>
+        <em:maxVersion>1.0+</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- front-end metadata -->
+    <em:name>My First Extension</em:name>
+    <em:description>Just an example.</em:description>
+    <em:creator>allpeers.com</em:creator>
+    <em:homepageURL>http://www.allpeers.com/blog/</em:homepageURL>
+  </Description>
+</RDF>
+
+

There's a detailed description of the format of the install.rdf file. Use the DIST_FILES variable in the makefile to tell make to copy the file into the extension directory and (optional) XPI file.

+

Public Interfaces(公共接口)

+

The public/ directory contains any interfaces that need to be accessed by other modules. These can be IDL files describing XPCOM 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.

+

The makefile in the public/ directory should follow this model:

+
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
+
+

XPIDL_MODULE is the name of the generated XPT file that contains type information about your IDL interfaces. If you have multiple modules, make absolutely sure that you use a different value for XPIDL_MODULE for each one. Otherwise the first module’s XPT file will be overwritten by the second and you’ll get NS_ERROR_XPC_BAD_IID errors when you try to access its IDL interfaces from your code. The files under EXPORTS are copied directly to the /mozilla/$(MOZ_OBJDIR)/dist/include/myextension/ directory and are thus accessible from other modules (the value of MOZ_OBJDIR is defined in /mozilla/.mozconfig). 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 components/ subdirectory of your extension.

+

Source Files(源文件)

+

Now it’s time to create the makefile and source files in the src/ subdirectory. If you're implementing interfaces that you've described using IDL, the easiest way to do this is to leave the src/ directory empty and run make on the public/ directory only; this will be explained shortly.

+

Then open the generated header file for your interface from /mozilla/$(MOZ_OBJDIR)/dist/include/myextension/. 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.

+

Here’s an example of the makefile you need to place into your src directory:

+
DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+IS_COMPONENT = 1
+MODULE = myextension
+LIBRARY_NAME =  myExtension
+USE_STATIC_LIBS = 1
+
+XPI_NAME = myextension
+
+REQUIRES	= xpcom \
+		  string \
+		  $(NULL)
+
+CPPSRCS		= \
+		  myFirstComponent.cpp \
+		  mySecondComponent.cpp \
+		  myExtension.cpp \
+		  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+EXTRA_DSO_LDOPTS += \
+  $(XPCOM_GLUE_LDOPTS) \
+  $(NSPR_LIBS) \
+  $(NULL)
+
+# NOTE: If you are coding against the 1.8.0 branch (not 1.8 branch or trunk), the
+# above line won't work, due to linker flag issues. 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.
+
+

The REQUIRES section tells make which modules your components uses. This causes the relevant subdirectories of /mozilla/$(MOZ_OBJDIR)/dist/include/ 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. CPPSRCS lists the source files that need to be built.

+

In this example, the first two files contain the implementation of the extension’s two components. The final file, myExtension.cpp, contains the code necessary to register these components, as described in the next section.

+

Registering Your Components(注册组件)

+

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 nsIModule 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.

+

The first step is to define a CID, contract ID and class name for each of your components. Place the following code (adapting the #defines accordingly) into the header of each component that you want to be able to instantiate using the component manager:

+
// {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"
+
+

Obviously you need to fill in the CID with a real GUID. Under Windows, this can be generated using guidgen.exe. Unix people can use uuidgen (comes standard with most unixes and Linux distros).

+

Now create the myExtension.cpp file like so:

+
#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)
+
+

The NS_IMPL_NSGETMODULE macro creates the appropriate module object providing access to all of the components listed in the nsModuleComponentInfo array.

+

Building It(编译扩展)

+

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 firefox.exe. Do not pass go. Do not collect $200.

+

Still here? Okay, now we have to modify your .mozconfig (in the /mozilla/ root directory) so that your extension is built along with Mozilla. Add the following line at the end of the file:

+
ac_add_options --enable-extensions=default,myextension
+
+

Now launch make from the Mozilla root:

+
make -f client.mk build
+
+

Even if you have an up-to-date Firefox build, you’ll have to wait a while for make 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 /mozilla/$(MOZ_OBJDIR)/:

+ +

A lot of this stuff won’t get created on this first pass since make 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 make. There might be exceptions to this rule, but if you’re changing the generated files directly, you’re probably doing something wrong.

+

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:

+
../build/autoconf/make-makefile extensions/myextension
+
+

If your $(MOZ_OBJDIR) is located outside your $(TOPSRCDIR), you'll need to do:

+
$(TOPSRCDIR)/build/autoconf/make-makefile -t $(TOPSRCDIR) extensions/myextension
+
+

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).

+

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 /mozilla/$(MOZ_OBJDIR)/extensions/myextension/ 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 /mozilla/$(MOZ_OBJDIR)/dist/bin/extensions. (If something goes wrong, figure out what, fix it and then come back here and add it to this article.)

+

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 MOZ_NO_REMOTE environment variable to "1" before running the development version of Firefox. You’ll also need to use a different profile for your development version:

+
firefox -P development
+
+

Where development 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.

+

No Place Like Chrome

+

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 JavaScript and XUL code. At this point, it would be very helpful to have a bit of experience writing "regular" extensions (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.

+

Assuming you know how to write XUL/JavaScript extensions, you’re aware that the most important stuff goes in the chrome/ 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 content/, locale/ and skin/ 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 chrome/ subdirectory or whatever. Let freedom reign!

+

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 JAR Manifest. For our simple extension example, this file might look something like this:

+
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)
+
+

Place this code in a file called jar.mn 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:

+
USE_EXTENSION_MANIFEST = 1
+
+

This tells make to create a single manifest file called chrome.manifest instead of creating separate manifests with goofy names for each package.

+

Now launch make again, and you should see a chrome subdirectory appear in your extension (/mozilla/$(MOZ_OBJDIR)/dist/bin/extensions/myextension@mycompany.com/). Note that the chrome directory contains a JAR (i.e. ZIP) file with all the chrome files listed in jar.mn 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.

+

Keeping it Complex

+

If you’re developing a really complex extension with lots of XPCOM components, you’ll probably want to divide your code up into smaller modules.

+
Kinda, Sorta Complex Extensions
+

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 base/ module that defines a bunch of basic XPCOM components and an advanced/ module that defines some chrome as well as other components that use the basic components. Your complete directory structure will look something like this:

+ +

Other than that, nothing really changes. The makefiles in the base/ and advanced/ directories should look more or less like your original root makefile, remembering to change the DEPTH variable to account for the fact that they’ve moved a level further away from the Mozilla root. You also need to remove the DIST_FILES variable since that’s going to be in the top-level makefile. Every makefile that generates anything should define the XPI_NAME variable to make sure generated files go into your extension and not into the global components/ directory. In fact, just define this in every makefile to be safe. You can use the same MODULE in both base/ and advanced/ so that all the generated include files go into the same directory, but make sure that you don’t use the same XPIDL_MODULE in the two public/ directories or one of the component type libraries (i.e. XPT files) will overwrite the other one and all hell will break loose.

+

Each module must also have a different value for the LIBRARY_NAME variable. This is the name of the generated dynamic library, so if we call the libraries "myBase" and "myAdvanced", we’ll end up with myBase.dll and myAdvanced.dll (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 myExtension.cpp in the original example, say Base.cpp and Advanced.cpp. Finally, each module will obviously have its own jar.mn, 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 install.rdf, which still exists once and only once in the extension root directory.

+

As for the top-level makefile, it will now look like this:

+
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
+
+
Seriously Complex Extensions
+

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 myExtension.cpp 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.

+

To split a module into submodules, first create a subdirectory for each submodule. Then create an additional directory called build/. Each submodule will be configured to create a static library, and the build/ directory will pull these libraries together to create a single dynamic component library. Confused? Here’s an example, showing just the advanced/ subbranch of the myextension/ directory:

+ +

As you can see, we’ve split advanced/ into two submodules: intricate/ and multifarious/, and we’ve added an additional build/ subdirectory. We’ve left the chrome directories directly under advanced/, since they aren’t tied to any specific submodule. This means that jar.mn will stay in the same place.

+

The intricate/ and multifarious/ makefiles will look a lot like the original advanced/ makefile, but we’ll need to tweak them a bit. As always, we have to adjust the DEPTH variable since the makefiles are deeper in the directory structure. And we should change the LIBRARY_NAME 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 FORCE_STATIC_LIB, resulting in a makefile that starts something like this:

+
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...
+
+

The build makefile pulls together the static libraries generated by the submodules and creates a single (dynamic) component library:

+
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)
+
+

The makefile in the advanced/ directory should list the intricate/, multifarious/ and build/ directories in its DIRS variable. Make sure that build/ comes last since it can’t create the component library until the other makefiles have completed.

+

Other Topics

+

Adding Data Files to Your Extensions

+

In some cases, you may wish to include additional files in your extension that don’t belong in the chrome/ 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.

+
Copying Data Files Into Target Directory
+

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 stats/ 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:

+
export::
+	if test ! -d $(FINAL_TARGET)/stats; then \
+		$(NSINSTALL) -D $(FINAL_TARGET)/stats; \
+	fi
+	$(INSTALL) $(srcdir)/*.txt $(FINAL_TARGET)/stats
+
+
Accessing Data Files From Components
+

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 nsIExtensionManager 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 __LOCATION__ (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.

+

This article explains how to create an XPCOM component in JavaScript. You’ll need an IDL file for an interface that looks something like this:

+
interface myILocation : nsISupports
+{
+    readonly attribute nsIFile locationFile;
+};
+
+

Place the IDL file in the public/ directory of your project or subproject. In the src/ 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:

+
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;
+  }
+}
+
+

This assumes that the component resides in a subdirectory of the extension directory (by convention, this directory is called components/). The parent property of __LOCATION__ returns the components/, and the parent of this is the extension directory.

+

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:

+
export::
+	$(INSTALL) $(srcdir)/*.js $(FINAL_TARGET)/components
+
+

Now you can instantiate an instance of this component and use the locationFile property to get an nsIFile interface that points to your extension’s home directory.

+

Using Third-Party Libraries

+

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.

+

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 db/sqlite. 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.

+

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 acmelib is used inside the multifarious/ subproject in the above example, it would be placed as a subdirectory underneath that subproject (at the same level as public/ and src/).

+

Of course, this means that you will have to build acmelib 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.

+

Building for Multiple Platforms

+

TODO

+
+

Original Document Information

+ +
+

 

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 +--- +

{{ fx_minversion_header("2") }}

+

Firefox 2 支持使用 OpenSearch 格式开发搜索引擎插件. 使用 OpenSearch 格式开发能够在IE 7 以及 Firefox上实现兼容. 这是这种语法被推荐使用的原因.

+

Firefox 也支持不被包括在 OpenSearch格式  中的其它的搜索功能,例如搜索建议(search suggestion)以及 SearchForm 元素. 这篇文章主要关注创建与OpenSearch格式兼容的支持额外的firefox特殊特征的搜索插件.

+

OpenSearch 描述文件也能被如在 Autodiscovery of search plugins  中描述的一样被advertised(道歉这里不知如何翻译) ,并且能够如在 Adding search engines from web pages中所说的进行编程安装.

+

OpenSearch 描述文件

+

遵循以下的模板,你就会发现通过 XML 文件写一个搜索引擎实际上是如此的简单。 粗体字部分需要根据具体你所写的搜索引擎需要来进行定制 。

+
<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+                       xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+  <ShortName>engineName</ShortName>
+  <Description>engineDescription</Description>
+  <InputEncoding>inputEncoding</InputEncoding>
+  <Image width="16" height="16" type="image/x-icon">data:image/x-icon;base64,imageData</Image>
+  <Url type="text/html" method="method" template="searchURL">
+    <Param name="paramName1" value="paramValue1"/>
+    ...
+    <Param name="paramNameN" value="paramValueN"/>
+  </Url>
+  <Url type="application/x-suggestions+json" template="suggestionURL"/>
+  <moz:SearchForm>searchFormURL</moz:SearchForm>
+</OpenSearchDescription>
+
+
+ ShortName
+
+ 对搜索引擎的简称
+
+ 限制: 名称仅能包含16个字符以下的纯文本. 名称不能包含HTML标志或其他标志.
+
+
+
+ Description
+
+ 对于搜索引擎的简单描述
+
+ 限制: 描述仅能包含少于1024个字符的纯文本.  名称不能包含HTML标志或其他标志.
+
+
+
+ InputEncoding
+
+ 向搜索引擎所输内容的字符编码.例如: <InputEncoding>UTF-8</InputEncoding>.
+
+
+
+ Image
+
+ 使用指向一个图标的URL来代表这个搜索引擎. 可能的话, 应提供16x16大小的"image/x-icon"类型的图像以及一个64x64大小的 "image/jpeg" 或 "image/png"类型的图像. 链接也可以使用 data: URI schemeThe data: URI kitchen在这能找到一个能有效地帮助你构建写在此处的数据的工具. +
<Image height="16" width="16" type="image/x-icon">http://example.com/favicon.ico</Image>
+  OR
+<Image height="16" width="16">data:image/x-icon;base64,AAABAAEAEBAAA ... DAAA=</Image>
+
+ Firefox以base64编码的data: URI (搜索插件被保存在 profile中的 "searchplugins" 文件夹) 缓存此图标. 当这完成时, http: URIs 被改变为 data: URIs.
+
+
+
+ Url
+
+ 描述用来实现搜索请求的一个或多个URL.  method 属性决定使用 GET 还是 POST请求来获取返回的数据. template 属性指定实现搜索请求的 URL.
+
+
+ 注意: IE7 不支持 POST 请求.
+
+
+
+
+ 这是两种firefox支持的URL类型:
+
+ +
+
+ 这两种URL任何一种你都能使用 {searchTerms}来替换用户在搜索栏中输入的搜索内容. 其他支持的动态搜索参数可见 OpenSearch 1.1 parameters.
+
+
+
+ 对使用搜索建议查询来说,  URL template用来获取JSON格式的建议列表. 若需要知道关于如何在服务器上实现搜索建议支持, 请见 Supporting search suggestions in search plugins.
+
+

Image:SearchSuggestionSample.png

+
+
+ Param
+
+ 这个参数用来包括那些需要和搜索查询一起被传递的作为键值对的参数. 你能使用{searchTerms}来指代用户输入的搜索条目.
+
+
+ 注意: IE7不支持此元素.
+
+
+
+
+ SearchForm
+
+ 跳往搜索页的 URL. 这使得Firefox能让用户直接浏览目的网站.
+
+
+ 注意: 这个元素是firefox限定的, 并不是 OpenSearch 的一部分, 我们在例子中使用 "moz:" XML命名前缀来确保其它的不支持此元素的用户代理能安全地忽略此元素.
+
+
+

自动搜寻搜索插件

+

提供搜索插件的网站能宣传自己以使firefox使用者能容易地下载并安装此插件.

+

要支持自动搜寻 你仅需在 你网页的<head> 中加上一条:

+
<link rel="search" type="application/opensearchdescription+xml" title="searchTitle" href="pluginURL">
+
+

斜体字部分解释如下:

+
+
+ searchTitle
+
+ 搜索的名称, 如 "Search MDC" or "Yahoo! Search". 这个值应该与你在插件文件中的ShortName相一致.
+
+
+
+ pluginURL
+
+ 指向 XML搜索插件的URL, 能让浏览者下载插件.
+
+

如果你的网站提供多个插件, 你能为他们每一个都支持自动搜寻功能. 例如:

+
<link rel="search" type="application/opensearchdescription+xml" title="MySite: By Author" href="http://www.mysite.com/mysiteauthor.xml">
+<link rel="search" type="application/opensearchdescription+xml" title="MySite: By Title" href="http://www.mysite.com/mysitetitle.xml">
+
+

这样,你的网站提供的插件就能同时以作者和名称分别作为搜索条目而被搜索.

+

为 OpenSearch 插件支持自动更新

+

{{ fx_minversion_note("3.5", "This section covers a feature introduced in Firefox 3.5.") }}

+

从Firefox 3.5开始, OpenSearch 插件能够自动更新.  要支持这个, 需要包括一个额外的 "application/opensearchdescription+xml"类型Url 元素.  rel属性需要设为 "self" , template 属性需要是指向能自动更新的OpenSearch文档的 URL.

+

例如:

+
<Url type="application/opensearchdescription+xml"
+     rel="self"
+     template="http://www.foo.com/mysearchdescription.xml" />
+
+
+ 注意:  addons.mozilla.org (AMO) 不支持 OpenSearch 插件的自动更新. 如果你想将你的插件发布在 AMO上, 你不应该使用自动更新.
+

排错指南

+

如果你的搜索插件有错误, 当在firefox2中添加插件时会出错. 然而,错误信息可能并不是完全有所帮助的, 因此接下来的建议能帮你发现问题.

+ +

另外, 搜索插件服务提供了日志机制,这对于插件开发者来说可能能起到一定作用 . 使用 about:config 设定 'browser.search.log' 为 true. 插件被加载后日志信息将显示在火狐的 Error Console 中(Tools->Error Console).

+

参考资料

+ +

{{ 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" } ) }}

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: + - 定制 + - 搜索 +--- +

{{ fx_minversion_header("2") }}

+ +

Firefox 2 支持使用 OpenSearch 格式开发搜索引擎插件. 使用 OpenSearch 格式开发能够在IE 7 以及 Firefox上实现兼容. 这是这种语法被推荐使用的原因.

+ +

Firefox 也支持不被包括在 OpenSearch格式  中的其它的搜索功能,例如搜索建议(search suggestion)以及 SearchForm 元素. 这篇文章主要关注创建与OpenSearch格式兼容的支持额外的firefox特殊特征的搜索插件.

+ +

OpenSearch 描述文件也能被如在 Autodiscovery of search plugins  中描述的一样被advertised(道歉这里不知如何翻译) ,并且能够如在 Adding search engines from web pages中所说的进行编程安装.

+ +

OpenSearch 描述文件

+ +

遵循以下的模板,你就会发现通过 XML 文件写一个搜索引擎实际上是如此的简单。 粗体字部分需要根据具体你所写的搜索引擎需要来进行定制 。

+ +
<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+                       xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+  <ShortName>engineName</ShortName>
+  <Description>engineDescription</Description>
+  <InputEncoding>inputEncoding</InputEncoding>
+  <Image width="16" height="16" type="image/x-icon">data:image/x-icon;base64,imageData</Image>
+  <Url type="text/html" method="method" template="searchURL">
+    <Param name="paramName1" value="paramValue1"/>
+    ...
+    <Param name="paramNameN" value="paramValueN"/>
+  </Url>
+  <Url type="application/x-suggestions+json" template="suggestionURL"/>
+  <moz:SearchForm>searchFormURL</moz:SearchForm>
+</OpenSearchDescription>
+ +
+
ShortName
+
对搜索引擎的简称
+
限制: 名称仅能包含16个字符以下的纯文本. 名称不能包含HTML标志或其他标志.
+
+ +
+
Description
+
对于搜索引擎的简单描述
+
限制: 描述仅能包含少于1024个字符的纯文本.  名称不能包含HTML标志或其他标志.
+
+ +
+
InputEncoding
+
向搜索引擎所输内容的字符编码.例如: <InputEncoding>UTF-8</InputEncoding>.
+
+ +
+
Image
+
使用指向一个图标的URL来代表这个搜索引擎. 可能的话, 应提供16x16大小的"image/x-icon"类型的图像以及一个64x64大小的 "image/jpeg" 或 "image/png"类型的图像. 链接也可以使用 data: URI schemeThe data: URI kitchen在这能找到一个能有效地帮助你构建写在此处的数据的工具. +
<Image height="16" width="16" type="image/x-icon">http://example.com/favicon.ico</Image>
+  OR
+<Image height="16" width="16">data:image/x-icon;base64,AAABAAEAEBAAA ... DAAA=</Image>
+
+ Firefox以base64编码的data: URI (搜索插件被保存在 profile中的 "searchplugins" 文件夹) 缓存此图标. 当这完成时, http: URIs 被改变为 data: URIs.
+
+ +
+
Url
+
描述用来实现搜索请求的一个或多个URL.  method 属性决定使用 GET 还是 POST请求来获取返回的数据. template 属性指定实现搜索请求的 URL.
+
+
注意: IE7 不支持 POST 请求.
+
+
+ +
+
这是两种firefox支持的URL类型:
+
+ + + +
+
这两种URL任何一种你都能使用 {searchTerms}来替换用户在搜索栏中输入的搜索内容. 其他支持的动态搜索参数可见 OpenSearch 1.1 parameters.
+
+ +
+
对使用搜索建议查询来说,  URL template用来获取JSON格式的建议列表. 若需要知道关于如何在服务器上实现搜索建议支持, 请见 Supporting search suggestions in search plugins.
+
+ +

Image:SearchSuggestionSample.png

+ +
+
Param
+
这个参数用来包括那些需要和搜索查询一起被传递的作为键值对的参数. 你能使用{searchTerms}来指代用户输入的搜索条目.
+
+
注意: IE7不支持此元素.
+
+
+ +
+
SearchForm
+
跳往搜索页的 URL. 这使得Firefox能让用户直接浏览目的网站.
+
+
注意: 这个元素是firefox限定的, 并不是 OpenSearch 的一部分, 我们在例子中使用 "moz:" XML命名前缀来确保其它的不支持此元素的用户代理能安全地忽略此元素.
+
+
+ +

自动搜寻搜索插件

+ +

提供搜索插件的网站能宣传自己以使firefox使用者能容易地下载并安装此插件.

+ +

要支持自动搜寻 你仅需在 你网页的<head> 中加上一条:

+ +
<link rel="search" type="application/opensearchdescription+xml" title="searchTitle" href="pluginURL">
+
+ +

斜体字部分解释如下:

+ +
+
searchTitle
+
搜索的名称, 如 "Search MDC" or "Yahoo! Search". 这个值应该与你在插件文件中的ShortName相一致.
+
+ +
+
pluginURL
+
指向 XML搜索插件的URL, 能让浏览者下载插件.
+
+ +

如果你的网站提供多个插件, 你能为他们每一个都支持自动搜寻功能. 例如:

+ +
<link rel="search" type="application/opensearchdescription+xml" title="MySite: By Author" href="http://www.mysite.com/mysiteauthor.xml">
+<link rel="search" type="application/opensearchdescription+xml" title="MySite: By Title" href="http://www.mysite.com/mysitetitle.xml">
+
+ +

这样,你的网站提供的插件就能同时以作者和名称分别作为搜索条目而被搜索.

+ +

为 OpenSearch 插件支持自动更新

+ +

{{ fx_minversion_note("3.5", "This section covers a feature introduced in Firefox 3.5.") }}

+ +

从Firefox 3.5开始, OpenSearch 插件能够自动更新.  要支持这个, 需要包括一个额外的 "application/opensearchdescription+xml"类型Url 元素.  rel属性需要设为 "self" , template 属性需要是指向能自动更新的OpenSearch文档的 URL.

+ +

例如:

+ +
<Url type="application/opensearchdescription+xml"
+     rel="self"
+     template="http://www.foo.com/mysearchdescription.xml" />
+
+ +
注意:  addons.mozilla.org (AMO) 不支持 OpenSearch 插件的自动更新. 如果你想将你的插件发布在 AMO上, 你不应该使用自动更新.
+ +

排错指南

+ +

如果你的搜索插件有错误, 当在firefox2中添加插件时会出错. 然而,错误信息可能并不是完全有所帮助的, 因此接下来的建议能帮你发现问题.

+ + + +

另外, 搜索插件服务提供了日志机制,这对于插件开发者来说可能能起到一定作用 . 使用 about:config 设定 'browser.search.log' 为 true. 插件被加载后日志信息将显示在火狐的 Error Console 中(Tools->Error Console).

+ +

参考资料

+ + + +

{{ 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" } ) }}

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 +--- +

这里是关于扩展开发中最常见问题的解答集锦。其中的绝大多数是关于 FireFox 的,但是大部分能够方便的移植到 SeaMonkey,Thunderbird 或其它 Mozilla 应用上。

+

如果你还不知道怎么开始,可以先看看我们的教程:构建一个扩展或者 MozillaZine 上的新手教程。然后用扩展向导创建一个供开始用的简单扩展。

+

不要忘记先设置好扩展的开发环境

+

调试

+

调试之前先设置扩展的开发环境

+

如果调试的代码很复杂,可能会用到 Venkman JavaScript 调试器。在用 Venkman 调试扩展代码之前需要把 "Debug -> Exclude Browser Files" 选项勾掉。

+

怎样记录代码中的错误?

+

javascript.options.showInConsole 设为 true,这样错误就会被记录在错误控制台中,使得 bug 容易追踪些。

+

怎样显示扩展当前状态?

+

要想显示变量值,调试消息等,可以使用 alert(),dump() ,Components.utils.reportError() 或者控制台服务。当然也可以用 Venkman 调试器。

+

为什么我的脚本不能正确运行?

+

如果你的脚本不能如预期运行,第一个要检查的是错误控制台(参见#)。

+

访问尚未加载完毕的 DOM 也常常是错误的来源。这种错误通常是因为初始化代码被放在程序顶层(即所有函数之外)。通过监听 load 事件延期执行初始化代码可以解决这个问题(load 事件表示窗口已经加载完毕):

+
function exampleBrowserStartup(event)
+{
+  // 初始化代码
+}
+window.addEventListener("load", exampleBrowserStartup, false);
+
+

 

+

不能访问网页的文档(document)对象

+

要从 browser.xul 这个 overlay 中访问当前网页,应当使用 content.document 而不是 document。这是因为 document 表示浏览器窗口自身。更多信息参考 Working with windows in chrome code

+

无法在扩展中使用 XMLHttpRequest

+

使用 XMLHttpRequest 发送接收信息时,一般都需要做跨域(crosss domain)操作。 一般来说跨域很麻烦,但因为在 chrome 窗口内发起请求时,是在安全区域内的,所以请求会被默许。

+

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.

+

XML 文件是规范的,但是却出现 XML 解析错误!

+

示例代码

+

得到更多帮助

+

 

+

 

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 +--- +

 

+

扩展为一种可安装包的形式,它可以由使用者下载并安装,或者是由外部程序或应用程序提供的预安装包。扩展使用目录结构,此结构提供有chrome,components,和其他文件以扩展XUL程序的功能。

+

每个扩展必须提供一个install.rdf文件,包含关于扩展的元数据,例如唯一的ID,版本,作者,和兼容性信息。

+

扩展文件和install.rdf准备好之后,有几种方法准备扩展以便安装:将扩展目录ZIP打包为用户可安装的XPI(xpinstall)文件,直接将扩展解开到用户程序或设置目录中,或将扩展注册到Windows注册表中。

+

制作扩展XPI

+

一个XPI (XPInstall) 文件就是一个简单的ZIP文件,包括了扩展文件,install.rdf文件在ZIP的根目录中。使用者可以从网站上下载或者从本地安装XPI文件,将其打开或拖拽到扩展管理窗口。

+

XPI文件的MIME类型被Firefox识别为 + + application/x-xpinstall + ,因为大多数HTTP服务器不能够默认设置为将.xpi返回MIME类型。在Apache HTTP服务器上,可以在设置文件或.htaccess中增加以下命令来实现:

+
AddType application/x-xpinstall .xpi
+
+

直接安装扩展文件

+

如果你知道程序的位置(例如,如果你作为应用程序安装者的角色来安装扩展),你可以直接将扩展文件安装到<appdir>/extensions/<extensionID>中。在下次程序启动的时候扩展管理器会自动找到此扩展。

+

当使用此方法的时候你必须核实以确保系统允许扩展目录和文件正确设置。否则,扩展管理器在此扩展下不能够正确运行,或者扩展本身不能正确工作。

+

使用Windows注册表工具注册扩展所在目录

+

外部安装程序(例如Java虚拟机)也许希望将应用程序整合点作为扩展安装,即便是应用程序还没有安装。这可以在Windows中使用注册表来完成。

+

多条目扩展 XPIs

+

在有些情况下也许希望用单独的XPI文件安装多个扩展/主题。一种特殊的扩展XPI称为多条目包,用来解释如何创建此类型的扩展包。(需要Firefox 1.5/XULRunner 1.8。)

+

Toolkit API的官方参考

+

+

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 +--- +
{{AddonSidebar}}
+ +

附加组件允许开发者们去扩展和修改 Firefox 的功能。开发者们能使用标准的 Web 技术「JavaScript,HTML 以及 CSS」再加上一些专用的 JavaScript APIs 来开发附加组件。除此之外,附加组件还能:

+ + + +

有几种附件组件类型,但最常见类型是扩展。

+ +

开发扩展

+ +

在过去,有几种工具集用于开发 Firefox 扩展,但是到 2017 年 11 月底,扩展必须使用 WebExtensions APIs 构建。其余工具集「包括 overlay add-ons、bootstrapped add-ons 和 Add-on SDK」将会同时被废弃。

+ +

如果你在编写一个新的扩展,请使用 WebExtensions APIs

+ +

使用 Firefox WebExtensions APIs 编写的扩展设计为跨浏览器兼容。在大多数情况下它也能在 Chrome,Edge 和 Opera 中运行,几乎没有任何变化。它们也完全兼容多进程 Firefox。

+ +

查看目前在火狐和其他浏览器中支持的 APIs. 我们将继续设计并改进新的 API 以满足开发人员的需求。

+ +

绝大多数的 WebExtensions APIs 对于 Firefox Android 版也是可用的。

+ +

迁移现有扩展

+ +

如果你正在维护一个旧式扩展,比如 XUL overlay、bootstrapped,或者基于 Add-on SDK 的扩展,我们建议你使用 WebExtension APIs 移植它。这里有一些  MDN 中的移植教程

+ +

我们在 wiki 页面收集了一些教程来支持开发者们过渡。在开始之前,请使用兼容性检测工具来查看你的附加组件是否受影响。

+ +

发布附加组件

+ +

Addons.mozilla.org,俗称 「AMO」,是 Mozilla 官方的官方站点, 方便开发者发布扩展组件和用户查找。通过上传附加组件到  AMO, 你可以加入我们的用户和开发者社区,为你的附加组件找到订阅者。

+ +

你不需要在 AMO 上发布你的附加组件,但你的附加组件必须要经过 Mozilla 签名,否则用户不能安装它。

+ +

为你发布的附加组件添加概述,请查看签名和部署你的附加组件

+ +

其他类型的附加组件

+ +

通常,当人们谈起附加组件时是指扩展工具,但是这里也有一些其他类型的附加组件允许用户定制 Firefox.  这些附加组件包括:

+ + + +

联系我们

+ +

你可以从以下链接获得帮助,时刻关注关于附加组件的最新消息,并且给予我们反馈。

+ +

附加组件论坛

+ +

附加组件交流论坛 讨论附加组件的任何方面并获得帮助。

+ +

邮件列表

+ +

通过 dev-addons 列表来讨论附加组件生态系统的发展,包括 WebExtensions 系统和 AMO。

+ + + +

IRC

+ +

如果你更喜欢使用 IRC,你可以在以下 channel 和其他人交流:

+ + 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 +--- +

简介

+

安装清单是一个附加文件,具有Add-on的XUL程序(例如火狐或者雷鸟),用这个文件来确定即将要安装的add-on的安装信息。他包含了add-on的元数据验证、创建者信息、add-on的详细介绍页面地址、版本号、如何更新、兼容性、等等。

+

安装清单的格式是 RDF/XML.

+

这个文件名字必须为 install.rdf 并且必须放在 XPI 文件的根目录。

+

结构

+

安装清单的最基本结构如下:

+
+
<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+  <Description about="urn:mozilla:install-manifest">
+    <!-- properties -->
+  </Description>
+</RDF>
+
+
+

有些属性是是必须的,有些是可选的。有些属性只是简单的字符串啥啥啥的,有些属性会很复杂。

+

必要的属性

+

你的清单必须要包含下面的这些属性,不听话的话,你的add-on是不会安装成功滴。

+

id

+

id是一个这样子的东东:

+ +
extensionname@example.org
+

后面的这个格式更容易生成和操作。火狐1.5已经检测你的id,确保它是属于第一种格式还是其他格式,并且让那些id格式乱七八糟的add-on不会被安装。

+

例如:

+
<em:id>extensionname@example.org</em:id>
+
+<em:id>{daf44bf7-a45e-4450-979c-91cf07434c3d}</em:id>
+

版本

+

一个标志当前add-on版本的字符串。

+

对于火狐/雷鸟1.0来说,这个格式必须满足这里所说的要求: Extension Versioning, Update and Compatibility. 对于火狐/雷鸟1.5, 看这里:Toolkit version format.

+

示例:

+
<em:version>2.0</em:version>
+
+<em:version>1.0.2</em:version>
+
+<em:version>0.4.1.2005090112</em:version>
+

Firefox 1.5 / XULRunner 1.8 - 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.

+

For addons hosted on addons.mozilla.org - Mozilla's update website may repackage your add-on and correct or reject malformed version strings.

+

类型

+

一个整数代表add-on的类型

+ + + + + + + + + + + + + + + + + + + + + + + +
2扩展
4主题
8地区(译者注:多语言)
32多个物品包
64拼写检测字典
+

例如:

+
<em:type>2</em:type>
+

{{ 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.

+

{{ Fx_minversion_inline(3) }} Firefox 2 and previous supported a value of 16 to represent plug-ins. In Firefox 3 this has been removed.

+

targetApplication

+

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 (<em:id>) specified (for a comprehensive list of application IDs and valid min/maxVersions for them see Valid application versions for add-on developers), from the minimum version (<em:minVersion>) up to and including the maximum version (<em:maxVersion>). These version strings are formatted in the same fashion as the version property 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.

+

id, minVersion, and maxVersion are all required.

+
+ Extensions compatible with Firefox 3.5 should specify a maxVersion of 3.5.*, so that they are automatically compatible with security and stability updates. For Firefox 3.0, a maxVersion of 3.0.* should be used. Extensions compatible only with Firefox or Thunderbird 2 should specify a maxVersion of 2.0.0.*.
+

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)

+

Examples

+
<em:targetApplication>
+ <Description>
+  <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!--Firefox-->
+  <em:minVersion>1.5</em:minVersion>
+  <em:maxVersion>3.0.*</em:maxVersion>
+ </Description>
+</em:targetApplication>
+

{{ Fx_minversion_inline(3) }} Gecko 1.9 based applications allow you to use the special targetApplication id toolkit@mozilla.org to say that the add-on is compatible with any toolkit app with a toolkit version matching the minVersion and maxVersion.

+

name

+

The name of the add-on; intended for display in the UI.

+

Examples

+
<em:name>My Extension</em:name>
+

Optional Property Reference

+

You may need to supply these properties, depending on the capabilities of your add-on.

+

bootstrap

+

{{ 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 false. For more information, see Bootstrapped extensions.

+

unpack

+

{{ 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:

+ +

Examples

+
<Description about="urn:mozilla:install-manifest">
+   <em:id>extension@mysite.com</em:id>
+   <em:unpack>true</em:unpack>
+   ...
+</Description>
+

localized

+

{{ 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 em:locale which indicates which locales to use this information for.

+

Examples

+

This declares a set of add-on metadata to be displayed when the application is running in the de-DE locale.

+
<em:localized>
+  <Description>
+    <em:locale>de-DE</em:locale>
+    <em:name>Tab Sidebar</em:name>
+    <em:description>Zeigt in einer Sidebar Vorschaubilder der Inhalte aller offenen Tabs an.</em:description>
+  </Description>
+</em:localized>
+

The following properties which are described elsewhere in this page can be included in the localized property:

+ +

More documentation can be found at Localizing extension descriptions.

+

description

+

A short description of the add-on - intended for display in the user interface. This description should fit on one short line of text.

+

Examples

+
<em:description>Advanced foo tools.</em:description>
+

creator

+

The name of the creator/principal developer - intended for display in the user interface.

+

Examples

+
<em:creator>John Doe</em:creator>
+

or

+
<em:creator>CoolExtension Team</em:creator>
+

developer

+

{{ Fx_minversion_inline(2) }} The name(s) of co-developers. You may specify more than one of this value to specify multiple developers.

+

Examples

+
<em:developer>Jane Doe</em:developer>
+<em:developer>Koos van der Merwe</em:developer>
+
+

translator

+

{{ Fx_minversion_inline(2) }} The name(s) of translators. You may specify more than one of this value to specify multiple translators.

+

Examples

+
<em:translator>Janez Novak</em:translator>
+<em:translator>Kari Nordmann</em:translator>
+
+

contributor

+

The name(s) of additional contributors. You may specify more than one of this value to specify multiple contributors.

+

Examples

+
<em:contributor>John Doe</em:contributor>
+
+<em:contributor>John Doe</em:contributor>
+<em:contributor>Jane Doe</em:contributor>
+<em:contributor>Elvis Presley</em:contributor>
+
+

homepageURL

+

A link to the add-on's home page - intended for display in the user interface.

+

Examples

+
<em:homepageURL>http://www.foo.com/</em:homepageURL>
+
+

updateURL

+

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.

+
+ Note: It is strongly recommended that the updateURL be an HTTPS (secure) link. Non-secure update URLs can be hijacked by a malicious update.rdf file, enabling malware to infiltrate the user's computer. Alternatively, you could host your extension on AMO and leave out the updateURL completely. This provides secure updates automatically.
+

{{ Fx_minversion_inline(3) }} For security reasons, Gecko 1.9 applications require that if you specify an updateURL, it must be an https URL, or you must include an updateKey.

+

Your server must send this file as text/rdf, text/xml or application/xml+rdf or the update checker may not work.

+

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:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
%REQ_VERSION%The version of the request. Currently 1
%ITEM_ID%The id of the addon being updated
%ITEM_VERSION%The version of the addon being updated
%ITEM_MAXAPPVERSION%The maxVersion of the targetApplication object corresponding to the current application for the addon being updated.
%ITEM_STATUS%{{ Fx_minversion_inline(2) }} Comma separated list of the add-ons operating status in the application. Contains at the least either userEnabled or userDisabled plus any number of incompatible, blockslisted or needsDependencies.
%APP_ID%The id of the current application
%APP_VERSION%The version of the application to check for updates for
%CURRENT_APP_VERSION%{{ Fx_minversion_inline(3.5) }} The version of the current application
%APP_OS%{{ Fx_minversion_inline(1.5) }} The value of OS_TARGET from the Firefox build system, identifying the operating system being used.
%APP_ABI%{{ Fx_minversion_inline(1.5) }} The value of the TARGET_XPCOM_ABI value from the Firefox build system, identifying the compiler/architecture combination used to compile the current application.
%APP_LOCALE%{{ Fx_minversion_inline(3) }} The current application's locale.
%UPDATE_TYPE%{{ Fx_minversion_inline(4) }} UPDATE_TYPE_COMPATIBILITY(32), UPDATE_TYPE_NEWVERSION(64)
%COMPATIBILITY_MODE%{{ Fx_minversion_inline(10) }} related to default to compatible, values could be normal, ignore or strict.
+

Examples

+
<em:updateURL>http://www.foo.com/update.cgi?id=%ITEM_ID%&amp;version=%ITEM_VERSION%</em:updateURL>
+<em:updateURL>http://www.foo.com/extension/windows.rdf</em:updateURL>
+
+

For add-ons hosted on addons.mozilla.org: You may not specify an updateURL property. By default, Mozilla applications using the Add-on Manager (such as Firefox and Thunderbird) will send update requests to addons.mozilla.org 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 experimental will not be updated due to security concerns.

+

Format of the Update Manifest: The Update Manifest is a RDF/XML datasource. For examples of an update manifest, see Extension Versioning, Update and Compatibility and Enabling Extension Updates (external).

+

updateKey

+
+ {{ Gecko_minversion_header(1.9) }} {{ Fx_minversion_header(3) }}
+

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 McCoy tool. Any line breaks and whitespace as part of this entry are ignored.

+
<em:updateKey>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK426erD/H3XtsjvaB5+PJqbhj
+              Zc9EDI5OCJS8R3FIObJ9ZHJK1TXeaE7JWqt9WUmBWTEFvwS+FI9vWu8058N9CHhD
+              NyeP6i4LuUYjTURnn7Yw/IgzyIJ2oKsYa32RuxAyteqAWqPT/J63wBixIeCxmysf
+              awB/zH4KaPiY3vnrzQIDAQAB</em:updateKey>
+
+

optionsURL

+

The chrome:// 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.

+
<em:optionsURL>chrome://myext/content/options.xul</em:optionsURL>
+

{{ gecko_minversion_note("7", "In Firefox 7 you can also simply include your options XUL as a file named options.xul, in the base directory of the add-on.") }}

+

{{ h3_gecko_minversion("optionsType", 7) }}

+

The type of user-interface used for displaying the options. Accepted values are:

+ + + + + + + + + + + + + + + +
1Opens optionsURL in a dialog box
2Options are displayed inside the Add-on Manager
3Opens optionsURL in a new tab (if the application supports that), or a dialog box
+

optionsType defaults to 1 if there is an optionsURL included in install.rdf or 2 if there is no optionsURL and the file options.xul exists in the root of the add-on.

+
<em:optionsType>2</em:optionsType>
+
+

aboutURL

+

The chrome:// 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.

+
+

{{ gecko_callout_heading("2.0") }}

+

The dialog receives the Addon object representing your add-on as a parameter.

+
+

Examples

+
<em:aboutURL>chrome://myext/content/about.xul</em:aboutURL>
+
+

iconURL

+

A chrome:// 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.

+
<em:iconURL>chrome://myext/skin/icon.png</em:iconURL>
+
+
+ Note: For the above example to work you will also have to add a skin package line to your chrome.manifest file. See Chrome Registration#skin. Alternatively you can place your icon in the directory specified in your content package line.
+

{{ gecko_minversion_note("1.9.2", "Starting in Gecko 1.9.2 (Firefox 3.6), you can also simply include your icon, named icon.png, 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 iconURL entry.") }}

+

{{ h3_gecko_minversion("icon64URL", "2.0") }}

+

A chrome:// 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.

+
<em:icon64URL>chrome://myext/skin/icon64.png</em:icon64URL>
+
+
+ Note: For the above example to work you will also have to add a skin package line to your chrome.manifest file. See Chrome Registration#skin. Alternatively you can place your icon in the directory specified in your content package line.
+

{{ h3_gecko_minversion("targetPlatform", "1.8") }}

+

A string specifying a platform that the add-on supports. It contains either the value of OS_TARGET alone or combined with TARGET_XPCOM_ABI, separated by an underscore (_).

+

You can specify multiple targetPlatform 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.

+

Examples

+
<em:targetPlatform>WINNT_x86-msvc</em:targetPlatform>
+
+<em:targetPlatform>Linux</em:targetPlatform>
+
+<em:targetPlatform>Darwin_ppc-gcc3</em:targetPlatform>
+
+<em:targetPlatform>SunOS_sparc-sunc</em:targetPlatform>
+

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 ABI (s) that you compiled the components with. If you want to include multiple versions of the components, you should also use Platform-specific Subdirectories.

+

Notes

+ +

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.

+

{{ h3_gecko_minversion("strictCompatibility", "10.0") }}

+

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 false meaning that the compatibility checking will not be performed against the max version.

+
<em:strictCompatibility>true</em:strictCompatibility>
+

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 do not 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).

+
+ Note: 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 extensions.strictCompatibility preference to true.
+
+

{{ gecko_callout_heading("11.0") }}

+

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.

+
+

Obsolete Property Reference

+

These properties were required in older versions of the Add-on Manager, but have been replaced with newer and better mechanisms.

+

file

+

Firefox 1.0 This property pointed to a chrome .jar file that contains chrome packages that require registration with the Chrome Registry.

+

The <em:file> property has a complex object value. The uri of the value is urn:mozilla:extension:file:jarFile.jar where jarFile.jar 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. urn:mozilla:extension:file:directory). In either case, the referenced chrome package file(s) must be placed in the chrome subdirectory of the XPI's top level.

+

This object has a package property (with a path within the jar file or directory that leads to the location where the contents.rdf file responsible for registering that package is located), a locale property (ditto, but to register the locale) and a skin property (ditto, but to register the theme material).

+

In extensions for Firefox 1.5, this property is no longer necessary: the chrome.manifest 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.

+

Examples

+
<em:file>
+ <Description about="urn:mozilla:extension:file:myext.jar">
+  <em:package>content/myext/</em:package>
+  <em:locale>locale/en-US/myext/</em:locale>
+  <em:skin>skin/classic/myext/<em:skin>
+ </Description>
+</em:file>
+
+

An Install Manifest may specify multiple file properties, one for each jar file or subdirectory that contains chrome to register.

+

hidden

+

Firefox 1.0 - 3.5 A boolean value that when true 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.

+
+ Note: 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.
+

Examples

+
<em:hidden>true</em:hidden>
+
+

requires

+

Firefox 2.0 - 3.6.x. Other versions will ignore the restrictions and install the add-on regardless of the requirements.

+

See Replacement for install.rdf property "requires" discussion for rationale behind removing this feature and the suggested workaround.

+

<em:requires> has a similar syntax to the <em:targetApplication> tag (i.e. you must specify <em:id>, <em:minVersion>, <em:maxVersion> when using it). If the add-on specified by the <em:id> 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 <em:requires> 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 <em:targetApplication>. See Extension Dependencies for more details.

+

Glossary

+

restricted access area

+

A restricted access area 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 ($APPDIR)/extensions folder and the registry install location under HKEY_LOCAL_MACHINE (see Adding Extensions using the Windows Registry for details) are restricted.

+

The ($PROFILE)/extensions and HKEY_CURRENT_USER install locations, on the other hand, are not restricted.

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 +--- +

{{LegacyAddonsNotice}}{{AddonSidebar}}

+ +

本节包含附件组件开发的旧式技术文档链接,包括:

+ + 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 +--- +

{{LegacyAddonsNotice}}{{AddonSidebar}}

+ +

本页面为那些基于 Gecko 的应用开发扩展插件的开发者们提供了可用的参考文献链接。

+ + + +

唯一可行的方法是开发扩展在 Gecko 2.0 发布之前. 但是现在有两种可以选择的技术:免重启扩展和基于 SDK 的扩展插件. 这些特定的 JavaScript APIs 仍旧可以被这些较新的技术使用。

+ +

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 restartless extensions, and the Add-on SDK, which is built on top of them. The privileged JavaScript APIs described here can still be used in these newer types of add-ons.

+ +

XUL 学校

+ +

XUL 学校 是一个综合性的拓展开发指南,主要针对 Firefox 的扩展开发,但是绝大多数可应用于其他基于 Gecko 的应用。

+ +

更多资源

+ +
+
+
+
设置环境
+
设置扩展开发需要的应用.
+
XUL
+
相关的指南介绍XUL 扩展的接口.
+
代码片段
+
提供了很多的简单示例代码片段.
+
安装扩展
+
如何通过把扩展的文件拷贝进应用的安装目录来安装扩展.
+
Firefox 插件的开发者指南
+
开发扩展的指南.
+
+
+ +
+
+
JavaScript 模块代码
+
适用于扩展开发者的 JavaScript 模块。
+
扩展偏好
+
如何在你的扩展出现在附加组件管理界面的时候指定偏好设置。
+
常见问题
+
常见的扩展开发中的错误。
+
扩展打包
+
看看扩展是如何被打包和安装的。
+
Firefox 的二进制扩展
+
为 Firefox 创建二进制扩展。
+
+
+
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 +--- +

Firefox 的一个巨大优势就是可扩展性非常强。扩展组件几乎可以做任何事情。但这也带来了一个劣势: 扩展组件如果写的不好,将会大大的影响浏览器性能,包括 firefox 的整体体验。 本文则提供了一些最佳实践方式,他们不仅能够提升你的组件的性能和速度,也会对 firefox 带来同样的影响。

+

提升启动性能

+

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.

+

只在需要的时候装载需要的东西

+

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.

+

使用  JavaScript code modules

+

You can create your own JavaScript code modules 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.

+

This has an advantage over XPCOM modules, which are always loaded when your extension starts up.

+

Of course, for extremely simple extensions it may not make sense to modularize your code.

+

Defer everything that you can

+

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.

+

If there is anything 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.

+

通用性能提示

+

避免产生内存泄漏

+

Memory leaks require the garbage collector and the cycle collector to work harder, which can significantly degrade performance.

+

Zombie compartments are a particular kind of memory leak that you can detect with minimal effort.  See the Zombie compartments page, especially the Proactive checking of add-ons section.

+

See Common causes of memory leaks in extensions for ways to avoid zombie compartments and other kinds of leaks.

+

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, bug 719601 featured a "System Principal" JavaScript compartment containing 100s of MBs of memory, which is much larger than usual.

+

Use JavaScript Modules

+

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 Using JavaScript Code Modules page.

+

Avoid Writing Slow CSS

+ +

Avoid DOM mutation event listeners

+

Adding DOM mutation listeners to a document disables most DOM modification optimizations and profoundly degrades the performance 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: DOMAttrModified, DOMAttributeNameChanged, DOMCharacterDataModified, DOMElementNameChanged, DOMNodeInserted, DOMNodeInsertedIntoDocument, DOMNodeRemoved, DOMNodeRemovedFromDocument, DOMSubtreeModified

+

For more on these events and their deprecation, see Mutation events. Use Mutation Observers instead if possible.

+

延迟加载服务 services

+

The XPCOMUtils JavaScript module provides two methods for lazily loading things:

+ +

As of Firefox 4.0, many common services are already cached for you in Services.jsm.

+

Reduce file I/O

+

TODO: Give examples below, link to code, bugs, docs.

+ +

Use the right compression level for JAR and XPI files

+

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 decrease 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 solid archive effect).

+

If your extension doesn't specify em:unpack 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.

+

使用异步 I/O

+

This cannot be stressed enough: never do synchronous I/O on the GUI thread.

+ +

Unnecessary onreadystatechange in XHR

+

addEventListener(load/error) and/or xhr.onload/.onerror are usually sufficient for most uses and will only be called once, contrary to onreadystatechange. When using XHR in websites people tend to use onreadystatechange (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 onreadystatechange, i.e. only once, and you don't need to check readyState or figure out if it is an error or not. Only use onreadystatechange if you want to process the response while it is still arriving.

+

Removing Event Listeners

+

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: function onMouseOver(evt) { if (is_active) { /* doSomeThing */ } } Also, remove "fire-once" listeners again:

+
 function init() {
+   var largeArray;
+   addEventListener('load', function onLoad() {
+        removeEventListener('load', onLoad, true);
+        largeArray.forEach();
+ }, true);
+
+

Else a lot of closure stuff might be still referenced (largeArray in this example). And the listener will sit idle in some internal table.

+

Populate menus as needed

+

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.

+

Avoid mouse movement events

+

Avoid mouse movement events (enter/over/exit) or at least keep computation to a minimum. Mouse movement events, especially the mouseover 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 popupshowing event). Also don't forget to remove the event listeners when no longer needed (see above).

+

Avoid polling

+

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.

+

aPNG/aGIF inappropriate in a lot of cases

+

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.

+

base64/md5/sha1 implementations

+

Do not ship your own base64/md5/sha1 implementations. Regarding base64 there are the built-in atob/btoa 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") }}.

+

Image sprites

+

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 imagesrc/src attributes to define images where possible.

+

Consider using Chrome Workers

+

You can use a {{ domxref("ChromeWorker") }} to execute long running tasks or do data processing.

+

参考

+ 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 +--- +
+

Important: Since Firefox 52, all plugin support except Flash has been dropped (see Plug-in support has been dropped other than Flash for more details). Flash usage is also set to be phased out in the future.

+
+ +
+

Note: 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.

+
+ +

For more information about plugin roadmap, see non-archived plugin information.

+ +

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.

+ +

Plugins are written using NPAPI, the cross-browser API for plugins. The main source of documentation for NPAPI is the Gecko Plugin API Reference. To make your plugin scriptable from web pages, use npruntime.

+ +

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 Firebreath, JUCE, or QtBrowserPlugin. There are also some code generation tools that may be helpful. More information about these tools can be found on the External Resources page.

+ +

Plugins are different from extensions, which modify or enhance the functionality of the browser itself. Plugins are also different from search plugins, which plug additional search engines in the search bar.

+ +
+
+
+
+
Gecko Plugin API Reference (NPAPI)
+
This reference describes the application programming interfaces for NPAPI plugins and provides information about how to use these interfaces.
+
Site Author Guide For Click-To-Activate Plugins
+
These guidelines will help website authors use plugins when they are blocked by default with the Firefox click-to-activate feature.
+
+ +
+
Scripting plugins (npruntime)
+
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.
+
+ +
+
Shipping a plugin as a Toolkit bundle
+
Plugins can be shipped as a Toolkit bundle, allowing a user to easily install, uninstall and manage their personal plugins.
+
+ +
+
Supporting private browsing in plugins
+
Firefox 3.5 introduced support for private browsing; learn how to make your plugin respect the user's privacy wishes.
+
Multi-Process Plugin Architecture
+
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.
+
Logging and Debugging for Multi-Process Plugins
+
How to create a plugin log to aid in debugging problems with multi-process plugins.
+
+
+ +
+
+
Writing a plugin for Mac OS X
+
Learn how to write a plugin for Mac OS X; a template Xcode project is provided.
+
+ +
+
Monitoring Plugins
+
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.
+
+ +
+
Scripting Plugins: Macromedia Flash
+
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.
+
+ +
+
Plugins: The First Install Problem
+
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.
+
+ +
+
Plugins: Samples and Test Cases
+
NPAPI plugin samples and test cases.
+
External Resources for Plugin Creation
+
External projects, frameworks, and blog posts that may be useful.
+
+ +
+
XEmbed Extension for Mozilla Plugins
+
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.
+
+
+
+ +
+

Categories

+ +

Interwiki Language Links

+ +
+
+

Join the plugin development community

+ +
+
Choose your preferred method for joining the discussion:
+ + +
+ +
+
+
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 +--- +

{{deprecated_header}}

+

The articles below describe each of the APIs related to NPAPI plugins.

+

{{LandingPageListSubpages}}

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 +--- +

NPAPI Plugin Samples

+

Collections of NPAPI plugin samples can be found in the Seamonkey source code at /modules/plugin/sdk/samples.

+

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.

+

There is a guide to compiling the npruntime sample in Visual Studio.

+

In addition to those samples, there are 2 more plugins in the tree that might be helpful.

+ +

NPAPI Plugin Test Cases

+ +

{{ languages( { "de": "de/Plugins/Beispiele_und_Testfälle" } ) }}

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 +--- +

One of the new features that is available in Firefox 1.5 is the ability to place browser plug-ins in a Firefox extension.

+

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.

+

Bundle structure

+

Toolkit bundles 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:

+
install.rdf
+plugins/
+    pluginlib.dll
+    plugintypes.xpt
+
+

The install.rdf file contains an install manifest that describes the plugin to the user. The library and scripting interfaces are held in the <tt>plugins</tt> directory.

+

Platform-specific files

+

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:

+
platform/
+    Linux_x86-gcc3/
+        plugins/
+            libplugin.so
+    Darwin_ppc-gcc3/
+        plugins/
+            libplugin.dylib
+
+

More specific information can be found in the platform-specific subdirectories documentation.

+

Install Manifest

+

The install manifest describes the plugin to the user. For a plugin the manifest only needs to be very simple:

+
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>mypluginid@myplugin.com</em:id>
+    <em:name>My Plugin</em:name>
+    <em:version>1.0</em:version>
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>1.5</em:minVersion>
+        <em:maxVersion>3.0.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+  </Description>
+</RDF>
+
+

This contains 4 required pieces of information.

+
    +
  1. 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 @.
  2. +
  3. The plugin must have a name to identify the plugin to the user in the list of add-ons.
  4. +
  5. The version is fairly self-descriptive, it must be a toolkit version format.
  6. +
  7. 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.
  8. +
+

Providing updates

+

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.

+

This is performed by including an updateURL in the install manifest. This should point to an update.rdf file on the internet which will include the updated versions and version information for the plugin.

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 +--- +

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 cfx command line tool. It was retired on April 1, 2014, and the "builder.addons.mozilla.org" domain now redirects to this page.
+
+ 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 high-level and low-level APIs used for Builder add-ons are exactly the same for Builder and SDK. To switch to the SDK:

+ 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 +--- +
{{AddonSidebar}} +

很多 add-ons 需要访问和修改 web 页面的内容。但是 add-on 的主代码不能直接访问 web 内容。替代方案是, SDK add-ons 需要使用一些分散的脚本代理访问 web 内容,这些脚本被称作内容脚本(content scripts)。本页面描述如何开发和部署内容脚本。

+ +

内容脚本是在使用SDK时很令人疑惑的点,但你很有可能不得不使用它们。下面有五个基本原则:

+ + + +

这个完整的 add-on 表现出所有的这些原则。它的"main.js"使用 tabs 模块附加了一个内容脚本到当前标签页。本例中内容脚本作为字符串传递,内容脚本简单地替换了页面的内容:

+ +
// main.js
+var tabs = require("sdk/tabs");
+var contentScriptString = 'document.body.innerHTML = "<h1>this page has been eaten</h1>";'
+
+tabs.activeTab.attach({
+  contentScript: contentScriptString
+});
+ +

下面的高层次 SDK 模块能使用内容脚本来修改 web 页面:

+ + + +

另外,还能使用 HTML 定义了一些 SDK 用户接口组件,并且使用分类的脚本来和这些内容交互。从很多方面来讲,这些脚本就像内容脚本一样,但它们并不是本文的关注点。要学习如何和用户接口模块的内容交互,请参看模块定义文档:panelsidebarframe

+ +

这篇指南中列出的几乎所有的示例都是完整并且且最小的,可以在 Github 的 addon-sdk-content-scripts repository 页面上获得。

+ +

加载用户脚本

+ +
+

你可以声明一个字符串或者指定 contentScriptcontentScriptFile 选项加载一个单独的脚本。contentScript 选项接受一个作为脚本的字符串:

+ +
// main.js
+
+var pageMod = require("sdk/page-mod");
+var contentScriptValue = 'document.body.innerHTML = ' +
+                         ' "<h1>Page matches ruleset</h1>";';
+
+pageMod.PageMod({
+  include: "*.mozilla.org",
+  contentScript: contentScriptValue
+});
+ +

contentScriptFile 选项接受一个作为 resource:// URL 的字符串,指向一个存储在你的 add-on 的 data 目录中的脚本文件。jpm不会默认创建"data"目录,所以你必须创建该目录并将你的用户脚本放进去。

+ +

本 add-on 提供一个 URL ,指向"content-script.js"文件,存储在 add-on 根目录下的 data 子目录:

+ +
// 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")
+});
+ +
// content-script.js
+
+document.body.innerHTML = "<h1>Page matches ruleset</h1>";
+ +
+

从 Firefox 34 开始,你可以使用"./content-script.js"替代 self.data.url("content-script.js")。所以你可以像这样重写:

+ +
var pageMod = require("sdk/page-mod");
+
+pageMod.PageMod({
+  include: "*.mozilla.org",
+  contentScriptFile: "./content-script.js"
+});
+
+
+ +
+

除非你的内容脚本非常简单并且固定是一个静态的字符串,请不要使用 contentScript:否则,你会在从 AMO 获取你的add-on上遇到问题。

+ +

相反,把脚本放到一个单独的文件并用 contentScriptFile 加载它。这回事你的代码更易维护、安全、调试和审核。

+
+ +

你可以给 contentScriptcontentScriptFile 传递字符串数组来加载多个脚本:

+ +
// 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");']
+  });
+});
+
+ +
// 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")]
+});
+ +

如果你这么做,这些脚本之间可以直接交互,就像他们被同一个 web 页面加载一样。

+ +

你也可以把 contentScriptcontentScriptFile 一起用。如果你这么做,使用 contentScriptFile 定义的脚本会在使用 contentScript 定义的脚本之前加载。这使你能够用 URL 加载比如 jQuery 这样的 JavaScript 库,然后传递一个简单的能够使用jQuery脚本:

+ +
// main.js
+
+var data = require("sdk/self").data;
+var pageMod = require("sdk/page-mod");
+
+var contentScriptString = '$("body").html("<h1>Page matches ruleset</h1>");';
+
+pageMod.PageMod({
+  include: "*.mozilla.org",
+  contentScript: contentScriptString,
+  contentScriptFile: data.url("jquery.js")
+});
+ +
+

除非你的内容脚本非常简单并且固定是一个静态的字符串,请不要使用 contentScript:否则,在从 AMO 获取你的 add-on 上,你会遇到问题。

+ +

相反,把脚本放到一个单独的文件并用 contentScriptFile 加载它。这回事你的代码更易维护、安全、调试和审核。

+
+ +

控制附加脚本的时间

+ +

contentScriptWhen 选项指定了什么时候加载内容脚本。从这里选一个:

+ +
    +
  • "start":页面 document 元素插入 DOM 之后,立即加载脚本。这时 DOM 的内容仍未加载,所以脚本不能与其交互。
  • +
  • "ready":页面 DOM 加载完后加载脚本:也就是说,在那个时间点 DOMContentLoaded 事件触发。这时,内容脚本可以和DOM内容交互,但外部引用的样式表和图片可能还没有完成加载。
  • +
  • "end":页面上所有内容(DOM、JS、CSS、images)加载完后,加载脚本,就是在 window.onload 事件触发的时候
  • +
+ +

默认值为 "end"

+ +

注意 tab.attach() 不支持 contentScriptWhen,因为它原来就是在页面加载页面的时候被调用的。

+ +

传递配置选项

+ +

contentScriptOptions 是一个作为只读对象暴露给内容脚本的JSON对象,在 self.options 的属性里:

+ +
// main.js
+
+var tabs = require("sdk/tabs");
+
+tabs.on('ready', function(tab) {
+  tab.attach({
+      contentScript: 'window.alert(self.options.message);',
+      contentScriptOptions: {"message" : "hello world"}
+  });
+});
+ +

这里可以使用任何可以转成json的值(object、array、string等等)。

+ +

访问 DOM

+ +

内容脚本可以访问页面的 DOM,就像任何页面中加载的脚本(页面脚本)一样。但是内容脚本和页面脚本之间是隔离的:

+ +
    +
  • 内容脚本不能看到任何由页面脚本添加到页面的 JavaScript 对象
  • +
  • 如果页面脚本重定义了某个 DOM 对象的行为,但内容脚本只会看到原来的那个行为。
  • +
+ +

相反也是如此:页面脚本不能看到内容脚本添加的 JavaScript 对象。

+ +

例如,假想一个页面用页面脚本添加变量 foowindow 对象:

+ +
<!DOCTYPE html">
+<html>
+  <head>
+    <script>
+    window.foo = "hello from page script"
+    </script>
+  </head>
+</html>
+ +

在这个脚本后面加载到页面的其他脚本也可以访问 foo。但是内容脚本不能:

+ +
// 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);
+ +
console.log: my-addon: null
+
+ +

这种隔离策略有着很合理的理由。首先,这意味着内容脚本不会泄露对象给 web 页面,这样可能会打开安全漏洞。第二,这意味着,在内容脚本创建对象的时候,可以不用担心是否会和页面脚本添加的对象相冲突。

+ +

这种隔离意味着,例如,如果一个 web 页面加载了 jQuery 库,那么内容脚本不能够看到由该库添加的 jQuery 对象——但是可以看到内容脚本添加的自己的 jQuery 对象,并且它不会和页面脚本的 jQuery 版本冲突。

+ +

和页面脚本交互

+ +

一般来说,这种内容脚本和页面脚本的隔离正是你所希望的。但是有时候你也许会希望和页面脚本交互:你想在内容脚本和页面脚本之间共享对象来,来在它们之间发送消息。如果你需要这么做,请阅读和页面脚本交互

+ +

事件监听器

+ +

你可以监听 DOM 的事件,就像在页面脚本中一样,但是有两个重要的区别:

+ +

第一,如果你向 setAttribute() 传递字符串,来定义了事件监听器,那么此监听器被当做是在页面上下文中的,所以它不能访问任何内容脚本中的变量。

+ +

如下,内容脚本会失败报错"theMessage is not defined":

+ +
var theMessage = "Hello from content script!";
+anElement.setAttribute("onclick", "alert(theMessage);");
+ +

Second, if you define an event listener by direct assignment to a global event handler like onclick, 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 window.onclick:

+ +
var myScript = "window.onclick = function() {" +
+               "  console.log('unsafewindow.onclick: ' + window.document.title);" +
+               "}";
+
+require("sdk/page-mod").PageMod({
+  include: "*",
+  contentScript: myScript,
+  contentScriptWhen: "start"
+});
+ +

这个示例会在大多数页面上正常工作,但是会在定义 onclick 的页面上失败:

+ +
<html>
+  <head>
+  </head>
+  <body>
+    <script>
+    window.onclick = function() {
+      window.alert("it's my click now!");
+    }
+    </script>
+  </body>
+</html>
+ +

由于这些原因,最好还是用 addEventListener() 添加一个事件监听器,定义监听器为一个函数:

+ +
var theMessage = "Hello from content script!";
+
+anElement.onclick = function() {
+  alert(theMessage);
+};
+
+anotherElement.addEventListener("click", function() {
+  alert(theMessage);
+});
+ +

和 add-on 通信

+ +

为了使 add-on 脚本和内容脚本相互通信,任何一通信端都要访问 port 对象。

+ +
    +
  • 要从一头发送消息到另一头,使用 port.emit()
  • +
  • 要从另一头接收消息,使用 port.on()
  • +
+ +

消息是异步的:也就是说,发送方不会等待接收方的回应,而仅仅是发送消息完后继续处理别的事情。

+ +

这里有一个简单的 add-on 使用 port 发送一个消息到内容脚本:

+ +
// 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");
+ +
// content-script.js
+
+self.port.on("alert", function(message) {
+  window.alert(message);
+});
+ +
+

context-menu 模块没有使用这里描述的通信模型。了解更多关于使用 context-menu 和内容脚本通信的事情,参看 context-menu documentation

+
+ +

在内容脚本中访问 port

+ +

内容脚本中,port 对象是作为global下 self 对象的属性。所以要从内容脚本中发送消息的话:

+ +
self.port.emit("myContentScriptMessage", myContentScriptMessagePayload);
+ +

要从 add-on 代码接收消息

+ +
self.port.on("myAddonMessage", function(myAddonMessagePayload) {
+  // Handle the message
+});
+ +
+

注意 global下 self 对象和 self 模块完全不一样,后者提供一个API给 add-on,用来访问它的数据文件和ID。

+
+ +

在内容脚本中访问 port

+ +

在 add-on 代码中,联通 add-on 和某一特定内容脚本上下文的通道被封装入 worker 对象。所以和内容脚本通信的 port 对象其实是其相对应的 worker 对象的一个属性。

+ +

但是,这个 worker 没有暴露给 add-on 代码,以及同样所有的模块。

+ +

page-worker

+ +

page-worker 对象直接整合了 work API。所以要从一个由 page-worker 关联的内容脚本接收消息的话,你可以使用 pageWorker.port.on()

+ +
// 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);
+});
+ +

要从你的 add-on 发送用户定义的消息,你可以只调用 pageWorker.port.emit()

+ +
// 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");
+ +
// content-script.js
+
+self.port.on("get-first-para", getFirstPara);
+
+function getFirstPara() {
+  var paras = document.getElementsByTagName("p");
+  if (paras.length > 0) {
+    var firstPara = paras[0].textContent;
+    self.port.emit("first-para", firstPara);
+  }
+}
+ +

page-mod

+ +

单个 page-mod 对象可以附加它的脚本到多个页面,每个页面有它自己的上下文来运行内容脚本,所以每个页面都需要相互隔离的通道(worker)。

+ +

所以 page-mod 没有直接整合 worker 的 API。而是在每次内容脚本被附加到页面时,page-mod 发送一个 attach 事件,它的监听器会给对应的上下文传递一个 worker。通过为 attach 提供一个监听器,你可以访问被一个 page-mod 附加到页面上的内容脚本的 port 对象:

+ +
// 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');
+  });
+}
+ +
// 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);
+});
+
+ +

上面的 add-on 里有两条消息:

+ +
    +
  • 当用户点击页面元素时,click 从 page-mod 被发送到当前 add-on。
  • +
  • warning 发送一条傻气的字符串回给page-mod
  • +
+ +

Tab.attach()

+ +

Tab.attach() 方法返回一个 worker,你可以用来和附加的内容脚本通信。

+ +

这个 add-on 添加了一个按钮到Firefox:等用户点击按钮是,这个 add-on 附加一个内容脚本到当前的标签页,发送给内容脚本一条名为 "my-addon-message"的消息,并且监听名为"my-script-response"的响应:

+ +
//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");
+}
+
+ +
// 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");
+}
+ +

port的API

+ +

参看 port 对象的参考文档.

+
+ +

postMessage的API

+ +

port 对象加载之前,add-on 代码和内容脚本可以使用另一个 API 通信:

+ + + +

这个API依然可用,并且还有文档,但是没有理由替代前文描述的 port API。 例外是 context-menu 模块,它还是使用 postMessage。

+ +

内容脚本的内容脚本

+ +

内容脚本可用直接和其他同一个上下文中的内容脚本通信。举个例子,如果一次 Tab.attach() 的调用附加了两个脚本,那么他们可用直接相互查看,就像加载在同一页面内的页面脚本一样。但是如果你调用 Tab.attach() 两次,每次附加一个内容脚本,那么这些内容脚本之间不能通信。你必须使用port API 通过 add-on 的主代码来传递消息。

+ +

跨域的内容脚本

+ +

默认情况下,内容脚本没有跨域的权限。特别是,它们不能访问在不同 iframe 中的在另外的域名上的内容,也不能发起跨域的 XMLHttpRequests。

+ +

但是,你可以把需要的域名添加到 package.json"permissions"键下的 "cross-domain-content"键下,为这些域名打开这些特性。参阅文章跨域内容脚本

+
+ +
 
+ +
 
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 +--- +

下面列出了一些文章可以加深你对SDK的理解

+
+

投稿者的教程

+
+
+
+
+ 起步
+
+ 学会如何使用SDK : 编写代码, 调试bug, 提交补丁, 审核项目, 获得帮助.
+
+ 模块
+
+ 通过SDK学会模块的使用 (以CommonJS为规范), 懂得如何使用 sandboxes 和compartments 提高安全性, 并且了解内置的 SDK module loader (被称为Cuddlefish).
+
+ 类 和 继承
+
+ 学会继承在JavaScript中的运行机制, 使用构造(constructors)原型(prototypes), 并知道如何使用SDK提供的函数帮助器简化它.
+
+
+
+
+
+ 私有成员
+
+ 通过 前缀, 闭包, 和WeakMaps 学会私有成员如何在JavaScript中的实现, 使用 命名空间(通常指WeakMaps) 学会SDK如何支持私有成员.
+
+ 脚本运行流程
+
+ SDK的设计目的是为了使控制网页内容的扩展脚本可以在不同进程的环境中运行. 这篇文章强调了这一设计的特点.
+
+
+
+
+

SDK的基础结构

+
+
+
+
+ SDK 模块结构
+
+ SDK是可重复使用的 JavaScript 模块. 这里解释了什么是模块, 怎样加载模块, 和SDK模块树的构造.
+
+ SDK API 生存周期
+
+ 为SDK的API定义生命周期,  包括API稳定性的排名
+
+
+
+
+
+ 程序 ID
+
+ 程序ID 是扩展独一无二的标识符. 教程解释了如何定义你自己的程序 ID.
+
+ Firefox 兼容
+
+ 解决不同版本SDK生成的扩展与不同版本Firefox的兼容问题
+
+
+
+
+

SDK 常用技巧

+
+
+
+
+ 善用 事件触发
+
+ 通过SDK的事件触发框架 写出以事件驱动为基础的代码
+
+
+
+
+
+ 脚本的两种类型
+
+ 这篇文章可以帮助你理解扩展中的API和普通脚本的区别
+
+
+
+

 

+
+

XUL 迁移

+
+
+
+
+ XUL 迁移教程
+
+ 把XUL扩展迁移到SDK的技巧
+
+ XUL 与 SDK 不同
+
+ 比较 传统的以XUL为基础的扩展 和 SDK 两者优点和缺点
+
+
+
+
+
+ 移植例子
+
+ 一个简单地教你如何让 基于XUL的扩展 迁移到 SDK中的实例
+
+
+
+

 

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 +--- +

我们目前正在使 Firefox 变为多进程,它为浏览器界面使用一个操作系统进程,为运行的网页使用另一个进程来执行代码,这个项目被称为 "electrolysis" 或者 "e10s"。更多信息请参考多进程 Firefox 相关页面

+ +

本文章介绍了开发者如何测试基于 SDK 的附加组件是否与多进程的 Firefox 兼容,以及如何解决出现的问题。

+ +

SDK 的合约

+ +

SDK 为附加组件的开发者承诺了:

+ + + +

在实践中,大多数底层 API 将正常工作,但可以直接访问网页内容的底层 API 无法正常工作。

+ +

兼容性垫片

+ +

举例来说,你可能认为这是行不通的:

+ +
var contentDocument = require("sdk/window/utils")
+  .getMostRecentBrowserWindow().content.document;
+ +

但是,Firefox 为附加组件提供了许多 API 的兼容性垫片。这意味着许多 API,包括上述例子的那个,仍然工作。虽然有两条警示需注意:

+ + + +

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.

+ +

测试

+ +

To test whether an add-on works without the shims, use the "multiprocess" permission.

+ +
+

Note that you can only do this if you are using jpm. You can't use the "multiprocess" permission if you are using cfx.

+
+ +

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.

+ +

However, there's a catch: some of the SDK's APIs themselves still depend on the shims. So by setting the "multiprocess" permission, your add-on might not work, even if you are only using high-level APIs. For example:

+ +
var selection = require("sdk/selection");
+
+function myListener() {
+  console.log(selection.text);
+}
+
+selection.on('select', myListener);
+
+ +

This add-on will not work if you've set the "multiprocess" permission, because sdk/selection depends on the shims. We're working on fixing these problems: see bug 1004745 and its dependencies.

+ +

使用框架脚本

+ +

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:

+ + + +

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 message manager documentation for the details on working with frame scripts.

+ +
+

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.

+ +

Differences between frame scripts and content scripts include:

+ + +
+ +

访问消息管理器

+ +

全局消息管理器

+ +

To access the global message manager, you load the nsIMessageListenerManager service. Before you can do this in an SDK add-on, you have to require("chrome") to get access to the Components object:

+ +
const {Cc, Ci} = require("chrome");
+
+var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+  .getService(Ci.nsIMessageListenerManager);
+ +

窗口消息管理器

+ +

The window message manager is available as the messageManager property of a chrome window. To understand what a chrome window is, you need to distinguish three sorts of windows:

+ + + +

So to get a window message manager from the SDK, you have a couple of options:

+ +

(1) Use the window/utils module:

+ +
// 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;
+ +

(2) Use viewFor to convert an SDK window to a chrome window:

+ +
// 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;
+ +

浏览器消息管理器

+ +

The browser message manager is available as the messageManager property of an XUL browser.

+ +

In the SDK, to get a browser for a given tab, you can use the tabs/utils module's getBrowserForTab function. getBrowserForTab expects an XUL tab as an argument, so if you have an SDK tab object, you'll need to convert it to an XUL tab using viewFor:

+ +
// 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;
+ +

Again, although this code uses tabs/utils, it's safe to run in the chrome process because it only accesses chrome objects.

+ +

载入框架脚本

+ +

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 self.data.url:

+ +
const self = require("sdk/self");
+
+messageManager.loadFrameScript(self.data.url("frame-script.js"), false);
+ +

Note that unlike the APIs to load content scripts, you can only load a single frame script here.

+ +

例子

+ +

For example, this add-on trivially accesses content directly using a low-level API:

+ +
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
+});
+ +

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:

+ +
/*
+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
+});
+ +

现在附加组件能正常工作了,即使你设置了 multiprocessCompatible。

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 +--- +

The Add-on SDK supports event-driven programming.

+

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.

+

We talk about content scripts in more detail in the Working with Content Scripts guide.

+

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.

+

So there are two main ways you will interact with the EventEmitter framework:

+ +

This guide only covers the first of these; the second is explained in the Working with Content Scripts guide.

+

Adding Listeners

+

You can add a listener to an event emitter by calling its on(type, listener) method.

+

It takes two parameters:

+ +

For example, the following add-on registers a listener with the tabs module to listen for the ready event, and logs a string to the console reporting the event:

+
var tabs = require("sdk/tabs");
+
+tabs.on("ready", function () {
+  console.log("tab loaded");
+});
+
+

It is not possible to enumerate the set of listeners for a given event.

+

The value of this in the listener function is the object that emitted the event.

+

Listening to all events

+
+

This example uses the action button API, which is only available from Firefox 29 onwards.

+
+

From Firefox 28 onwards, you can pass the wildcard "*" as the type 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:

+
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
+  });
+}
+

This wildcard feature does not yet work for the tabs or windows modules.

+

Adding Listeners in Constructors

+

Event emitters may be modules, as is the case for the ready event above, or they may be objects returned by constructors.

+

In the latter case the options 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 on() method.

+

For example: the ActionButton object emits an event when the button is clicked.

+

The following add-on creates a button and assigns a listener to the onClick property of the options object supplied to the button's constructor. The listener loads https://developer.mozilla.org/:

+
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/");
+  }
+});
+
+

This is exactly equivalent to constructing the button and then calling the button's on() method:

+
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/");
+});
+
+

Removing Event Listeners

+

Event listeners can be removed by calling removeListener(type, listener), supplying the type of event and the listener to remove.

+

The listener must have been previously been added using one of the methods described above.

+

In the following add-on, we add two listeners to the tabs module's ready event. One of the handler functions removes the listener again.

+

Then we open two tabs.

+
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");
+
+

We should see output like this:

+
info: tabevents: Listener 1
+info: tabevents: Listener 2
+info: tabevents: Listener 2
+
+

Listeners will be removed automatically when the add-on is unloaded.

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 +--- +

{{AddonSidebar}}

+ +
+

不稳定

+
+ +

使用Base64算法编码和解码数据

+ +
var base64 = require("sdk/base64");
+
+var encodedData = base64.encode("Hello, World");//"SGVsbG8sIFdvcmxk"
+var decodedData = base64.decode(encodedData);//"Hello, World"
+ +

Globals

+ +

函数

+ +

encode(data, charset)

+ +

将数据编码成ASCII的Base64字符串。

+ +
参数
+ +

data : string
+ 需要被编码的字符串

+ +

charset : string
+ 字符串的编码字符集(可选)。唯一能接受的值“UTF-8”。为了进行编码和解码Unicode字符串,需要设置字符集参数:

+ +
var base64 = require("sdk/base64");
+
+var encodedData = base64.encode(unicodeString, "utf-8");
+
+ +
返回
+ +

string : 编码后的Base64字符串。

+ +

decode(data, charset)

+ +

解码一个已使用base-64编码的数据字符串

+ +
参数
+ +

data : string
+ 需要被解码的字符串

+ +

charset : string
+ 字符串的编码字符集(可选)。唯一能接受的值“UTF-8”。为了进行编码和解码Unicode字符串,需要设置字符集参数:

+ +
var base64 = require("sdk/base64");
+
+var decodedData = base64.decode(encodedData, "utf-8");
+
+ +
返回
+ +

string : 解码后的字符串

+ +
 
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 +--- +

{{AddonSidebar}}

+ +
+

稳定版

+
+ +

操作系统剪贴板,设置或获取其内容

+ +

用法

+ +

你可以选择性地设置将要获取或设置的内容的格式. 支持一下格式:

+ + + +

如果没有提供格式参数的话,剪贴板模块会自动检测。

+ +

现在在Windows操作系统下,"image"格式并不支持透明度。

+ +

示例

+ +

设置和获取剪贴板内容。

+ +
var clipboard = require("sdk/clipboard");
+clipboard.set("Lorem ipsum dolor sit amet");
+var contents = clipboard.get();
+ +

将剪贴板内容设置为某些html。

+ +
var clipboard = require("sdk/clipboard");
+clipboard.set("<blink>Lorem ipsum dolor sit amet</blink>", "html");
+ +

如果剪贴板内容中包含有html,则将其在新标签页中打开。

+ +
var clipboard = require("sdk/clipboard");
+if (clipboard.currentFlavors.indexOf("html") != -1)
+  require("sdk/tabs").open("data:text/html;charset=utf-8," + clipboard.get("html"));
+ +

将剪贴板内容设置为一幅图片。

+ +
var clipboard = require("sdk/clipboard");
+clipboard.set("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
+              "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
+              "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
+              "bWRR9AAAAABJRU5ErkJggg%3D%3D");
+ +

如果剪贴板内容中包含图片,则将其在新标签页中打开。

+ +
var clipboard = require("sdk/clipboard");
+if (clipboard.currentFlavors.indexOf("image") != -1)
+  require("sdk/tabs").open(clipboard.get());
+ +

如前所述,图片的参数类型很容易被忽略,例如在网页中选中复制一张图片,得到的格式会是html而不是所预期的image。如果你是想将剪贴板的内容设置成像data URL这样的文本字符串而不是图片的话,可以通过将格式设置为text实现。

+ +
var clipboard = require("sdk/clipboard");
+
+clipboard.set("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
+              "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
+              "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
+              "bWRR9AAAAABJRU5ErkJggg%3D%3D", "text");
+ +

Globals

+ +

函数

+ +

set(data, datatype)

+ +

将用户剪贴板上的内容用data替换。

+ +
参数
+ +

data : string
+ 要放入剪贴板的内容。

+ +

datatype : string
+ 内容的格式 ,为"text"或"html" 或 "image"。可选参数.

+ +

get(datatype)

+ +

获取用户当前剪贴板的内容。

+ +
参数
+ +

datatype : string
+ 只有当剪贴板中的内容格式为datatype指定的格式时才获取 (可选).。当剪贴板中的内容非所提供的datatype指定的格式时,函数回返回null。

+ +

属性

+ +

currentFlavors

+ +

剪贴板上的内容有时会是多种格式。例如,HTML内容即能匹配HTML格式(html),又能匹配纯文本格式(text)。这个属性为一个数组,数组中的元素是剪贴板内容所匹配的所有格式,如["text","html"]。

+ +
 
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 +--- +

{{AddonSidebar}}

+ +

此页面列出的模块使用的是高级的API:创建用户界面,与网络进行交互并与浏览器交互。

+ +

除非文件明确说明,否则这些API是稳定的,我们避免做出不兼容的改变。 + +{{ LandingPageListSubpages ("/en-US/Add-ons/SDK/High-Level_APIs", 5) }}

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 +--- +

{{AddonSidebar}}

+ +
+

Stable

+
+ +

向用户展示短暂的 toaster 风格的桌面消息。

+ +

用法

+ +

本 API 支持Windows、使用Growl(或者像OS X 10.9 Mavericks那样的通知中心)的 OS X 的桌面通知,以及使用 libnotify 的Linux系统

+ +

这儿有个典型的例子。当消息被点击,控制台上回记录一个字符串。

+ +
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.
+  }
+});
+
+ +

下面这个示例用来展示一个保存在 add-on 的 data 目录下的图标。参看 self 模块文档以获取更多信息。

+ +
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
+});
+ +
+

从 Firefox 34 起,你能使用 "./myIcon.png" 作为 self.data.url("myIcon.png") 的别名。所以你也可以把上面的代码重写成这样:

+ +
var notifications = require("sdk/notifications");
+var myIconURL = "./myIcon.png";
+
+notifications.notify({
+  text: "I have an icon!",
+  iconURL: myIconURL
+});
+
+ +

本模块依赖于底层系统的通知服务。如果用户的系统不支持桌面通知或者通知服务没有运行:

+ + + +

Globals

+ +

函数

+ +

notify(options)

+ +

向用户展示一个短暂的通知

+ +
参数
+ +

options : object
+ 可选项:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
titlestring +

作为消息标题的字符串。

+
text作为消息体的字符串。 +

 

+
iconURLstring +

消息里的图标的 URL 。可以是个远程的、本地的或者使用 self 模块的 URL。

+
onClickfunction +

用户点击消息是调用的函数。它会传递一个 data 值。

+
datastring +

传递给 onClick 的字符串。

+
+ +
 
+ +
 
+ +
 
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 +--- +
+

稳定版本

+
+ +

创建临时的 add-on's 用户界面对话框.

+ +

用法

+ +

该模块导出了一个单独的构造函数函数 Panel() 构建一个Panel对话框 .

+ +

面板是一个对话框。其内容是指定的HTML,你可以在它执行脚本,所以面板的外观和行为是有限的只有你可以使用HTML,CSS,JavaScript。

+ +

下面的截图显示了一个面板,其内容是从当前打开的选项卡的列表中构建的:

+ +

+ +

面板是呈现临时用户界面中容易忽视和解聘的用户比模态对话框的方式,是有用的,因为面板隐藏瞬间用户交互部分的应用程序接口外。

+ +


+ 面板的内容加载快作为它是创建,面板显示之前,和内容仍然加载时面板是隐藏的,所以它是可能保持面板周围的背景,更新其内容适当地准备下一次显示。

+ +


+ 您的插件可以接收通知,当面板显示或隐藏通过听其显示和隐藏事件。
+ 打开面板将关闭已打开的面板。

+ +

Panel 内容

+ +

该面板的内容指定为HTML,它是在contenturl选项面板的构造函数提供的URL加载。

+ +


+ 你可以加载远程HTML到面板:

+ +
var panel = require("sdk/panel").Panel({
+  width: 180,
+  height: 180,
+  contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&useformat=mobile"
+});
+
+panel.show();
+ +

+ +

你也可以加载HTML已经打包你的 add-on,这可能是你将如何创建对话框。要做到这一点,在你的 add-on 的 data 目录中保存的HTML 和加载使用 data.url()方法,由 self 模块导出, 像下面:

+ +
var panel = require("sdk/panel").Panel({
+  contentURL: require("sdk/self").data.url("myFile.html")
+});
+
+panel.show();
+ +
+

从Firefox 34以后, 你可以使用 "./myFile.html" 作为self.data.url("myFile.html")别名. 所以你可以重写成下面的示例:

+ +
var panel = require("sdk/panel").Panel({
+  contentURL: "./myFile.html"
+});
+
+panel.show();
+
+
+ +

Panel positioning

+ +

By default the panel appears in the center of the currently active browser window. You can position the panel by passing a position to the panel's constructor or to its show() method.

+ +

Attaching panels to buttons

+ +

You can attach a panel to a toggle button by passing the button itself as the position option to the panel's show() method or to its constructor:

+ +
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});
+}
+ +

+ +

Updating panel content

+ +

You can update the panel's content by:

+ + + +

Scripting panel content

+ +

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.

+ +

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.

+ + + +

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 self.port.emit() and the add-on script receives them using panel.port.on().

+ +
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();
+ +

This example uses contentScript to supply the script as a string. It's usually better practice to use contentScriptFile, which is a URL pointing to a script file saved under your add-on's data directory.

+ +
+

Warning: Unless your content script is extremely simple and consists only of a static string, don't use contentScript: if you do, you may have problems getting your add-on approved on AMO.

+ +

Instead, keep the script in a separate file and load it using contentScriptFile. This makes your code easier to maintain, secure, debug and review.

+
+ +

Getting user input

+ +
+

Note: This example uses the action button API, which is only available from Firefox 29 onwards.

+
+ +

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 return key, the contents of the <textarea> is sent to the main add-on code.

+ +

+ +

The add-on consists of six files:

+ + + +

"main.js" is saved in your add-on's lib directory, and the other files go in your add-on's data directory:

+ +
my-addon/
+         data/
+              get-text.js
+              icon-16.png
+              icon-32.png
+              icon-64.png
+              text-entry.html
+         lib/
+             main.js
+
+ +

The "main.js" looks like this:

+ +
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();
+});
+ +

The content script "get-text.js" looks like this:

+ +
// 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();
+});
+ +

Finally, the "text-entry.html" file defines the <textarea> element:

+ +
<html>
+<head>
+    <style type="text/css" media="all">
+      textarea {
+        margin: 10px;
+      }
+      body {
+        background-color: gray;
+      }
+    </style>
+  </head>
+<body>
+    <textarea rows="13" cols="33" id="edit-box"></textarea>
+  </body>
+</html>
+ +

Finally, save these three icon files to the "data" directory:

+ + + + + + + + + + + + + + + + +
icon-16.png
icon-32.png
icon-64.png
+ +

To learn much more about content scripts, see the Working with Content Scripts guide.

+ +

Scripting trusted panel content

+ +
+

Note: This example uses the action button API, which is only available from Firefox 29 onwards.

+
+ +

We've already seen that you can package HTML files in your add-on's data 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 script tags.

+ +

Like a content script, these scripts can communicate with the add-on code using the postMessage() API or the port API. The crucial difference is that these scripts access the postMessage and port objects through the addon object, whereas content scripts access them through the self object.

+ +

To show the difference, we can easily convert the text-entry add-on above to use normal page scripts instead of content scripts.

+ +

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:

+ +
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();
+});
+ +

The page script is exactly the same as the content script above, except that instead of self, we use addon to access the messaging APIs:

+ +
// 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();
+});
+ +

Finally, the HTML file now references "get-text.js" inside a {{HTMLElement("script")}} tag:

+ +
<html>
+<head>
+    <style type="text/css" media="all">
+      textarea {
+        margin: 10px;
+      }
+      body {
+        background-color: gray;
+      }
+    </style>
+  </head>
+  <body>
+    <script src="get-text.js"></script>
+    <textarea rows="13" cols="33" id="edit-box"></textarea>
+  </body>
+</html>
+
+ +

Styling panel content

+ +

The panel's default style is different for each operating system:

+ +

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.

+ +

If the panel's content is packaged along with your add-on and specified using an HTML file in your data directory, you can style it by embedding CSS directly in the HTML file or by referencing a CSS file stored under data:

+ +
<!DOCTYPE HTML>
+<html>
+  <head>
+    <link href="panel-style.css" type="text/css" rel="stylesheet">
+  </head>
+  <body>
+    My panel content
+  </body>
+</html>
+ +

From Firefox 31 onwards, you can style panel content using the contentStyle or contentStyleFile options. You can use these options even if the panel content is not packaged along with the add-on:

+ +
var panel = require("sdk/panel").Panel({
+  contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&useformat=mobile",
+  contentStyle: "body { border: 3px solid blue; }"
+});
+
+panel.show();
+ +
var self = require("sdk/self");
+
+var panel = require("sdk/panel").Panel({
+  contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&useformat=mobile",
+  contentStyleFile: self.data.url("panel-style.css")
+});
+
+panel.show();
+ +

Private browsing

+ +

If your add-on has not opted into private browsing, and it calls panel.show() when the currently active window is a private window, then the panel will not be shown.

+ +

Panel limitations

+ +

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:

+ + + +

Globals

+ +

Constructors

+ +

Panel(options)

+ +

Creates a panel.

+ +
Parameters
+ +

options : object
+ Optional options:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
widthnumber +

The width of the panel in pixels. Optional.

+
heightnumber +

The height of the panel in pixels. Optional.

+
position +

object, button, widget

+
+

The position of the panel. Ignored if the panel is opened by a widget.

+ +

This may be one of three things:

+ +
    +
  • a toggle button. If this is supplied the panel will be shown attached to the button. See the section on attaching panels to buttons.
  • +
  • a widget object. If this is supplied the panel will be shown attached to the widget.
  • +
  • an object which specifies where in the window the panel should be shown. The rest of this section describes this object.
  • +
+ +

The position object has one or more of the following properties: top, right, bottom and left. Their values are expressed in pixels. Any other properties will be ignored.

+ +

The default alignment along each axis is centered: so to display a panel centred along the vertical or horizontal axis, just omit that axis:

+ +
+// 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();
+ +

As with the CSS top, bottom, left, and right properties, setting both top and bottom or both left and right will implicitly set the panel's height or width relative to the content window:

+ +
+// 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();
+ +

If you set both top and bottom, but also set the panel's height explicitly using the height property, then the panel will ignore bottom, just as CSS does for its properties with the same name:

+ +
+// 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();
+ +

The same principle is applied in the horizontal axis with width, left and right.

+
focusboolean +

Set to false to prevent taking the focus away when the panel is shown. Only turn this off if necessary, to prevent accessibility issue. Optional, default to true.

+
contentURLstring,URL +

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 self.data.url().

+ +
+

From Firefox 34, you can use "./my-file.html" as an alias for self.data.url("my-file.html").

+
+
allowobject +

An optional object describing permissions for the content. It should contain a single key named script whose value is a boolean that indicates whether or not to execute script in the content. script defaults to true.

+
contentScriptFilestring,array +

A URL or an array of URLs. The URLs point to scripts to load into the panel.

+ +

The scripts must be packaged with the add-on under the add-on's data directory. That is, they can't refer to remote scripts. The URLs are usually constructed using self.data.url().

+ +
+

From Firefox 34, you can use "./my-script.js" as an alias for self.data.url("my-script.js").

+
+ +

Content scripts specified by this property are loaded before those specified by the contentScript property.

+
contentScriptstring,array +

A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded after those specified by the contentScriptFile property.

+
contentStyleFilestring, array +

A URL or an array of URLs. The URLs point to CSS stylesheets to load into the panel.

+ +

The stylesheets must be packaged with the add-on under the add-on's data directory. That is, they can't refer to remote stylesheets. The URLs are usually constructed using self.data.url().

+ +

Stylesheets specified by this property are loaded before those specified by the contentStyle property.

+
contentStylestring, array +

A string or an array of strings containing the texts of stylesheets to load. Stylesheets specified by this property are loaded after those specified by the contentStyleFile property.

+
contentScriptWhenstring +

When to load the content scripts. This may take one of the following values:

+ +
    +
  • "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
  • +
  • "ready": load content scripts once DOM content has been loaded, corresponding to the DOMContentLoaded event
  • +
  • "end": load content scripts once all the content (DOM, JS, CSS, images) for the panel has been loaded, at the time the window.onload event fires
  • +
+ +

This property is optional and defaults to "end".

+
contentScriptOptionsobject +

Read-only value exposed to content scripts under addon.options property.

+ +

Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.

+
contextMenuboolean +
+

New in Firefox 33

+
+ +

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 false.

+
onMessagefunction +

Include this to listen to the panel's message event.

+
onShowfunction +

Include this to listen to the panel's show event.

+
onHidefunction +

Include this to listen to the panel's hide event.

+
+ +

Panel

+ +

The Panel object represents a floating modal dialog that can by an add-on to present user interface content.

+ +

Once a panel object has been created it can be shown and hidden using its show() and hide() methods. Once a panel is no longer needed it can be deactivated using destroy().

+ +

The content of a panel is specified using the contentURL option. An add-on can interact with the content of a panel using content scripts which it supplies in the contentScript and/or contentScriptFile options. For example, a content script could create a menu and send the user's selection to the add-on.

+ +

Methods

+ +

destroy()

+ +

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 hide instead.

+ +

postMessage(message)

+ +

Sends a message to the content scripts.

+ +
Parameters
+ +

message : value
+ The message to send. Must be stringifiable to JSON.

+ +

show(options)

+ +

Displays the panel.

+ +

If the options argument is given, it will be shallow merged with the options provided in the constructor: the options passed in the show method takes precedence.

+ +

Passing options here is useful for making temporary changes without touching the default values.

+ +
Parameters
+ +

options : object
+ Optional options:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
widthnumber +

The width of the panel in pixels. Optional.

+
heightnumber +

The height of the panel in pixels. Optional.

+
positionobject +

The position of the panel. Optional. See Panel's options for further details.

+
focusboolean +

Set to false to prevent taking the focus away when the panel is shown.

+
+ +

hide()

+ +

Stops displaying the panel.

+ +

resize(width, height)

+ +

Resizes the panel.

+ +
Parameters
+ +

width : number
+ The new width of the panel in pixels.

+ +

height : number
+ The new height of the panel in pixels.

+ +

on(type, listener)

+ +

Registers an event listener with the panel.

+ +
Parameters
+ +

type : string
+ The type of event to listen for.

+ +

listener : function
+ The listener function that handles the event.

+ +

removeListener(type, listener)

+ +

Unregisters an event listener from the panel.

+ +
Parameters
+ +

type : string
+ The type of event for which listener was registered.

+ +

listener : function
+ The listener function that was registered.

+ +

Properties

+ +

port

+ +

EventEmitter object that allows you to:

+ + + +

See the guide to communicating using port for details.

+ +

isShowing

+ +

Tells if the panel is currently shown or not. This property is read-only.

+ +

height

+ +

The height of the panel in pixels.

+ +

width

+ +

The width of the panel in pixels.

+ +

focus

+ +

Whether or not focus will be taken away when the panel is shown. This property is read-only.

+ +

contentURL

+ +

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.

+ +

allow

+ +

An object describing permissions for the content. It contains a single key named script whose value is a boolean that indicates whether or not to execute script in the content.

+ +

contentScriptFile

+ +

A local file URL or an array of local file URLs of content scripts to load. Content scripts specified by this property are loaded before those specified by the contentScript property.

+ +

contentScript

+ +

A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded after those specified by the contentScriptFile property.

+ +

contentScriptWhen

+ +

When to load the content scripts. This may have one of the following values:

+ + + +

contentScriptOptions

+ +

Read-only value exposed to content scripts under addon.options property.

+ +

Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.

+ +

Events

+ +

show

+ +

This event is emitted when the panel is shown.

+ +

hide

+ +

This event is emitted when the panel is hidden.

+ +

message

+ +

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 self.postMessage(), the message is delivered to the add-on code in the panel's message event.

+ +
Arguments
+ +

value : Listeners are passed a single argument which is the message posted from the content script. The message can be any JSON-serializable value.

+ +

error

+ +

This event is emitted when an uncaught runtime error occurs in one of the panel's content scripts.

+ +
Arguments
+ +

Error : Listeners are passed a single argument, the Error object.

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 +--- +

{{AddonSidebar}}

+ +
+

Stable

+
+ +

打开、操作和访问标签页,以及接收标签页事件

+ +

用法

+ +

打开标签页

+ +

你可以注册事件监听器,以便在标签打开、关闭、完成DOM内容加载、被激活或被闲置时接收通知:

+ +
var tabs = require("sdk/tabs");
+tabs.open("http://www.example.com");
+ +

跟踪标签页

+ +

You can register event listeners to be notified when tabs open, close, finish loading DOM content, or are made active or inactive:

+ +
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);
+});
+ +

访问标签页

+ +

The module itself can be used as a list of all opened tabs across all windows. In particular, you can enumerate it:

+ +
var tabs = require('sdk/tabs');
+for (let tab of tabs)
+  console.log(tab.title);
+ +

You can also access individual tabs by index:

+ +
var tabs = require('sdk/tabs');
+
+tabs.on('ready', function () {
+  console.log('first: ' + tabs[0].title);
+  console.log('last: ' + tabs[tabs.length-1].title);
+});
+ +

You can access the currently active tab:

+ +
var tabs = require('sdk/tabs');
+
+tabs.on('activate', function () {
+  console.log('active: ' + tabs.activeTab.url);
+});
+ +

跟踪单个标签页

+ +

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 "back-forward cache":

+ +
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);
+ +

操作标签页

+ +

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 ready event fires). By setting the url property you can load a new page in the tab:

+ +
var tabs = require("sdk/tabs");
+tabs.on('activate', function(tab) {
+  tab.url = "http://www.example.com";
+});
+ +

在标签页中运行脚本

+ +

You can attach a content script to the page hosted in a tab, and use that to access and manipulate the page's content (see the Modifying the Page Hosted by a Tab tutorial):

+ +
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)
+  })
+});
+ +

Note that tab.attach 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.

+ +

附加样式表

+ +
+

Firefox 34 新增。

+
+ +

You can't attach style sheets to a tab using tab.attach(), but from Firefox 34 onwards you can attach and detach them using the low-level stylesheet/style and content/mod 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:

+ +
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);
+    }
+  }
+});
+ +

隐私窗口

+ +

If your add-on has not opted into private browsing, then you won't see any tabs that are hosted by private browser windows.

+ +

Tabs hosted by private browser windows won't be seen if you enumerate the tabs module itself, and you won't receive any events for them.

+ +

To learn more about private windows, how to opt into private browsing, and how to support private browsing, refer to the documentation for the private-browsing module.

+ +

转为XUL标签页

+ +

To convert from the high-level Tab objects used in this API to the low-level XUL tab objects used in the tabs/utils API and by traditional add-ons, use the viewFor() function exported by the viewFor module.

+ +

To convert back the other way, from a XUL tab to a high-level Tab object, use the modelFor() function, exported by the modelFor module.

+ +

Here's an example converting from a high-level Tab to a XUL tab and then back the other way:

+ +
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);
+
+ +

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 multiprocess Firefox.

+ +

全局变量

+ +

函数

+ +

open(options)

+ +

Opens a new tab. The new tab will open in the active window or in a new window, depending on the inNewWindow option.

+ +

示例

+ +
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.
+  }
+});
+ +
参数
+ +

options : object
+ 必选项:

+ + + + + + + + + + + + + + + + +
NameType 
urlstring +

String URL to be opened in the new tab. This is a required property.

+
+ +

可选项:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
isPrivateboolean +

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 private-browsing documentation for more information. Defaults to false.

+
inNewWindowboolean +

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.

+
inBackgroundboolean +

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.

+
isPinnedboolean +

If present and true, then the new tab will be pinned as an app tab.

+
onOpenfunction +

A callback function that will be registered for the 'open' event. This is an optional property.

+
onClosefunction +

A callback function that will be registered for the 'close' event. This is an optional property.

+
onReadyfunction +

A callback function that will be registered for the 'ready' event. This is an optional property.

+
onLoadfunction +

A callback function that will be registered for the 'load' event. This is an optional property.

+
onPageShowfunction +

A callback function that will be registered for the 'pageshow' event. This is an optional property.

+
onActivatefunction +

A callback function that will be registered for the 'activate' event. This is an optional property.

+
onDeactivatefunction +

A callback function that will be registered for the 'deactivate' event. This is an optional property.

+
+ +

属性

+ +

activeTab

+ +

The currently active tab in the active window. This property is read-only. To activate a Tab object, call its activate method.

+ +

示例

+ +
// Get the active tab's title.
+var tabs = require("sdk/tabs");
+console.log("title of active tab is " + tabs.activeTab.title);
+ +

length

+ +

The number of open tabs across all windows.

+ +

事件

+ +

open

+ +

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.

+ +

Properties relating to the tab's content (for example: title, favicon, and url) will not be correct at this point. If you need to access these properties, listen for the ready event:

+ +
var tabs = require("sdk/tabs");
+tabs.on('open', function(tab){
+  tab.on('ready', function(tab){
+    console.log(tab.url);
+  });
+});
+ +
参数
+ +

Tab : Listeners are passed the tab object that just opened.

+ +

close

+ +

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.

+ +
参数
+ +

Tab : Listeners are passed the tab object that has closed.

+ +

ready

+ +

This event is emitted when the DOM for a tab's content is ready. It is equivalent to the DOMContentLoaded event for the given content page.

+ +

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.

+ +
参数
+ +

Tab : Listeners are passed the tab object that has loaded.

+ +

activate

+ +

This event is emitted when an inactive tab is made active.

+ +
参数
+ +

Tab : Listeners are passed the tab object that has become active.

+ +

deactivate

+ +

This event is emitted when the active tab is made inactive.

+ +
参数
+ +

Tab : Listeners are passed the tab object that has become inactive.

+ +

Tab

+ +

A Tab instance represents a single open tab. It contains various tab properties, several methods for manipulation, as well as per-tab event registration.

+ +

Tabs emit all the events described in the Events section. Listeners are passed the Tab object that triggered the event.

+ +

方法

+ +

pin()

+ +

Pins this tab as an app tab.

+ +

unpin()

+ +

Unpins this tab.

+ +

close(callback)

+ +

Closes this tab.

+ +
参数
+ +

callback : function
+ A function to be called when the tab finishes its closing process. This is an optional argument.

+ +

reload()

+ +

Reloads this tab.

+ +

activate()

+ +

Makes this tab active, which will bring this tab to the foreground.

+ +

getThumbnail()

+ +

Returns thumbnail data URI of the page currently loaded in this tab.

+ +

attach(options)

+ +

Attach one or more scripts to the document loaded in the tab. Note that by attaching inside ready 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.

+ +

示例

+ +
var tabs = require("sdk/tabs");
+
+tabs.on('ready', function(tab) {
+  var worker = tab.attach({
+      contentScript:
+        'document.body.style.border = "5px solid red";'
+  });
+});
+ +
参数
+ +

options : object
+ 可选项:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
contentScriptFilestring,array +

The local file URLs of content scripts to load. Content scripts specified by this option are loaded before those specified by the contentScript option. Optional.

+
contentScriptstring,array +

A string or an array of strings of code to be evaluated in the context. Content scripts specified by this option are loaded after those specified by the contentScriptFile option. Optional.

+
contentScriptOptionsobject +

You can use this option to define read-only values for your content scripts.

+ +

The option consists of an object literal listing name:value pairs for the values you want to provide to the content script. For example:

+ +
+// main.js
+
+const tabs = require("sdk/tabs");
+
+tabs.open({
+  url: "./page.html",
+  onReady: function(tab) {
+    tab.attach({
+      contentScriptFile: "./content-script.js",
+      contentScriptOptions: {
+        a: "blah"
+      }
+    });
+  }
+});
+ +

The values are accessible to content scripts via the self.options property:

+ +
+// content-script.js
+
+alert(self.options.a);
+
onMessagefunction +

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.

+
onErrorfunctionA function called when the content worker receives an error from content scripts. Listeners are passed a single argument, error, which is the error posted from the content script and an object of type Error. Optional
+ +
返回
+ +

Worker : Worker 对象能够用来和内容脚本通信。查看 Content Scripts guide 了解详细信息。

+ +

属性

+ +

id

+ +

The unique id for the tab. This property is read-only.

+ +

title

+ +

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.

+ +

url

+ +

The URL of the page currently loaded in the tab. This property can be set to load a different URL in the tab.

+ +

favicon

+ +

The URL of the favicon for the page currently loaded in the tab. This property is read-only.

+ +
This property is deprecated. From version 1.15, use the favicon module's getFavicon() function instead.
+ +

contentType

+ +
+

This is currently an experimental API, so we might change it in future releases.

+ +

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.

+
+ +

index

+ +

The index of the tab relative to other tabs in the application window. This property can be set to change its relative position.

+ +

isPinned

+ +

Whether or not this tab is pinned as an app tab. This property is read-only.

+ +

window

+ +

标签页的window对象.

+ +

readyState

+ +
+

Firefox 33 新增。

+
+ +

A string telling you the load state of the document hosted by this tab. This corresponds directly to Document.readyState. It has one of four possible values:

+ + + +

Once a tab's readyState has entered "interactive", you can retrieve properties such as the document's URL.

+ +

事件

+ +

close

+ +

This event is emitted when the tab is closed. It's also emitted when the tab's window is closed.

+ +
参数
+ +

Tab : Listeners are passed the tab object.

+ +

ready

+ +

This event is emitted when the DOM for the tab's content is ready. It is equivalent to the DOMContentLoaded 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.

+ +

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.

+ +
参数
+ +

Tab : Listeners are passed the tab object.

+ +

load

+ +

This event is emitted when the page for the tab's content is loaded. It is equivalent to the load event for the given content page. At this point the document and its resources, such as images and stylesheets, have finished loading.

+ +

This event can be used for pages that do not have a DOMContentLoaded event, like images. For pages that have a DOMContentLoaded event, load is fired after ready.

+ +

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.

+ +
参数
+ +

Tab : Listeners are passed the tab object.

+ +

pageshow

+ +

The pageshow event is emitted when the page for a tab's content is loaded. It is equivalent to the pageshow event for the given content page.

+ +

This event is similar to the load and ready events, except unlike load and ready, pageshow is triggered if the page was retrieved from the bfcache. 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 pageshow event is emitted when the user moves back to the previous page, while the load and ready events are not.

+ +

This event is not emitted when the tab is made the active tab: to get notified about that, you need to listen to the activate event.

+ +

After this event has been emitted, all properties relating to the tab's content can be used. It is emitted after load and ready.

+ +
参数
+ +

Tab : Listeners are passed the tab object.

+ +

persisted : Listeners are passed a boolean value indicating whether or not the page was loaded from the bfcache.

+ +

activate

+ +

This event is emitted when the tab is made active.

+ +

Note that you cannot guarantee that a tab's content, or even its url, are initialized at the time activate is emitted. This is because when a new tab is opened, its activate event may be emitted before the content is loaded.

+ +

You can use the tab's readyState property to determine whether the tab's content and url will be available: if readyState is uninitialized or loading, then you can't access the tab's properties and must wait for the tab's ready event.

+ +
参数
+ +

Tab : Listeners are passed the tab object.

+ +

deactivate

+ +

This event is emitted when the tab is made inactive.

+ +
参数
+ +

Tab : Listeners are passed the tab object.

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 +--- +
+

实验性的

+
+ +

构建,验证,解析URL

+ +

Globals

+ +

构造函数

+ +

URL(source, base)

+ +

URL构造函数可以创建一个URL对象,并验证提供的字符串是否是有效的URL。SDK中,任何接受URL参数的API,除非特殊说明,均接受的是此对象而不是字符串。

+ +
参数
+ +

source : string
+ 一个表示URL的字符串,如果接受的参数不是有效的URL字符串,此构造函数会抛出一个异常。

+ +

base : string
+ 一个设置的字符串,用来表示一个相对路径的源。

+ +

DataURL(uri)

+ +

DataURL构造函数创建一个data: URL对象, 并验证提供的字符串是否是一个有效的data: URL。

+ +
参数
+ +

uri : string
+ 一个表示Data URL的字符串。如果它不是一个合法的URL字符串,此构造函数会抛出一个错误。

+ +

函数

+ +

toFilename(url)

+ +

尝试将给定的URL转换成本地文件路径。这个方法会自动尝试解决非文件协议, such as the resource: protocol, to their place on the file system. 除非URL无法转换,否则,本方法会将本地路径作为字符串返回。

+ +
参数
+ +

url : string
+ 字符串格式的URL。

+ +
返回
+ +

string : 转换后的本地路径字符串

+ +

fromFilename(path)

+ +

讲一个给定的路径转换成 file: URL.

+ +
参数
+ +

path : string
+ 需要被转换的本地文件路径字符串。

+ +
Returns
+ +

string : 转换后的字符串。

+ +

isValidURI(uri)

+ +

检查一个URL字符串是合法。 isValidURI("http://mozilla.org") 将返回 true, 而 isValidURI("mozilla.org") 将返回 false

+ +
参数
+ +

uri : string
+ 需要被测试的URL。

+ +
Returns
+ +

boolean : 代表字符串是否有效的布尔值。

+ +

getTLD(url)

+ +

返回给定域名的顶级域名: 内部使用的是 getPublicSuffix()

+ +
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"
+ +
参数
+ +

url : string
+ 给定的URL字符串

+ +
返回
+ +

string : 对应的顶级域名。

+ +

URL

+ +

方法

+ +

toString()

+ +

返回URL的字符表示形式。

+ +
返回
+ +

string : 字符串格式的URL。

+ +

属性

+ +

scheme

+ +

URL使用的协议

+ +

userPass

+ +

URL中的username:password 部分,null 表示不存在。

+ +

host

+ +

URL的主机部分。 null 表示无此部分。例子:

+ +
var url = require("sdk/url").URL("https://developer.mozilla.org/en-US/Add-ons");
+console.log(url.host);  // developer.mozilla.org
+ +

port

+ +

URL使用的端口。 null 表示不存在。

+ +

path

+ +

URL的路径部分,例子:

+ +
var url = require("sdk/url").URL("https://developer.mozilla.org/en-US/Add-ons");
+console.log(url.path);  // /en-US/Add-ons
+ +

hostname

+ +

表示URL的域的字符串。参见 window.location.hostname

+ +

pathname

+ +

'/'开始的路径字符串。参见 window.location.pathname

+ +

hash

+ +

'#' 开始的hash字符串,参见 window.location.hash

+ +

href

+ +

整个URL字符串,参见 window.location.href

+ +

origin

+ +

该URL的源的字符串,参见 window.location.origin

+ +

protocol

+ +

该URL使用的协议字符串,包括最后的':',参见 window.location.protocol

+ + + +

以'?'开始的URL的参数段,包括最开始的'?'参见window.location.search.

+ +

DataURL

+ +

方法

+ +

toString()

+ +

返回数据的URL字符串形式。如果是 base64 的URL,数据会以base64编码方式编码。

+ +
返回
+ +

string : URL字符串

+ +

属性

+ +

mimeType

+ +

数据的MIME类型,默认为空字符串。

+ +

parameters

+ +

一个HashMap的数据包含URL参数。默认情况下是一个空对象。

+ +

base64

+ +

定义了数据属性的编码。

+ +

data

+ +

包含数据的URL字符串。如果URI给构造函数包含Base64参数,这个字符串会被解码。

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 +--- +

{{LegacyAddonsNotice}}{{AddonSidebar}}

+ +
+

Deprecated in Firefox 29 and removed in Firefox 38.

+ +

The widget API is deprecated from Firefox 29 onwards. Please see the ui module for replacements. In particular, for a simple button, try the action button or toggle button APIs, and for a more complex widget try the toolbar or sidebar APIs.

+
+ +

Create a simple user interface for an add-on in Firefox's add-on bar.

+ +

Usage

+ +

"Widgets" are small pieces of content that live in the Firefox 4 add-on bar. They can be simple icons or complex web pages. You can attach panels 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.

+ +

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.

+ +

Creation and content

+ +

Widgets can contain images or arbitrary web content. You can include this content inline as a string by using the content property, or point to content using a URL with the contentURL property.

+ +

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.

+ +

For example, this widget contains an image, so it looks like a simple icon:

+ +
require("sdk/widget").Widget({
+  id: "mozilla-icon",
+  label: "My Mozilla Widget",
+  contentURL: "http://www.mozilla.org/favicon.ico"
+});
+ +

You can make contentURL point to an HTML or icon file which you have packaged inside your add-on. Just save the file in your add-on's data directory, and reference it using the data.url() method of the self module:

+ +
var data = require("sdk/self").data;
+
+require("sdk/widget").Widget({
+  id: "my-widget",
+  label: "My Widget",
+  contentURL: data.url("my-content.html")
+});
+ +

This widget contains an entire web page:

+ +
require("sdk/widget").Widget({
+  id: "hello-display",
+  label: "My Hello Widget",
+  content: "Hello!",
+  width: 50
+});
+ +

Widgets are quite small by default, so this example used the width property to grow it in order to show all the text.

+ +

Scripting widget content

+ +

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.

+ +

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.

+ + + +
+

Unless your content script is extremely simple and consists only of a static string, don't use contentScript: if you do, you may have problems getting your add-on approved on AMO.

+ +

Instead, keep the script in a separate file and load it using contentScriptFile. This makes your code easier to maintain, secure, debug and review.

+
+ + +

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.

+ +

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.

+ +

The widget's content is specified using HTML like this:

+ +
<html>
+  <body>
+    <img src="play.png" id="play-button">
+    <img src="pause.png" id="pause-button">
+    <img src="stop.png" id="stop-button">
+  </body>
+</html>
+ +

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 data directory.

+ +

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:

+ +
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");
+}
+ +

We save this file in the add-on's data 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:

+ +
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");
+});
+ +

To learn much more about content scripts, see the Working with Content Scripts guide.

+ +

Scripting trusted widget content

+ +

We've already seen that you can package HTML files in your add-on's data 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 script tags.

+ +

Like a content script, these scripts can communicate with the add-on code using the postMessage() API or the port API. The crucial difference is that these scripts access the postMessage and port objects through the addon object, whereas content scripts access them through the self object.

+ +

To show the difference, convert the player add-on above to use normal page scripts instead of content scripts.

+ +

First, in the content script, change self to addon, and wrap it in a function:

+ +
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");
+  }
+}
+ +

Next, add a script tag to reference "button-script.js", and call its init() function on load:

+ +
<html>
+  <head>
+    <script src="button-script.js"></script>
+  </head>
+  <body onLoad="init()">
+    <img src="play.png" id="play-button">
+    <img src="pause.png" id="pause-button">
+    <img src="stop.png" id="stop-button">
+  </body>
+</html>
+
+ +

Finally, remove the line attaching the content script from "main.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");
+});
+ +

Attaching panels to widgets

+ +

You can supply a panel to the widget's constructor: if you do this, the panel is automatically displayed when the user clicks the widget.

+ + +

+ +
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
+});
+ +

Note that this is, at the moment, the only way you can attach a panel to a widget.

+ +

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:

+ +
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();
+ +

Also, if you try to call panel.show() inside your widget's click event listener, the panel will not be anchored:

+ +
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();
+  }
+});
+ +

See bug 638142.

+ +

Private windows

+ +

If your add-on has not opted into private browsing, then your widget will not appear in any private browser windows.

+ +

To learn more about private windows, how to opt into private browsing, and how to support private browsing, refer to the documentation for the private-browsing module.

+ +

Examples

+ +

For conciseness, these examples create their content scripts as strings and use the contentScript property. In your own add-ons, you will probably want to create your content scripts in separate files and pass their URLs using the contentScriptFile property. See Working with Content Scripts for more information.

+ +
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/";
+  }
+});
+ +
// 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";
+  }
+});
+ +
// 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"
+});
+ +
// 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);
+ +
// A widget communicating bi-directionally with a content script.
+var widget = widgets.Widget({
+  id: "message-test",
+  label: "Bi-directional communication!",
+  content: "<foo>bar</foo>",
+  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");
+  }
+});
+ +

Globals

+ +

Constructors

+ +

Widget(options)

+ +

Creates a new widget. The widget is immediately added to the add-on bar.

+ +
Parameters
+ +

options : object
+ Required options:

+ + + + + + + + + + + + + + + + + + + + + +
NameType 
labelstring +

A string description of the widget used for accessibility, title bars, and error reporting.

+
idstring +

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.

+
+ +

Optional options:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
contentstring +

An optional string value containing the displayed content of the widget. It may contain HTML. Widgets must have either the content property or the contentURL property set.

+ +

If the content is an image, it is automatically scaled to be 16x16 pixels.

+
contentURLstring +

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 content property or the contentURL property set.

+ +

If the content is an image, it is automatically scaled to be 16x16 pixels.

+
panelPanel +

An optional panel 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 this.panel.show().

+
widthinteger +

Optional width in pixels of the widget. If not given, a default width is used.

+
onClickfunction +

Include this to listen to the widget's click event.

+
onMessagefunction +

Include this to listen to the widget's message event.

+
onMouseoverfunction +

Include this to listen to the widget's mouseover event.

+
onMouseoutfunction +

Include this to listen to the widget's mouseout event.

+
onAttachfunction +

Include this to listen to the widget's attach event.

+
tooltipstring +

Optional text to show when the user's mouse hovers over the widget. If not given, the label is used.

+
allowobject +

An optional object describing permissions for the content. It should contain a single key named script whose value is a boolean that indicates whether or not to execute script in the content. script defaults to true.

+
contentScriptFilestring,array +

A local file URL or an array of local file URLs of content scripts to load. Content scripts specified by this property are loaded before those specified by the contentScript property.

+
contentScriptstring,array +

A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded after those specified by the contentScriptFile property.

+
contentScriptWhenstring +

When to load the content scripts. This may take one of the following values:

+ +
    +
  • "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
  • +
  • "ready": load content scripts once DOM content has been loaded, corresponding to the DOMContentLoaded event
  • +
  • "end": load content scripts once all the content (DOM, JS, CSS, images) for the widget has been loaded, at the time the window.onload event fires
  • +
+ +

This property is optional and defaults to "end".

+
contentScriptOptionsobject +

Read-only value exposed to content scripts under self.options property.

+ +

Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.

+
+ +

Widget

+ +

Represents a widget object.

+ +

Methods

+ +

destroy()

+ +

Removes the widget from the add-on bar.

+ +

postMessage(data)

+ +

Sends a message to the widget's content scripts.

+ +
Parameters
+ +

data : value
+ The message to send. The message can be any JSON-serializable value.

+ +

on(type, listener)

+ +

Registers an event listener with the widget.

+ +
Parameters
+ +

type : string
+ The type of event to listen for.

+ +

listener : function
+ The listener function that handles the event.

+ +

removeListener(type, listener)

+ +

Unregisters an event listener from the widget.

+ +
Parameters
+ +

type : string
+ The type of event for which listener was registered.

+ +

listener : function
+ The listener function that was registered.

+ +

getView(window)

+ +

Retrieve a WidgetView instance of this widget relative to a browser window.

+ +
Parameters
+ +

window : BrowserWindow
+ The BrowserWindow instance to match.

+ +
Returns
+ +

WidgetView : A WidgetView instance associated with the browser window. Any changes subsequently applied to this object will only be applied to the widget attached to that window.

+ +

Properties

+ +

label

+ +

The widget's label. Read-only.

+ +

content

+ +

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 contentURL, then this property is meaningless, and setting it has no effect.

+ +

contentURL

+ +

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 content, then this property is meaningless, and setting it has no effect.

+ +

Setting the contentURL 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 bug 825434.

+ +

panel

+ +

A panel to open when the user clicks on the widget.

+ +

width

+ +

The widget's width in pixels. Setting it updates the widget's appearance immediately.

+ +

tooltip

+ +

The text of the tooltip that appears when the user hovers over the widget.

+ +

allow

+ +

A object describing permissions for the content. It contains a single key named script whose value is a boolean that indicates whether or not to execute script in the content.

+ +

contentScriptFile

+ +

A local file URL or an array of local file URLs of content scripts to load.

+ +

contentScript

+ +

A string or an array of strings containing the texts of content scripts to load.

+ +

contentScriptWhen

+ +

When to load the content scripts. This may have one of the following values:

+ + + +

contentScriptOptions

+ +

Read-only value exposed to content scripts under self.options property.

+ +

Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.

+ +

port

+ +

Object that allows you to:

+ + + +

See the guide to communicating using port for details.

+ +

Events

+ +

attach

+ +

This event is emitted when a browser window is opened and a new WidgetView object is created. If the widget has a content script, this event is fired only when the content script is applied according to the contentScriptWhen attribute.

+ +
Arguments
+ +

WidgetView : The related WidgetView object.

+ +

click

+ +

This event is emitted when the widget is clicked.

+ +
Arguments
+ +

WidgetView : Listeners are passed a single argument which is the WidgetView that triggered the click event.

+ +

message

+ +

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 self.postMessage(), the message is delivered to the add-on code in the widget's message event.

+ +
Arguments
+ +

value : Listeners are passed a single argument which is the message posted from the content script. The message can be any JSON-serializable value.

+ +

mouseover

+ +

This event is emitted when the user moves the mouse over the widget.

+ +

mouseout

+ +

This event is emitted when the user moves the mouse away from the widget.

+ +

WidgetView

+ +

Represents a widget instance specific to one browser window.

+ +

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.

+ +

By contrast, any changes you make to an instance of the normal Widget class will be applied across all browser windows.

+ +

This class has all the same methods, attributes and events as the Widget class except for the getView method and the attach event.

+ +

In this example WidgetView is used to display different content for http and https schemes:

+ +
// 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);
+ +

Methods

+ +

destroy()

+ +

Removes the widget view from the add-on bar.

+ +

postMessage(data)

+ +

Sends a message to the widget view's content scripts.

+ +
Parameters
+ +

data : value
+ The message to send. The message can be any JSON-serializable value.

+ +

on(type, listener)

+ +

Registers an event listener with the widget view.

+ +
Parameters
+ +

type : string
+ The type of event to listen for.

+ +

listener : function
+ The listener function that handles the event.

+ +

removeListener(type, listener)

+ +

Unregisters an event listener from the widget view.

+ +
Parameters
+ +

type : string
+ The type of event for which listener was registered.

+ +

listener : function
+ The listener function that was registered.

+ +

Properties

+ +

label

+ +

The widget view's label. Read-only.

+ +

content

+ +

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 contentURL, then this property is meaningless, and setting it has no effect.

+ +

contentURL

+ +

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 content, then this property is meaningless, and setting it has no effect.

+ +

Setting the contentURL 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 bug 825434.

+ +

panel

+ +

A panel to open when the user clicks on the widget view.

+ +

width

+ +

The widget view's width in pixels. Setting it updates the widget view's appearance immediately.

+ +

tooltip

+ +

The text of the tooltip that appears when the user hovers over the widget view.

+ +

allow

+ +

A object describing permissions for the content. It contains a single key named script whose value is a boolean that indicates whether or not to execute script in the content.

+ +

contentScriptFile

+ +

A local file URL or an array of local file URLs of content scripts to load.

+ +

contentScript

+ +

A string or an array of strings containing the texts of content scripts to load.

+ +

contentScriptWhen

+ +

When to load the content scripts. This may have one of the following values:

+ + + +

contentScriptOptions

+ +

Read-only value exposed to content scripts under self.options property.

+ +

Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.

+ +

port

+ +

Object that allows you to:

+ + + +

See the guide to communicating using port for details.

+ +

Events

+ +

detach

+ +

The detach 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.

+ +

click

+ +

This event is emitted when the widget view is clicked.

+ +

message

+ +

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 self.postMessage(), the message is delivered to the add-on code in the widget view's message event.

+ +
Arguments
+ +

value : Listeners are passed a single argument which is the message posted from the content script. The message can be any JSON-serializable value.

+ +

mouseover

+ +

This event is emitted when the user moves the mouse over the widget view.

+ +

mouseout

+ +

This event is emitted when the user moves the mouse away from the widget view.

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 +--- +
+

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.

+ +

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 WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.

+ +

Starting from Firefox 53, no new legacy add-ons will be accepted on addons.mozilla.org (AMO) for desktop Firefox and Firefox for Android.

+ +

Starting from Firefox 57, only extensions developed using WebExtensions APIs will be supported on Desktop Firefox and Firefox for Android.

+ +

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 "Compatibility Milestones" document for more information.

+ +

A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.

+
+ +

你可以使用Add-on SDK来开发Firefox的附加组件。你可以使用各种各样的标准Web技术:JavaScript, HTML和CSS。该SDK不仅包括一些用来创建附加组件的 JavaScript API,还提供了开发、运行、测试、打包附加组件的一些工具。

+ +
+

教程

+ +
+
+
+
快速入门
+
如何安装SDK使用jpm工具开发、测试、打包附加组件
+
与浏览器交互
+
打开网页监听页面加载列出打开的标签页
+
开发技术
+
学习常用开发技术,如单元测试日志创建可复用模块本地化移动开发
+
+
+ +
+
+
创建用户界面组件
+
创建用户界面组件如工具条按钮, 上下文菜单菜单项对话框
+
修改网页
+
+

通过URL匹配修改页面或者动态修改某个tab选项卡

+
+
将其组合在一起
+
关于注释器的附加组件的例子演示.
+
+
+
+ +
+

指南

+ +
+
+
+
贡献者指南
+
学习如何开始构建 SDK和关于SDK最重要的术语, 如 模块 类和继承, 私有属性, 内容处理.
+
SDK的基础构建
+
SDK的底层技术方面: 模块,程序ID, Firefox 兼容的规则定义.
+
内容脚本
+
+
+

一个详细的指南内容脚本

+
+
+
+
+ +
+
+
SDK语法
+
SDK的事件框架和插件的脚本和内容脚本之间的区别。
+
SDK的 事件框架add-on scripts 和 content scripts 的区别.
+
XUL 迁移
+
指导  移植 XUL add-ons 到 SDK. 本指南包括 两工具 和 一个 工作实例 比较 XUL 和 add-on.
+
+
+
+ +
+

参考

+ +
+
+
+
高级API
+
高级SDK API的参考文档.
+
工具参考
+
用于 jpm工具 开发的参考文档, 测试, 打包add-ons, 全局 控制台记录, 和package.json 文件.
+
+
+ +
+
+
低级API
+
低级SDK API的参考文档.
+
+
+
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 +--- +

{{AddonSidebar}}

+ +

本节的模块实现了低层的 API,这些模块大至分为三类:

+ + + +

这些模块仍在开发中,我们预期在将来发布的版本中会做出不兼容的变更。

+ +

{{ LandingPageListSubpages ("/zh-CN/Add-ons/SDK/Low-Level_APIs", 5) }}

+ +

 

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 +--- +

{{LegacyAddonsNotice}}{{AddonSidebar}}

+ +
+

Unstable

+
+ +

实现在 CommonJS Unit Testing specification version 1.1 其中定义的断言接口。

+ +

Usage

+ +

To use the assert module, write a set of unit tests following the instructions in the unit testing tutorial. Each test will be passed an Assert object when you run the tests using jpm test. You can use this object to make assertions about your program's state.

+ +

For example:

+ +
var a = 1;
+
+exports["test value of a"] = function(assert) {
+  assert.ok(a == 1, "test that a is 1");
+}
+
+require("sdk/test").run(exports);
+ +

Globals

+ +

Constructors

+ +

Assert(logger)

+ +

Create a new Assert object. This function is only called by the unit test framework, and not by unit tests themselves.

+ +
Parameters
+ +

logger : object
+ Object used to log the results of assertions.

+ +

Assert

+ +

An object used to make assertions about a program's state in order to implement unit tests.

+ +

The Assert object's interface is defined by the CommonJS Unit Testing specification, version 1.1.

+ +

Methods

+ +

ok(guard, message)

+ +

Tests whether an expression evaluates to true.

+ +
assert.ok(a == 1, "test that a is equal to one");
+ +

This is equivalent to:

+ +
assert.equal(a == 1, true, "test that a is equal to one");
+ +
Parameters
+ +

guard : expression
+ The expression to evaluate.

+ +

message : string
+ Optional message to log, providing extra information about the test.

+ +

equal(actual, expected, message)

+ +

Tests shallow, coercive equality with ==:

+ +
assert.equal(1, 1, "test that one is one");
+ +
Parameters
+ +

actual : object
+ The actual result.

+ +

expected : object
+ The expected result.

+ +

message : string
+ Optional message to log, providing extra information about the test.

+ +

notEqual(actual, expected, message)

+ +

Tests that two objects are not equal, using !=:

+ +
assert.notEqual(1, 2, "test that one is not two");
+ +
Parameters
+ +

actual : object
+ The actual result.

+ +

expected : object
+ The expected result.

+ +

message : string
+ Optional message to log, providing extra information about the test.

+ +

deepEqual(actual, expected, message)

+ +

Tests that two objects have a deep equality relation. Deep equality is defined in the CommonJS specification for Assert, item 7, which is quoted here:

+ +
+
    +
  1. All identical values are equivalent, as determined by ===.
  2. +
  3. 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.
  4. +
  5. Other pairs that do not both pass typeof value == "object", equivalence is determined by ==.
  6. +
  7. 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.
  8. +
+
+ +
assert.deepEqual({ a: "foo" }, { a: "foo" }, "equivalent objects");
+ +
Parameters
+ +

actual : object
+ The actual result.

+ +

expected : object
+ The expected result.

+ +

message : string
+ Optional message to log, providing extra information about the test.

+ +

notDeepEqual(actual, expected, message)

+ +

Tests that two objects do not have a deep equality relation, using the negation of the test for deep equality:

+ +
assert.notDeepEqual({ a: "foo" }, Object.create({ a: "foo" }),
+                    "object's inherit from different prototypes");
+ +
Parameters
+ +

actual : object
+ The actual result.

+ +

expected : object
+ The expected result.

+ +

message : string
+ Optional message to log, providing extra information about the test.

+ +

strictEqual(actual, expected, message)

+ +

Tests that two objects are equal, using the strict equality operator ===:

+ +
// 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'");
+}
+ +
Parameters
+ +

actual : object
+ The actual result.

+ +

expected : object
+ The expected result.

+ +

message : string
+ Optional message to log, providing extra information about the test.

+ +

notStrictEqual(actual, expected, message)

+ +

Tests that two objects are not equal, using the negation of the strict equality operator ===:

+ +
// 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'");
+}
+ +
Parameters
+ +

actual : object
+ The actual result.

+ +

expected : object
+ The expected result.

+ +

message : string
+ Optional message to log, providing extra information about the test.

+ +

throws(block, error, message)

+ +

Assert that a block of code throws the expected exception.

+ +

This method takes an optional Error argument:

+ + + + +

For example, suppose we define two different custom exceptions:

+ +
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;
+ +

We can check the type of exception by passing a function as the Error argument:

+ +
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");
+}
+ +

We can check the message by passing a regular expression:

+ +
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");
+}
+ +
Parameters
+ +

block : block
+ The block of code to test.

+ +

error : function|RegExp
+ Either a constructor function returning the type of exception expected, or a regular expression expected to match the exception's message property.

+ +

message : string
+ Optional message to log, providing extra information about the test.

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 +--- +
+

实验性的(译者备注:暂不翻译,可能会废弃)

+
+

Add a button to the Firefox user interface. With this module you can create buttons that display icons and can respond to click events.

+

Usage

+


+ Creating buttons

+

To create a button you must give it an ID, an icon, and a label:

+
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");
+    }
+  });
+

By default, the button appears in the Firefox toolbar:

+

However, users can move it to the Firefox menu panel using the toolbar customization feature:

+

+

Badged buttons

+
+

New in Firefox 36.

+
+

You can add a "badge" to a button using its badge 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 badgeColor property, specified as a CSS <color> value:

+
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";
+  }
+}
+

+

Specifying multiple icons

+

You can specify just one icon, or multiple icons in different sizes.

+

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 ActionButton constructor.

+

Responding to click events

+

You can respond to click events by assigning a listener to the button's click event. You can do this in the button's constructor, by assigning the listener to the onClick option. You can also add, or change, the listener afterwards:

+
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");
+}
+

The listener is passed a state object that contains all the button's properties.

+

You can generate click events programmatically with the button's click() method.

+

Disabling buttons

+

You can disable a button by setting its disabled property to true. A disabled button will not generate click events and its icon will appear disabled:

+

+

Updating state

+

You can update all the button's properties except for its id.

+

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.

+

You can set state to be specific to a window or tab using the button's state() method. To set state like this, call state() with 2 parameters:

+ +

Here's an add-on with a button that disables itself when you click it, but only for the currently active window:

+
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
+  });
+}
+

To fetch the state for a specific window or tab, call state(), passing in the window or tab you are interested in, and it will return the state:

+
var labelForActiveTab = button.state("tab").label;
+

To learn more about this, see the API documentation for state().

+

Destroying buttons

+

When you've finished with a button, destroy it by calling its destroy() method. After that, any attempts to access any of its properties or to call any of its methods will throw exceptions.

+

Globals

+

Constructors

+

ActionButton(options)

+

Creates an action button.

+
Parameters
+

options : object
+ Required options:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
idstring +

The button's ID. This is used internally to keep track of this button. The ID must be unique within your add-on.

+
labelstring +

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.

+
iconurl, string, object +

One or more icons for the button. You can specify this in one of three ways: 

+
    +
  • as a resource:// URL pointing at an icon file in your add-on's "data" directory, typically constructed using self.data.url(iconfile)
  • +
  • as a relative path: a string in the form "./iconfile", where "iconfile" is a relative path to the icon file beginning in your add-on's "data" directory
  • +
  • as an object, or dictionary of key-value pairs. Here you can specify a range of sizes for your button's icon. Each key-value pair specifies an icon: +
      +
    • each value specifies an image file as a resource:// URL or relative path.
    • +
    • each key must be a numeric string such as "16", or "32", which represents the size in pixels of the corresponding image.
    • +
    +
  • +
+
+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"
+    }
+  });
+

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 HiDPI display), these are doubled to 36 x 36 and 64 x 64 pixels, respectively. So you can supply three icon files:

+
+icon: {
+  "16": "./addon16.png",
+  "32": "./addon32.png",
+  "64": "./addon64.png"
+}
+

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:

+
+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
+}
+
+
+

Optional options:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameType 
disabledboolean +

Determines whether the button is disabled. Disabled buttons appear disabled in the UI, and do not respond to clicks. Defaults to false.

+
onClickfunction +

Click handler for the button.

+
badgeNumber or String +
+

New in Firefox 36.

+
+

Badge to attach to the button.

+
badgeColorCSS <color> value +
+

New in Firefox 36.

+
+

Color for the badge. If badgeColor is omitted and badge is specified, then the badge is red.

+
+

ActionButton

+

Methods

+

click()

+

Click the button. This will cause the button to generate the click event:

+
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();
+
+

state()

+

Get or set the button's state for a specific window or tab.

+

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 state() is for.

+

To set a button's properties for a specific window or tab, call state(), passing it the window or tab 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.

+

For example, if you have a button like this:

+
var { ActionButton } = require('sdk/ui/button/action');
+
+var button = ActionButton({
+  id: "my-button",
+  label: "default",
+  icon: "./firefox-16.png"
+});
+

You can change its label for only the currently active window like this:

+
button.state("window", {
+  "label" : "window-specific label"
+});
+

You can change its label for only the currently active tab like this:

+
button.state("tab", {
+  "label" : "tab-specific label"
+});
+
+

To fetch the button state for a specific window or tab, call state(), passing it the window or tab you're interested in, and it will return a state object containing all the properties 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:

+ +
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 -> "default label"
+  console.log(button.label);
+
+  // access the window's label -> "default label"
+  console.log(button.state("window").label);
+
+  // access the first tab's label -> "default label"
+  console.log(button.state(tabs[0]).label);
+
+  // access the second tab's label -> "tab-specific label"
+  console.log(button.state(tabs[1]).label);
+}
+

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:

+
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 -> "default label"
+  console.log(button.label);
+
+  // access the window's label -> "window-specific label"
+  console.log(button.state("window").label);
+
+  // access the first tab's label -> "window-specific label"
+  console.log(button.state(tabs[0]).label);
+
+  // access the second tab's label -> "tab-specific label"
+  console.log(button.state(tabs[1]).label);
+}
+

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 state(), 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 label only for tab A, then tab B will inherit label's value from the window, and changing the value for the window will implicitly change the value for tab B.

+

To delete a tab- or window-specific state, assign null to the property. After that, the property will inherit its value from the less-specific state as before:

+
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 -> "default label"
+  console.log(button.label);
+
+  // access the window's label -> "window-specific label"
+  console.log(button.state("window").label);
+
+  // access the first tab's label -> "window-specific label"
+  console.log(button.state(tabs[0]).label);
+
+  // access the second tab's label -> "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 -> "window-specific label"
+  console.log(button.state(tabs[1]).label);
+}
+

Finally, you can pass the button itself into state(). 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:

+
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);
+    }
+  });
+
+
Parameters
+

target : button, tab, window, string

+ +

state : object, null
+ Include this parameter only if you are setting state. It is an object containing all the properties you wish to set. For example:

+
button.state("tab", {
+  "label" : "tab-specific label",
+  "icon": "./tab-specific-icon.ico"
+});
+

To reset state, pass null:

+
button.state("tab", null);
+
Returns
+

state : if you have passed the second state argument to make this function a setter, it returns undefined. 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:

+
console.log(button.state("tab"));
+

This object represents a snapshot of the state at the time state() is called. It is not kept up to date with changes made to the button:

+
button.label = "foo";
+var state = button.state(button);
+button.label = "bar";
+console.log(state.label) // foo
+

on()

+

Add a listener to an event emitted by the button. The button only emits one type of event, click:

+
button.on("click", handleClick)
+
+function handleClick(state) {
+  console.log("button '" + state.label + "' was clicked");
+}
+
Parameters
+

event : string
+ The event to listen for. Action buttons only emit one type of event, "click".

+

listener : function
+ Function that will be called on click.

+

once()

+

Assign a listener to the first occurrence only of an event emitted by the button. The button only emits one type of event, click. The listener is automatically removed after the first time the event is emitted.

+
Parameters
+

event : string
+ The event to listen for. Action buttons only emit one type of event, "click".

+

listener : function
+ Function that will be called on click.

+

removeListener()

+

Removes an event listener. For example, this code is equivalent to once():

+
button.on("click", handleClick)
+
+function handleClick(state) {
+  console.log("button '" + state.label + "' was clicked");
+  button.removeListener("click", handleClick);
+} 
+
Parameters
+

event : string
+ The event to listener is listening for. Action buttons only emit one type of event, "click".

+

listener : function
+ The listener to remove.

+

destroy()

+

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.

+

Properties

+

id

+

The button's unique ID. This is read-only.

+

label

+

The button's label.

+

icon

+

The button's icon or icons, as a URL, relative path, or object containing a set of key-value pairs.

+

disabled

+

Boolean property indicating whether or not the button is disabled.

+

badge

+
+

New in Firefox 36.

+
+

Value to attach to the button as a badge. May be a number or a string.

+

badgeColor

+
+

New in Firefox 36.

+
+

Color for the badge, specified as a CSS <color> value.

+

Events

+

click

+

This event is emitted when a user clicks the button or your add-on calls the button's click() method.

+
Arguments
+

state : The button's state. This contains all the button's properties.

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 +--- +

Articles listed here provide a reference for the SDK's tools:

+ +

{{ LandingPageListSubpages ("/en-US/Add-ons/SDK/Tools", 7) }}

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 +--- +

{{AddonSidebar}}

+ +
+

你能在Firefox 38或更高的版本中使用jpm。

+ +

本文为jpm参考。

+
+ +

cfx 的Node版本允许你测试、运行以及打包扩展。

+ +

你也可以阅读 jpm教程 开始学习。

+ +

jpm 用法:

+ +
jpm [command] [options]
+
+ +

jpm支持以下全局参数:

+ +
-h, --help        - 显示帮助信息并退出
+-V, --version     - 打印出jpm版本号
+--addon-dir       - 源代码目录,默认为当前目录
+
+ +

安装

+ +

jpm发布在node包管理器 npm 上。

+ +

安装npm

+ +

有两种方法来获取npm。

+ + + +

要测试安装是否成功,运行:

+ +
​/usr/bin/env node -v
+ +

如果出现错误提示  /usr/bin/env: node: No such file or directory 并且你的 nodejs 是通过包管理的方式安装的,那你的 nodejs 很有可能安装为其它的名字。为了保证jpm的兼容,PATH之中必须是以node为可执行文件名的。在Debian和Ubuntu系统上,你可以通过安装兼容包nodejs-legacy来解决这个问题:

+ +
sudo apt-get install nodejs-legacy
+ +

在其它的发行版中,你或许必须手动创建一共本地符号链接:​

+ +
sudo ln -s "$(which nodejs)" /usr/local/bin/node
+ +

安装jpm

+ +

在你安装好npm并且将其加入你的PATH中后,你可以像安装其他npm包一样来安装jpm。

+ +

全局安装jpm

+ +
npm install jpm --global
+ +

取决于你的安装,你可能需要管理员权限执行:

+ +
sudo npm install jpm --global
+ +

局部安装jpm

+ +

如果你不想,或者不能够全局安装jpm,你或许可以只为你安装它:

+ +
npm install jpm
+ +

在局部安装的情况下,为了在终端中运行jpm,你必须首先将目录"$HOME/node_modules/.bin/"添加到你的终端PATH中。将下行中的命令添加到$HOME/.profile的末尾来实现永久添加(.profile将在每次运行一个新终端时被执行):

+ +
export PATH="$HOME/node_modules/.bin/:$PATH"
+ +

通过git来安装jpm

+ +

另外,你也可以通过git安装jpm的最新版本

+ +
git clone https://github.com/mozilla-jetpack/jpm.git
+cd jpm
+npm install
+npm link
+
+ +

jpm安装完毕后

+ +

在全部搞定后,在命令行窗口中输入:

+ +
jpm
+ +

屏幕上显示了一系列可用的 jpm 命令。不同于 cfx,当在安装时使用了 --global 参数,你能在任何路径下启动的命令提示符中使用 jpm 命令。

+ +

还有问题?

+ +

如果你看不懂本文,要寻求帮助。SDK 用户和项目团队成员在项目邮件列表中讨论问题和建议。其他人也许会和你有一样的问题,所以试着搜索一下列表。也欢迎你发表一个新问题。你也可以在 Mozilla 的 IRC 网络#jetpack 房间里和其他SDK的用户聊天。

+ +

命令参考

+ +

有六个命令:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
jpm init创建一个基本的 add-on 作为你 add-on 的开端。
jpm run运行一个带有你的 add-on 的 Firefox 实例。
jpm test运行你插件的单元测试
jpm xpi将你的插件打包为 XPI 文件(火狐的插件扩展文件名)
jpm post把你的 add-on 打包成 XPI 文件,然后发送到某一个URL。
jpm watchpost无论是否有文件变更,把你的 add-on 打包成 XPI 文件发送到某一个URL。
jpm sign将你的插件打包为 XPI 文件并且取回一个由Mozilla签名的新XPI文件。
+ +

jpm init

+ +

这个命令从头开始初始化一个新的 add-on。

+ +

新建一个目录,转到该目录下,然后运行 jpm init

+ +
mkdir my-addon
+cd my-addon
+jpm init
+ +

然后你会被要求提供关于你的 add-on 的一些信息:这会用来创建 package.json 文件。

+ + + +

大部分字段都有一个默认值,显示在那些问题的后面的括号里。如果你按了回车,那么你的 add-on 就用那个默认值。

+ +

一旦你提供了一个值或者接受了默认值,你会看到"package.json"的完整内容,并被询问是否接受。

+ +

然后 jpm 创建一个基本的 add-on,作为你开发的起点,文件结构如下:

+ + + +

jpm run

+ +

此命令运行一个新的装有你的 add-on 的 Firefox实例:

+ +
jpm run
+ +

jpm run 有以下选项:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-b --binary BINARY +

指定二进制文件,使用该版本的火狐。可以用全路径,也可以用相对路径。

+ +
+jpm run -b /path/to/Firefox/Nightly
+ 参看选择浏览器版本
--binary-args CMDARGS +

传递附件参数到 Firefox。

+ +

例如,为了传递 -jsconsole参数给 Firefox 并打开浏览器,试试下面命令:

+ +
+jpm run --binary-args -jsconsole
+ +

要传递多个参数,或者参数中间有空格,就把他们用引号括起来:

+ +
+jpm run --binary-args '-url mzl.la -jsconsole'
+
--debug运行这个 add-on 的Add-on 调试器
-o --overload PATH +

不再使用 Firefox 内建的 SDK 模块,使用指定 PATH 路径下的模块。如果加了 -o 但 PATH 没有指定,jpm 会寻找 JETPACK_ROOT 环境变量用作路径

+ +

参看重载内建模块以获取更多信息

+
-p --profile= PROFILE +

在你每次调用jpm run时,jpm 默认使用一个干净的临时的 Firefox 配置文件(profile)。使用--profile 选项以使得 jpm 使用已有的配置文件来打开 Firefox。

+ +

PROFILE的值可以是一个profile的名字或路径。

+ +

参看 使用 profile 以获取更多信息。

+
-v --verbose(查看)详细操作
--no-copy +
小心使用,因为 jpm run|test 会改变很多配置,不要和你的主配置文件一起使用。
+ +
只有使用 --profile 的时候回生效
+ 禁止配置文件的拷贝,允许重用配置。
 
+ +

jpm test

+ +

这个命令用来运行 add-on 的单元测试。命令:

+ + + +
jpm test
+ +

查看 单元测试教程 assert 模块参考文档获取更多具体内容。

+ +

jpm test 接受一下选项:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-b --binary BINARY +

指定所用 Firefox 的版本。BINARY 可被指定为绝对路径或者基于当前路径的相对路径。

+ +
+jpm test -b /path/to/Firefox/Nightly
+ +

请查看选择一个浏览器版本

+
--binary-args CMDARGS +

传递附件参数给 Firefox。

+ +

例如,传递 -jsconsole 参数,它会打开浏览器控制台,试试下面的命令:

+ +
+jpm test --binary-args -jsconsole
+ +

传递多个参数,或者参数间有空格,请将它们用引号括起来:

+ +
+jpm test --binary-args '-url mzl.la -jsconsole'
+
--debug运行 add-on debugger 附件到当前 add-on 上。
-f --filter FILE[:TEST] +

只运行名字和 FILE 匹配的测试文件,且名字匹配 TEST(可选)的测试函数。

+ +
+jpm test --filter base64:btoa
+ +

上面的命令值会运行名字中含有"base64"的文件,在这些文件中只会运行名字中含有"btoa"的测试函数。

+
-o --overload PATH +

不使用 Firefox 内建的模块,而使用 PATH 路径下的模块。如果 -o 指定而 PATH 被忽略,jpm会查找 JETPACK_ROOT 环境变量并将其用作路径。

+ +

查看重载内建模块以获取更多信息。

+
-p --profile PROFILE +

你每次运行jpm call时,默认地,jpm使用一个干净的临时 Firefox 配置文件。使用--profile 选项来让 jpm 使用一个现有配置文件来打开火狐。

+ +

PROFILE 的值可以是配置文件的名称或者指向配置文件的路径。

+ +

查看使用配置文件来获取更多信息。

+
--stop-on-error +

即使测试失败,jpm test 默认还会继续运行测试。指定 --stop-on-error 的话,会在第一次失败后停止运行测试

+ +
+jpm test --stop-on-error
+
--tbplTreeherder 格式打印 test 的输出
--times NUMBER +

运行几遍 test:

+ +
+jpm test --times 2
+
-v --verbose详细操作。
--no-copy +

小心使用,因为 jpm run|test 会修改许多首选项,这些首选项在你的主配置文件中从未用过。

+ +

这仅仅在使用 --profile 时生效。

+ 禁用配置未经的拷贝,允许用户重用配置文件。
+ +

jpm xpi

+ +

这个命令将 add-on 打包为一个 XPI 文件,这是 Mozilla 附加组件的安装文件的格式。

+ +
jpm xpi
+ +

它会在当前目录(或者 --addon-dir 指定的目录)查找 package.json 文件,并创建相关的 XPI 文件。它忽略任何 ZIP 或 XPI文件(译者注:OSX 上测试下来不会默认忽略这些文件,若要忽略请编辑.jpmignore文件),以及任何测试文件。它会包含其他所有文件。如果你想排除其他文件,查看 .jpmignore 文件

+ +

一旦你构建了一个 XPI 文件,你可以通过提交到 addons.mozilla.org 来分发你的附加组件。

+ +

jpm xpi 接受下列选项:

+ + + + + + + + +
-v --verbose +

打印详细操作:

+ +
+jpm xpi -v
+
+ +

jpm post

+ +

这个命令把附加组件打包为 XPI 后 post 到某个URL。

+ +
jpm post
+ +

查找当前目录(或 --addon-dir)下的package.json 文件,创建 XPI 文件,post 到 --post-url

+ +

jpm post 接受以下选项:

+ + + + + + + + + + + + +
--post-url URL +

创建 XPI 文件后,将扩展 post 到这个URL。

+ +
+jpm post --post-url http://localhost:8888/
+ +

查看使用 Post 和 Watchpost 获取更多信息。

+
-v --verbose +

打印详细操作:

+ +
+jpm post --post-url http://localhost:8888/ -v
+
+ +

jpm watchpost

+ +

这个命令在打包附件组件为 XPI 文件后,无论文件是否改变都将其 post 到某个URL。

+ +
jpm watchpost
+ +

无论文件是否改变,在当前目录(或 --addon-dir)下创建一个 XPI并将其post到 --post-url

+ +

jpm watchpost 接受以下选项:

+ + + + + + + + + + + + +
--post-url URL +

创建 XPI 文件后,将扩展 post 到这个URL。

+ +
+jpm watchpost --post-url http://localhost:8888/
+ +

查看 Using Post 和 Watchpost 获取更多信息。

+
-v --verbose +

打印详细信息:

+ +
+jpm watchpost --post-url http://localhost:8888/ -v
+
+ +

jpm sign

+ +

此特性仅从 jpm 1.0.4 起被支持。

+ +

此命令为你的附加组件重新生成一个新的被Mozilla签名的 XPI 文件。这就允许你自己托管你的 add-on,这样用户可以在安装时避免 signed add-ons are required 错误。在用这个命令之前,你需要在 addons.mozilla.org 创建 API 证书

+ +

你可以为你已经生成的 XPI 文件签名,就像如下,通过传递 XPI 文件给 --xpi参数:

+ +
jpm sign --api-key ${AMO_API_KEY} --api-secret ${AMO_API_SECRET} --xpi <xpi file>
+ +

或者,你可以省略 --xpi 参数,这样 jpm sign 会从当前目录(或者 --addon-dir)生成一个XPI文件。

+ +
jpm sign --api-key ${AMO_API_KEY} --api-secret ${AMO_API_SECRET}
+ +

上面提交了一个 XPIaddons.mozilla.org 签名g API,如果通过验证,然后下载一个签名后的 XPI 文件到工作目录。

+ +

下面是一些运行 sign 命令的结果:

+ + + +

在底层,jpm signaddons.mozilla.org里创建了一个不会被列出的附加组件,这就意味着你必须自己把XPI文件分发给你的用户来安装。如果你需要创建一个在列表中的附加组件,只要直接将它提交到 addons.mozilla.org,在那里它自动会被签名。如果你在安装一个已签名的附加组件时遇到困难,参看调试一节。

+ +

jpm sign 接收以下参数:

+ + + + + + + + + + + + + + + + + + + + +
--api-key=API_KEY +

addons.mozilla.org key管理页面生成的API访问key(字符串)。

+
--api-secret=API_SECRET +

addons.mozilla.org key 管理页面生成的API访问密钥(字符串)。这个值应该被小心保密并且永远不要记录到版本控制中。如果你的密钥被破解,另一个开发者就能上传附加组件到你的账号上。你应该立即撤销泄露的API证书并且重新生成一份。

+
--api-url-prefix=http://.../api +

可选的API URL前缀,如果你想使用一个试用签名的API。

+ +

例如,你可以通过https://addons-dev.allizom.org/api/v3的认证来使用addons.mozilla.org的开发者版本。

+
--xpi=/path/to/file.xpi +

需要签名的XPI文件。如果没指定文件,一个新的XPI会在当前目录(或者--addon-dir)中生成。

+
+ +

一些技巧

+ +

选择浏览器版本

+ +

默认地,jpm runjpm test 运行 release 版本的 FireFox。你可以有一两种办法来告诉 jpm 使用一个不同的版本:

+ + + +

使用 .jpmignore 来忽略文件

+ +

使用 .jpmignore 就像使用 git.gitignore,Mercurial 的 .hgignore,或者 npm 的 .npmignore。通过使用这个文件,你可以在使用 jpm xpi 编译 .xpi 文件时,让 jpm 知道你想要忽略哪些文件。

+ +

这是个例子:

+ +
# Ignore .DS_Store files created by mac
+.DS_Store
+
+# Ignore any zip or xpi files
+*.zip
+*.xpi
+ +

有着以上内容的 .jpmignore 文件会忽略所有的 zip 文件和 .DS_Store 文件,这些文件不会包括在 jpm xpi 所生成的 xpi 文件中。

+ +

使用配置

+ +

默认地,jpm run 每次都会使用一个新的配置。这就意味着前一次运行 jpm 时的任何配置,默认都不会在下一次中使用。

+ +

这其中包括,比如你安装的任何附加组件,或者你的历史记录,或者任何使用 simple-storage API 存储的数据。

+ +

为了让 jpm 使用一个特定的配置,传递 --profile 选项,设定你想使用的配置文件的名字,或者是配置文件的路径。

+ +
jpm run --profile boogaloo
+ +
jpm run --profile path/to/boogaloo
+ +

如果你提供了 --profile 但是它的参数不是一个已有配置文件的名字或路径,jpm 会打开 配置文件管理器 让你选择一个已有的配置文件或者创建一个新的配置文件:

+ +
jpm run --profile i-dont-exist
+ +

开发时不用重启浏览器

+ +

因为每次调用 jpm run 时都会重启浏览,如果你十分频繁地修改附加组件,这就可能有点笨重了。一个替代的开发模型是使用 扩展自动安装器附加组件:它会在特定端口监听新 XPI 文件并且自动安装它们。这样,你就能测试新的改动,而不用重启浏览器:

+ + + +

你甚至可以用一个简单的脚本来自动化这一工作流程。例如:

+ +
jpm watchpost --post-url http://localhost:8888/
+ +

注意,比起使用 jpm run 运行附加组件时的日志级别,你在使用这个方法时控制台定义的日志级别是不一样的。这意味着,如果你想看到 console.log() 消息的输出,你必须微调一下配置。查看 logging levels 文档以获取这方面的详细信息。

+ +

重载内建模块

+ +

你用来实现你的附加组件的SDK模快是 Firefox 内建的。当你使用 jpm runjpm xpi 来运行或者打包附加组件时,附加组件使用其所在的 Firefox 版本中的模块版本。

+ +

作为附件组件开发者,这一般就是你想要的。但是如果你在开发 SDK 模块本身,这就不合适了。这时你需要:

+ + + +
jpm run -o
+ +

这会通知 jpm 去使用 SDK 模块的本地拷贝,而不是 Firefox 内部的模块。如果你不想设置 JETPACK_ROOT 环境变量,你可以使用 -o 传递SDK模块本地拷贝的位置:

+ +
jpm run -o "/path/to/addon-sdk/"
+ +

路径必须是一个绝对路径并且指向 SDK 的根目录(不是 addon-sdk/sdk 或 addon-sdk/sdk/lib)。

+ +

支持自托管附加组件的更新

+ +

此特性仅被 jpm 1.0.3 及之后版本支持,

+ +

当你给你的附加组件来添加特性或者修复 bug 时,你想让之前安装好的附加组件将自己从老版本更新到新版本。

+ +

如果你在 addons.mozilla.org 上列出你的附加组件,那么你要做的只是提交一个新的版本;附加组件默认会检查它们在 addons.mozilla.org 上的新版本。好了,你不用继续往下看这一节了。

+ +

如果你没有在 addons.mozilla.org 上列出你的附加组件,你需要生成一个 Mozilla 签名的 XPI 文件并告诉 Firefox 哪里可以找到这个附加组件的新版本。方法就是:

+ + + +

为了达到这个目的,package.json中需要包含两个额外的key :

+ + + +

+ +

如果你设置了 updateURLupdateLink(如果 updateKey 不是 HTTPS 的,那也要包括 updateKey),那么 jpm xpi 会:

+ + + +

然后你将更新清单托管到 updateURL,并且将新版 XPI 托管到 updateLink

+ +

获取更多这方面的详细信息,参看自动检查附件组件更新

+ +
 
+ +
 
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 +--- +

{{AddonSidebar}}

+ +

The package.json 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.

+ +

一些条目, 比如icon, namedescription, 有类似install manifest的格式, 并且package.json会写入install manifest, 当使用jpm xpi的时候.

+ +

Others, such as lib, permissions, and preferences, represent instructions to the jpm tool itself to generate and include particular code and data structures in your add-on.

+ +

其他如lib, permissionspreferences表示使用jpm工具的步骤, 生成你扩展包含的特殊代码和数据结构.

+ +

创建manifest

+ +

package.json起初是通过运行jpm init生成的,通常在扩展的根目录.比如下面(假设扩展目录是"my-addon")

+ +
{
+  "name": "my-addon",
+  "title": "my-addon",
+  "id": "jid1-1FERGV45e4f4f",
+  "description": "a basic add-on",
+  "author": "",
+  "license": "MPL-2.0",
+  "version": "0.1"
+}
+ +

如果你使用新的jpm tool话,可以方便的从package.json获取manifest数据, 通过require其他模块的方式:

+ +
var title = require("./package.json").title;
+ +

Key reference

+ +

package.json may contain the following keys:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
author +

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.

+ +

This value will be used as the add-on's em:creator element in the install.rdf file generated by cfx.

+ +
Note: jpm supports NodeJS people fields.
+
contributors +

An array of additional author strings, identifying other contributors to the add-on.

+ +

These values will be used as the add-on's em:contributor elements in its install.rdf.

+ +
Note: This is deprecated along with cfx; it's not available when using jpm.
+
dependencies +

A string or an array of strings specifying the names of packages that this add-on requires in order to function properly.

+
description +

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".

+ +

This value will be used as the add-on's em:description element in its install.rdf.

+
engines +

Object with supported applications (key) and required version numbers (value).

+ +
    +
  • firefox: Firefox Desktop
  • +
  • fennec: Firefox for Android
  • +
+ +

Example:

+ +
+  "engines": {
+    "firefox": ">=38.0a1",
+    "fennec": ">=38.0a1"
+  }
+
fullName {{deprecated_inline}} +
Note: This is deprecated along with cfx; it's not available when using jpm.
+ +

The full name of the package. It can contain spaces.

+ +

If this key is present its value will be used as the add-on's em:name element in its install.rdf.

+
harnessClassID {{deprecated_inline}} +
Note: This is deprecated along with cfx; it's not available when using jpm.
+ +

String in the GUID format.

+ +

This is used as a classID of the "harness service" XPCOM component. Defaults to a random GUID generated by cfx.

+
homepage +

The URL of the add-on's website.

+ +

This value will be used as the add-on's em:homepageURL element in its install.rdf.

+
icon +

The path to an image file containing the icon for the add-on. Defaults to icon.png. If no icon is specified, the standard add-on icon will be used by default.

+ +
+

When using jpm, 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:

+ +

resource://ID/data/icon-name.png

+ +

ID is the value from the id field. If it does not begin with the @-character, then @ has to be escaped as -at- and . as -dot-. If the ID is a GUID, the curly braces used in the id field are not included.

+
+ +

This value will be used as the add-on's em:iconURL element in its install.rdf.

+ +

The icon may be up to 48x48 pixels in size (although a bigger icon is tolerated here too)

+
icon64 {{deprecated_inline}} +
+

Note: This is deprecated along with cfx; it's not available when using jpm.

+
+ +

The path to an image containing the large icon for the add-on. Defaults to icon64.png. If you don't provide an icon here, the same icon as specified by icon will be used.

+ +

This value will be used as the add-on's em:icon64URL element in its install.rdf.

+ +

The icon may be up to 64x64 pixels in size.

+
id +

A globally unique identifier for the add-on.

+ +

This value will be used as the add-on's em:id element in its install.rdf.

+ +

See the Program ID documentation.

+
lib +

String representing the top-level module directory provided in this add-on. Defaults to "lib".

+ +
+

Note: This is deprecated along with cfx and is not available when using jpm.

+
+
license +

The name of the license under which the add-on is distributed, with an optional URL in parentheses. Defaults to "MPL-2.0".

+ +
+

Note: It is recommend that you use an SPDX license ID.

+
+
main +

A string representing the name of a program module that is located in one of the top-level module directories specified by lib. Defaults to "main".

+
name +

The add-on's name. This name cannot contain spaces or periods, and defaults to the name of the parent directory.

+ +

When the add-on is built as an XPI, if the fullName and title keys are not present, name is used as the add-on's em:name element in its install.rdf.

+
packages +
+

Note: This is deprecated along with cfx and is not available when using jpm.

+
+ +

A string pointing to a directory containing additional packages. Defaults to "packages".

+
permissions +

A set of permissions that the add-on needs.

+ +

private-browsing: a boolean indicating whether or not the add-on supports private browsing. If this value is not true 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 private-browsing module.

+ +

cross-domain-content: 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 enabling cross-domain content scripts.

+ +

multiprocess: a Boolean value declaring whether this add-on is, or is not, compatible with multiprocess Firefox.

+ +
+

Note the multiprocess permission is not supported by cfx.

+
+
preferences +

An array of JSON objects that use the following keys: name,type, value, title, and description. These JSON objects will be used to create a preferences interface for the add-on in the Add-ons Manager.

+ +

See the documentation for the simple-prefs module.

+
preferences-branchUse this to specify an alternative branch for your add-on's simple-prefs. See "Simple-prefs in the preferences system" for more details.
title +

The human-readable title of the package; this can contain spaces.

+ +

If this key is present its value will be used as the add-on's em:name element in its install.rdf.

+
translators +

An array of strings listing the people who contributed to the localization of this add-on.

+ +

These values will be used as the add-on's em:translator elements in its install.rdf.

+ +
Note: jpm supports NodeJS people fields.
+
unpack +

Same as the unpack in an install.rdf file.

+ +

Useful when the extension contains binaries.

+
updateKey +

Same as the updateKey in an install.rdf file.

+ +

See Supporting updates for self-hosted add-ons.

+ +
+

Note: This key is only available with jpm.

+
+
+

Same as the updateLink for an update.rdf file. Previously was --update-link in cfx.

+ +

See Supporting updates for self-hosted add-ons.

+ +
+

Note: This key is only available with jpm.

+
+
updateURL +

Same as the updateURL for an install.rdf file.

+ +

See Supporting updates for self-hosted add-ons.

+ +
+

Note: This key is only available with jpm.

+
+
version +

String representing the version of the add-on. Defaults to "0.0.1".

+ +

This value is used as the add-on's em:version element in its install.rdf.

+ +
+

Note: For jpm the version must be a valid semver.

+
+
+ +

 

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 +--- +
+

学习本模块你需要 安装SDK 学习基础工具cfx.

+
+
+

如果你使用 jpm 替代cfx, 使用第三方模块的方式是不同的, 你应该阅读 jpm的相应版本替代本教程.

+

给予Python可能未来废弃,使用JPM基于nodejs(译者备注).

+
+

SDK还不能为火狐浏览器提供一个API添加新的菜单项。但它是可扩展的设计,所以任何人都可以建立和发布模块,使用插件开发者。幸运的是埃里克沃尔德写的MenuItems模块,能够使我们添加菜单项

+

本教程有双重的责任。它描述的一般方法,使用一个外部的在你的插件的第三方模块描述了如何使用特别的MenuItems模块添加一个菜单项

+

首先,创建一个新的扩展程序。创建一个目录名称为clickme(名称随意)找到它并运行cfx init初始化

+
mkdir clickme
+cd clickme
+cfx init
+
+

通常将创建目录结构:

+ +
+  
+

安装 menuitems

+

在 "clickme"下创建一个名称为"packages"的目录. 从 https://github.com/mykmelez/menuitems-jplib  下载 menuitems 并展开到刚才创建的"packages" 目录下:

+
mkdir packages
+cd packages
+tar -xf ../erikvold-menuitems-jplib-d80630c.zip
+
+

模块依赖

+

如果第三方模块取决于SDK模块可以马上使用它们但如果他们依赖于其他第三方模块你需要安装依赖以及

+

在软件包的主目录,你会发现一个叫做 "package.json"的文件.  打开它,看看一个名称"dependencies"的入口.  menuitems 包的入口:

+
"dependencies": ["vold-utils"]
+
+

这告诉我们需要安装 vold-utils 包, 我们可以从https://github.com/mykmelez/vold-utils-jplib 下载,并添加到 packages 目录下的旁边的menuitems.

+

使用menuitems

+

 Menuitems模块文档 告诉使用MenuItem()创建一个新的菜单项. MenuItem()可接受的附加选项, 我们将使用最迷你的配置:

+ +
+
+
var menuitem = require("menuitems").Menuitem({
+  id: "clickme",
+  menuid: "menu_ToolsPopup",
+  label: "Click Me!",
+  onCommand: function() {
+    console.log("clicked");
+  },
+  insertbefore: "menu_pageInfo"
+});
+
+  
+
+
+

接下来, 我们将声明menuitems的依赖包. 在你的add-on's package.json文件添加一行:

+
"dependencies": "menuitems"
+
+

Note that due to bug 663480, if you add a dependencies line to package.json, and you use any modules from the SDK, then you must also declare your dependency on that built-in package, like this:

+
"dependencies": ["menuitems", "addon-sdk"]
+
+

现在我们要做的。运行插件你会看到新的项目出现在工具菜单:选择它,你会看到info: clicked 出现在控制台

+

Caveats

+

第三方模块使用不直接支持的SDK功能的好方法,但由于第三方模块通常使用低级别的API它们可以通过Firefox的新版本

+

 

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 +--- +
+

动手之前,必须先安装SDK并学习cfx基础.

+ +

这篇教程使用动作按钮API,需要Firefox 29或更新版本。

+
+ +

如果要给工具栏添加一个按钮,需要使用动作按钮切换按钮模块。

+ +

新建一个目录,打开它,执行cfx init

+ +

然后,把这三个图标保存到data文件夹:

+ + + + + + + + + + + + + + + + +
icon-16.png
icon-32.png
icon-64.png
+ +

随后打开lib目录下的main.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/");
+}
+ +

现在输入cfx run来执行附加组件。按钮添加到了浏览器顶部的工具栏上:

+ +

你无法设置按钮的初始位置,但是用回可以使用浏览器的自定义功能移动它。其中的id属性是必需的,用来记录按钮的位置,因此,你最好不要在后续版本中修改它。

+ +

单击按钮,https://www.mozilla.org/将会在新的标签页中加载。

+ +

设定图标

+ +

icon属性可以设定单个或是一组不同大小图标。如果你用的是一组不同大小的图标,浏览器将会自动选择最适合当前屏幕分辨率的,然后显示在浏览器界面的按钮上。更多内容,参考设定多个图标

+ +

图标文件必须打包在附加组件内:它不可以指向一个远程文件。

+ +

你只要正确地设置了按钮的icon属性,它就会立刻生效。你可以改变全局的,在特定窗口的或者是特定标签页中显示的图标或者是其他状态属性。更多内容,参考更新状态

+ +

附加一个面板

+ +

如果你想把一个面板附加到按钮上,使用切换按钮API。这就和动作按钮API类似,只不过多了一个boolean值属性,表示按钮是否被checked。附加面板,要把按钮传递给面板的show()方法。更多细节,参考切换按钮文档

+ +

显示更多样的内容

+ +

添加按钮做不到的复杂界面功能,需要使用工具栏API。 使用工具栏API你可以得到一个用户界面内容的水平条。可以添加按钮或者是可以包含HTML,CSS,javaScript的frame到工具栏上。

+ +

进一步学习

+ + 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 +--- +

我们想要控件做两件事:

+ + + +

因为控件无法区分鼠标左右键的点击,我们应当使用内容脚本来捕获单击事件并发送相应的消息到附加组件。

+ +

控件将有两个图标:一个在注释器启用时显示,一个在禁用时显示。

+ +

因此,我们需要创建三个文件:控件的内容脚本和两个图标。

+ +

在data子目录创建一个widget子目录,我们将把控件的文件保存在这里(注意,这个不是强制性的:你可以仅仅把它们放在data里,但分类放置会更加整洁)。

+ +

控件的内容脚本

+ +

控件的内容脚本仅仅监听鼠标的左右单击并发送相应的消息到附加组件代码:

+ +
this.addEventListener('click', function(event) {
+  if(event.button == 0 && event.shiftKey == false)
+    self.port.emit('left-click');
+
+  if(event.button == 2 || (event.button == 0 && event.shiftKey == true))
+    self.port.emit('right-click');
+    event.preventDefault();
+}, true);
+ +

把它保存在data/widget并命名为widget.js。

+ +

控件图标

+ +

你可以从这里复制图标:

+ +

+ +

或者自己动手做你觉得有创造性的图标。把它们保存在data/widget目录。

+ +

main.js

+ +

现在在lib目录创建main.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');
+  });
+}
+ +

注释器默认禁用。它创建控件并通过切换注释器的活动状态来回应来自控件内容脚本的消息。注意,由于bug 626326,附加组件状态栏的环境菜单会显示,尽管在控件的内容脚本中调用了event.preventDefault()。由于我们没有任何代码来显示注释,所以我们们仅仅记录右击事件到控制台。

+ +

现在在注释器目录输入cfx run,你应该看见在附加组件状态栏的控件:

+ +

+ +

左击和右击应当产生合适的调试输出,同时左击应当改变控件的图标为启用状态。

+ +

 

+ +

下一步,我们将添加代码来创建注释器

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 +--- +
+

请注意教程中Widget API适合的浏览器版本。(译者注)

+
+ +

在这个教程中,我们将构建一个使用许多SDK高级API的附加组件.

+ +

这个附加组件是一个注释器:它可以让用户选择网页的元素并输入有关的笔记(注释).注释器储存笔记.无论用户何时载入包含被注释元素的页面,这些元素都将会高亮显示,并且用户若把鼠标移动到被注释元素的上面,将会显示它的注释.

+ +

接着我们将给出这个注释器设计的快速简介,然后一步步的讨论如何实现.

+ +

如果你想参阅完整的附加组件,你可以在SDK例子目录找到它.

+ + 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 +--- +

注释器使用内容脚本(content scripts)来构建用户界面,得到用户输入,并检查用户载入页面的DOM。

+ +

同时,主要模块包括程序逻辑和调节不同SDK对象的交互。

+ +

我们可以描述在主要模块和不同内容脚本的交互,像这样:

+ +

+ +

用户界面

+ +

注释器的主要用户界面由一个控件和三个面板组成。

+ + + +

除此之外,我们使用 notifications 模块来告知用户附加组件的储存限额已满。

+ +

用DOM工作

+ +

我们将使用 page-mods 来和用户打开的网页的DOM进行交互。

+ + + +

处理数据

+ +

我们将使用simple-storage模块来储存数据。

+ +

由于我们将记录潜在的敏感信息,我们想阻止用户在隐私浏览模式下创建注释,最简单的方式是删除附加组件中“package.json“文件的”private-browsing"键。这样,附加组件就不能看见任何隐私浏览窗口,同时注释器的控件也将不再出现。

+ +

开始行动

+ +

现在让我们来创建叫“注释器”的目录。Navigate to it and type cfx init.

+ +

下一步,我们将实现控件

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 +--- +
+

动手之前,必须先安装SDK并学习cfx基础知识.

+

T这篇教程使用动作按钮API需要Firefox 29或更新版本。

+
+

可以使用面板(panel)模块来显示弹出对话框。面板的内容通过HTML编写。你可以在面板上运行content script:尽管在面板里的脚本无法直接访问插件代码,但是你可以在面板脚本和插件代码间交换信息。

+

这里,我们做了一个会在单击时显示面板的动作按钮。面板上有一个<textarea>元素:用户按下return键时,<textarea>的内容会被发送给插件代码主程序。插件代码主程序会在控制台输出日志。.

+

The add-o插件由六个文件组成n consists of six files:

+ +

"main.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();
+}
+
+// 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");
+});
+
+// 监听来自content脚本的text-entered消息。消息主体L是用户输入的文本。
+// 此实现,我们只在控制台显示日志。
+text_entry.port.on("text-entered", function (text) {
+  console.log(text);
+  text_entry.hide();
+});
+

content脚本"get-text.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();
+});
+
+  
+
+

最后,"text-entry.html"文件定义了<textarea>元素:

+
+
+
<html>
+<head>
+    <style type="text/css" media="all">
+      textarea {
+        margin: 10px;
+      }
+      body {
+        background-color: gray;
+      }
+    </style>
+  </head>
+<body>
+    <textarea rows="13" cols="33" id="edit-box"></textarea>
+  </body>
+</html>
+
+  
+
+
+

最后,把这三个图标文件保存在"data"目录:

+ + + + + + + + + + + + + + + +
icon-16.png
icon-32.png
icon-64.png
+

试用以下:保存在lib目录,其他五个文件存放在插件的data目录:

+
my-addon/
+         data/
+              get-text.js
+              icon-16.png
+              icon-32.png
+              icon-64.png
+              text-entry.html
+         lib/
+             main.js
+
+

运行插件,点击按钮,你就会看见一个面板。输入几行文本,然后按下回车,你就会看见控制台里的输出。

+

自Firefox 30起,如果你使用切换按钮,就可以给它附加一个面板

+

进一步学习

+

学习panel模块的更多内容,见panel API参考

+

学习关于按钮的更多内容,见动作按钮切换按钮API参考。

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 +--- +

{{AddonSidebar}}

+ +
+

Add-on SDK 里包含了一个命令行工具,你可以用此工具来初始化、运行、测试以及打包 add on。 这个工具称为 jpm,基于 Node.js 。它替代了以前的cfx工具。

+ +

你可以在 Firefox 38或之后的版本中使用。

+ +

本文阐述如何使用 jpm 开发。

+
+ +

本教程会过一遍使用 SDK 创建一个简单 add-on 的过程。

+ +

准备

+ +

要使用 SDK 创建 add-on,你需要:

+ + + +

初始化空的 add-on

+ +

在命令行提示符下,创建一个新目录。进入新文件夹,键入 jpm init,然后敲回车

+ +
mkdir my-addon
+cd my-addon
+jpm init
+
+ +

接着你会被要求提供一些关于你的 add-on 的信息:这会用来创建 package.json 文件。如果光按回车的话,就表示接受属性的默认值。关于 jpm init 的更多信息,参看 jpm command reference.

+ +

一旦你设置了这些属性的值或者接受默认值,你会看到 "package.json" 的完整内容并被询问是否接受这些设置。

+ +

实现 add-on

+ +

现在你可以写 add-on 的代码了。除非你修改了"entry point"的值(package.json 中的 "main"),一般情况将从你的 add-on 的根目录下的"index.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/");
+}
+
+ +
+

注意在jpm中"entry point"的默认值为"index.js",意思是你的主文件是"index.js",且在你的 add-on的根目录下。

+ +

cfx中,入口默认是"main.js",并且在"lib"目录下

+
+ +

保存文件

+ +

接下来,在根目录下创建目录"data"

+ +
mkdir data
+
+ +

并保存这三个图标文件到"data"目录:

+ + + + + + + + + + + + + + + + +
icon-16.png
icon-32.png
icon-64.png
+ +

返回命令行,键入:

+ +
jpm run
+ +

这个 jpm 命令会运行一个带有你的 add-on 的 Firefox 的新实例。

+ +

如果找不到 Firefox,你可能要为它提供一个路径(如在Ubuntu中):

+ + +
jpm run -b /usr/bin/firefox
+ +

Firefox 启动以后,在浏览器右上角你能看到一个 Firefox logo 的图标。点击该图标,就会打开一个新标签页 http://www.mozilla.org/

+ +

这就是这个 add-on 的全部功能了。它用到了 SDK 的两个模块:action button 模块,使你能加个按钮到浏览器上,以及 tabs 模块,使你能完成对标签页的基本操作。本例中,我们以及创建了一个图标是Firefox图标的按钮,并添加一个点击处理程序,可以在新标签页中打开 Mozilla 页面。

+ +

试着编辑这个文件。例如,我们可以改变加载的页面:

+ +
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/");
+}
+ +

在命令行提示符下,再次执行 jpm run。这次点击按钮,它会带你到 https://developer.mozilla.org/ 页面。

+ +

打包 add-on

+ +

当你完成了 add-on 并准备发布它,你会需要把它打包为 XPI 文件。你能自己分发 XPI 文件,也可以把它们发布到 https://addons.mozilla.org,这样其他用户就能下载并按照它们。

+ +

要构建 XPI,只要在 add-on 的根目录下运行命令 jpm xpi

+ +
jpm xpi
+
+ +

你应该看到像这样的信息:

+ +
JPM info Successfully created xpi at /path/to/my-addon/@my-addon-0.0.1.xpi
+
+ +

要测试附加组件是否能正常运行,可以尝试在你自己的火狐中安装 XPI 文件。你可以在 Firefox 中按 Ctrl+O 组合键(Mac 中是 Cmd+O),或者选择"文件"菜单里的“打开”。这样会弹出一个文件选择对话框:转到"@my-addon.xpi"文件,打开并按照提示安装 add-on。

+ +

注意 Firefox 默认需要 add-on 有签名,即使是本地开发的 add-on。安装完后他们会在已安装的 add-on 列表中出现,只因没有签名而被禁用。开发的时候,又或者你不准备发布,你可以打开 about:config 设置 xpinstall.signatures.requiredfalse 来运行未经签名的组件。这个设置会应用到所有的 add-on,所以要十分小心,不要一不当心从别的地方安装了恶意组件。

+ +

要发布你的 add-on,请提交 XPI 文件到 addons.mozilla.org 或者如果你想在你自己的服务器上发布,运行 jpm sign

+ +

总结

+ +

本教程中我们使用了下面三个命令来构建和打包 add-on :

+ + + +

这是你在开发SDK add-on会用到的三个主要命令。完全的参考文档包含了所以你能使用的命令,以及这些命令的可选项。

+ +

这次开发的add-on 的代码用到了两个 SDK 模块,action buttontabs。这儿有参考文档,描述 SDK 中所有高层次低层次的 API。

+ +

下一步?

+ +

要了解你能用 SDK API 做些什么,试着继续阅读教程

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) +--- +
+

该附加SDK包含一个用于初始化,运行,测试和打包加载项的命令行工具。当前工具称为jpm,并且基于  Node.js .它替代了旧的cfx工具。

+ +

Firefox 38 以上的版本才可以使用jpm。

+ +

本文介绍如何使用jpm开发。

+
+ +

本教程将介绍使用SDK创建一个简单的附加组件。

+ +

先决条件

+ +

要使用SDK为Firefox创建附加组件,您需要:

+ + + +

初始化一个空的附加组件

+ +

在命令提示符下,创建一个新目录。导航到它,键入 jpm init, 然后按Enter键

+ +
mkdir my-addon
+cd my-addon
+jpm init
+
+ +

You'll then be asked to supply some information about your add-on: this will be used to create your add-on's package.json file. For now, just press Enter to accept the default for each property. For more information on jpm init, see the jpm command reference.

+ +

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.

+ +

实现附加组件

+ +

Now you can write the add-on's code. Unless you've changed the value of "entry point" ("main" 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:

+ +
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/");
+}
+
+ +
+

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.

+ +

In cfx, the entry point defaults to "main.js", and is located in the "lib" directory under the add-on's root.

+
+ +

Save the file.

+ +

Next, create a directory called "data" in your add-on's root, and save these three icon files to the "data" directory:

+ + + + + + + + + + + + + + + + +
icon-16.png
icon-32.png
icon-64.png
+ +

Back at the command prompt, type:

+ +
jpm run
+ +

This is the jpm command to run a new instance of Firefox with your add-on installed.

+ +

If Firefox can not be located, you may need to provide the path to it (example in Ubuntu):

+ + +
jpm run -b /usr/bin/firefox
+ +

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 http://www.mozilla.org/ loaded into it.

+ +

That's all this add-on does. It uses two SDK modules: the action button module, which enables you to add buttons to the browser, and the tabs 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.

+ +

Try editing this file. For example, we could change the page that gets loaded:

+ +
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/");
+}
+ +

At the command prompt, execute jpm run again. This time clicking it takes you to https://developer.mozilla.org/.

+ +

Packaging the add-on

+ +

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 https://addons.mozilla.org so other users can download and install them.

+ +

To build an XPI, just execute the command jpm xpi from the add-on's directory:

+ +
jpm xpi
+
+ +

You should see a message like:

+ +
JPM info Successfully created xpi at /path/to/getting-started/@getting-started.xpi
+
+ +

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.

+ +

Summary

+ +

In this tutorial we've built and packaged an add-on using three commands:

+ + + +

These are the three main commands you'll use when developing SDK add-ons. There's comprehensive reference documentation covering all the commands you can use and all the options they take.

+ +

The add-on code itself uses two SDK modules, action button and tabs. There's reference documentation for all the high-level and low-level APIs in the SDK.

+ +

What's next?

+ +

To get a feel for some of the things you can do with the SDK APIs, try working through some of the tutorials.

+ +

 

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 +--- +

{{LegacyAddonsNotice}}{{AddonSidebar}}

+ +

本文列出了许多关于如何通过SDK完成特定任务要求的实际动手的文章。

+ +
+

开发之旅

+ +
+
+
+
安装
+
在Windows, OS X和Linux上下载,安装,初始化SDK工具。
+
+ +
+
常见问题
+
解决常见问题的建议和获取更多帮助。
+
+
+ +
+
+
快速开始
+
走马观花地使用SDK开发一个简单的扩展
+
+
+
+ +
+

创建用户交互界面

+ +
+
+
+
添加一个工具按钮
+
添加一个按钮到火狐Add-on工具栏。
+
添加一个菜单选项到火狐
+
添加多个菜单选项到火狐主菜单。
+
+
+ +
+
+
显示一个弹出对话框
+
通过HTML和JavaScript实现并显示一个弹窗对话框。
+
添加一个上下文菜单
+
添加一个上下文菜单(一般都是右键菜单)到火狐浏览器
+
+
+
+ +
+

与浏览器交互

+ +
+
+
+
打开Web页面
+
在一个新的浏览器选项卡里打开一个Web页面或窗口使用tabs模块并获取内容。
+
监听页面加载
+
当新页面载入时使用tabs模块得到通知并获取页面内容。
+
+
+ +
+
+
获取打开的选项卡(Tab)列表
+
使用tabs模块遍历当前打开的tab,并获取其内容。
+
+
+
+ +
+

更改网页

+ +
+
+
+
更改网页通过URL
+
基于URL过滤网页:当载入的页面的URL与过滤器匹配时执行特定的脚本。
+
+
+ +
+
+
修改页面内容
+
动态加载脚本到当前页面。
+
+
+
+ +
+

开发技术

+ +
+
+
+
日志
+
在终端中记录日志以便调试。
+
创建可复用的模块
+
拆分扩展程序为多个分离的模块,可以使开发调试和维护更加简单。封装你的模块使其成为可复用的包,以便其他开发者可以再次使用。
+
单元测试
+
使用SDK的测试框架书写和进行单元测试。
+
Chrome授权
+
获得Components对象,使你的扩展程序能够加载和使用任何XPCOM对象。
+
创建事件目标
+
使你定义的对象能够响应相关事件。
+
+
+ +
+
+
监听载入和卸载
+
当你的扩展程序被加载和卸载时获得通知,并从终端传递参数给扩展程序。
+
使用第三方模块
+
安装和使用与SDK无关额外的模块
+
本地化
+
书写本地化代码.
+
移动开发
+
为Andriod上的火狐浏览器开发扩展程序。
+
扩展调试
+
调试扩展应用的JavaScript。
+
+
+
+ +
+

打包

+ +
+
+
+
扩展应用:Annotator
+
一起开发一个相对复杂的扩展应用。
+
+
+
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 +--- +

先决条件

+ +

请不要把任何相关的开发工具和扩展程序(命名推荐小写英文和数字,不推荐特殊符号等),放到有空格的目录(如Progaram Files\Python),会导致意想不到的错误,无法进行后续操作。(最新开发SDK可能修复了该错误,参见https://github.com/mozilla/addon-sdk/pull/1738)

+ +

开发 Add-on SDK,你需要:

+ + + +

另外,可以从它GitHub repository库中得到最新的开发版本

+ +

为AMO开发扩展

+ +

如果提交到AMO只有最新发布或许使用。

+ +

git archive 需要扩展一些Git属性占位符

+ +
git checkout 1.16
+
+git archive 1.16 python-lib/cuddlefish/_version.py | tar -xvf -
+ +

通过Homebrew自动安装到Mac OS X

+ +

使用以下命令通过 homebrew来安装SDK插件工具:

+ +
brew install mozilla-addon-sdk
+ +

安装到Mac OS X/Linux

+ +

无论你选择哪个方式都要解压缩文件的内容作为根路径,并通过shell/命令提示符切换到SDK的根目录下例如:

+ +
tar -xf addon-sdk.tar.gz
+cd addon-sdk
+
+ +

如果你是Bash的用户,则继续运行(大多数人都是的):

+ +
source bin/activate
+
+ +

如果你是一个非Bash的用户你应该运行

+ +
bash bin/activate
+
+ +

命令提示符现在应该有一个包含SDK的目录名称的新的前缀

+ +
(addon-sdk)~/mozilla/addon-sdk >
+
+ +

安装到Windows

+ +

同样解压缩文件,并通过命令符进入到SDK根目录下,例如:

+ +
7z.exe x addon-sdk.zip
+cd addon-sdk
+
+ +

接着运行激活命令:

+ +
bin\activate
+
+ +

同样可以看到命令提示符现在应该有一个包含SDK的目录名称新的前缀

+ +
(C:\Users\mozilla\sdk\addon-sdk) C:\Users\Work\sdk\addon-sdk>
+
+ +

SDK 的虚拟环境

+ +

当命令提示符出现新的前缀表明你的已经搭建好了SDK的运行环境,那么你就可以使用Add-on SDK来开发命令行工具

+ +

任何时候,你都可以通过运行 deactivate 命令停用虚拟环境.

+ +

配置好的虚拟环境是特定于这个特定的命令提示符。如果您关闭命令提示符, 它会关闭运行环境,你需要source bin/activate bin\activate 在一个新的命令提示符重新激活它。如果你打开一个新命令提示符SDK将不会被激活在新的提示

+ +

可以将SDK的多个副本拷贝在磁盘上的不同位置,并在它们之间切换,甚至可以让他们同时激活运行在不同的命令提示

+ +

制作启动项

+ +

所有 activate 的作用是通过设置环境变量,使位于顶层 bin 目录下的脚本 位于当前命令符下,制作的启动项 ,通过永久环境中的这些变量设置,以便每一个新的命令提示符下都能读取它们那么就不需要每次都去打开新的命令提示符来激活 activate

+ +

因为变量精确设置可能随SDK发布新版本的变化,所以最好是指激活脚本来确定哪些变量需要设置。激活使用不同的脚本设置bash环境不同的变量LinuxMAC OS X和Windows环境

+ +

Windows

+ +

在Windows上,使用 bin\activate\activate.bat批处理脚本,也可以使用命令行setx工具或控制面板激活永久使用

+ +

Linux/Mac OS X

+ +

在 Linux 和 Mac OS X,使用source bin/activate/activate bash 脚本, 你可以 ~/.bashrc ( Linux) 或~/.bashprofile (Mac OS X) 来激活。

+ +

作为替代,你可以在 ~/bin 目录中创建到cfx 程序的符号链接

+ +
ln -s PATH_TO_SDK/bin/cfx ~/bin/cfx
+
+ +

完整性检查

+ +

在shell提示符运行:

+ +
cfx
+
+ +

它会产生下面信息,这里是第一行内容,后面大量的使用信息

+ +
Usage: cfx [options] [command]
+
+ +

这是 CFX命令行程序界面加载项的SDK可以使用它来启动Firefox和测试插件,打包附加分发,查看​​文档和运行单元测试

+ +

出现问题?

+ +

尝试通过故障排除页面来解决遇到的问题。

+ +

下一步

+ +

接下来, 开始学习 cfx 教程, 其中介绍了如何使用CFX的工具来创建附加组件

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 +--- +

该SDK支持本地化字符串出现在:

+ + + +

目前为止还不支持本地化CSS和content scripts。

+ +

本地化字符串

+ +

翻译后的字符串都保存在你的add-on扩展目录下一个名为 "locale"的目录 ,每个本地化地域对应一个文件。这些文件:

+ + + +

假设你的附加组件包含一个单一的本地化字符串,用英语表示为“Hello!”,你想提供英语和法语的本地化支持。

+ +

你需要添加两个文件到"locale"目录:

+ +
my-addon/
+         data
+         lib
+         locale/
+                en-US.properties
+                fr-FR.properties
+
+ +

"en-US.properties" 文件中内容:

+ +
hello_id= Hello!
+
+ +

"fr-FR.properties" 文件中内容:

+ +
hello_id= Bonjour !
+
+ +

现在,每当你的JavaScript或HTML向本地化系统请求hello_id标识的翻译,它将获得与当前区域语言一致的翻译。

+ +

在HTML中使用本地化字符串

+ +
+

本例使用的 action button API需要 Firefox 29 或者更高版本。

+
+ +

要从HTML中引用本地化字符串,需要添加一个 data-l10n-id 的属性,到你想本地化的字符串所属的HTML标签中,然后为该属性指定一个ID值(To reference localized strings from HTML, add a data-l10n-id attribute to the HTML tag where you want the localized string to appear, and assign the identifier to it):

+ +
<html>
+  <body>
+    <h1 data-l10n-id="hello_id"></h1>
+  </body>
+</html>
+
+ +

然后你就可以使用这个HTML文件来建立你的界面, 比如插入一个 panel 面板:

+ +
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")
+});
+ +

“en-US”和“fr-FR”提供了翻译标识为hello_id字符串的本地化文件,面板将根据当前区域语言设置,显示“Hello!”或者“Bonjour!”:

+ +

+ +

翻译文本会插入到具有data-l10n-id属性集的节点中。任何之前存在的内容只是被替换掉了。(The translation is inserted into the node which has the data-l10n-id attribute set. Any previously existing content is just replaced.)

+ +

本地化字符串只能作为text文本插入, 所以你不能使用下面的语句插入HTML:

+ +
hello_id= <blink>Hello!</blink>
+
+ +

Localizing Element Attributes

+ +
这是 Firefox 39 上的新功能
+ +


+ 你可以在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):
+  

+ +
hello_id.accesskey= H
+ +

可以支持以下几个属性:

+ + + +

更多的 ARIA 属性aria-label, aria-valuetextaria-moz-hint 的本地化将通过在Firefox OS上同样的别名被支持(Further the localization of the ARIA attributes aria-label, aria-valuetext and aria-moz-hint are supported with the same aliases as on Firefox OS):

+ + + +

在JavaScript代码中使用本地化字符串

+ +

为了在主附加组件代码中引用本地化字符串,你需要这样做:

+ +
var _ = require("sdk/l10n").get;
+console.log(_("hello_id!"));
+ +

指定的 "_" 并不是必需的,但是作为 gettext 工具的默认约定,这能更好的配合其他默认使用 "_" 来表示本地化字符串的现有工具。

+ +
    +
  1. 导入 l10n 模块,然后指定 "_" (下划线)为模块的 get 函数。
  2. +
  3. 把所有涉及本地化的字符串放到 _() 函数中包括起来。
  4. +
+ +

如果你运行它,你会看到输出为预期的当前设置的区域语言:

+ +
info: Hello!
+
+ +
info: Bonjour !
+
+ +

注意你不能在content scripts中 require() 一个模块,所以目前还不能在content script 中引用本地化字符串。

+ +

复数

+ +

 l10n 模快支持复数形式,不同的语言有不同的复数形态。例如,英语有两种形式:相对于"one"的单数形式,和对于"everything else, including zero"的复数形式:

+ +
one tomato
+no tomatoes
+two tomatoes
+
+ +

但是俄罗斯语对于以 1 结尾(除了11)的数字、以 2-4 结尾(除了12-14)的数字和其他数字,有着不同的复数形态:

+ +
один помидор     // one tomato
+два помидора     // two tomatoes
+пять помидоров   // five tomatoes
+
+ +

SDK使用 Unicode CLDR 数据描述由不同的语言使用的不同复数形式。

+ +

Unicode CLDR 复数形式

+ +

Unicode CLDR项目定义了用于描述一个特定语言的多个规则的一种方案。在这个方案中一种语言对应最多有六种不同的范围的数字,有以下类别区分:zero(零个),one(一个),two(两个),few(几个),many(很多),other(其他)。(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: zero, one, two, few, many, and other.)

+ +

英语有两种复数形式,可以表示为 "1" 映射到 "one" 和 "everything else" 映射到 "other"的形式(English has two forms, which can be described by mapping "1" to "one" and "everything else" to "other"):

+ +
one   → n is 1;
+other → everything else
+
+ +

俄罗斯语有四种形式,可以使用以下方式表示:

+ +
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
+
+ +

所有语言的多个规则可以在CLDR的 语言复数规则 页面查到 (即使这个规则表相对于 CLDR XML source 已经过时了).

+ +

SDK中的复数形式

+ +

代码中,在 _()函数中的本地化ID参数之后提供一个额外的参数,用来表示代表多少个项的本地化字符串(In the code, you supply an extra parameter alongside the identifier, describing how many items there are):

+ +
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));
+ +

.properties 文件中通过使用 CLDR 关键字,对于每种语言可能的复数形式你可以自定义不同的本地化字符串。所以对于英语可以有两种本地化(注意"other" 分类不是 CDLR 关键字)。(In the .properties 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 not take the CLDR keyword))

+ +
# en-US translations
+tomato_id[one]= %d tomato
+tomato_id= %d tomatoes
+
+ +

俄罗斯语中可以定义四种本地化的复数形式:

+ +
# ru-RU translations
+tomato_id[one]= %d помидор
+tomato_id[few]= %d помидора
+tomato_id[many]= %d помидоров
+tomato_id= %d помидоры
+
+ +

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 ru-RU.properties file. Then it retrieves and returns the localization appropriate for the count you supplied.

+ +

Placeholders

+ +

The l10n 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:

+ +
# en-US translations
+hello_id= Hello %s!
+
+ +
# fr-FR translations
+hello_id= Bonjour %s !
+
+ +

To use placeholders, supply the placeholder string after the identifier:

+ +
var _ = require("sdk/l10n").get;
+console.log(_("hello_id", "Bob"));
+console.log(_("hello_id", "Alice"));
+ +

In the "en-US" locale, this gives us:

+ +
info: Hello Bob!
+info: Hello Alice!
+
+ +

In "fr-FR" we get:

+ +
info: Bonjour Bob !
+info: Bonjour Alice !
+
+ +

Ordering Placeholders

+ +

When a localizable string can take two or more placeholders, translators can define the order in which placeholders are inserted, without affecting the code.

+ +

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.

+ +

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:

+ +
var _ = require("sdk/l10n").get;
+console.log(_("home_town_id", "Bob", "London"));
+ +

An English translator might want to choose between the following:

+ +
"<town_name> is <person_name>'s home town."
+
+ +
"<person_name>'s home town is <town_name>"
+
+ +

To choose the first option, the .properties file can order the placeholders as follows:

+ +
home_town_id= %2s is %1s's home town.
+
+ +

This gives us the following output:

+ +
info: London is Bob's home town.
+
+ +

在首选项设置中的本地化字符串

+ +

通过加入一个 "preferences" 字段的结构到你的附加组件的 "package.json" 文件中,你可以为你的附加组件定义首选项选项,用户可以在Firefox的 Add-ons Manager 看到和编辑它。

+ +

Preferences (首选项)有一个必需的title标题项和一个可选的description描述项 这些字符串将出现在 Add-ons Manager中,来帮助向用户解释各个首选项设置的意义。

+ + + +

例如, 假设你的 "package.json" 中只定义了一个设置选项:

+ +
{
+    "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"
+}
+
+ +

在你的"en-US.properties"文件中, 应该包括下面两个项:

+ +
monster_name_title= Name
+monster_name_description= What is the monster's name?
+
+ +

在你的"fr-FR.properties"文件中, 应该包括下面两个法语的翻译项:

+ +
monster_name_title= Nom
+monster_name_description= Quel est le nom du monstre ?
+
+ +

现在,当浏览器的区域设置为 "en-US", 用户会在 Add-ons Manager看到这样:

+ +

+ +

当浏览器区域设置为 "fr-FR", 用户会看到:

+ +

+ +

下拉菜单menulist和单选按钮radio的类型有多个选项,每一个选项的标签属性都会展示给用户。如果本地化文件中有一项是以前缀是"{name} _options" 为键的键值对,其中"{name}"是选项的标签名字,该键值对的值就是一个选项标签的本地化字符串。(The menulist and the radio preference types have options. The label attribute of each option is displayed to the user. If the locale file has a entry with the value of the label attribute prefixed with "{name}_options." as its key, where {name} is the name of the preference, its value is used as a localized label.)

+ +

Using Identifiers

+ +

If the localization system can't find an entry for a particular identifier using the current locale, then it just returns the identifier itself.

+ +

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 .properties files for all the additional locales you want to support.

+ +

For example, in the case above you could use "Hello!" as the identifier, and just have one .properties file for the "fr-FR" locale:

+ +
Hello!= Bonjour !
+
+ +

Then when the locale is "en-US", the system would fail to find a .properties file, and return "Hello!".

+ +

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.

+ +

Locale Updater

+ +

The locale updater 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:

+ +

+ +

Click the button and you'll be prompted for a new .properties file for that add-on. If you provide a new file, the add-on's locale data will be updated with the new file.

+ +

Limitations

+ +

The current localization support is a first step towards full support, and contains a number of limitations.

+ + + +

See Also - for developers looking to localize non-SDK add-ons

+ + 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 +--- +

{{AddonSidebar}}

+ +
+

学习本教程之前你需要学习 jpm 基础

+
+ +

列出打开的标签页,你可以遍历 tabs 对象本身。

+ +

下面的 add-on 添加一个 action button 当用户单击该按钮时,该日志将在打开的标签页中记录:

+ +
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);
+}
+
+ +
+

注意:为此你需要一个按钮图标,以"icon-16.png"的文件名保存到你的 add-on 的"data"目录下。你可以从这里下载图标:

+
+ +

运行该 add-on,加载一对标签页,并点击按钮,你会看到在控制台输出如下的内容:

+ +
info: http://www.mozilla.org/en-US/about/
+info: http://www.bbc.co.uk/
+
+ +
+

你不能直接访问到标签页中的任何宿主内容(具体概念请查阅相关内容:JavaScript 本地对象、内置对象、宿主对象 )。

+ +

为了访问标签页的内容,你需要使用 tab.attach() 添加一个脚本,此 add-on 加载加载一个页面,然后将一个脚本附加到所有打开的标签页,该脚本将向标签页的文档添加红色边框:

+
+ +
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';"
+  });
+}
+
+ +

学习更多

+ +

要了解更多关于SDK中标签如何工作, 查看 tabs API reference

+ +

要了解更多关于在标签中运行脚本, 查看 tutorial on using tab.attach()

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 +--- +

{{AddonSidebar}}

+ +
学习本教程之前你需要了解 jpm 基础
+ +

你可以使用 tabs 模块来获取关于新页面加载的通知。下面的附加组件监听标签页内建的 ready 事件,并且记录下每一个标签加载时的URL:

+ +
require("sdk/tabs").on("ready", logURL);
+
+function logURL(tab) {
+  console.log(tab.url);
+}
+
+ +
+

你会在浏览器控制台,而非 Web 控制台中,找到这些输出的内容。

+
+ +

你不能直接访问标签页里面的内容。

+ +

为了访问标签页内容,你需要使用 tab.attach() 把一个脚本附到标签页上。这个示例给每一个打开后的标签页附上了一个脚本。这个脚本给标签页的 document 加上了一个红色边框:

+ +
require("sdk/tabs").on("ready", runScript);
+
+function runScript(tab) {
+  tab.attach({
+    contentScript: "if (document.body) document.body.style.border = '5px solid red';"
+  });
+}
+
+ +

(本示例仅仅表示:可以像这样实现一些功能,而你应当使用 page-mod,并且指定匹配模式为 "*"。)

+ +

了解更多

+ +

想要了解更多关于如何在SDK中处理标签页的内容,请看 tabs API 参考。你能够监听其他一些标签页事件,包括 openclose、和 activate

+ +

想要了解更多关于在标签页中运行脚本的事情,请看 tab.attach() 使用教程

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 +--- +
+

为了进一步学习本教程,你需要安装 Add-on SDK 和学习 cfx的基本使用

+ +

这篇教程使用动作按钮API,需要Firefox 29或更新版本。

+
+ +

为了修改特定标签页中的页面, 可以使用 tab对象的attach() 方法加载一个script脚本到页面中。因为他们的工作是和Web内容进行交互,所以这些脚本被称为content scripts(内容脚本)。

+ +

这是个简单的示例:

+ +
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";'
+    });
+  }
+});
+ +

要运行这个示例你必须保存一个名为”icon-16.png“的图标文件在你的Add-on目录下的”data”目录下。你可以下载这个图标:

+ +

这个插件创建一个按钮,其中包含Mozilla的图标作为一个图标。这个按钮产生一个点击事件处理程序,处理事件中将获取当前活动标签页和加载一个脚本到该标签页中的页面。使用contentscript选项指定加载的脚本,该脚本只绘制一个红色边框页。

+ +

然后在浏览器窗口中打开任何网页,点击按钮 。你会看到一个红色的边界出现在页面中, 就像这样:

+ +

+ +

保持Content Script在一个单独的文件中

+ +

在上面的例子中我们的content script作为一个字符串来直接使用.除非脚本非常简单,你应该保持脚本作为一个单独的文件。这使得代码更容易维护、调试和审查。

+ +

比如,我们把上面的脚本代码保存在Add-on目录下的data目录中并取名为my-script.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")
+    });
+  }
+});
+
+ +

你可以加载多个脚本,同时这些脚本可以直接相互作用。所以你可以加载 jQuery, 然后在你的其他 content script使用它。

+ +

与Content Script传递信息

+ +

你的扩展插件脚本Add-on script和内容脚本content script 不能直接访问对方的变量和函数,但他们之间可以互相发送消息。

+ +

从一方发送消息到另外一方, 发送方需要调用 port.emit()发送消息, 同时接收方使用port.on()接收消息。

+ + + +

让我们重写上面的例子来从附加内容脚本 content script 传递一个消息。现在content script 需要像下面这样:

+ +
// "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;
+});
+
+ +

在 add-on script 扩展脚本中,我们使用 attach()方法返回的对象向 content script 中发送一个“drawBorder”消息:

+ +
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");
+  }
+});
+
+ +

名为 drawBorder 的消息并不是一个内置的消息, 而是通过 port.emit()方法自定义的。

+ +

注入 CSS

+ +

不像 page-mod API, tab.attach() 不允许你直接注入CSS到页面中。

+ +

你需要使用 JavaScript 来修改页面的样式,就像前面的示例那样。

+ +

学习更多

+ +

要了解更多关于在SDK中标签页的使用, 可以查看打开一个网页教程,  列出打开的标签页教程, 和tabs API 参考手册.

+ +

要学习更多关于content scripts, 查看 content scripts guide.

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 +--- +
开始本教程之前,您必须安装好 SDK,并且学习 cfx 的基本的使用方法。
+ +

要修改任何页面匹配特定的模式(比如,“http://example.org/”)当它们加载后,使用page-mod模块。

+ +

要创建 page-mod,您必须指定两件事:

+ + + +
+

content scripts为内容脚本,只能使用普通浏览器支持的 JS,不能使用 add-on 的API

+
+ +

这里有一个范例。内容脚本提供contentScript选项,地址样本提供include选项:

+ +
// 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 = ' +
+                 ' "<h1>Page matches ruleset</h1>";'
+});
+
+ +

试试吧:

+ + + +

您将看到:

+ +

+ +

指定匹配模式

+ +

匹配模式使用 match-pattern 语法。您可以通过单一的匹配字符串,或者数组。

+ +

把内容脚本放在独立的文件中

+ +

在上面的范例中我们通过字符串来实现内容脚本。除非是用作简单的例子,通常情况下您应该将内容脚本放在独立文件中,这将使您的代码更易维护、调式和查看。

+ +

要这样做,您需要:

+ + + +

例如,如果我们将内容脚本保存在 data 目录下,命名为 my-script.js,在main.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")
+});
+ +

加载多个Content Scripts

+ +

您可以加载更多脚本,且脚本可以相互交互。所以,您可以使用jQuery重写 my-script.js:

+ +
$("body").html("<h1>Page matches ruleset</h1>");
+
+ +

然后下载 jQuery 库到您的扩展开发目录的 data 目录下,并且将 jQuery 和 my-script 一起加载(确保先加载 jQuery 库):

+ +
// 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")]
+});
+
+ +

您也可以在同一 page-mod 中同时使用 contentScriptcontentScriptFile 。如果您这么做的话,contentScript的脚本将会先加载。(应该是contentScriptFile的先加载吧?)

+ +
// 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("<h1>Page matches ruleset</h1>");'
+});
+
+ +

注意,您不能直接加载网站上的脚本。脚本必须从 data 目录中加载。

+ +

与 Content Script 通信

+ +

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.

+ +

从 Content Script 与 main.js 通信,发送方使用 port.emit() ,接收方使用 port.on() 监听.

+ + + +

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:

+ +
// "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 = "<h1>" + message + "</h1>";
+});
+
+ +

In the add-on script, we'll send the content script a message inside onAttach:

+ +
// 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");
+  }
+});
+
+ +

The replacePage message isn't a built-in message: it's a message defined by the add-on in the port.emit() call.

+ +

注入 CSS

+ +
+

请注意,本节中描述的功能是实验性的:我们很可能继续支持的功能,但可能需要改变的细节。

+
+ +

Rather than injecting JavaScript into a page, you can inject CSS by setting the page-mod's contentStyle option:

+ +
var pageMod = require("sdk/page-mod").PageMod({
+  include: "*",
+  contentStyle: "body {" +
+                "  border: 5px solid green;" +
+                "}"
+});
+
+ +

As with contentScript, there's a corresponding contentStyleFile 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 contentStyle if the CSS is at all complex:

+ +
var pageMod = require("sdk/page-mod").PageMod({
+  include: "*",
+  contentStyleFile: require("sdk/self").data.url("my-style.css")
+});
+
+ +

You can't currently use relative URLs in style sheets loaded with contentStyle or contentStyleFile. If you do, the files referenced by the relative URLs will not be found.

+ +

To learn more about this, and read about a workaround, see the relevant section in the page-mod API documentation.

+ +

Learning More

+ +

To learn more about page-mod, see its API reference page. In particular, the PageMod constructor takes several additional options to control its behavior:

+ + + +

To learn more about content scripts in general, see the content scripts guide.

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}} + +
学习本教程之前你需要学习 jpm 基础
+ +

打开一个新的网页,你可以使用 tabs 模块:

+ +
var tabs = require("sdk/tabs");
+tabs.open({
+"http://www.example.com");
+
+ +

这个函数是异步的,所以你不能立即获取一个可以检查的标签对象。要做到这一点,通过一个回调函数为open()。将回调函数赋值给 onready 属性,并将通过标签作为参数:

+ +
var tabs = require("sdk/tabs");
+tabs.open({
+  url: "http://www.example.com",
+  onReady: function onReady(tab) {
+    console.log(tab.title);
+  }
+});
+
+ +
+

尽管这样,你还是不能直接访问到标签页中的任何宿主内容(具体概念请查阅相关内容:JavaScript 本地对象、内置对象、宿主对象 )。

+
+ +

+要访问标签页的内容,你需要使用 tab.attach()把一个脚本添加到该标签页。此add-on加载加载一个页面,然后将一个脚本附加到该页,该将向页面添加红色边框:

+ +
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';"
+  });
+}
+
+ +

学习更多

+ +

要了解更多关于SDK中标签如何工作, 查看 tabs API reference.

+ +

要了解更多关于在标签中运行脚本, 查看 tutorial on using tab.attach().

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 +--- +

{{AddonSidebar}}

+ +

如果你的SDK安装和运行遇到了问题,不要慌!本页面列出了一些基本点,来帮助你追踪你的问题。

+ +

检查你的 Firefox

+ +

jpm 会搜索你系统中 Firefox 常见的地址,jpm 也许不能找到火狐安装在哪,或者你有多个地方安装了火狐,jpm 也许找错了地方。这种情况下,你需要使用 jpm--binary 选项。参看 jpm 指南以获取更多信息

+ +

当你运行 jpm 来测试你的 add-on 或者运行单元测试时,它会打印出 Firefox 或 XULRunner 二进制文件的地址,所有你可以检查一下它的输出内容来做确认。

+ +

检查你的文本控制台

+ +

当你的代码代码和SKD的API产生错误时,他们会被记录到文本控制台。这应该和你运行 jpm 命令的是同一控制台或shell

+ +

搜索已知的问题

+ +

也许有人已经遇到过和你一样的问题了。其他用户经常发布问题到 项目邮件列表。你也可以浏览已知问题列表或者搜索特定的关键词。

+ +

与项目团队和用户组交流

+ +

SDK的用户和项目团队成员对问题和建议在 项目的邮件列表.  别人可能有与你相同的问题,所以试着搜索列表。也欢迎你发表问题.

+ +

你也可以与其他SDK用户在 Mozilla的 IRC 网络#jetpack 聊天室聊天.

+ +

如果你想报告SDK的bug,我们非常欢迎!您将需要创建一个 Bugzilla 的帐号,Bugzilla 是 Mozilla 的 bug 追踪系统。

+ +
 
+ +
 
+ +
 
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 +--- +
+

学习本教程你将需要安装SDK, 学习 基本操作cfx,和学习过编写可重复模块(writing reusable modules).

+
+
+

如果你在使用 jpm 而不是 cfx, 请看关于cfx, 而且重点看加载测试模块(loading modules from test code).

+
+

SDK提供了一个框架,为你的代码创建和运行单元测试.接下来我们将演示如何写一个关于Base64 模块的单元测试.

+

一个Base64模块例子

+

在一个网页中, 你可以进行Base64的加密和解密,通过使用函数btoa() and atob() .不幸的是这些函数依附在window对象: 由于这个对象在你的add-on(插件) main 的代码里不是有效对象,所以 atob() and btoa() 也不是有效的. 因此我们将展示如何在这个平台上创建一个base64模块 .

+

To begin with, create a new directory, navigate to it, and run cfx init. Now create a new file in "lib" called "base64.js", and give it the following contents:

+
const { atob, btoa } = require("chrome").Cu.import("resource://gre/modules/Services.jsm", {});
+
+exports.atob = a => atob(a);
+exports.btoa = b => btoa(b);
+
+

This code exports two functions, which just call the platform's btoa() and atob() functions. To show the module in use, edit the "main.js" file as follows:

+
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);
+  }
+});
+

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: .

+

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:

+
info: aGVsbG8=
+info: hello
+
+

Testing the Base64 Module

+

Navigate to the add-on's test directory and delete the test-main.js file. In its place create a file called test-base64.js with the following contents:

+
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);
+
+

This file: exports three functions, each of which expects to receive a single argument which is an assert object. assert is supplied by the test/assert module and implements the CommonJS Unit Testing specification.

+ +

At this point your add-on ought to look like this:

+
  /base64
+      package.json
+      README.md
+      /doc
+          main.md
+      /lib
+          main.js
+          base64.js
+      /test
+          test-base64.js
+
+

Now execute cfx --verbose test from the add-on's root directory. You should see something like this:

+
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.
+
+

What happens here is that cfx test:

+

Note the hyphen after "test" in the module name. cfx test will include a module called "test-myCode.js", but will exclude modules called "test_myCode.js" or "testMyCode.js".

+ +

Obviously, you don't have to pass the --verbose option to cfx if you don't want to; doing so just makes the output easier to read.

diff --git "a/files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\227\245\345\277\227/index.html" "b/files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\227\245\345\277\227/index.html" new file mode 100644 index 0000000000..e581a0811c --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\227\245\345\277\227/index.html" @@ -0,0 +1,62 @@ +--- +title: 日志 +slug: Mozilla/Add-ons/SDK/Tutorials/日志 +translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Logging +--- +

{{AddonSidebar}}

+ +
学习本教程之前你需要学习 jpm 基础.
+ +

DOM console 对象对调试 Javascript 非常有帮助。但是由于扩展程序无法访问 DOM 对象,sdk 提供了一个拥有大部分 DOM console 对象方法的全局 console 对象,包括打印错误日车、警告和数据信息的方法。你无需 require() 任何模块,就可以直接使用 console 对象。

+ +

使用 console.log() 方法来打印信息:

+ +
console.log("Hello World");
+
+ +

尝试:

+ + + +

Firefox 将会启动,并在你执行 jpm run 的命令行窗口显示下面的信息:

+ +
console.log: console: Hello world
+
+ +

在内容脚本(conent script)中使用 console

+ +

与 addon 主代码一样,你可以在内容脚本中直接使用 console 对象。下面这个扩展在内容脚本中调用了 console.log() 方法,作用是在控制台打印出每个打开的标签页内的 HTML 内容:

+ +
require("sdk/tabs").on("ready", function(tab) {
+  tab.attach({
+    contentScript: "console.log(document.body.innerHTML);"
+  });
+});
+
+ +

控制台输出

+ +

如果你是在命令行启动你的扩展(例如:执行 jpm runjpm test),那么控制台信息将在你使用的命令行界面中显示。

+ +

如果你将扩展安装到了 Firefox 中,控制台信息将显示在 Firefox 浏览器控制台中。

+ +

但请注意,默认情况下,任何已经安装的扩展不会在错误控制台中输出任何信息,包括使用扩展构建程序安装的扩展或者使用其它工具例如:Extension Auto-installer

+ +

关于此项内容的更多信息请参阅控制台参考文档 “日志等级”。

+ +

更多

+ +

完整的 console API,请看 API 参考文档

diff --git "a/files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\267\273\345\212\240\344\270\200\344\270\252\350\217\234\345\215\225\351\241\271/index.html" "b/files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\267\273\345\212\240\344\270\200\344\270\252\350\217\234\345\215\225\351\241\271/index.html" new file mode 100644 index 0000000000..77d743e806 --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/sdk/tutorials/\346\267\273\345\212\240\344\270\200\344\270\252\350\217\234\345\215\225\351\241\271/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 +--- +
+

学习本章前,您要先 安装SDK 和学习 cfx的基本用法

+
+

右键菜单模块添加右键菜单项或子菜单

+

下面的例子是增加了一个新的上下文菜单项。当页面被选中时才会显示该菜单项,选择的部分会被发送到main.js的add-on代码中,它只是记录:

+
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);
+  }
+});
+

Try it: run the add-on, load a web page, select some text and right-click. You should see the new item appear:

+

试一试:运行该扩展,加载一个网页,选中一些文本并右键单击。你应该能看到新的项目出现:

+

+

点击,选中的文本记录到控制台:

+
info: elephantine lizard
+
+

细节

+


+ 这个add-on所有的操作是构建一个上下文菜单项。你不需要添加它:一旦你已经建立了项目,它会自动添加在正确的上下文。在这种情况下,构造函数接受四个选项:labelcontext,和contentscript,onMessage。

+

label

+


+ 标签是字符串的显示。

+

context

+


+ 上下文应该在不同的情境中显示它该做的显示。上下文菜单模块提供了一些简单的内置的上下文,包括selectioncontext(),这意味着:当页面被选中的时候将会显示菜单项。
+ 如果这些简单的背景是不够的,你可以使用脚本定义更复杂的环境。

+

contentScript

+

这将一个脚本项目。在这种情况下,脚本侦听用户点击该项目,然后选定文本用消息发送到add-on。

+

onMessage

+

onMessage属性提供附加的代码来响应来自连接到上下文菜单项脚本报文的一种方法。在这种情况下,它只是记录选定的文本。

+

所以:
+ 用户点击项目
+ 内容脚本的点击事件触发,和内容脚本检索选定的文本和发送邮件的附件
+ 附加的消息事件触发,并附加代码的处理函数是通过选定的文本,它的日志
+  

+

获取更多

+

如果想获取更多信息关于context-menu模块,查看context-menu API reference.

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 +--- +

本文给出了关于如何为扩展开发配置Mozilla应用程序的建议.

+

开发配置

+

为了避免由于设置了开发相关的预定义选项导致的性能上的问题,以及避免破坏你的个人数据,建议你可以创建一个新的Profile,而不是使用默认的进行开发工作.

+

如果你使用-no-remote参数启动Firefox,你可以用不同的Profile运行两个Firefox实例.例如,不管是否"正常"的Firefox是否运行,下面的命令将运行你的开发Profile(假设你的开发Profile命名为"dev").

+
start "" "%ProgramFiles%\Mozilla Firefox\firefox.exe" -no-remote -P dev
+
+

用默认的Profile允许Firefox通常仅仅是"firefox"或者"firefox -P default".

+

你可以使用Firefox稳定版本和开发版本来检查扩展的兼容性(Installing Firefox 3 or Minefield while keeping Firefox 2).

+

开发预定义选项

+

这些已定义参数使在低性能的情况下使调试更容易.

+

查看编辑配置文件关于设置预定义选项的信息.注意某些设置默认不存在与abount:config中.所以你需要创建一个新的(boolean)的项.

+

要这样做, 添加下面的代码行到你的Profile目录的 user.js 文件中,如果文件不存在,创建之:

+
user_pref("nglayout.debug.disable_xul_cache",true);
+user_pref("browser.dom.window.dump.enabled",true);
+
+

注意: 对于Firefox 版本 3.0"user.js" 已被 "prefs.js" 替换.

+

See below under "Development Profile" to setup a separate development profile before you make these changes.

+ +

开发扩展

+

这些扩展可以帮组你进行扩展开发.

+ +

扩展开发目录设定

+

每次因遇到某些变更而不得不重新添加扩展部分的时候,以及,为了保护您的"扩展源文件"不受到卸载过程中被意外删除的风险,其实您可以把"扩展插件目录"从"标准用户配置目录"中移出到你自己想要的文件目录中进行开发。具体操作步骤如下:

+
    +
  1. 找到扩展ID:从install.rdf中找到你的扩展ID号,install.rdf就安装在扩展插件的根目录中;
  2. +
  3. 建立文件:在“用户配置目录/extensions/”目录下,用你的扩展插件ID号作为文件名新建一个文件。 (比如: `用户配置目录/extensions/{46D1B3C0-DB7A-4b1a-863A-6EE6F77ECB58}`) (找到你的用户配置目录所在位置),记得没有文件扩展名。(为了方便说明暂把这个文件称作“扩展外链定位文件” )
  4. +
  5. 设定文件内容:“扩展外链定位文件”里要包含一个路径,这个路径是指向扩展程序的install.rdf所在目录的路径。(例如:`/full/path/to/yourExtension`. Windows用户注意,用大写书写驱动器名以及反斜杠而不是正斜杠,比如:`C:\full\path\to\yourExtension` Here is an example 'C:\sam\workspace\toolbar\helloWorldtoolbar\'). 在Firefox3中, 如果你是通过XPI包安装的扩展,`用户配置目录`下部分或者所有extensions.*的文件可能会被重新设置。虽然这些文件系统会自动重新生成的,还是备份一下先。
  6. +
  7. 把“扩展外链定位文件”放在你的用户配置目录中的扩展目录(`用户配置目录/extension`)下,重启Firefox。
  8. +
+

使用目录而非JAR

+

无论你是否选择将你的扩展 chrome打包成JAR或是目录,在目录下开发会更简单。如果你选择了一个用于分发的JAR,你仍然可以通过编辑chrome.manifest工作在目录形式下。比如下面的例子

+
content	myExtension	jar:chrome/myExtension.jar!/content/
+
+

不如

+
content	myExtension	chrome/content/
+
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 +--- +

当你为基于Mozilla的软件(如Firefox,Thunderbird等)制作出了一个全新的附加组件时,你一定希望其他人能够找,到下载并使用它。

+

Mozilla provides the http://addons.mozilla.org (AMO) web site to provide a repository for add-ons for Mozilla software. When users click the "Get Extensions" link in the Add-ons window in Firefox, for example, they are directed to this site.

+

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.

+
+ Note: 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.
+

第一步:编写你的附加组件

+

This is important. It's hard to get an add-on accepted into AMO if you don't write it first. Really hard.

+

第二步:测试你的附加组件

+

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.

+

第三步:打包你的附加组件

+

Add-ons distributed by AMO need to be packaged properly as XPI files. See Extension Packaging for information on how to do this.

+

第四部:注册一个AMO账户

+

You'll need to have an AMO account so that you can make submissions. To get one, visit the Register link at the top of any page on the AMO website. Fill out the form and follow the instructions to activate your account.

+

Obviously, you can skip this step if you already have an AMO account.

+

第五步:提交你的附加组件

+

To submit an add-on, go to the Developer Control Panel.

+

You will then be asked to supply a file, as well as information about the add-on.

+

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.

+

{{ languages( { "fr": "fr/Soumettre_un_module_sur_AMO" } ) }}

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 +--- +

+

+
Getting Started
+介绍如何为Firefox开发主题。
+
主题指的是程序的皮肤,通过它可以改变程序的外观,满足不同人的不同需要。一个主题可以只改变界面的颜色,也可以改变界面相关的所有元素。
+ + +
+

Documentation

+
创建一套 Firefox 皮肤 +
介绍如何为Firefox创建新的主题。 +
+

一般style翻译成样式 +

+
主题打包 +
如何将Firefox和Thunderbird的主题打包。 +
+
Firefox 2.0 和 3.0 间的主题变更 +
+
Firefox 1.5 和 2.0 间的主题变更 +
Firefox 发行版1.5和2.0之间的主题全部变更清单。 +
+
Firefox 1.5 和 2.0 间的主题变更 (forum post) +
A forum post at MozillaZine outlining the basic theme-related changes between Firefox 1.0 and 1.5. +
+
主题设计的第一步 +
A somewhat aged article discussing theme design for Firefox. +
+

View All... +

+
+

Community

+
  • View Mozilla forums... +
+

{{ DiscussionList("dev-themes", "mozilla.dev.themes") }} +

+ +

Tools

+ +

View All... +

+ +
CSS +
+
+

Categories +

Interwiki Language Links +


+


+

+
+
+{{ 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 +--- +

 

+

说明

+

为了为 Firefox 创建一套皮肤, 你必须知道三件事:如何编辑图像、如何释放zip文件、以及如何更改CSS。Firefox 的按钮图标使用标准的gif、png、和 jpeg 图像并使用 CSS 来定义界面上的一切。

+

什么是皮肤?

+

皮肤不会改版总体的界面;相反的,它仅仅定义了界面看上去的样子。你无法改版用户右击一个图像时发生什么事情,但你可以改版右键菜单的外观(例如使其变为带有粉色圆点装饰)。如果你想更改Firefox的功能,你不得不去改变chrome,这不在本文讨论的范围之内。

+

内容

+ +
+

文章原始信息

+ +
+
+  
+

{{ 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" } ) }}

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 +--- +

{{wiki.localize('System.API.page-generated-for-subpage')}}

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 +--- +

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.

+

{{ ListSubPages ("/en-US/Add-ons/Themes/Obsolete", 5) }}

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 +--- +

{{ Fx_minversion_header(3) }} {{ Draft() }}

+

本文包含了更新FireFox主题以使其可以在Firefox 3下良好表现所需进行的一些改动。

+
+ Note: We could use an article called Updating themes for Firefox 3 that would serve as a how-to guide for updating themes. If anyone with theming experience would like to write one, please do!
+

默认主题的改动

+

下表列出了Firefox 3默认主题的一些改动。你可以对照此表,确认你所需要做出的改动。

+

所有文件

+

所有平台

+ + + + + + + + + + + +
文件变更
<tt>browser/themes/*/browser/browser.css</tt>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").
+

Mac OS X

+ + + + + + + + + + + + + + + +
文件变动信息
<tt>browser/themes/pinstripe/browser/tabbrowser/tabDragIndicator.png</tt>删除了图片边缘多余的空白,现在图片尺寸变小。也许会对其他使用此图片的Mac平台下的主题产生影响。
<tt>browser/themes/pinstripe/browser/browser.css</tt>.tabbrowser-tab{{ mediawiki.external('first-tab=\"true\"') }} > .tab-image-left不再具有margin-left属性,现在使用定义了相同宽度的.tabs-left元素来替代。在FireFox 2的默认皮肤Winstripe中已经作此处理。
+

<tt>browser</tt>的改动

+

<tt>global</tt>的改动

+

所有平台

+

“跳转到”按钮现在被放置在地址栏内部,所以此按钮所用的图片(<tt>chrome://browser/skin/Go-arrow.png</tt>)需要设计的小一些。控制“跳转到”及其他地址栏中所用到的按钮的显示及隐藏的CSS规则为:

+
#urlbar[pageproxystate="invalid"] > #urlbar-icons > :not(#go-button) ,
+#urlbar[pageproxystate="valid"] > #urlbar-icons > #go-button {
+  visibility: collapse;
+}
+
+
增加的图片
+

增加了以下图片:

+
+
+ <tt>chrome://global/skin/icons/information-16.png</tt>
+
+ Used when presenting information notices。
+
+ <tt>chrome://global/skin/icons/warning-16.png</tt>
+
+ 用作显示警告窗口。
+
+
移除的图片
+

以下图片被移除:

+
+
+ <tt>chrome://mozapps/skin/extensions/question.png</tt>
+
+ 不再使用。
+
+

Mac OS X

+

为Mac OS X平台上的Firefox 3制作的皮肤需要在<tt>chrome://global/skin/wizard.css</tt>末尾增加两条CSS规则:

+
.wizard-buttons-btm {
+  padding:Xpx;
+}
+
+.wizard-label-box {
+  display: none;
+}
+
+

此处的数字 + + X + ,即<tt>.wizard-buttons-btm</tt>中的padding值,需要和<tt>.wizard-buttons-box-2</tt>中的margin值相同。

+
图片变动
+

chrome://global/skin/icons/loading_16.gif 被chrome://global/skin/icons/loading_16.png 替代。

+

<tt>mozapps</tt>的改动

+

参考文章

+

Theme changes in Firefox 2

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 +--- +
{{AddonSidebar}}
+ +
工具栏按钮是webextensions的一种主要UI组件,它在浏览器的工具栏中作为图标显示。当用户点击图标时,就会发生下面两种事件中的一样:
+ + + +

在WebExtensions中这种按钮被称为浏览器行为按钮,它们可以像下面这样生成:

+ + + +

一个简单的按钮

+ +

在这一节中我们将创建一个工具栏按钮的 WebExtension 。当用户单击按钮时,会打开一个https://developer.mozilla.org 的新标签页.

+ +

首先,新建名为 "button"的文件夹, 在该文件夹下创建名为"manifest.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"
+    }
+  }
+
+}
+ +

上面内容显示有一个名为“ background .js ”后台脚本,以及在“ icons ”文件夹下的浏览器行为按钮图标。

+ +
+
These icons are from the bitsies! iconset created by Recep Kütük.
+
+ +

接下来,在"buttons" 文件夹下创建 "icons" 文件夹,在该文件夹下存放下面的图标文件 :

+ + + +
 
+ +

我们有两个图标,大图标用于在高分辨率状态下显示。浏览器会自动选择合适的图标。

+ +

接着,在附加组件的根目录下创建 "background.js"文件 , 内容如下:

+ +
function openPage() {
+  browser.tabs.create({
+    url: "https://developer.mozilla.org"
+  });
+}
+
+browser.browserAction.onClicked.addListener(openPage);
+ +

该文件用来监听浏览器单击事件。当单击事件发生时运行 openPage() 函数,这个函数通过使用tabs 接口加载指定的页面。

+ +

现在完整的附加组件看上去应该像下面这样:

+ +
button/
+    icons/
+        page-16.png
+        page-32.png
+    background.js
+    manifest.json
+ +

安装这个WebExtension ,然后单击按钮:

+ +

{{EmbedYouTube("kwwTowgT-Ys")}}

+ +

添加一个弹出菜单

+ +

尝试在按钮上添加一个弹出菜单。 修改 "manifest.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"
+    }
+  }
+
+}
+ +

我们把原文件做了三处改变:

+ + + +

现在我们要创建弹出菜单。新建名为 "popup" 的文件夹,然后在文件夹内创建"choose_page.html" 文件,该文件内容如下:

+ +
<!DOCTYPE html>
+
+<html>
+  <head>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="choose_page.css"/>
+  </head>
+
+<body>
+  <div class="page-choice">developer.mozilla.org</div>
+  <div class="page-choice">support.mozilla.org</div>
+  <div class="page-choice">addons.mozilla.org</div>
+  <script src="choose_page.js"></script>
+</body>
+
+</html>
+ +

你会发现这是一个普通的HTML页面,它包含三个 {{htmlelement("div")}}元素,在每个元素中有一个Mozilla页面地址。另外还包括一个 CSS文件和一个JavaScript文件,我们会在后面添加它们。

+ +

在 "popup" 文件夹下,创建名为 "choose_page.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;
+}
+ +

这是我们弹出菜单的部分样式。

+ +

接着,在 "popup" 文件夹下,创建名为 "choose_page.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
+  });
+
+});
+ +

在我们的脚本中,我们会监听单击的弹出项。首先检查单击的对象是否在给出的页面选择项中,如果不在,则不做任何处理;如果在,则从单击的页面选择项中获取URL地址,然后打开一个对应页面的新标签页。注意:我们在弹出脚本中使用WebExtension接口,和在后台脚本中使用接口一样。

+ +

附加组件的结构最后看上去应该像下面这样:

+ +
button/
+    icons/
+        page-16.png
+        page-32.png
+    popup/
+        choose_page.css
+        choose_page.html
+        choose_page.js
+    manifest.json
+ +

重新加载附加组件,再次单击按钮,并尝试在弹出菜单中单击某个选择项:

+ +

{{EmbedYouTube("QPEh1L1xq0Y")}}

+ +

页面行为

+ +

页面行为(Page actions) 类似浏览器行为,只是页面行为仅针对特定页面,而浏览器行为则全局有效。

+ +

由于浏览器行为总是发生,而页面行为只在特定页面显示。所以页面行为按钮在URL地址栏中显示,而浏览器行为按钮则在浏览器工具栏中显示。

+ +

了解更多

+ + 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 +--- +
{{AddonSidebar}}
+ +

拓展是指一个包含若干文件的安装包,可直接分发至用户。本文中,我们快速地介绍一遍安装包内可能出现的文件。

+ +

manifest.json

+ +

这是唯一一个在每个 WebExtension 里面必须存在的文件。它包含了关于这个扩展插件基本的元数据(metadata),比如它的名字、版本和所需权限。并且,它也对 WebExtension 中其他文件进行了链接。

+ +

这个 manifest 文件还可以指向其它一些类型的文件:

+ + + +

+ +

浏览其他的详细信息请到 manifest.json

+ +

除了这些 manifest 引用的文件之外,扩展也可以携带额外的 Extension pages

+ +

后台脚本

+ +

扩展常常需要独立于任何浏览器窗口或特定网页来维持一种长期的状态或者执行长期的操作。这就是后台脚本(background scripts)的职责。

+ +

后台脚本将在拓展加载完毕后开始运行,直到拓展被禁用或卸载。只要获得了相应的权限,你就可以在脚本中使用任何 WebExtension API

+ +

指定后台脚本

+ +

你可以通过在 manifest.json 中添加关键字 background 来引入后台脚本:

+ +
// manifest.json
+
+"background": {
+  "scripts": ["background-script.js"]
+}
+ +

可以添加多份后台脚本:而且,就像同一个网页中的多个脚本一样,它们将会运行在同一上下文环境中。

+ +

 

+ +

与此同时,你也可以先引入一个后台页面,再在后台页面中引入脚本。这样做能为后台脚本添加 ES 6 模块支持,算是一个优势。

+ +

manifest.json

+ +
// manifest.json
+
+"background": {
+  "page": "background-page.html"
+}
+ +

background-page.html

+ +
<!DOCTYPE html>
+<html lang="zh-CN">
+  <head>
+    <meta charset="utf-8">
+    <script type="module" src="background-script.js"></script>
+  </head>
+</html>
+ +

 

+ +

后台脚本的运行环境

+ +

DOM API

+ +

后台脚本在一个被称为后台页面的特殊页面的上下文环境中运行。此环境为其提供了全局变量 window ,也提供了所有的标准 DOM API。

+ +

WebExtension API

+ +

只要扩展获得了必要的权限,后台脚本就可以使用所有的 WebExtension API

+ +

跨域访问

+ +

后台脚本可以向任何拥有主机权限的主机发送 XHR 请求。

+ +

网页内容

+ +

后台脚本没有直接访问页面的权限。不过,他们可以在页面中加载内容脚本(content scripts),并且可以通过 message-passing API 与内容脚本通信

+ +

内容安全策略

+ +

根据一个内容安全策略(Content Security Policy),后台脚本不能执行一些可能有危险的操作,例如使用 eval()。 详情请参考内容安全策略

+ +

侧边栏,弹出窗口,选项页面

+ +

您的扩展程序可以包含各种用户界面组件,其内容通过 HTML 文件来定义:

+ + + +

对于这些组件,你可以创建一个 HTML 文件,并使用 manifest.json 中的特定属性指向它。HTML 文件可以引用 CSS 和 JavaScript 文件,就像普通的网页一样。

+ +

所有这些都是扩展页面的一种,与普通网页不同的是,你可以在其 JavaScript 中使用所有有权限使用的 WebExtension API。 它们甚至可以通过 {{WebExtAPIRef("runtime.getBackgroundPage()")}} 直接访问后台页面中的变量。

+ +

扩展页面

+ +

您也可以在扩展中包含HTML文档,这些文档不附加到某个预定义的用户界面组件。与您可能为侧边栏,弹出窗口或选项页面提供的文档不同,它们在manifest.json中没有条目。但是,他们也可以访问所有与您的后台脚本相同的特权WebExtension API。

+ +

你通常可以使用 {{WebExtAPIRef("windows.create()")}} 或 {{WebExtAPIRef("tabs.create()")}}加载一个页面.

+ +

若想了解更多,请参考 扩展页面

+ +

内容脚本

+ +

一般使用内容脚本来访问和操作页面。内容脚本会被加载到页面中并运行在页面的特定环境下。

+ +

内容脚本是由扩展提供的脚本,与页面本身的脚本以及 {{HTMLElement("script")}} 标签中的脚本是不同的。

+ +

内容脚本可以像普通脚本一样获取、操作页面的 DOM。

+ +

与普通的页面内脚本不同,Content scripts可以:

+ + + +

内容脚本无法直接访问普通网页中的脚本,但是可以通过 window.postMessage() API 来与之传递信息。

+ +

通常情况下,当我们讨论内容脚本时,是在指(一类)使用 JavaScript 编写的脚本,但是你也可以用同样的机制来注入 CSS 文件。(译者注:不讨论含有编译器的情况。例如,若你事先引入了可编译 TypeScript 的 JavaScript 内容脚本,不论性能问题,你也很可能可以引入使用 TypeScript 编写的内容脚本:类似这样的情况,在此不计。)

+ +

若想了解更多,请参考内容脚本

+ +

Web accessible resources

+ +

Web accessible resources 是指像图片、HTML、CSS 和 JavaScript 之类的、被引入插件并且想要获得访问权限的内容脚本和页面脚本。这些 web-accessible 的资源可以在页面脚本和内容脚本中通过使用特定的URL方案来引用。
+ 举个例子来说,如果一个内容脚本想要把一些图片插入网页,你可以在插件中引入它们并且使他们成为web-accseeible。接下来内容脚本就可以创建并追加包含 src 属性的 img 标签了。

+ +

若想了解更多,请参考 manifest.json key 的文档:web_accessible_resources

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 +--- +
{{AddonSidebar()}}
+ +

创建一个新的alarm.

+ +

使用语法

+ +
browser.alarms.create(
+  name,              // 可选的字符串(string)类型
+  alarmInfo          // 可选的对象(object)类型
+)
+
+ +

参数介绍

+ +
+
name{{optional_inline}}
+
字符串(string)类型。alarm的名称。默认为空的字符串。
+
alarm的名称可以在{{WebExtAPIRef('alarms.get()')}}方法和{{WebExtAPIRef('alarms.clear()')}}方法中引用。同时它也可以通过{{WebExtAPIRef('alarms.onAlarm')}}监听方法传入的参数对象{{WebExtAPIRef('alarms.Alarm')}}的name属性访问到。
+
Alarm的名称是唯一的 (在单个附件范围内). 如果传入了已经在这个附件存在的名称, 原来的同名alarm会被移除并且没有警告。
+
alarmInfo{{optional_inline}}
+
+

对象(object)类型. 你可以对过它来指定什么时间alarm会开始触发,其值可以是一个具体的时间值或者是一个延时(从alarm设置开始)。为了让alarm能复现,需要指定periodInMinutes。

+ +

在Chrome浏览器上,除非附件以非打包(unpackaged)方式加载,alarm的创建每分钟不允许超过一次。如果附件尝试设置delayInMinutes为小于1的值,alarm只能在到达1分钟之后才会触发,并且会变成每分钟触发一次。

+ +

alarmInfo对象可以设置以下属性:

+
+
+
+
when{{optional_inline}}
+
double类型. alarm第一次触发的时间,值为自1970-01-01 00:00:00 UTC过去的毫秒数。请使用Date.now()来获取1970-01-01 00:00:00 UTC到当前时间过去的毫秒数。如果你设置了when属性,请不要设置delayInMinutes属性。
+
delayInMinutes{{optional_inline}}
+
double类型. alarm设置好到第一次触发之间的分钟数。如果你设置了delayInMinutes属性,请不要设置when属性。
+
periodInMinutes{{optional_inline}}
+
double类型. 如果设置此属性,alarm会从第一次触发开始每隔periodInMinutes分钟再次触发。如果你没有设置when及delayInMinutes属性,alarm会在alarm设置好之后periodInMinutes分钟第一次触发。如果periodInMinutes属性没有设置,则alarm只会触发一次。
+
+
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.alarms.create")}}

+ +

示例

+ +

Create a one-time delay-based alarm with "" for the name:

+ +
const delayInMinutes = 5;
+
+browser.alarms.create({
+  delayInMinutes
+});
+ +

Create a periodic delay-based alarm named "my-periodic-alarm":

+ +
const delayInMinutes = 5;
+const periodInMinutes = 2;
+
+browser.alarms.create("my-periodic-alarm", {
+  delayInMinutes,
+  periodInMinutes
+});
+ +

Create a periodic absolute alarm named "my-periodic-alarm":

+ +
const when = 1545696000;
+const periodInMinutes = 2;
+
+browser.alarms.create("my-periodic-alarm", {
+  when,
+  periodInMinutes
+});
+ +
Acknowledgements + +

This API is based on Chromium's chrome.alarms API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

在未来一个特定的时间运行的计划任务代码。这很像setTimeout()setInterval(),不过这些函数仅可以按需使用而不能在后台页面工作。

+ +

想要使用这个API,您需要获取"alarms"的permission

+ +

类型

+ +
+
{{WebExtAPIRef("alarms.Alarm")}}
+
Information about a particular alarm.
+
+ +

方法

+ +
+
{{WebExtAPIRef("alarms.create()")}}
+
创建新的alarm.
+
{{WebExtAPIRef("alarms.get()")}}
+
通过名称获取指定的alarm.
+
{{WebExtAPIRef("alarms.getAll()")}}
+
获取所有的alarm.
+
{{WebExtAPIRef("alarms.clear()")}}
+
清除指定名称的alarm.
+
{{WebExtAPIRef("alarms.clearAll()")}}
+
清除所有的alarm.
+
+ +

事件

+ +
+
{{WebExtAPIRef("alarms.onAlarm")}}
+
当alarm发生的时候触发.
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.alarms")}}

+ + + +

 {{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.alarms API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
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 +--- +

{{AddonSidebar()}}

+ +

代表书签树中的一个节点(书签或文件夹),子节点在它们的父文件夹中按顺序排列。

+ +

类型

+ +

这种类型的值都是对象。它们包含以下属性:

+ +
+
id
+
string. 节点的唯一标识符。唯一标识符在当前用户配置文件中保证唯一,并且在浏览器重新启动后仍然有效。
+
parentId{{optional_inline}}
+
string. 父节点的标识符(id)。根节点没有此属性。
+
index{{optional_inline}}
+
integer. 该节点在父文件夹中的位置(从 0 开始)。
+
url{{optional_inline}}
+
string. 当用户单击书签时打开的URL。文件夹没有此属性。
+
title
+
string. 该节点显示的文字。
+
dateAdded{{optional_inline}}
+
number. 该节点创建的时间,表示为自 1970 年 1 月 1 日午夜至今所经过的毫秒数(new Date(dateAdded))。
+
dateGroupModified{{optional_inline}}
+
number. 该文件夹内容的上一次修改时间,表示为自 1970 年 1 月 1 日午夜至今所经过的毫秒数。
+
unmodifiable{{optional_inline}}
+
{{WebExtAPIRef('bookmarks.BookmarkTreeNodeUnmodifiable')}}. 表示该节点不可修改的原因,"managed"表示该节点由系统管理员配置。如果该节点可以由用户和扩展程序修改(默认)则省略。
+
children{{optional_inline}}
+
array of {{WebExtAPIRef('bookmarks.BookmarkTreeNode')}}. 该节点的所有子节点(已排序)。
+
+ +

 

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.bookmarks.BookmarkTreeNode", 10)}}

+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.bookmarks API. This documentation is derived from bookmarks.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

bookmarks.getTree() 返回一个数组,该数组每一项为{{WebExtAPIRef("bookmarks.BookmarkTreeNode")}}对象,作为书签树的根节点。

+ +

如果它们是文件夹的话,你可以通过其children属性及其后代的children属性递归地访问整个树。

+ +

这是一个异步的函数,返回Promise

+ +

使用格式

+ +
var gettingTree = browser.bookmarks.getTree()
+
+ +

参数

+ +

无。

+ +

返回值

+ +

Promise对象,该对象未来会得到一个填充代表根节点的bookmarks.BookmarkTreeNode对象的数组。

+ +

浏览器兼容性

+ + + +

 

+ +

{{Compat("webextensions.api.bookmarks.getTree")}}

+ +

 

+ +

示例

+ +

这个示例会打印出整个书签树:

+ +
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);
+
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.bookmarks API. This documentation is derived from bookmarks.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

WebExtensions {{WebExtAPIRef("bookmarks")}} API允许一个附加组件和浏览器的书签系统交互和操作。您可以用它给页面加书签,获取已有的书签,以及编辑,移除和管理书签。

+ +

欲使用此API,一个附件组件必须请求"bookmarks" permission在它的manifest.json文件当中。

+ +

类型

+ +
+
{{WebExtAPIRef("bookmarks.BookmarkTreeNode")}}
+
表示在书签树中的一个书签或者文件夹。
+
{{WebExtAPIRef("bookmarks.BookmarkTreeNodeType")}}
+
一个描述在树中的一个节点是否是一个书签,一个文件夹或是一个分割符的 {{jsxref("String")}} 枚举类型。
+
{{WebExtAPIRef("bookmarks.BookmarkTreeNodeUnmodifiable")}}
+
一个说明了为什么一个书签或者文件夹是不可修改的 {{jsxref("String")}} 枚举类型。
+
{{WebExtAPIRef("bookmarks.CreateDetails")}}
+
当创建一个新书签时,包含被传递给这个 {{WebExtAPIRef("bookmarks.create()")}} 函数的信息。
+
+ +
+
+ +

方法

+ +
+
{{WebExtAPIRef("bookmarks.create()")}}
+
创建一个书签或文件夹。
+
{{WebExtAPIRef("bookmarks.get()")}}
+
获得一个或者多个{{WebExtAPIRef("bookmarks.BookmarkTreeNode", "BookmarkTreeNode")}},提供一个书签的编号或者一个书签编号的数组。
+
{{WebExtAPIRef("bookmarks.getChildren()")}}
+
获取指定{{WebExtAPIRef("bookmarks.BookmarkTreeNode", "BookmarkTreeNode")}}节点的所有子节点。
+
{{WebExtAPIRef("bookmarks.getRecent()")}}
+
获取最近添加的几个书签。
+
{{WebExtAPIRef("bookmarks.getSubTree()")}}
+
获取从指定节点开始的部分书签树。
+
{{WebExtAPIRef("bookmarks.getTree()")}}
+
获取整个书签树。
+
{{WebExtAPIRef("bookmarks.search()")}}
+
搜索书签树节点,找出匹配的结果。如果以对象方式指定查询,得到的 BookmarkTreeNodes 匹配所有指定的属性。
+
{{WebExtAPIRef("bookmarks.create()")}}
+
在指定的上一级文件夹下创建新的书签或文件夹。如果 url 为 null 或者省略,则创建文件夹。
+
{{WebExtAPIRef("bookmarks.move()")}}
+
将指定的书签树节点移到指定位置
+
{{WebExtAPIRef("bookmarks.update()")}}
+
更新书签或文件夹的属性。只需要指定您需要更改的属性,未指定的属性不会更改。注意:目前只支持“title”和“url”属性。
+
{{WebExtAPIRef("bookmarks.remove()")}}
+
删除书签或者空文件夹。
+
{{WebExtAPIRef("bookmarks.removeTree()")}}
+
删除整个书签文件夹。
+
{{WebExtAPIRef("bookmarks.import()")}}
+
从一个html书签文件导入书签
+
{{WebExtAPIRef("bookmarks.export()")}}
+
导出书签为一个html书签文件
+
+ +

事件

+ +
+
{{WebExtAPIRef("bookmarks.onCreated")}}
+
当书签或文件夹创建时产生。
+
{{WebExtAPIRef("bookmarks.onRemoved")}}
+
当删除书签或文件夹时产生。当删除整个文件夹(包括其中所有内容)时,仅为该文件夹发送通知,不为其中任何内容发送通知。
+
{{WebExtAPIRef("bookmarks.onChanged")}}
+
一个书签或文件夹更改时发生。注意:目前只有标题和URL更改时会触发这一事件。
+
{{WebExtAPIRef("bookmarks.onMoved")}}
+
当书签或文件夹移动到另一个父文件夹中时产生。
+
{{WebExtAPIRef("bookmarks.onChildrenReordered")}}
+
文件夹中的子节点在用户界面中调整顺序时产生。调用 move() 不会触发该事件。
+
{{WebExtAPIRef("bookmarks.onImportBegan")}}
+
开始导入书签时产生。复杂的事件处理函数在这一事件产生后不应该再处理 onCreated 事件,直到 onImportEnded 事件产生,在此过程中其他事件仍然应该立即处理。
+
{{WebExtAPIRef("bookmarks.onImportEnded")}}
+
书签导入结束时产生。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.bookmarks")}}

+ + + +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.bookmarks API. This documentation is derived from bookmarks.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

 bookmarks.remove() 方法用于删除单个书签或一个空的书签文件夹。

+ +
+

如果你的扩展尝试从书签树的根节点中移除一个书签,该调用将会引发一个“书签根不能被修改的”的错误信息并且这个书签不会被移除。

+
+ +

这是一个异步方法,返回Promise对象。

+ +

语法

+ +
var removingBookmark = browser.bookmarks.remove(
+  id                 // 字符串
+)
+
+ +

参数

+ +
+
id
+
{{jsxref("string")}} 要删除的书签或空书签文件夹的id标识
+
+ +

返回值

+ +

若方法执行完成,返回一个无参的 Promise对象。

+ +

若未找到该书签或该空书签文件夹,将返回一个带有错误信息的Promise对象。

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.bookmarks.remove")}}

+ +

例子

+ +
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);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.bookmarks API. This documentation is derived from bookmarks.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

添加按钮到浏览器的工具栏。

+ +

您可以为该按钮指派一个弹出窗。弹出窗可采用 HTML、CSS 和 JavaScript 编写,就像是一个普通的网页。运行在该弹出窗中的 JavaScript 可以同您的后台脚本一样访问所有的 WebExtension API,但它的全局上下文是该弹出窗,而不是浏览器中的当前页面。要影响网页,您需要通过消息通信。

+ +

如果您指定了弹出窗,它将显示——内容将在用户点击该图标时被加载。如果您没有指定一个弹出窗,用户单击该图标的事件将派发到您的扩展。

+ +

您可以用 manifest.json 中的 browser_action 键值声明定义大多数浏览器动作属性。

+ +

使用 browserAction API,您可以:

+ + + +

另见用户界面组件中的浏览器动作章节。

+ +

类型

+ +
+
{{WebExtAPIRef("browserAction.ColorArray")}}
+
0-255范围内的四个整数的数组,定义RGBA颜色。
+
{{WebExtAPIRef("browserAction.ImageDataType")}}
+
一个图像的像素数据。必须为一个 ImageData 对象(例如,来自一个 {{htmlelement("canvas")}} 元素)。
+
+ +

函数

+ +
+
{{WebExtAPIRef("browserAction.setTitle()")}}
+
设置浏览器动作的标题。这将在工具提示(鼠标悬停时)显示。
+
{{WebExtAPIRef("browserAction.getTitle()")}}
+
获取浏览器动作的标题。
+
{{WebExtAPIRef("browserAction.setIcon()")}}
+
设置浏览器动作的图标。
+
{{WebExtAPIRef("browserAction.setPopup()")}}
+
设置 HTML 文档作为浏览器动作图标被用户点击时显示的弹出窗。
+
{{WebExtAPIRef("browserAction.getPopup()")}}
+
获取作为浏览器动作的弹出窗的 HTML 文档。
+
{{WebExtAPIRef("browserAction.setBadgeText()")}}
+
设置浏览器动作的徽章文本。该徽章显示在图标上方。
+
{{WebExtAPIRef("browserAction.getBadgeText()")}}
+
获取浏览器动作的徽章文本。
+
{{WebExtAPIRef("browserAction.setBadgeBackgroundColor()")}}
+
设置徽章的后台颜色。
+
{{WebExtAPIRef("browserAction.getBadgeBackgroundColor()")}}
+
获取徽章的后台颜色。
+
{{WebExtAPIRef("browserAction.enable()")}}
+
为一个标签页启用浏览器动作。默认情况下,浏览器动作为所有标签页启用。
+
{{WebExtAPIRef("browserAction.disable()")}}
+
为一个标签页禁用浏览器动作,使该标签页为活动时无法单击它。
+
+ +

事件

+ +
+
{{WebExtAPIRef("browserAction.onClicked")}}
+
在浏览器动作图标点击时被触发。如果浏览器动作有弹出窗,则该事件不会触发。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.browserAction")}}

+ + + +

{{WebExtExamples("h2")}}

+ +
致谢 + +

此 API 基于 Chromium 的 chrome.browserAction API。此文档派生自 Chromium 代码中的 browser_action.json

+ +

Microsoft Edge 兼容性数据由微软公司提供,并以 知识共享 署名 3.0 美国版 许可。

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

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. 

+ +

To use this API you need to have the "captivePortal" permission.

+ +

Properties

+ +
+
{{WebExtAPIRef("captivePortal.canonicalURL")}}
+
Return the canonical URL of the captive-portal detection page. Read-only.
+
+ +

Functions

+ +
+
{{WebExtAPIRef("captivePortal.getLastChecked()")}}
+
Returns the time, in milliseconds, since the last request was completed.
+
{{WebExtAPIRef("captivePortal.getState()")}}
+
Returns the portal state as one of unknown, not_captive, unlocked_portal, or locked_portal.
+
+ +

Events

+ +
+
{{WebExtAPIRef("captivePortal.onConnectivityAvailable")}}
+
Fires when the captive portal service determines that the user can connect to the internet.
+
{{WebExtAPIRef("captivePortal.onStateChanged")}}
+
+

Fires when the captive portal state changes.

+
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.captivePortal")}}

+ + + +

{{WebExtExamples("h2")}}

+ + 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 +--- +
{{AddonSidebar()}}
+ +

Fires when the captive portal state changes.

+ +

Syntax

+ +
browser.captivePortal.onStateChanged.addListener(callback)
+browser.captivePortal.onStateChanged.removeListener(listener)
+browser.captivePortal.onStateChanged.hasListener(listener)
+
+ +

Events have three functions:

+ +
+
addListener(callback)
+
Adds a listener to this event.
+
removeListener(listener)
+
Stop listening to this event. The listener argument is the listener to remove.
+
hasListener(listener)
+
Check whether listener is registered for this event. Returns true if it is listening, false otherwise.
+
+ +

addListener syntax

+ +

Parameters

+ +
+
callback
+
+

Function that is called when this event occurs. The function is passed the following arguments:

+ +
+
details
+
+

string The captive portal state, being one of unknown, not_captive, unlocked_portal, or locked_portal.

+
+
+
+
+ +

Examples

+ +

Handle a change in captive portal status:

+ +
function handlePortalStatus(portalstatusInfo) {
+  console.log("The portal status is now: " + portalstatusInfo.details);
+}
+
+browser.captivePortal.onStateChanged.addListener(handlePortalStatus)
+
+ +

{{WebExtExamples}}

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.captivePortal.onStateChanged")}}

+ + 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 +--- +
{{AddonSidebar}}
+ +

使用此 API 以注册内容脚本。“注册内容脚本”意味着浏览器会将给定的内容脚本插入到每个与给定的 URL 模式相匹配的页面中。

+ +

此 API 与 manifest.json 的  "content_scripts" 键非常相似,但  "content_scripts" 键所能注册的内容脚本是固定的,自拓展安装后便不可更改。但通过 contentScripts API,拓展可以在运行时动态地注册或取消注册脚本。

+ +

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 Promise that is resolved with a {{WebExtAPIRef("contentScripts.RegisteredContentScript")}} object.

+ +

The RegisteredContentScript object represents the scripts that were registered in the register() call. It defines an unregister() 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.

+ +

没有与 contentScripts API 相关联的权限,但是拓展必须拥有与其试图通过 register() 注册的脚本的匹配模式相对应的主机权限,才能实现注入。

+ +

类型

+ +
+
{{WebExtAPIRef("contentScripts.RegisteredContentScript")}}
+
+

{{WebExtAPIRef("contentScripts.register()")}} 函数会返回一个持有此类型的对象。它表示被通过调用此函数注册的内容脚本,可被用于取消注册对应的内容脚本。

+
+
+ +

函数

+ +
+
{{WebExtAPIRef("contentScripts.register()")}}
+
注册给定的内容脚本。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.contentScripts", 10, 1)}}

+ +

{{WebExtExamples("h2")}}

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 +--- +
{{AddonSidebar}}
+ +
在浏览器菜单中添加条目。
+ +
+ +
此API基于Chrome的“contextMenus”API构建,该API可让Chrome扩展程序将项目添加到浏览器的上下文菜单中。 browser.menus API为Chrome的API添加了一些功能,特别是可以将项目添加到浏览器的“工具”菜单以及上下文菜单中。
+ +
+ +
在Firefox 55之前,这个API最初也被命名为contextMenus,并且这个名字被保留为别名,所以你可以使用contextMenus编写在Firefox和其他浏览器中工作的代码。
+ +
+ +
你需要拥有“menus”(或别名" contextMenus ")权限来使用此API。
+ +

创建菜单项

+ +

使用 {{WebExtAPIRef("menus.create()")}}方法创建一个菜单项。你需要传递一个包含条目选项的对象,它包括条目的id,类型,和需要显示出来的文本值。

+ +

绑定一个监听器到{{WebExtAPIRef("contextMenus.onClicked")}}事件来监听你菜单项目的点击事件。此监听器会传递一个{{WebExtAPIRef("contextMenus.OnClickData")}},它包含该事件的详细信息。

+ +

你可以根据在调用create()时所传递的参数中使用不同的type值来创建四种不同类型的菜单:

+ + + +

如果您创建了多个上下文菜单项目或多个工具菜单项目,则这些项目将被放置在子菜单中。 子菜单的父项将标有扩展名。 例如,下面是一个名为“Menu Demo”的扩展,添加了两个上下文菜单项:

+ +

+ +

图标

+ +

如果你使用 "icons" manifest key 为你的扩展指定一个图标,你的菜单项的旁边就会显示一个指定的图标。浏览器会尝试在普通分辨率下使用16 x 16像素的图标,在高分辨率下使用32 x 32像素的图标:

+ +

你可以通过调用 {{WebExtAPIRef("menus.create()")}} 时指定icons选项来给子菜单项设置图标。

+ +

+ +

例子

+ +

下面是一个包含四个项目的菜单,他们分别是:一个普通选项,两个周围有分割线的单选,和一个复选框。单选框使用了自定义图标。

+ +

+ +

你可以使用以下代码创建一个这样的子菜单:

+ +
browser.menus.create({
+  id: "remove-me",
+  title: browser.i18n.getMessage("menuItemRemoveMe"),
+  contexts: ["all"]
+}, onCreated);
+
+browser.menus.create({
+  id: "separator-1",
+  type: "separator",
+  contexts: ["all"]
+}, onCreated);
+
+browser.menus.create({
+  id: "greenify",
+  type: "radio",
+  title: browser.i18n.getMessage("menuItemGreenify"),
+  contexts: ["all"],
+  checked: true,
+  icons: {
+    "16": "icons/paint-green-16.png",
+    "32": "icons/paint-green-32.png"
+  }
+}, onCreated);
+
+browser.menus.create({
+  id: "bluify",
+  type: "radio",
+  title: browser.i18n.getMessage("menuItemBluify"),
+  contexts: ["all"],
+  checked: false,
+  icons: {
+    "16": "icons/paint-blue-16.png",
+    "32": "icons/paint-blue-32.png"
+  }
+}, onCreated);
+
+browser.menus.create({
+  id: "separator-2",
+  type: "separator",
+  contexts: ["all"]
+}, onCreated);
+
+var checkedState = true;
+
+browser.menus.create({
+  id: "check-uncheck",
+  type: "checkbox",
+  title: browser.i18n.getMessage("menuItemUncheckMe"),
+  contexts: ["all"],
+  checked: checkedState
+}, onCreated);
+ +

类型

+ +
+
{{WebExtAPIRef("contextMenus.ContextType")}}
+
菜单里可以出现的不同内容。可能的值有:"all", "audio", "browser_action", "editable", "frame", "image", "link", "page", "page_action", "password", "selection", "tab", "video".
+
{{WebExtAPIRef("contextMenus.ItemType")}}
+
菜单项的类别有: "normal", "checkbox", "radio", "separator".
+
{{WebExtAPIRef("contextMenus.OnClickData")}}
+
当菜单项被点击时发送的信息。
+
+ +

属性

+ +
+
{{WebExtAPIRef("contextMenus.ACTION_MENU_TOP_LEVEL_LIMIT")}}
+
可以被添加进上下文菜单项的顶级扩展项的最大值,其ContextType可以是"browser_action" 或者 "page_action".
+
+ +

函数

+ +
+
{{WebExtAPIRef("contextMenus.create()")}}
+
创建一个新的上下文菜单项目。
+
{{WebExtAPIRef("contextMenus.update()")}}
+
更新一个已经创建了的上下文菜单项目。
+
{{WebExtAPIRef("contextMenus.remove()")}}
+
删除一个上下文菜单项目。
+
{{WebExtAPIRef("contextMenus.removeAll()")}}
+
移除该插件创建的所有上下文菜单项目。
+
+ +

事件

+ +
+
{{WebExtAPIRef("contextMenus.onClicked")}}
+
当一个上下文菜单项被点击时触发。
+
+ +

浏览器兼容性

+ +

{{ Compat("webextensions.api.menus", 1, "true") }}

+ +

{{WebExtExamples("h2")}}

+ +
致谢 + +

此API基于Chromium的 chrome.contextMenus API. 此文档来自于Chromium代码中的context_menus.json

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

The Cookie type of the {{WebExtAPIRef("cookies")}} API represents information about an HTTP cookie.

+ +

类型

+ +

这玩意是一个 Object,可以包含以下的属性:

+ +
+
domain
+
储存这个 cookie 对应网站的字符串 (例如 "www.tengxun.com")。
+
expirationDate{{optional_inline}}
+
A number representing the expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.
+
firstPartyDomain
+
A string 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 First-party isolation.
+
hostOnly
+
A boolean, true if the cookie is a host-only cookie (i.e. the request's host must exactly match the domain of the cookie), or false otherwise.
+
httpOnly
+
A boolean, true if the cookie is marked as HttpOnly (i.e. the cookie is inaccessible to client-side scripts), or false otherwise.
+
name
+
A string representing the name of the cookie.
+
path
+
A string representing the path of the cookie.
+
secure
+
A boolean, true if the cookie is marked as secure (i.e. its scope is limited to secure channels, typically HTTPS), or false otherwise.
+
session
+
A boolean, true if the cookie is a session cookie, or false if it is a persistent cookie with an expiration date.
+
sameSite
+
A {{WebExtAPIRef("cookies.SameSiteStatus")}} value that indicates the SameSite state of the cookie.
+
storeId
+
A string representing the ID of the cookie store containing this cookie, as provided by {{WebExtAPIRef("cookies.getAllCookieStores()")}}.
+
value
+
代表 cookie 的值的一个字符串。
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.cookies.Cookie")}}

+ +

举例

+ +

Cookies API中的大多数方法都将 Cookie 对象用作输入参数或用作返回值的一部分。例如调用 {{WebExtAPIRef("cookies.getAll()")}} 将会返回一个 Cookie 对象的数组。

+ +

在下面的例子中我们将会获取所有的 cookie ,然后 console.log() 出这些 Cookie 对象所对应的值。

+ +
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);
+ +

{{WebExtExamples}}

+ +
声明 + +

这 API 是基于 Chromium 的 chrome.cookies API 的。 这个文档来自于 Chromium code 中的 cookies.json

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + + +
+
+
+ +
+
+
+ +
+

+ +

+
+
+
+
+
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 +--- +
{{AddonSidebar}}
+ +

使用 WebExtensions 获取或设置 cookies, 并且在修改时能够获得通知。

+ +

你需要在 manifest.json 文件中开启“cookies”API 权限,并且需要对应站点的 主机权限 才能设置指定站点的cookie。详细信息查看 cookie 权限.

+ +

类型

+ +
+
{{WebExtAPIRef("cookies.Cookie")}}
+
代表一个HTTP cookie的信息。
+
{{WebExtAPIRef("cookies.CookieStore")}}
+
代表一个保存在浏览器中的 cookie。
+
{{WebExtAPIRef("cookies.OnChangedCause")}}
+
代表 cookie 改变的原因。
+
+ +

方法

+ +
+
{{WebExtAPIRef("cookies.get()")}}
+
返回一个单独的 cookie 的信息。
+
{{WebExtAPIRef("cookies.getAll()")}}
+
返回所有符合筛选条件的 cookies。
+
{{WebExtAPIRef("cookies.set()")}}
+
根据给定cookie数据设置一个cookie;如果同样的cookie存在讲会覆盖。
+
{{WebExtAPIRef("cookies.remove()")}}
+
根据名字删除cookie。
+
{{WebExtAPIRef("cookies.getAllCookieStores()")}}
+
列出所有保存的cookie。
+
+ +

事件句柄

+ +
+
{{WebExtAPIRef("cookies.onChanged")}}
+
当设置或删除cookie时触发。
+
+ +

权限

+ +

为了使用这个API,插件必须在它的manifest中指定"cookies" API 权限,和它想要使用cookie的任何网站的 host 权限 。插件将能读取或写入host权限中所匹配的URL可以读取或写入的任何cookie。例如:

+ +
+
http://*.example.com/
+
+

拥有这个host权限的插件将可以:

+ +
    +
  • 读取一个www.example.com任意路径下的不安全cookie。
  • +
  • 写入一个www.example.com任意路径下的不安全cookie。
  • +
+ +

它不能:

+ +
    +
  • 读取www.example.com的安全cookie。
  • +
+
+
http://www.example.com/
+
+

拥有这个host权限的插件将可以:

+ +
    +
  • 读取 www.example.com任意路径下的不安全cookie。
  • +
  • 读取 .example.com 任意路径下的不安全cookie。
  • +
  • 写入 www.example.com 任意路径下的安全和不安全cookie。
  • +
  • 写入 .example.com 任意路径下的安全和不安全cookie。
  • +
+ +

它不能:

+ +
    +
  • 读取或写入 foo.example.com 的cookie。
  • +
  • 读取或写入 foo.www.example.com 的cookie。
  • +
+
+
*://*.example.com/
+
+

拥有这个host权限的插件将可以:

+ +
    +
  • 读取或写入 www.example.com 任意路径下安全的和不安全的cookie。
  • +
+
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.cookies")}}

+ + + +

Edge 不兼容

+ +

在 Edge 中不支持 Promises,使用 callbacks 代替。

+ +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

这个API 基于 Chromium 的 chrome.cookies API. 这篇文档来源于Chromium 代码的 cookies.json

+ +

Microsoft Edge 兼容性数据由 Microsoft Corporation 提供,并包含在 Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +
+

This page describes the WebExtensions devtools APIs as they exist in Firefox 54. Although the APIs are based on the Chrome devtools APIs, 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 Limitations of the devtools APIs.

+
+ +

The devtools.inspectedWindow API lets a devtools extension interact with the window that the developer tools are attached to.

+ +

Like all the devtools APIs, this API is only available to code running in the document defined in the devtools_page manifest.json key, or in other devtools documents created by the extension (such as the document hosted by a panel the extension created). See Extending the developer tools for more.

+ +

Properties

+ +
+
devtools.inspectedWindow.tabId
+
The ID of the window that the developer tools are attached to.
+
+ +

Functions

+ +
+
devtools.inspectedWindow.eval()
+
Evaluate some JavaScript in the target window.
+
devtools.inspectedWindow.reload()
+
Reload the target window's document.
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.devtools.inspectedWindow")}}{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.devtools.inspectedWindow API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

{{WebExtAPIRef("downloads")}} API 的 download() 函数根据给出的URL和其他首选项下载一个文件。

+ + + +

这是一个异步函数,其返回值为 Promise.

+ +

语法

+ +
var downloading = browser.downloads.download(
+  options                   // object
+)
+
+ +

参数

+ +
+
options
+
一个 object ,用来指定你想要下载的文件和其他想要在下载时设置的首选项。可以包含以下属性:
+
+
+
allowHttpErrors{{optional_inline}}
+
一个 boolean,启用后即使遇到HTTP错误仍然继续下载。 例如,可以使用该标志下载服务错误页面。默认值为false. 当设置为以下值时: +
    +
  • false,遇到HTTP错误时下载会被取消。
  • +
  • true, 即使遇到HTTP错误也会继续下载,并且不会弹出HTTP服务错误报告。但是,如果下载失败的原因是文件相关,网络相关,用户相关,或者说其他错误,仍然会报错。
  • +
+
+
body{{optional_inline}}
+
一个 string,代表请求的内容。
+
conflictAction{{optional_inline}}
+
一个字符串,表示如果存在命名冲突时你希望进行的操作,字符串内容所代表的类型由 {{WebExtAPIRef('downloads.FilenameConflictAction')}} 定义(未指定时默认为 "uniquify" )。
+
filename{{optional_inline}}
+
一个 string ,表示相对默认保存位置的文件路径——这里提供你希望文件保存的位置,和你想要使用的文件名。绝对路径,空路径,以及包含反向引用的路径 (../) 会导致错误产生。 如果省略,该值将默认为已经提供给下载文件的文件名,并且直接保存到下载文件夹中。
+
headers{{optional_inline}}
+
如果URL使用HTTP或者HTTPS协议, 保存在 array 中的一系列 objects 表示与请求一起发送的额外HTTP请求头。每一个请求头表示为字典对象,包含有关键字 name 还有 valuebinaryValue中的一个。 无法指定 XMLHttpRequestfetch禁止的请求头,但是 Firefox 70 之后允许使用Referer请求头。尝试使用被禁止的请求头会产生一个错误。
+
incognito{{optional_inline}}
+
一个 boolean:如果被设置为 true,那么这次下载会建立一个隐私浏览会话。 这意味着它只会出现在当前打开的任意隐私窗口的下载管理器。
+
method{{optional_inline}}
+
一个 string,表示url使用HTTP[S] 协议时使用的HTTP方法。其值可能是 "GET" 或 "POST"。
+
saveAs{{optional_inline}}
+
+

一个boolean 指定是(true)否(false)提供一个文件选择对话框允许用户选择文件名。.

+ +

如果该选项省略, 浏览器会根据用户对于该行为的偏好设置决定是否提供一个文件选择对话框 (在火狐这项设置标签在about:preferences里为"每次都问您要存到哪" ,或者about:config里 browser.download.useDownloadDir )。

+ +
+

Note: 如果 saveAs 被设置为 true,Firefox for Android 将会引发一个错误。 当 saveAsfalse 或空时这个参数会被忽略.

+
+
+
url
+
一个 string,表示需要下载的链接地址。
+
+
+
+ +

返回值

+ +

一个 Promise. 如果成功开始下载,promise会被新创建的{{WebExtAPIRef("downloads.DownloadItem")}} 的 id 填充。否则 promise 会被拒绝并产生一条{{WebExtAPIRef("downloads.InterruptReason")}}错误信息.

+ +

如果你使用 URL.createObjectURL() 下载由 JavaScript 创建的数据并且之后想要(使用 revokeObjectURL)撤销对象链接(并且强烈推荐这么做),你必须在下载完成后再这么做。监听 downloads.onChanged 事件来判断是否下载完成。

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.downloads.download")}}

+ +

例子

+ +

下面这段代码尝试下载一个example文件,同时指定文件名和保存位置,还有 uniquify conflictAction 选项。

+ +
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);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

这个 API 基于 Chromium的 chrome.downloads API.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

{{WebExtAPIRef("downloads")}} API 的 DownloadItem 类代表了一个被下载的文件。

+ +

Type

+ +

这个类型的值是对象,包含了以下属性:

+ +
+
byExtensionId{{optional_inline}}
+
一个代表了触发此下载的扩展的 ID 的 string (如果是被扩展触发的话)。一旦设置,不会改变。如果下载不是由扩展触发的,则为 undefined。
+
byExtensionName{{optional_inline}}
+
一个代表了触发此下载的扩展的名字的 string (如果是被扩展触发的话)。如果用户改变了扩展的语言环境,则这个属性的值也可能变化。如果下载不是由扩展触发的,则为 undefined。
+
bytesReceived
+
一个代表了在下载过程中从主机接收到的字节数的 number ;不考虑文件压缩。
+
canResume
+
一个标识当前中断(例如暂停)的下载是否可以从当前位置恢复的 boolean
+
danger
+
一个标识这个下载是否通过一个不安全的或已知的可疑的站点。可能被设置为 {{WebExtAPIRef('downloads.DangerType')}} 类型。
+
endTime{{optional_inline}}
+
A string (in ISO 8601 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.
+
error{{optional_inline}}
+
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.
+
estimatedEndTime{{optional_inline}}
+
A string (in ISO 8601 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 DownloadItem that's passed into {{WebExtAPIRef("downloads.onCreated")}}).
+
exists
+
A boolean indicating whether a downloaded file still exists (true) or not (false). 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.
+
filename
+
A string representing the file's absolute local path.
+
fileSize
+
A number 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.
+
id
+
An integer representing a unique identifier for the downloaded file that is persistent across browser sessions.
+
incognito
+
A boolean that indicates whether the download is recorded in the browser's history (false), or not (true).
+
mime
+
A string representing the downloaded file's MIME type.
+
paused
+
A boolean 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 true, false if not.
+
referrer
+
A string representing the downloaded file's referrer.
+
startTime
+
A string (in ISO 8601 format) representing the number of milliseconds between the UNIX epoch and when this download began.
+
state
+
A string Indicating whether the download is progressing, interrupted, or complete. Possible values are defined in the {{WebExtAPIRef('downloads.State')}} type.
+
totalBytes
+
A number 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.
+
url
+
A string representing the absolute URL from which the file was downloaded.
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.downloads.DownloadItem")}}

+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.downloads API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +
启用与浏览器的下载管理器交互的扩展。你可以使用这个 API 模块来下载文件、取消、暂停、恢复下载和在文件管理器中显示下载的文件。
+ +

为使用此 API,你需要在你的 manifest.json 文件中声明 "downloads" API 权限

+ +

Types

+ +
+
{{WebExtAPIRef("downloads.FilenameConflictAction")}}
+
定义当一个下载的文件与现存的文件命名冲突时要做什么。
+
{{WebExtAPIRef("downloads.InterruptReason")}}
+
定义一系列中断下载的可能理由。
+
{{WebExtAPIRef("downloads.DangerType")}}
+
定义一组与可下载文件相关的潜在危险的常见警告。
+
{{WebExtAPIRef("downloads.State")}}
+
定义当前下载可能处于的不同状态。
+
{{WebExtAPIRef("downloads.DownloadItem")}}
+
代表下载的文件。
+
{{WebExtAPIRef("downloads.StringDelta")}}
+
表示两个字符串之间的差异。
+
{{WebExtAPIRef("downloads.DoubleDelta")}}
+
代表两个双精度浮点数之间的差异。
+
{{WebExtAPIRef("downloads.BooleanDelta")}}
+
代表两个布尔数之间的差异。
+
{{WebExtAPIRef("downloads.DownloadTime")}}
+
代表一个下载将会花费的时间。
+
{{WebExtAPIRef("downloads.DownloadQuery")}}
+
定义一组参数,可用于在下载管理器中搜索一组特定的下载。
+
+ +

Functions

+ +
+
{{WebExtAPIRef("downloads.download()")}}
+
下载一个文件,给出它的 URL 和其他可选的参数。
+
{{WebExtAPIRef("downloads.search()")}}
+
查询 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItems")}} 是否在浏览器的下载管理器中可用,返回匹配指定的搜索标准的条目。
+
{{WebExtAPIRef("downloads.pause()")}}
+
暂停一个下载。
+
{{WebExtAPIRef("downloads.resume()")}}
+
恢复一个暂停的下载。
+
{{WebExtAPIRef("downloads.cancel()")}}
+
取消一个下载。
+
{{WebExtAPIRef("downloads.getFileIcon()")}}
+
检索指定下载的图标。
+
{{WebExtAPIRef("downloads.open()")}}
+
用下载的文件相关联的程序打开它。
+
{{WebExtAPIRef("downloads.show()")}}
+
打开当前平台的文件管理应用来在它包含的文件夹中显示下载的文件。
+
{{WebExtAPIRef("downloads.showDefaultFolder()")}}
+
用当前平台的文件管理应用显示默认下载文件夹。
+
{{WebExtAPIRef("downloads.erase()")}}
+
擦除浏览器的下载历史中匹配 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItems")}} 的下载记录,不会在磁盘中删除文件。
+
{{WebExtAPIRef("downloads.removeFile()")}}
+
从磁盘中移除下载的文件,但不从浏览器的下载历史中去除。
+
{{WebExtAPIRef("downloads.acceptDanger()")}}
+
提示用户接受或取消危险的下载。
+
{{WebExtAPIRef("downloads.drag()")}}
+
   将下载的文件拖动到另一个应用程序。
+
{{WebExtAPIRef("downloads.setShelfEnabled()")}}
+
启用或禁用与当前浏览器配置文件关联的每个窗口底部的灰色架子。 只要至少一个扩展名已禁用该架子,它就会被禁用。
+
+ +

Events

+ +
+
{{WebExtAPIRef("downloads.onCreated")}}
+
当一个下载开始时被 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItem")}} 对象触发。
+
{{WebExtAPIRef("downloads.onErased")}}
+
当一个下载从历史中擦除时被 Fires with the downloadId 触发。
+
{{WebExtAPIRef("downloads.onChanged")}}
+
当任意一个 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItem")}} 的属性期望 bytesReceived 改变时,此事件被这个 `downloadId` 和包含了变化属性的对象触发。
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.downloads")}}

+ +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.downloads API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

在网页中查找文本,并突出显示匹配项。

+ +

要使用此API,您需要具有“查找” 权限

+ +

功能

+ +
+
{{WebExtAPIRef("find.find()")}}
+
在网页中查找文本。
+
{{WebExtAPIRef("find.highlightResults()")}}
+
突出显示找到的最后一组匹配项。
+
{{WebExtAPIRef("find.removeHighlighting()")}}
+
删除所有突出显示。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.find", 1, 1)}} {{WebExtExamples("h2")}}

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 +--- +
{{AddonSidebar}}
+ +

使用 history API与浏览器历史记录进行交互。

+ +
+

注意:下载也被当做一个 HistoryItem 对象。因此,history.onVisited等事件也会被下载所触发。

+
+ +

浏览器历史记录是对用户所访问的页面按时间顺序进行的记录和保存。history API 可以帮你实现以下功能:

+ + + +

然而,用户可能多次访问单个页面,因此API中有访问集合“visits”的概念。所以,该API还可以做如下使用:

+ + + +

使用该API之前,扩展程序必须在其 manifest.json 文件中获取history的许可

+ +

类型

+ +
+
{{WebExtAPIRef("history.TransitionType")}}
+
描述浏览器如何转到特定页面。
+
{{WebExtAPIRef("history.HistoryItem")}}
+
+

提供浏览器历史记录中单个特定页面的详细信息。

+
+
{{WebExtAPIRef("history.VisitItem")}}
+
+

描述对一个页面的单次访问。

+
+
+ +

方法

+ +
+
{{WebExtAPIRef("history.search()")}}
+
在浏览器历史记录中查找符合给定条件的history.HistoryItem
+
{{WebExtAPIRef("history.getVisits()")}}
+
获取指定页面的访问集信息。
+
{{WebExtAPIRef("history.addUrl()")}}
+
为浏览器历史记录添加一个指定页面的访问。
+
{{WebExtAPIRef("history.deleteUrl()")}}
+
移除浏览器历史记录中所有对指定URL的访问。
+
{{WebExtAPIRef("history.deleteRange()")}}
+
移除指定时间段内对用户指定页面的访问。
+
{{WebExtAPIRef("history.deleteAll()")}}
+
移除浏览器历史记录中的所有访问。
+
+ +

事件

+ +
+
{{WebExtAPIRef("history.onTitleChanged")}}
+
+
当用户访问的页面标题被记录时触发。
+
+
{{WebExtAPIRef("history.onVisited")}}
+
每次用户访问页面时会触发,并提供该页面的 {{WebExtAPIRef("history.HistoryItem")}} 数据。
+
{{WebExtAPIRef("history.onVisitRemoved")}}
+
+

当一个URL被彻底从浏览器历史记录中移除时触发。

+
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.history")}}

+ +

{{WebExtExamples("h2")}}

+ +
致谢 + +

该 API 基于Chromium的chrome.history API。该文档由Chromium代码中的history.json衍生而来。

+ +

微软 Edge 兼容性数据由微软公司提供并包含在如下证书中—— Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +
当document的标题更改时触发
+ +
 
+ +
你可以使用 {{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 history.onVisited is sent.
+ +
 
+ +
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 history.onTitleChanged.
+ +

Syntax

+ +
browser.history.onTitleChanged.addListener(listener)
+browser.history.onTitleChanged.removeListener(listener)
+browser.history.onTitleChanged.hasListener(listener)
+
+ +

Events have three functions:

+ +
+
addListener(listener)
+
Adds a listener to this event.
+
removeListener(listener)
+
Stop listening to this event. The listener argument is the listener to remove.
+
hasListener(listener)
+
Check whether listener is registered for this event. Returns true if it is listening, false otherwise.
+
+ +

addListener syntax

+ +

Parameters

+ +
+
callback
+
+

Function that will be called when this event occurs. The function will be passed an object with the following properties:

+ +
+
url
+
String. URL of the page visited.
+
title
+
String. Title of the page visited.
+
+
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.history.onTitleChanged")}}

+ +

Examples

+ +

Listen for title change events, and log the URL and title of the visited pages.

+ +
function handleTitleChanged(item) {
+  console.log(item.title);
+  console.log(item.url);
+}
+
+browser.history.onTitleChanged.addListener(handleTitleChanged);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.history API. This documentation is derived from history.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

国际化扩展的函数。您可以使用这些 api 从与扩展打包在一起的本地化文件中获取本地化字符串,查找浏览器的当前语言,并查找其 Accept-Language header头的值。

+ +

有关对扩展使用 i18n 的详细信息,请参阅:

+ + + +

类型

+ +
+
{{WebExtAPIRef("i18n.LanguageCode")}}
+
一个语言标记 例如 "en-US" 或者 "fr".
+
+ +

方法

+ +
+
{{WebExtAPIRef("i18n.getAcceptLanguages()")}}
+
得到浏览器 支持的语言 。这与浏览器使用的区域设置不同。要获得区域设置,请使用{{WebExtAPIRef('i18n.getUILanguage')}}.
+
{{WebExtAPIRef("i18n.getMessage()")}}
+
获取指定消息的本地化字符串。
+
{{WebExtAPIRef("i18n.getUILanguage()")}}
+
获取浏览器的用户界面语言。 这与返回首选的用户语言 {{WebExtAPIRef('i18n.getAcceptLanguages')}} 不同。
+
{{WebExtAPIRef("i18n.detectLanguage()")}}
+
使用 Compact Language Detector属性检测所提供文本的语言。
+
+ +
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.i18n")}}

+ +

{{WebExtExamples("h2")}}

+ +
+
+ +
Acknowledgements + +

这个 API 是基于 Chromium 的 chrome.i18n API,这个文档源自 Chromium 代码中的  history.json 。

+ +

微软 Edge 的兼容性数据由微软公司提供,并在这里收录在《知识共享3.0美国许可证》中。

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

找出用户系统何时处于空闲,锁定或活动状态。

+ +

要使用此API,您需要具有“空闲”权限

+ +

类型

+ +
+
{{WebExtAPIRef("idle.IdleState")}}
+
+

描述设备空闲状态的字符串。

+
+
+ +

函数

+ +
+
{{WebExtAPIRef("idle.queryState()")}}
+
如果系统被锁定则返回“已锁定”,如果用户未在指定的秒数内生成任何输入,则返回“空闲”,否则返回“活动”。
+
{{WebExtAPIRef("idle.setDetectionInterval()")}}
+
设置用于确定系统何时处于 {{WebExtAPIRef("idle.onStateChanged")}}  事件的空闲状态的时间间隔。
+
+ +

事件

+ +
+
{{WebExtAPIRef("idle.onStateChanged")}}
+
当系统改变状态时触发。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.idle")}}

+ +

{{WebExtExamples("h2")}}

+ +
确认 + +

此 API基于 Chromium 的 chrome.idle API。本文档源自 Chromium代码中的 idle.json

+ +

Microsoft Edge 兼容性数据由 Microsoft Corporation提供,并包含在Creative Commons Attribution 3.0 United States License下。

+
+ + + +
+ +

了解更多:

+ +
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback
+ +
+ +
+ +
...
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 +--- +
{{AddonSidebar}}
+ +
+

WebExtension JavaScript API 可以在附加组件的后台脚本和附加组件定义的任何浏览器动作页面动作中使用。这里的部分API也可以通过附加组件的内容脚本访问(见内容脚本指南列表)。

+ +

要使用更强大的 API,您需要在您的 manifest.json 中申请权限

+ +

您可以使用 browser 命名空间访问这些 API。

+ +
function logTabs(tabs) {
+  console.log(tabs);
+}
+
+browser.tabs.query({currentWindow: true}, logTabs);
+
+ +
+

许多 API 为异步,返回一个 Promise

+ +
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);
+
+ +
+

请注意,这不同于 Google Chrome 的扩展系统,它使用 chrome 而非 browser 名字空间,并且对异步函数使用回调而不是 promises。为辅助移植,Firefox 实现的 WebExtensions 支持 chrome 和回调以及 browser 和 promises。Mozilla 也写了一个 polyfill 使使用 browser 和 promises 的代码能不经修改的在 Chrome 中使用:https://github.com/mozilla/webextension-polyfill

+ +

微软 Edge 使用 browser 名字空间,但尚不支持基于 promise 的异步API。目前在 Edge 中,异步 API 必须使用回调。

+ +

并非所有浏览器都支持这里的所有 API:详情见浏览器对 JavaScript API 的支持

+
+ +
{{SubpagesWithSummaries}}
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 +--- +
{{AddonSidebar()}}
+ +

检查扩展名是否具有给定 {{WebExtAPIRef("permissions.Permissions")}}  对象中列出的权限。

+ +

The Permissions argument may contain either an origins property, which is an array of host permissions, or a permissions property, which is an array of API permissions, or both.

+ +

This is an asynchronous function that returns a Promise. 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 pattern-match the permissions listed in origins, then they are considered to match.

+ +

Syntax

+ +
var getContains = browser.permissions.contains(
+  permissions                // Permissions object
+)
+
+ +

Parameters

+ +
+
permissions
+
A {{WebExtAPIRef("permissions.Permissions")}} object.
+
+ +

Return value

+ +

A Promise that will be fulfilled with true if the extension already has all the permissions listed in the permissions argument, or false otherwise.

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.permissions.contains")}}

+ +

Examples

+ +
// Extension permissions are:
+// "webRequest", "tabs", "*://*.mozilla.org/*"
+
+var testPermissions1 = {
+  origins: ["*://mozilla.org/"],
+  permissions: ["tabs"]
+};
+
+browser.permissions.contains(testPermissions1).then((result) => {
+  console.log(result);    // true
+});
+
+var testPermissions2 = {
+  origins: ["*://mozilla.org/"],
+  permissions: ["tabs", "alarms"]
+};
+
+browser.permissions.contains(testPermissions2).then((result) => {
+  console.log(result);   // false, "alarms" doesn't match
+});
+
+var testPermissions3 = {
+  origins: ["https://developer.mozilla.org/"],
+  permissions: ["tabs", "webRequest"]
+};
+
+browser.permissions.contains(testPermissions3).then((result) => {
+  console.log(result);   // true: "https://developer.mozilla.org/"
+});                      // matches: "*://*.mozilla.org/*"
+
+var testPermissions4 = {
+  origins: ["https://example.org/"]
+};
+
+browser.permissions.contains(testPermissions4).then((result) => {
+  console.log(result);   // false, "https://example.org/"
+});                      // does not match
+
+
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.permissions API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ +
+
+
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 +--- +
{{AddonSidebar}}
+ +
Enables extensions to request extra permissions at runtime, after they have been installed.
+ +
+ +

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 permissions manifest.json key. The main advantages of asking for permissions at install time are:

+ + + +

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.

+ +

With the permissions API, an extension can ask for additional permissions at runtime. These permissions need to be listed in the optional_permissions manifest.json key. Note that some permissions are not allowed in optional_permissions. The main advantages of this are:

+ + + +
To use the permissions API, decide which permissions your extension can request at runtime, and list them in optional_permissions. After this, you can request any permissions that were included in optional_permissions. Requests may only be made in the handler for a user action (for example, a click handler).
+ +
+ +
For advice on designing your request for runtime permissions, to maximize the likelihood that users grant them, see Request permissions at runtime.
+ +

Types

+ +
+
{{WebExtAPIRef("permissions.Permissions")}}
+
Represents a set of permissions.
+
+ +

Methods

+ +
+
{{WebExtAPIRef("permissions.contains()")}}
+
Discover an extension's given set of permissions.
+
{{WebExtAPIRef("permissions.getAll()")}}
+
Get all the permissions this extension currently has.
+
{{WebExtAPIRef("permissions.remove()")}}
+
Give up a set of permissions.
+
{{WebExtAPIRef("permissions.request()")}}
+
Ask for a set of permissions.
+
+ +

Event handlers

+ +
+
{{WebExtAPIRef("permissions.onAdded")}}
+
Fired when a new permission is granted.
+
{{WebExtAPIRef("permissions.onRemoved")}}
+
Fired when a permission is removed.
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.permissions")}}

+ +

See also

+ + + +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.permissions API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
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 +--- +
{{AddonSidebar}}
+ +
+ +
+

Warning
+ 不推荐使用 {{WebExtAPIRef("proxy.register()")}} 或者 {{WebExtAPIRef("proxy.unregister()")}} 方法使用 Proxy Auto-Configuration (PAC) file. 这个 API 将会在 Firefox 68 中废弃并且在 Firefox 71中删除.

+
+ +

使用proxy API来代理web请求。你可以使用{{WebExtAPIRef("proxy.onRequest")}}事件监听器来拦截web请求,并且返回一个可以描述是否代理并且怎样代理它们的对象。

+ +

{{WebExtAPIRef("proxy.onRequest")}}的好处在于,用于实现你拦截策略的代码在你的扩展的后台脚本运行,所以,它可以让WebExtension APIs能够完全的访问你的扩展(举例来说,可以访问你扩展的storage和像dns等类似的网络api)

+ +

除了这个api,扩展也能够使用browserSettings.proxyConfig属性来重新编辑你全局的proxy设置

+ +

Chrome浏览器提供了一个叫做'proxy'api扩展,它的功能跟这个api类似,在chrome的api中也可以用来实现一个拦截策略。然而,Chrome 的API的设计跟这个API设计完全不同。因为这个API跟谷歌的proxyAPI完全不同, 这个API只能通过'browser'命名空间访问

+ +

如果你想用这个API你需要得到'proxy'的permission.并且,如果你想拦截一个请求,你同样也需要当前拦截请求的url的 host permission

+ +

Types

+ +
+
{{WebExtAPIRef("proxy.ProxyInfo")}}
+
Describes a proxy.
+
{{WebExtAPIRef("proxy.RequestDetails")}}
+
+

Contains information about a web request that the browser is about to make.

+
+
+ +

Properties

+ +
+
{{WebExtAPIRef("proxy.settings")}}
+
Get and set proxy settings.
+
+ +

Functions

+ +
+
{{WebExtAPIRef("proxy.register()")}} {{Deprecated_Inline}}
+
Registers the given proxy script.
+
{{WebExtAPIRef("proxy.unregister()")}} {{Deprecated_Inline}}
+
Unregisters the proxy script.
+
+ +

Events

+ +
+
{{WebExtAPIRef("proxy.onError")}}
+
Fired when the system encounters an error running the PAC script or the onRequest listener.
+
{{WebExtAPIRef("proxy.onRequest")}}
+
Fired when a web request is about to be made, giving the extension an opportunity to proxy it.
+
+ +

{{WebExtExamples("h2")}}

+ +

Browser compatibility

+ +

{{Compat("webextensions.api.proxy")}}

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 +--- +
{{AddonSidebar()}}
+ +
该方法能够把附加组件和用户计算机上的一个本地应用程序相连接.
+ +
 
+ +
同时我们需要本地应用程序的名称作为参数. 当启动本地应用程序的时候会返回一个{{WebExtAPIRef("runtime.Port")}} 对象给调用者.
+ +
 
+ +
之后可以通过该对象的 Port.onMessage() 和 Port.postMessage()方法来和本地应用程序进行信息交互.
+ +
 
+ +
本地应用程序会一直运行直到退出, 除非调用了 Port.disconnect()方法, 亦或创建该Port对象的页面被摧毁了. 一旦Port对象断开连接, 浏览器会给该进程几秒的时间以便安全优雅的退出和释放, 之后如果发现该进程没退出的话就直接暴力干掉.
+ +
 
+ +

更多信息, 请查看 Native messaging.

+ +

语法

+ +
var port = browser.runtime.connectNative(
+  application // 这是一个字符串
+)
+
+ +

参数

+ +
+
application
+
值类型为string. 该参数的值为要连接的本地应用程序的名称. 必须要跟 native application's manifest file 中的"name"特性的值一致.
+
+ +

返回值

+ +

是一个 {{WebExtAPIRef('runtime.Port')}} 对象. 该对象是用来跟本地应用程序进行消息交互的.

+ +

浏览器的兼容性

+ + + +

{{Compat("webextensions.api.runtime.connectNative")}}

+ +

示例

+ +

本示例中连接了本地应用程序"ping_pong"并且启动了监听以便接收消息. 当用户单击浏览器上的操作按钮时它会发送一个本地应用程序的消息:

+ +
/*
+启动时, 连接"ping_pong"本地应用程序.
+*/
+var port = browser.runtime.connectNative("ping_pong");
+
+/*
+监听(接收)来自"ping_pong"本地应用程序的消息.
+*/
+port.onMessage.addListener((response) => {
+  console.log("Received: " + response);
+});
+
+/*
+当浏览器上的单击操作被触发时, 发送一个消息给本地应用程序.
+*/
+browser.browserAction.onClicked.addListener(() => {
+  console.log("Sending:  ping");
+  port.postMessage("ping");
+});
+ +

{{WebExtExamples}}

+ +
万分感谢 + +

该 API 是基于 Chromium 的 chrome.runtime API. 本文档采自 Chromium 代码中的 runtime.json.

+ +

Microsoft Edge 的兼容性数据由微软公司提供, 并被列入以下许可证 Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +
该方法会获取一个完整的主文件 manifest.json , 并返回一个序列化后的 JSON 对象.
+ +
 
+ +

语法

+ +
browser.runtime.getManifest()
+
+ +

参数

+ +

无.

+ +

返回值

+ +

是一个能表示主文件所有信息的 JSON 对象.

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.runtime.getManifest")}}

+ +

示例

+ +

取得主文件中的 name 特性的值, 并输出到控制台:

+ +
var manifest = browser.runtime.getManifest();
+console.log(manifest.name);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

该模块提供关于附加组件以及运行环境的信息。

+ +

它提供一组消息通信API,允许你:

+ + + +

Types

+ +
+
{{WebExtAPIRef("runtime.Port")}}
+
表示两个特定上下文之间的连接的一端,可用于交换消息。
+
{{WebExtAPIRef("runtime.MessageSender")}}
+
+
+
+
+
+

包含有关消息或连接请求的发件人的信息。

+
+
+
+
+
+
{{WebExtAPIRef("runtime.PlatformOs")}}
+
标识浏览器的操作系统。
+
{{WebExtAPIRef("runtime.PlatformArch")}}
+
标识浏览器的处理器架构。
+
{{WebExtAPIRef("runtime.PlatformInfo")}}
+
包含有关浏览器正在运行的平台的信息。
+
{{WebExtAPIRef("runtime.RequestUpdateCheckStatus")}}
+
{{WebExtAPIRef("runtime.requestUpdateCheck()")}} 的返回结果。
+
{{WebExtAPIRef("runtime.OnInstalledReason")}}
+
{{WebExtAPIRef("runtime.onInstalled")}} 事件被触发的原因。
+
{{WebExtAPIRef("runtime.OnRestartRequiredReason")}}
+
{{WebExtAPIRef("runtime.onRestartRequired")}} 事件被触发的原因。
+
+ +

Properties

+ +
+
{{WebExtAPIRef("runtime.lastError")}}
+
当异步方法执行时发生了错误,它需要向其调用方报告时,该值会被设置。
+
{{WebExtAPIRef("runtime.id")}}
+
当前扩展的ID。
+
+ +

Functions

+ +
+
{{WebExtAPIRef("runtime.getBackgroundPage()")}}
+
取得当前扩展的后台页的 Window 对象。
+
{{WebExtAPIRef("runtime.openOptionsPage()")}}
+
+

打开你的扩展的 选项页面

+
+
{{WebExtAPIRef("runtime.getManifest()")}}
+
获得完整的 manifest.json 声明文件的序列化对象。
+
{{WebExtAPIRef("runtime.getURL()")}}
+
给定某个打包在扩展中的资源的基于 manifest.json 相对路径,返回一个完整有效的 URL。
+
{{WebExtAPIRef("runtime.setUninstallURL()")}}
+
指定一个此扩展被卸载后打开的 URL。
+
{{WebExtAPIRef("runtime.reload()")}}
+
重新加载此扩展。
+
{{WebExtAPIRef("runtime.requestUpdateCheck()")}}
+
检查此扩展的更新。
+
{{WebExtAPIRef("runtime.connect()")}}
+
建立一个页面脚本到扩展主进程,或扩展主进程到页面脚本之间的通信连接。
+
{{WebExtAPIRef("runtime.connectNative()")}}
+
+
建立一个浏览器扩展与用户电脑上的原生应用的通信连接。
+
+
{{WebExtAPIRef("runtime.sendMessage()")}}
+
发送一条消息到此扩展或其他扩展的事件监听器,类似于  {{WebExtAPIRef('runtime.connect')}} 但只能发送一条消息,以及可选的响应处理函数。
+
{{WebExtAPIRef("runtime.sendNativeMessage()")}}
+
从扩展发送一条消息到原生应用。
+
{{WebExtAPIRef("runtime.getPlatformInfo()")}}
+
返回当前所在平台的信息。
+
{{WebExtAPIRef("runtime.getBrowserInfo()")}}
+
返回此扩展所在的浏览器的信息。
+
{{WebExtAPIRef("runtime.getPackageDirectoryEntry()")}}
+
返回此扩展所在目录的 DirectoryEntry。
+
+ +

Events

+ +
+
{{WebExtAPIRef("runtime.onStartup")}}
+
当一个拥有此扩展的账户第一次启动时触发,注意若处于隐私模式中则不会触发。
+
{{WebExtAPIRef("runtime.onInstalled")}}
+
当扩展第一次安装,扩展更新,浏览器更新后触发。
+
{{WebExtAPIRef("runtime.onSuspend")}}
+
当扩展将被停止前触发,使得扩展可以执行一些清理工作。
+
{{WebExtAPIRef("runtime.onSuspendCanceled")}}
+
在此事件 {{WebExtAPIRef("runtime.onSuspend")}} 后触发,表明扩展最终没有被停止。
+
{{WebExtAPIRef("runtime.onUpdateAvailable")}}
+
当扩展更新可用时触发,注意若扩展运行中,更新不会马上被安装。
+
{{WebExtAPIRef("runtime.onBrowserUpdateAvailable")}}
+
当浏览器更新可用时触发,注意浏览器需要重启才能安装更新。
+
{{WebExtAPIRef("runtime.onConnect")}}
+
与扩展进程或页面脚本(content script)建立通信连接时触发。
+
{{WebExtAPIRef("runtime.onConnectExternal")}}
+
与其他扩展建立通信连接时触发。
+
{{WebExtAPIRef("runtime.onMessage")}}
+
当收到扩展进程或页面脚本(content script)的消息时触发。
+
{{WebExtAPIRef("runtime.onMessageExternal")}}
+
当收到其他扩展的消息时触发,不能在页面脚本(content script)中使用。
+
{{WebExtAPIRef("runtime.onRestartRequired")}}
+
当设备要重启时触发。
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.runtime")}}

+ + + +

{{Compat("webextensions.api.runtime")}} {{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

当使用扩展处理或content script建立连接时触发.

+ +

Syntax

+ +
browser.runtime.onConnect.addListener(listener)
+browser.runtime.onConnect.removeListener(listener)
+browser.runtime.onConnect.hasListener(listener)
+
+ +

事件有三个方法:

+ +
+
addListener(callback)
+
为 这个事件添加一个监听器.
+
removeListener(listener)
+
停止监听这个事件. listener 参数就是要移除的监听器.
+
hasListener(listener)
+
检查监听器是否已经注册到这个事件上. 如果已经监听,则返回 true 否则返回 false.
+
+ +

addListener 语法

+ +

参数

+ +
+
function
+
+

A callback function that will be called when this event occurs. The function will be passed the following arguments:

+ +
+
port
+
A {{WebExtAPIRef('runtime.Port')}} object connecting the current script to the other context it is connecting to.
+
+
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.runtime.onConnect")}}

+ +

Examples

+ +

This content script:

+ + + +
// 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!"});
+});
+ +

The corresponding background script:

+ + + +
// 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!"});
+});
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + + +
+ + + + + +
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 +--- +
{{AddonSidebar()}}
+ +
利用此事件来监听来自你的扩展其他部分的消息。例如,使用:
+ +
+ + + +

To send a message that is received by the onMessage listener, use {{WebExtAPIRef("runtime.sendMessage()")}} or (to send a message to a content script) {{WebExtAPIRef("tabs.sendMessage()")}}.

+ +
+

Avoid creating multiple onMessage 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 connection-based approach to exchange messages.

+
+ +

Along with the message itself, the listener is passed:

+ + + +

You can send a synchronous response to the message by calling the sendResponse function inside your listener. See an example.

+ +

To send an asynchronous response, there are two options:

+ + + +
+

Returning a Promise is now preferred as sendResponse will be removed from the W3C spec. The popular webextension-polyfill library has already removed the sendResponse function from its implementation.

+
+ +
+

You can also use a connection-based approach to exchange messages.

+
+ +

Syntax

+ +
browser.runtime.onMessage.addListener(listener)
+browser.runtime.onMessage.removeListener(listener)
+browser.runtime.onMessage.hasListener(listener)
+
+ +

Events have three functions:

+ +
+
addListener(callback)
+
Adds a listener to this event.
+
removeListener(listener)
+
Stop listening to this event. The listener argument is the listener to remove.
+
hasListener(listener)
+
Checks whether a listener is registered for this event. Returns true if it is listening, false otherwise.
+
+ +

addListener syntax

+ +

Parameters

+ +
+
function
+
+

A listener function that will be called when this event occurs. The function will be passed the following arguments:

+ +
+
message
+
object. The message itself. This is a JSON-ifiable object.
+
+ +
+
sender
+
A {{WebExtAPIRef('runtime.MessageSender')}} object representing the sender of the message.
+
+ +
+
sendResponse
+
+

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.

+ +

If you have more than one onMessage listener in the same document, then only one may send a response.

+ +

To send a response synchronously, call sendResponse before the listener function returns. To send a response asynchronously:

+ +
    +
  • either keep a reference to the sendResponse argument and return true from the listener function. You will then be able to call sendResponse after the listener function has returned.
  • +
  • or return a Promise from the listener function and resolve the promise when the response is ready. This is a preferred way.
  • +
+
+
+ +

The listener function can return either a Boolean or a Promise.

+ +
+

Do not call addListener using the async function, as in:

+ +
browser.runtime.onMessage.addListener(async (data, sender) => {
+  if (data.type === 'handle_me') return 'done';
+});
+
+ +

as the listener will consume every message it receives, effectively blocking all other listeners from receiving and processing messages.

+ +

If you want to take an asynchronous approach, use a promise instead, as in:

+ +
browser.runtime.onMessage.addListener(data, sender) => {
+  if (data.type === 'handle_me') return Promise.resolve('done');
+});
+
+
+
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.runtime.onMessage")}}

+ +

Examples

+ +

Simple example

+ +

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:

+ +
// content-script.js
+
+window.addEventListener("click", notifyExtension);
+
+function notifyExtension(e) {
+  if (e.target.tagName != "A") {
+    return;
+  }
+  browser.runtime.sendMessage({"url": e.target.href});
+}
+
+ +

The background script listens for these messages and displays a notification using the notifications API:

+ +
// 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
+  });
+}
+ +

Sending a synchronous response

+ +

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:

+ +
// 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);
+ +

Here is a version of the corresponding background script, that sends a response synchronously, from inside in the listener:

+ +
// 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);
+ +

And here is another version, that uses Promise.resolve():

+ +
// 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);
+ +

Sending an asynchronous response using sendResponse

+ +

Here is an alternative version of the background script from the previous example. It sends a response asynchronously after the listener has returned. Note return true; in the listener: this tells the browser that you intend to use the sendResponse argument after the listener has returned.

+ +
// background-script.js
+
+function handleMessage(request, sender, sendResponse) {
+  console.log(`content script sent a message: ${request.content}`);
+  setTimeout(() => {
+    sendResponse({response: "async response from background script"});
+  }, 1000);
+  return true;
+}
+
+browser.runtime.onMessage.addListener(handleMessage);
+
+ +

Sending an asynchronous response using a Promise

+ +

This content script gets the first <a> link on the page and sends a message asking if the link's location is bookmarked. It expects to get a Boolean response: true if the location is bookmarked, false otherwise:

+ +
// 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);
+ +

Here is the background script. It uses {{WebExtAPIRef("bookmarks.search()")}} to see if the link is bookmarked, which returns a Promise:

+ +
// background-script.js
+
+function isBookmarked(message, sender, response) {
+  return browser.bookmarks.search({
+    url: message.url
+  }).then(function(results) {
+    return results.length > 0;
+  });
+}
+
+browser.runtime.onMessage.addListener(isBookmarked);
+ +

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 Window.setTimeout():

+ +
// background-script.js
+
+function handleMessage(request, sender, sendResponse) {
+  return new Promise(resolve => {
+    setTimeout(() => {
+      resolve({response: "async response from background script"});
+    }, 1000);
+  });
+}
+
+browser.runtime.onMessage.addListener(handleMessage);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
 
+ +
假如你的页面有options page(设置页面)的定义,使用此方法打开它。
+ +
 
+ +
这是一个异步方法,返回一个 Promise对象
+ +
 
+ +

语法

+ +
var openingPage = browser.runtime.openOptionsPage()
+
+ +

参数

+ +

+ +

返回值

+ +

当设置页面成功创建,执行Promise的无参成功回调方法,否则执行Promise的失败回调方法,参数为错误信息。

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.runtime.openOptionsPage")}}

+ +

例子

+ +

当用户点击浏览器行为图标时,打开一个设置页面。

+ +
function onOpened() {
+  console.log(`Options page opened`);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+var opening = browser.runtime.openOptionsPage();
+opening.then(onOpened, onError);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

当前浏览器所在的计算机的处理器架构.

+ +

值类型

+ +

该值的类型是字符串. 可能的值如下:

+ +
+
"arm"
+
标识平台基于 arm 架构.
+
"x86-32"
+
表示平台基于 x86 32-bit 架构.
+
"x86-64"
+
表示平台基于 x86 64-bit 架构.
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.runtime.PlatformArch")}}

+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

获取当前浏览器运行所在的操作系统.

+ +

值类型

+ +

该值的类型是字符串. 可能的值如下:

+ +
+
"mac"
+
表示底层操作系统是 Mac OS X.
+
"win"
+
表示底层操作系统是 Windows.
+
"android"
+
表示底层操作系统是 Android.
+
"cros"
+
表示底层操作系统是 Chrome OS.
+
"linux"
+
表示底层操作系统是 Linux.
+
"openbsd"
+
表示底层操作系统是 Open/FreeBSD.
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.runtime.PlatformOs")}}

+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +
向你的扩展或其他扩展发送单条消息。
+ +
 
+ +
如果想发给你自己的扩展,则省略 extensionId 参数。扩展中所有页面的{{WebExtAPIRef('runtime.onMessage')}}将会被触发,除了调用runtime.sendMessage的页面。
+ +

 

+ +

如果发送给其他扩展,则将参数 extensionId 设置为其他扩展的ID。其他扩展的 {{WebExtAPIRef('runtime.onMessageExternal')}} 将会被触发。

+ +

此接口不能给 content script 发消息,如果要给 content script 发消息,请使用 {{WebExtAPIRef('tabs.sendMessage')}}。

+ +

这是个异步方法,将返回一个 Promise

+ +

Syntax

+ +
var sending = browser.runtime.sendMessage(
+  extensionId,             // optional string
+  message,                 // any
+  options                  // optional object
+)
+
+ +

参数

+ +
+
extensionId{{optional_inline}}
+
string. 若你想要发给不同的扩展,这里传入接收方的扩展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 applications key in manifest.json, then extensionId should have this value. Otherwise it should be have the ID that was generated for the intended recipient.
+
若此省略此参数,则发送给自己的扩展。
+
message
+
any. 任何可以序列化成JSON的东西。
+
options{{optional_inline}}
+
object. +
+
includeTlsChannelId{{optional_inline}}
+
boolean. Whether the TLS channel ID will be passed into {{WebExtAPIRef('runtime.onMessageExternal')}} for processes that are listening for the connection event.
+
toProxyScript{{optional_inline}}
+
boolean. Must be True if the message is intended for a PAC file loaded using the {{WebExtAPIRef("proxy")}} API.
+
+
+
+ +

根据给出的参数不同,API遵循如下规则:

+ + + +
+

在Firefox 55之前,只给出2个参数时,规则会有所不同:
+ Under the old rules, if the first argument was a string, it was treated as the extensionId, with the message as the second argument. This meant that if you called sendMessage() with arguments like ("my-message", {}), 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.

+
+ +

Return value

+ +

返回一个 Promise。若接收方响应,Promise将会变为 fulfilled 并且返回接收方响应的JSON对象(数字、字符串、数组、true/false都是合法的JSON对象)。否则,Promise会变为 fulfilled 但是不返回任何参数。如果发生了连接错误,Promise将会变为 rejected 并返回一个错误消息。

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.runtime.sendMessage")}}

+ +

Examples

+ +

Here's a content script that sends a message to the background script when the user clicks the content window. The message payload is {greeting: "Greeting from the content script"}, and the sender also expects to get a response, which is handled in the handleResponse function:

+ +
// 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);
+ +

The corresponding background script looks like this:

+ +
// 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);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.runtime API. This documentation is derived from runtime.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

从 WebExtension 发送单条消息到 native application。

+ +

它需要两个强制的参数:native application 的名字和要发送给它的JSON对象。浏览器将会加载 native application 然后发送这个消息。

+ +

这是一个异步函数,返回一个 Promise对象。native application 发送的第一条消息将被当作sendNativeMessage() 的回复,并且 promise 将这个消息作为参数.。注意你不能使用 {{WebExtAPIRef("runtime.onMessage")}} 从应用获取回复:你必须使用回调函数来替代。

+ +

每次调用 runtime.sendNativeMessage()都会生成一个新的实例。浏览器将会在收到回复后结束这个 native application。为了结束这个 native application,浏览器将会关闭 pipe,并给进程几秒的时间优雅的退出,如果它没有关闭就杀死它。

+ +

更对信息,参考 Native messaging

+ +

语法

+ +
var sending = browser.runtime.sendNativeMessage(
+  application,             // string
+  message                  // object
+)
+
+ +

参数

+ +
+
application
+
字符串类型。native application的名字。它必须和 native application's manifest file中的‘name’字段一致。
+
message
+
对象类型。一个将要发送给 native application的JSON对象。
+
+ +

返回值

+ +

一个 Promise对象。如果native application发送了一个回复,它将会填充回复的JSON对象作为参数。否则它不会填充参数。如果在native application连接期间发生了错误,promise将会被一个错误的消息拒绝。

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.runtime.sendNativeMessage")}}

+ +

示例

+ +

这是一个 background script ,当使用者点击浏览器的browser action时,它会发送 "ping" 消息到 "ping_pong" 应用并且把回复记录下来:

+ +
function onResponse(response) {
+  console.log(`Received ${response}`);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+/*
+On a click on the browser action, send the app a message.
+*/
+browser.browserAction.onClicked.addListener(() => {
+  console.log("Sending:  ping");
+  var sending = browser.runtime.sendNativeMessage("ping_pong", "ping");
+  sending.then(onResponse, onError);
+});
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

这个API 基于 Chromium 的 chrome.runtime API。 本文来自 Chromium 代码中的 runtime.json

+ +

微软 Edge 的兼容性数据由 Microsoft Corporation 提供,并且包含在这里基于 Creative Commons Attribution 3.0 United States License。

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

Retrieves search engines and executes a search with a specific search engine.

+ +

To use this API you need to have the "search" permission.

+ +

Functions

+ +
+
{{WebExtAPIRef("search.get()")}}
+
Retrieve all search engines.
+
{{WebExtAPIRef("search.search()")}}
+
Search using the specified search engine.
+
+

Browser compatibility

+
+
+ +

{{Compat("webextensions.api.search", 1, 1)}} {{WebExtExamples("h2")}}

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 +--- +
{{AddonSidebar()}}
+ +

使用指定的搜索引擎或默认搜索引擎进行搜索。

+ +

结果将显示在一个新的选项卡中,或者如果给出了tabId参数,则显示在由此标识的选项卡中。

+ +

要在扩展程序中使用此功能,您必须要求"search" 有明确许可.

+ +

获取安装的搜索引擎, 请使用 {{WebExtAPIRef("search.get()")}}.

+ +

语法

+ +
browser.search.search(
+  searchProperties       // object
+)
+
+ +

参数

+ +
+
searchProperties
+
+

object. 拥有以下属性的对象:

+ +
+
query
+
字符串. 进行查询的内容。
+
engine{{optional_inline}}
+
+

字符串。.搜索引擎的名称。 如果指定的搜索引擎名称不存在,该函数将引发错误。 如果省略此属性,则使用默认的搜索引擎。

+
+
tabId{{optional_inline}}
+
+

整型。用于显示搜索结果的选项卡。如果省略此属性,搜索结果将显示在新选项卡中。

+
+
+
+
+ +

返回值

+ +

无.

+ +

浏览器兼容

+ + + +

{{Compat("webextensions.api.search.search", 10)}}

+ +

例子

+ +

使用默认搜索引擎进行搜索。 结果显示在新选项卡中:

+ +
function search() {
+  browser.search.search({
+    query: "styracosaurus"
+  });
+}
+
+browser.browserAction.onClicked.addListener(search);
+
+ +

使用维基百科进行搜索。 结果显示在新选项卡中:

+ +
function search() {
+  browser.search.search({
+    query: "styracosaurus",
+    engine: "Wikipedia (en)"
+  });
+}
+
+browser.browserAction.onClicked.addListener(search);
+
+ +

使用维基百科进行搜索。 结果将显示在活动选项卡中:

+ +
function search(tab) {
+  browser.search.search({
+    query: "styracosaurus",
+    engine: "Wikipedia (en)",
+    tabId: tab.id
+  });
+}
+
+browser.browserAction.onClicked.addListener(search);
+
+ +

{{WebExtExamples}}

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 +--- +
{{AddonSidebar}}
+ +

Use the sessions API to list, and restore, tabs and windows that have been closed while the browser has been running.

+ +

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")}}.

+ +

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.

+ +

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.

+ +

To use the sessions API you must have the "sessions" API permission.

+ +

Types

+ +
+
{{WebExtAPIRef("sessions.Filter")}}
+
Enables you to restrict the number of {{WebExtAPIRef("sessions.Session", "Session")}} objects returned by a call to {{WebExtAPIRef("sessions.getRecentlyClosed()")}}.
+
{{WebExtAPIRef("sessions.Session")}}
+
+

Represents a tab or window that the user has closed in the current browsing session.

+
+
+ +

Properties

+ +
+
{{WebExtAPIRef("sessions.MAX_SESSION_RESULTS")}}
+
The maximum number of sessions that will be returned by a call to sessions.getRecentlyClosed().
+
+ +

Functions

+ +
+
{{WebExtAPIRef("sessions.forgetClosedTab()")}}
+
Removes a closed tab from the browser's list of recently closed tabs.
+
{{WebExtAPIRef("sessions.forgetClosedWindow()")}}
+
Removes a closed window from the browser's list of recently closed windows.
+
{{WebExtAPIRef("sessions.getRecentlyClosed()")}}
+
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).
+
{{WebExtAPIRef("sessions.restore()")}}
+
+

Restores a closed tab or window.

+
+
{{WebExtAPIRef("sessions.setTabValue()")}}
+
+

Store a key/value pair associated with a given tab.

+
+
{{WebExtAPIRef("sessions.getTabValue()")}}
+
+

Retrieve a previously stored value for a given tab, given its key.

+
+
{{WebExtAPIRef("sessions.removeTabValue()")}}
+
+

Remove a key/value pair from a given tab.

+
+
{{WebExtAPIRef("sessions.setWindowValue()")}}
+
+

Store a key/value pair associated with a given window.

+
+
{{WebExtAPIRef("sessions.getWindowValue()")}}
+
+

Retrieve a previously stored value for a given window, given its key.

+
+
{{WebExtAPIRef("sessions.removeWindowValue()")}}
+
+

Remove a key/value pair from a given window.

+
+
+ +

Events

+ +
+
{{WebExtAPIRef("sessions.onChanged")}}
+
+

Fired when a tab or window is closed.

+
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.sessions")}}

+ +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.sessions API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

Session对象表示用户在当前浏览会话中已关闭的选项卡或窗口。

+ +

如果关闭了选项卡但未关闭其窗口,则会话以{{WebExtAPIRef("tabs.Tab", "Tab")}}对象表示:例如,因为用户单击了“关闭选项卡”按钮,并且此选项卡不是其窗口中的唯一选项卡。

+ +

如果关闭窗口,则会话表示为{{WebExtAPIRef("windows.Window", "Window")}}对象:例如,由于用户单击“关闭窗口”按钮,或关闭了窗口中唯一打开的选项卡。

+ +

请注意,不同的浏览器可能对会话何时为Tab和何时为Window有不同的想法。例如:

+ + + +

打开的选项卡的Tab对象没有sessionId关闭选项卡时,它将具有一个sessionId但没有选项卡id如果恢复了该标签页,它将获得一个新的标签页,id并且会丢失sessionId

+ +

类型

+ +

此类型的值是对象。它们包含以下属性:

+ +
+
lastModified
+
number选项卡或窗口关闭的时间,自epoch以来的毫秒数
+
tab{{optional_inline}}
+
object如果对象表示关闭的选项卡,则此属性存在,并且将是{{WebExtAPIRef("tabs.Tab")}}对象。仅当扩展名具有“ tabs” 许可权时url它才会包含titlefavIconUrl
+
window{{optional_inline}}
+
object如果对象表示一个关闭的窗口,则此属性存在并且将是{{WebExtAPIRef("windows.Window")}}对象。
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.sessions.Session")}}

+ +
致谢 + +

该API基于Chromium的chrome.sessionsAPI。

+ +

Microsoft Edge兼容性数据由Microsoft Corporation提供,并在此处包含在Creative Commons Attribution 3.0美国许可证下。

+
+ + 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 +--- +
{{AddonSidebar}}
+ +
使浏览器扩展能够储存及获取数据,以及监听储存的数据的变化。
+ +
+ +

此存储系统API基于 Web Storage API, 并有少许不同。

+ +

为了使用该API,您需要在manifest.json文件包含"storage"权限。每一个浏览器扩展有自己的储存区域,每一个储存区域又分为几种不同的存储类型。

+ +

虽然此API类似于{{domxref("Window.localStorage")}},但仍建议您不要在插件中使用Window.localStorage。当用户由于隐私原因清除历史浏览记录及数据时,火狐会将在浏览器扩展使用 localStorage API存储的数据一并清除。而使用 storage.localAPI存储的数据将会恰当保留。

+ +

类型

+ +
+
{{WebExtAPIRef("storage.StorageArea")}}
+
代表存储区域的对象
+
{{WebExtAPIRef("storage.StorageChange")}}
+
代表改变一个储存区域的对象
+
+ +

属性

+ +

storage有3个属性,每一个代表不同的存储区域。

+ +
+
{{WebExtAPIRef("storage.sync")}}
+
表示一个同步的储存区域。在此区域的数据通过浏览器进行同步,用户可通过登录使用不同的设备访问到浏览器所有可用的实例对象。
+
{{WebExtAPIRef("storage.local")}}
+
表示一个本地的存储区域。此区域的数据属于其所在的插件。
+
{{WebExtAPIRef("storage.managed")}}
+
表示管理的存储区域。此区域的数据由本域名下的管理员设置且对该插件是只读的。试图修改此区域数据会得到一个错误。
+
+ +

事件

+ +
+
{{WebExtAPIRef("storage.onChanged")}}
+
当storage有数据变化时,此事件将被触发。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.storage")}}

+ + + +

在Edge中的不兼容

+ +

Promises在Edge中不被支持,使用callbacks代替。

+ +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

这个API基于Chromium的 chrome.storage API. 这篇文档也来源于Chromium 代码中的 storage.json.

+ +

Microsoft Edge的适配数据由Microsoft Corporation提供并且被包含在Creative Commons Attribution 3.0 United States License许可证下.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

新建一个 tab.

+ +

这是一个异步函数,返回 Promise.

+ +

语法

+ +
var creating = browser.tabs.create(
+  createProperties   // object
+)
+
+ +

参数

+ +
+
createProperties
+
object. Properties to give the new tab. To learn more about these properties, see the {{WebExtAPIRef("tabs.Tab")}} documentation.
+
+
+
active{{optional_inline}}
+
boolean. 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 true.
+
cookieStoreId {{optional_inline}}
+
string. Use this to create a tab whose cookie store ID is cookieStoreId. This option is only available if the extension has the "cookies" permission.
+
index{{optional_inline}}
+
integer. 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.
+
openerTabId{{optional_inline}}
+
integer. 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.
+
openInReaderMode{{optional_inline}}
+
boolean. If true, open this tab in Reader Mode. Defaults to false.
+
pinned{{optional_inline}}
+
boolean. Whether the tab should be pinned. Defaults to false.
+
selected{{optional_inline}}
+
boolean. Whether the tab should become the selected tab in the window. Defaults to true. +
This property is deprecated, and is not supported in Firefox. Use active instead.
+
+
url{{optional_inline}}
+
string. The URL to navigate the tab to initially. Defaults to the New Tab Page.
+
Fully-qualified URLs must include a scheme (i.e. 'http://www.google.com', not 'www.google.com').
+
For security reasons, in Firefox, this may not be a privileged URL. So passing any of the following URLs will fail:
+
+
    +
  • chrome: URLs
  • +
  • javascript: URLs
  • +
  • data: URLs
  • +
  • file: URLs (i.e., files on the filesystem. However, to use a file packaged inside the extension, see below)
  • +
  • privileged about: URLs (for example, about:config, about:addons, about:debugging) . Non-privileged URLs (e.g., about:blank) are allowed.
  • +
  • The New Tab page (about:newtab) can be opened if no value for URL is provided.
  • +
+ +

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.

+
+
windowId{{optional_inline}}
+
integer. The window to create the new tab in. Defaults to the current window.
+
+
+
+ +

返回值

+ +

A Promise 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 url used a privileged scheme) the promise will be rejected with an error message.

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.tabs.create", 10)}}

+ +

实例

+ +

在新标签页打开 "https://example.org" :

+ +
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);
+});
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.tabs API. This documentation is derived from tabs.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

丢弃一个或多个标签页。

+ +

一些浏览器会自动“丢弃”它们认为近期不再被用户所需要的标签页。这些标签页会在标签栏中保持可见,浏览器会记住它们的状态,所以,如果用户选中了被丢弃的标签页,它会立即还原到被丢弃之前的状态。

+ +

对于不同的浏览器,被丢弃内容的详细内容是有所不同的,但是从大体上来说,丢弃一个标签页允许浏览器释放一些该标签页所占用的内存。

+ +

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 beforeunload listener that would display a prompt.

+ +

This is an asynchronous function that returns a Promise.

+ +

语法

+ +
var discarding = browser.tabs.discard(
+  tabIds          // integer or integer array
+)
+
+ +

Parameters

+ +
+
tabIds
+
integer or array of integer. The IDs of the tab or tabs to discard.
+
+ +

Return value

+ +

A Promise 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.

+ +

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.

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.tabs.discard", 10)}}

+ +

示例

+ +

丢弃一个标签页:

+ +
function onDiscarded() {
+  console.log(`Discarded`);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+var discarding = browser.tabs.discard(2);
+discarding.then(onDiscarded, onError);
+ +

丢弃多个标签页:

+ +
function onDiscarded() {
+  console.log(`Discarded`);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+var discarding = browser.tabs.discard([15, 14, 1]);
+discarding.then(onDiscarded, onError);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.tabs API.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

将 JavaScript 代码注入页面。

+ +

You can inject code into pages whose URL can be expressed using a match pattern: 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 host permission, or via the activeTab permission.

+ +

You can also inject code into pages packaged with your own extension:

+ +
browser.tabs.create({url: "/my-page.html"}).then(() => {
+  browser.tabs.executeScript({
+    code: `console.log('location:', window.location.href);`
+  });
+});
+ +

You don't need any special permissions to do this.

+ +

You can't 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.

+ +

The scripts you inject are called content scripts. Learn more about content scripts.

+ +

This is an asynchronous function that returns a Promise.

+ +

Syntax

+ +
var executing = browser.tabs.executeScript(
+  tabId,                 // optional integer
+  details                // object
+)
+
+ +

Parameters

+ +
+
tabId {{optional_inline}}
+
integer. The ID of the tab in which to run the script. Defaults to the active tab of the current window.
+
details
+
An object describing the script to run. It contains the following properties:
+
+
+
allFrames {{optional_inline}}
+
boolean. If true, the code will be injected into all frames of the current page. If true and frameId is set, then it will raise an error,  frameId and allFrames are mutually exclusive. If it is false, code is only injected into the top frame. Defaults to false.
+
code {{optional_inline}}
+
string. Code to inject, as a text string. Warning: Don’t use this property to interpolate untrusted data into JavaScript, as this could lead to a security issue.
+
file {{optional_inline}}
+
string. 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: "/path/to/script.js".
+
frameId {{optional_inline}}
+
integer. The frame where the code should be injected. Defaults to 0 (the top-level frame).
+
matchAboutBlank {{optional_inline}}
+
boolean. If true, 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 false.
+
runAt {{optional_inline}}
+
{{WebExtAPIRef('extensionTypes.RunAt')}}. The soonest that the code will be injected into the tab. Defaults to "document_idle".
+
+
+
+ +

Return value

+ +

A Promise that will be fulfilled with an array of objects, representing the result of the script in every injected frame.

+ +

The result of the script is the last evaluated statement, which is similar to what would be output (the results, not any console.log() output) if you executed the script in the Web Console. For example, consider a script like this:

+ +
var foo='my result';foo;
+ +

Here the results array will contain the the string "my result" as an element. The result values must be structured clonable.

+ +

If any error occurs the promise will be rejected with an error message.

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.tabs.executeScript")}}

+ +

Examples

+ +

This example executes a one-line code snippet in the currently active tab:

+ +
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);
+ +

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:

+ +
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);
+ +

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:

+ +
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);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.tabs API. This documentation is derived from tabs.json in the Chromium code.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

与浏览器标签系统进行交互。

+ +

你可以使用该API获取一个已打开标签的列表并且使用各种标准过滤标签,并进行 打开, 刷新,移动,重载,移除操作。该API不能直接访问标签中的主机内容,但是你可以使用 {{WebExtAPIRef("tabs.executeScript()")}} 或者 {{WebExtAPIRef("tabs.insertCSS()")}} APIs,来插入javascript和CSS。

+ +

你可以在不需要任何特殊权限的情况下使用该APIS的大部分, 除了:

+ + + +

或者你可以仅仅只为当前的活动标签临时的获取这些权限并且仅仅只响应一个显示的用户行为,请查看 "activeTab" permission.

+ +

枚举值

+ +
+
{{WebExtAPIRef("tabs.MutedInfoReason")}}
+
确定一个标签静音与否的原因(用户修改,扩展修改)。
+
{{WebExtAPIRef("tabs.MutedInfo")}}
+
该对象包含一个布尔值只是该标签是否静音,以及最近一次静音的原因。
+
{{WebExtAPIRef("tabs.Tab")}}
+
该值包含了一个标签的信息。
+
{{WebExtAPIRef("tabs.TabStatus")}}
+
指示某个标签是否已经加载完成
+
{{WebExtAPIRef("tabs.WindowType")}}
+
包含该标签的窗口类型。
+
{{WebExtAPIRef("tabs.ZoomSettingsMode")}}
+
定义缩放由浏览器控制或是扩展,或者禁用。
+
{{WebExtAPIRef("tabs.ZoomSettingsScope")}}
+
定义缩放将对某个网址持续生效,或者仅仅只针对该标签。
+
{{WebExtAPIRef("tabs.ZoomSettings")}}
+
定义缩放设置。 {{WebExtAPIRef("tabs.ZoomSettingsMode", "mode")}}, {{WebExtAPIRef("tabs.ZoomSettingsScope", "scope")}}, 和默认缩放比例。
+
+ +

属性

+ +
+
{{WebExtAPIRef("tabs.TAB_ID_NONE")}}
+
给予非浏览器标签的一个特殊ID值 (比如,在开发工具中的标签)。
+
+ +

方法

+ +
+
{{WebExtAPIRef("tabs.connect()")}}
+
在运行于该标签的任何 content scripts  和该扩展的后台脚本(或者其他的比如弹出菜单脚本或者设置页面脚本)间创建一个消息连接。
+
{{WebExtAPIRef("tabs.create()")}}
+
创建一个新标签。
+
{{WebExtAPIRef("tabs.captureVisibleTab()")}}
+
创意一个数据统一资源标识符解码在规定窗口中当前活动标签的可视区域重的一个图片。
+
{{WebExtAPIRef("tabs.detectLanguage()")}}
+
检查在一个标签中的主要语言。
+
{{WebExtAPIRef("tabs.duplicate()")}}
+
复制一个标签
+
{{WebExtAPIRef("tabs.executeScript()")}}
+
向一个页面注入脚本。
+
{{WebExtAPIRef("tabs.get()")}}
+
取回制定标签的详细信息。
+
{{WebExtAPIRef("tabs.getAllInWindow()")}} {{deprecated_inline}}
+
获取指定窗口所有标签的详细信息。
+
{{WebExtAPIRef("tabs.getCurrent()")}}
+
返回一个 tabs.Tab 对象包含了该脚本当前的宿主标签的信息。
+
{{WebExtAPIRef("tabs.getSelected()")}} {{deprecated_inline}}
+
获取在指定窗口被选定的标签。
+
{{WebExtAPIRef("tabs.getZoom()")}}
+
获取制定标签的缩放系数。
+
{{WebExtAPIRef("tabs.getZoomSettings()")}}
+
获取指定标签的缩放设置。
+
{{WebExtAPIRef("tabs.highlight()")}}
+
高亮显示一个或多个标签。
+
{{WebExtAPIRef("tabs.insertCSS()")}}
+
向一个页面注入CSS。
+
{{WebExtAPIRef("tabs.removeCSS()")}}
+
移除之前调用{{WebExtAPIRef("tabs.insertCSS()")}} 注入的一个css。
+
{{WebExtAPIRef("tabs.move()")}}
+
移动一个或多个标签页到同一窗口的一个新的位置或是到不同窗口。
+
{{WebExtAPIRef("tabs.query()")}}
+
获取所有包含指定属性的标签,如果没有属性则获取所有标签。
+
{{WebExtAPIRef("tabs.reload()")}}
+
重在一个标签,可选的可以绕过本地缓存。
+
{{WebExtAPIRef("tabs.remove()")}}
+
关闭一个或多个标签。
+
{{WebExtAPIRef("tabs.sendMessage()")}}
+
向一个指定标签的content script 发送单个消息。
+
{{WebExtAPIRef("tabs.sendRequest()")}} {{deprecated_inline}}
+
向一个指定标签的content script 发送一个单一请求。 过时: 请使用 {{WebExtAPIRef("tabs.sendMessage()")}} 替代。
+
{{WebExtAPIRef("tabs.setZoom()")}}
+
缩放指定标签。
+
{{WebExtAPIRef("tabs.setZoomSettings()")}}
+
为一个制定标签设置缩放选项。
+
{{WebExtAPIRef("tabs.update()")}}
+
导航一个标签到新的地址,或是修改其它的属性。
+
+ +

Events

+ +
+
{{WebExtAPIRef("tabs.onActivated")}}
+
当窗口活动标签改变时触发,注意当该消息触发时,标签地址可能没有被设置。
+
{{WebExtAPIRef("tabs.onActiveChanged")}} {{deprecated_inline}}
+
 已过时: 请使用 {{WebExtAPIRef("tabs.onActivated")}} 代替。
+
{{WebExtAPIRef("tabs.onAttached")}}
+
当一个标签被附加到一个窗口时触发,因为他可能在窗口间移动。
+
{{WebExtAPIRef("tabs.onCreated")}}
+
当一个标签被创建时触发,注意当该事件触发时可能没有设置地址。
+
{{WebExtAPIRef("tabs.onDetached")}}
+
当一个标签脱离一个窗口时被触发。
+
{{WebExtAPIRef("tabs.onHighlightChanged")}} {{deprecated_inline}}
+
过时: 请使用 {{WebExtAPIRef("tabs.onHighlighted")}} 代替。
+
{{WebExtAPIRef("tabs.onHighlighted")}}
+
当一个标签被高亮显示或是被选中时触发。
+
{{WebExtAPIRef("tabs.onMoved")}}
+
当一个标签在一个窗口内移动时被触发。
+
{{WebExtAPIRef("tabs.onRemoved")}}
+
当一个标签关闭时被处罚。
+
{{WebExtAPIRef("tabs.onReplaced")}}
+
当一个标签因为预载取代另一个标签时被触发。
+
{{WebExtAPIRef("tabs.onSelectionChanged")}} {{deprecated_inline}}
+
 以过时: 请使用 {{WebExtAPIRef("tabs.onActivated")}} 代替。
+
{{WebExtAPIRef("tabs.onUpdated")}}
+
当一个标签被更新时触发。
+
{{WebExtAPIRef("tabs.onZoomChange")}}
+
当一个标签被缩放时触发
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.tabs")}}

+ + + +

 {{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.tabs API. This documentation is derived from tabs.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

向一个页面注入CSS

+ +

使用该API前你必须拥有目标页面的权限, 可以是 主机权限, 或者使用 activeTab 权限.

+ +

你只能向符合 match pattern 的网页注入CSS: 其形式必定是 "http", "https", "file", "ftp" 之一. 你不能向任何浏览器内置页面注入CSS, 比如 about:debugging, about:addons, 或者你打开的一个新的空白页。

+ +

当再次调用{{WebExtAPIRef("tabs.removeCSS()")}} 时,已经注入的CSS可能会被清除。

+ +

这是一个返回Promise 的异步函数。

+ +

Syntax

+ +
var inserting = browser.tabs.insertCSS(
+  tabId,           // optional integer
+  details          // extensionTypes.InjectDetails
+)
+
+ +

参数

+ +
+
tabId {{optional_inline}}
+
integer, 将要注入css的标签ID。默认为当前窗口的活动标签。
+
details
+
{{WebExtAPIRef('extensionTypes.InjectDetails')}}. 对注入的描述,包含以下属性:
+
+
+
allFrames{{optional_inline}}
+
boolean. 如果为真,该CSS会被注入到该页面的所有框架,如果为假,Css只会注入到最顶层框架,默认为假。
+
code{{optional_inline}}
+
string. 将要注入的代码。
+
file{{optional_inline}}
+
string. 包含将要注入代码的文件路径,在Firefox中,相对URLs 决定于当前页面的URL,在Chrome中,决定于扩展的基础URL。为了跨浏览器工作,你应该使用一个从扩展根目录开始的绝对路径,比如 : "/path/to/stylesheet.css".
+
frameId{{optional_inline}}
+
integer. CSS应该被注入的框架. 默认为 0 (顶层框架).
+
matchAboutBlank{{optional_inline}}
+
boolean. If true, 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 false.
+
runAt{{optional_inline}}
+
{{WebExtAPIRef('extensionTypes.RunAt')}}. The soonest that the code will be injected into the tab. Defaults to "document_idle".
+
+
+
+ +

Return value

+ +

 Promise 将会在CSS成功注入时 被填充,如果有任何错误发生,promise将会被注入一个错误消息。

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.tabs.insertCSS")}}

+ +

例子

+ +

下面例子将通过字符串变量形式向当前活动标签注入一段CSS代码

+ +
var css = "body { border: 20px dotted pink; }";
+
+browser.browserAction.onClicked.addListener(() => {
+
+  function onError(error) {
+    console.log(`Error: ${error}`);
+  }
+
+  var insertingCSS = browser.tabs.insertCSS({code: css});
+  insertingCSS.then(null, onError);
+});
+ +

下面例子将以通过加载文件形式向页面注入CSS。CSS被注入在ID为2的tab中。

+ +
browser.browserAction.onClicked.addListener(() => {
+
+  function onError(error) {
+    console.log(`Error: ${error}`);
+  }
+
+  var insertingCSS = browser.tabs.insertCSS(2, {file: "content-style.css"});
+  insertingCSS.then(null, onError);
+});
+ +

{{WebExtExamples}}

+ +
致谢 + +

本页 API 以谷歌 Chromium的 chrome.tabs API为基础. 该篇文档由Chromium 代码 tabs.json衍变而来.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +
当窗体的活动标签变化时触发。请注意事件触发时标签的 URL 可能尚未设置,但是你可以通过监听 {{WebExtAPIRef("tabs.onUpdated")}} 事件在 URL 被设置后得到通知。
+ +

语法

+ +
browser.tabs.onActivated.addListener(listener)
+browser.tabs.onActivated.removeListener(listener)
+browser.tabs.onActivated.hasListener(listener)
+
+ +

此事件有三个方法:

+ +
+
addListener(callback)
+
向此事件添加一个监听。
+
removeListener(listener)
+
停止监听此事件。 listener 参数是将要移除的监听。
+
hasListener(listener)
+
检查 listener 是否在此事件中注册。如果正在监听返回 true ,否则 false。
+
+ +

addListener 语法

+ +

参数

+ +
+
callback
+
+

事件发生时被执行的方法。以下参数会被传递至该方法:

+ +
+
activeInfo
+
object. 被激活标签的ID , 以及它的窗体的 ID 。
+
+
+
+ +

额外的对象

+ +

activeInfo

+ +
+
tabId
+
integer. 被激活的标签的ID。
+
windowId
+
integer. 此标签的窗体的ID。
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.tabs.onActivated")}}

+ +

示例

+ +

监听并记录标签激活事件:

+ +
function handleActivated(activeInfo) {
+  console.log("Tab " + activeInfo.tabId +
+              " was activated");
+}
+
+browser.tabs.onActivated.addListener(handleActivated);
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.tabs API. This documentation is derived from tabs.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

从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.

+ +

这个消息将被content scripts中 {{WebExtAPIRef("runtime.onMessage")}} 事件的所有监听者收到,然后它们可以选择通过使用 sendResponse 这个方法发送一个response到background scripts。

+ +

This is an asynchronous function that returns a Promise.

+ +

Syntax

+ +
var sending = browser.tabs.sendMessage(
+  tabId,                   // integer
+  message,                 // any
+  options                  // optional object
+)
+
+ +

Parameters

+ +
+
tabId
+
integer. ID of the tab whose content scripts we want to send a message to.
+
message
+
any. An object that can be serialized to JSON.
+
options{{optional_inline}}
+
object.
+
+
+
frameId{{optional_inline}}
+
integer. Sends the message to a specific frame identified by frameId instead of all frames in the tab. Whether the content script is executed in all frames depends on the all_frames setting in the content_scripts section of manifest.json.
+
+
+
+ +

Return value

+ +

A Promise 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.

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.tabs.sendMessage")}}

+ +

Examples

+ +

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:

+ +
// 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 => {
+      console.log("Message from the content script:");
+      console.log(response.response);
+    }).catch(onError);
+  }
+}
+
+browser.browserAction.onClicked.addListener(() => {
+  browser.tabs.query({
+    currentWindow: true,
+    active: true
+  }).then(sendMessageToTabs).catch(onError);
+});
+ +

Here's the corresponding content script:

+ +
// content-script.js
+"use strict";
+
+browser.runtime.onMessage.addListener(request => {
+  console.log("Message from the background script:");
+  console.log(request.greeting);
+  return Promise.resolve({response: "Hi from content script"});
+});
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.tabs API. This documentation is derived from tabs.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

 tabs.Tab 包含有关标签页的信息 . 这样可以访问有关标签页中的内容,内容有多大,特殊状态或限制有效的信息等等。

+ +

类型

+ +

这种类型的值是对象。它包含以下属性:

+ +
+
active
+
boolean. 该标签页是否在其窗口中处于活动状态。即使标签的窗口当前没有被关注,也可能是true。
+
audible {{optional_inline}}
+
boolean. 如果标签页没有静音:标签页是否正在发出声音。如果标签页被静音:如果没有静音标签页是否会发出声音。
+
autoDiscardable {{optional_inline}}
+
boolean. 资源不足时浏览器是否可以自动丢弃该标签页。
+
cookieStoreId {{optional_inline}}
+
string. 该标签页的Cookie存储. 如果不同的标签可以有不同的cookie存储 (例如, 支持 contextual identity), you can pass this as the storeId option into various methods of the {{WebExtAPIRef("cookies")}} API, 设置和获取与此标签页的Cookie存储关联的Cookie。 只有在扩展名具有“cookies”
+
string. 该标签页的Cookie存储. 如果不同的标签可以有不同的cookie存储 (例如, 支持 contextual identity), 你可以将此作为 storeId 选项传递给 {{WebExtAPIRef("cookies")}} API的各种方法, 设置和获取与此标签页的Cookie存储关联的Cookie。 只有在扩展具有“cookies”权限的情况下才会出现.
+
discarded {{optional_inline}}
+
boolean. 是否丢弃的标签页。被丢弃的标签页是其内容已经从内存中卸载的标签页,但在标签页条中仍可见。它的内容在下一次被激活时被重新加载。
+
favIconUrl {{optional_inline}}
+
string. 该标签的图标的网址。 只有在扩展具有“cookies”权限的情况下才会出现. 如果标签页正在加载中,该值可以为空字符串
+
height {{optional_inline}}
+
integer. 标签页的像素单位高度。
+
highlighted
+
boolean. 标签页是否突出显示。
+
id {{optional_inline}}
+
integer. 标签页的ID. 标签 ID在浏览器的会话中是唯一的 。 在浏览器窗口中不包含内容的标签页 (例如, devtools 窗口),标签 ID 也可以设置为 {{WebExtAPIRef('tabs.TAB_ID_NONE')}} 。
+
incognito
+
boolean. 该标签页是否在隐私浏览窗口中。
+
index
+
integer. 窗口中的标签页从零开始的索引。
+
isArticle
+
boolean. 如果标签页可以在 Reader模式下呈现,则返回true,否则返回false。
+
isInReaderMode
+
boolean. 如果标签页正在 Reader模式下呈现,则返回true,否则返回false。
+
lastAccessed
+
double. 上次访问该标签页的时间 , 参考 milliseconds since the epoch.
+
mutedInfo {{optional_inline}}
+
{{WebExtAPIRef('tabs.MutedInfo')}}.标签页的当前静音状态以及上次状态更改的原因。
+
openerTabId {{optional_inline}}
+
integer. 打开此标签页的标签页ID(如果有)。如果开启者标签页仍然存在,该属性才会出现。
+
pinned
+
boolean. 标签页是否被固定
+
selected {{deprecated_inline}}
+
boolean.标签页是否被选中
+
sessionId {{optional_inline}}
+
string. 从{{WebExtAPIRef('sessions')}} API 获取的标签页的唯一标识会话ID.
+
status {{optional_inline}}
+
string.加载完成.
+
title {{optional_inline}}
+
string. 标签页的标题. 只有当扩展具有 "tabs" 权限 时才会出现.
+
url {{optional_inline}}
+
string. 该选项卡正在显示的文档的URL。只有当扩展具有 "tabs" 权限 时才会出现.
+
width {{optional_inline}}
+
integer. 标签页的像素单位宽度。
+
windowId
+
integer. 包含此标签页的窗口ID。
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.tabs.Tab", 10)}}

+ +

{{WebExtExamples}}

+ +
感谢 + +

此 API 基于 Chromium的 chrome.tabs API. 本文档来源于Chromium 代码中的 tabs.json.

+ +

Microsoft Edge兼容性数据由Microsoft Corporation提供,并包含在Creative Commons Attribution 3.0美国许可证下。

+
+ + diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/\346\237\245\350\257\242/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/\346\237\245\350\257\242/index.html" new file mode 100644 index 0000000000..9afe6e80a8 --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/\346\237\245\350\257\242/index.html" @@ -0,0 +1,179 @@ +--- +title: 选项卡. 查询 () +slug: Mozilla/Add-ons/WebExtensions/API/tabs/查询 +translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/query +--- +
[阿登侧边栏()]
+ +

获取具有指定属性的所有选项卡,如果未指定任何属性,则获取所有选项卡。

+ +

这是返回 的异步函数。Promise

+ +

语法

+ +
let querying = browser.tabs.query(queryObj)
+
+ +

参数

+ +
+
queryObj
+
+

object.函数将仅获取其属性与此处包含的属性匹配的选项卡。query()

+ +

请参阅 \WebExtAPIRef("选项卡")。Tab")=文档以了解有关这些属性的详细信息。

+ +
+
active[optional_inline]
+
boolean.选项卡是否在窗口中处于活动状态。
+
audible[optional_inline]
+
boolean.标签是否可听见。
+
autoDiscardable[optional_inline]
+
boolean.当资源不足时,浏览器是否可以自动丢弃选项卡。
+
cookieStoreId[optional_inline]
+
string.使用此仅返回其 Cookie 存储 ID 为 的选项卡。此选项仅在加载项具有权限时才可用cookieStoreId"cookies"
+
currentWindow[optional_inline]
+
boolean.选项卡是否在当前窗口中。
+
discarded[optional_inline]
+
boolean.是否丢弃选项卡。丢弃的选项卡是其内容已从内存中卸载,但仍在选项卡条中可见的选项卡。下次激活时,其内容将重新加载。
+
hidden[optional_inline]
+
boolean.选项卡是否隐藏。
+
highlighted[optional_inline]
+
boolean.选项卡是否突出显示。
+
index[optional_inline]
+
integer.选项卡在其窗口中的位置。
+
muted[optional_inline]
+
boolean.选项卡是否为静音。
+
lastFocusedWindow[optional_inline]
+
boolean.选项卡是否在上一个焦点窗口中。
+
pinned[optional_inline]
+
boolean.选项卡是否固定。
+
status[optional_inline]
+
{WebExtAPIRef('选项卡。TabStatus ')=。选项卡是否已完成加载。
+
title[optional_inline]
+
string.将页面标题与图案匹配。
+
url[optional_inline]
+
string或。将选项卡与一个或多个匹配模式匹配。请注意,片段标识符不匹配。array of string
+
windowId{{optional_inline}}
+
integer. The of the parent window, or {{WebExtAPIRef('windows.WINDOW_ID_CURRENT')}} for the current window.id
+
windowType{{optional_inline}}
+
{{WebExtAPIRef('tabs.WindowType')}}. The type of window the tabs are in.
+
+
+
+ +

Return value

+ +

A that will be fulfilled with an of objects, containing information about each matching tab.Promisearray{{WebExtAPIRef('tabs.Tab')}}

+ +

If any error occurs, the promise will be rejected with an error message.

+ +

Examples

+ +

Get all tabs:

+ +
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);
+ +

Get all tabs in the current window:

+ +
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);
+ +

Get the active tab in the current window:

+ +
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);
+ +

Get tabs for all HTTP and HTTPS URLs under or any of its subdomains:"mozilla.org"

+ +
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);
+ +

{{WebExtExamples}}

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.tabs.query")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.tabs API. This documentation is derived from tabs.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

A BrowserSetting is an object representing a browser setting.

+ +

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.

+ +

Note that while this object is based on the ChromeSetting 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 scope option to ChromeSetting.set()) are not implemented.

+ +

Methods

+ +
+
{{WebExtAPIRef("types.BrowserSetting.get()")}}
+
Get the current value of the setting, and an enumeration representing how the setting is currently controlled.
+
{{WebExtAPIRef("types.BrowserSetting.set()")}}
+
Set the setting to a new value.
+
{{WebExtAPIRef("types.BrowserSetting.clear()")}}
+
Clear any change made to the setting by this extension.
+
+ +

Events

+ +
+
{{WebExtAPIRef("types.BrowserSetting.onChange")}}
+
Fired when the setting's value changes.
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.types.BrowserSetting")}}

+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.types API.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

Use BrowserSetting.set() to change the browser setting to a new value.

+ +

There are some rules that can restrict when extensions are able to change settings:

+ + + +

This means that if extension X tries to change a setting:

+ +
    +
  1. 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.
  2. +
  3. 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.
  4. +
  5. 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.
  6. +
  7. 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.
  8. +
+ +

An extension can find out which of these scenarios applies by examining the "levelOfControl" property returned from a call to BrowserSetting.get().

+ +

The BrowserSetting.set() 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 true: otherwise it is false.

+ +

Syntax

+ +
var setting = setting.set(
+  details     // object
+)
+
+ +

Parameters

+ +
+
details
+
An object that must contain the following property:
+
+
+
value
+
any. The value you want to change the setting to. Its type depends on the particular setting.
+
+
+
+ +

Return value

+ +

A Promise that will be fulfilled with a boolean: true if the setting was modified, false otherwise (for example, because the extension did not control the setting).

+ +

Browser compatibility

+ +

See {{WebExtAPIRef("types.BrowserSetting")}}.

+ +

Example

+ +

Modify the hyperlinkAuditingEnabled setting (this requires the "privacy" permission):

+ +
function onSet(result) {
+  if (result) {
+    console.log("Value was updated");
+  } else {
+    console.log("Value was not updated");
+  }
+}
+
+browser.browserAction.onClicked.addListener(() => {
+
+    var setting = browser.privacy.websites.hyperlinkAuditingEnabled.set({
+      value: false
+    });
+    setting.then(onSet);
+
+});
+
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.types API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

Defines the BrowserSetting type, which is used to represent a browser setting.

+ +

Types

+ +
+
{{WebExtAPIRef("types.BrowserSetting")}}
+
Represents a browser setting.
+
+ +

Browser compatibility

+ +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.types API.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

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.

+ +

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.

+ +

Each event corresponds to a particular stage in the navigation. The sequence of events is like this:

+ +

+ + + +

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 iframe.

+ +

Each event's addListener() 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.

+ +

The onCommitted 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.

+ +

To use this API you need to have the "webNavigation" permission.

+ +

Types

+ +
+
{{WebExtAPIRef("webNavigation.TransitionType")}}
+
Cause of the navigation: for example, the user clicked a link, or typed an address, or clicked a bookmark.
+
{{WebExtAPIRef("webNavigation.TransitionQualifier")}}
+
+
Extra information about a transition.
+
+
+ +

Functions

+ +
+
{{WebExtAPIRef("webNavigation.getFrame()")}}
+
Retrieves information about a particular frame. A frame may be the top-level frame in a tab or a nested iframe, and is uniquely identified by a tab ID and a frame ID.
+
{{WebExtAPIRef("webNavigation.getAllFrames()")}}
+
+

Given a tab ID, retrieves information about all the frames it contains.

+
+
+ +

Events

+ +
+
{{WebExtAPIRef("webNavigation.onBeforeNavigate")}}
+
+

Fired when the browser is about to start a navigation event.

+
+
{{WebExtAPIRef("webNavigation.onCommitted")}}
+
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.
+
{{WebExtAPIRef("webNavigation.onDOMContentLoaded")}}
+
Fired when the DOMContentLoaded event is fired in the page.
+
{{WebExtAPIRef("webNavigation.onCompleted")}}
+
Fired when a document, including the resources it refers to, is completely loaded and initialized. This is equivalent to the DOM load event.
+
{{WebExtAPIRef("webNavigation.onErrorOccurred")}}
+
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.
+
{{WebExtAPIRef("webNavigation.onCreatedNavigationTarget")}}
+
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.
+
{{WebExtAPIRef("webNavigation.onReferenceFragmentUpdated")}}
+
Fired if the fragment identifier for a page is changed.
+
{{WebExtAPIRef("webNavigation.onTabReplaced")}}
+
+

Fired when the contents of the tab is replaced by a different (usually previously pre-rendered) tab.

+
+
{{WebExtAPIRef("webNavigation.onHistoryStateUpdated")}}
+
Fired when the page used the history API to update the URL displayed in the browser's location bar.
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.webNavigation")}}

+ + + +

Edge incompatibilities

+ +

Promises are not supported in Edge. Use callbacks instead.

+ +

{{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.webNavigation API. This documentation is derived from web_navigation.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

在页面中触发DOMContentLoaded 事件时触发。此时,文档被加载和解析,并且DOM被完全构造,但链接的资源(例如图像,样式表和子框架(subframes))可能尚未被加载。

+ +

Syntax

+ +
browser.webNavigation.onDOMContentLoaded.addListener(
+  listener,                   // function
+  filter                      // optional object
+)
+browser.webNavigation.onDOMContentLoaded.removeListener(listener)
+browser.webNavigation.onDOMContentLoaded.hasListener(listener)
+
+ +

事件有三个方法:

+ +
+
addListener(callback)
+
为此事件添加监听方法.
+
removeListener(listener)
+
停止监听此事件. listener 参数为需要移出的监听方法.
+
hasListener(listener)
+
检测是否有 listener 被注册在事件上. 如果有返回 true , 否则返回false .
+
+ +

addListener syntax

+ +

参数

+ +
+
callback
+
+

为当此事件发生是需要被调用的函数. 该函数将传递以下参数:

+ +
+
details
+
object. 有关导航(navigation)事件的详细信息.
+
+
+
filter{{optional_inline}}
+
+

object. 包含单个属性 url 的对象,  这是一个  {{WebExtAPIRef("events.UrlFilter")}} 数组对象. 如果包含此参数,则该事件将仅触发转换为与数组中至少一个UrlFilter匹配的URL。 在数组中。如果您省略此参数,则该事件将触发所有转换。

+
+
+ +

Additional objects

+ +

details

+ +
+
tabId
+
integer. The ID of the tab in which the navigation has occurred.
+
url
+
string. The URL to which the given frame has navigated.
+
processId
+
integer. The ID of the process in which this tab is being rendered.
+
frameId
+
integer. Frame in which the navigation is occurring. 0 indicates that navigation happens in the tab's top-level browsing context, not in a nested iframe. A positive value indicates that navigation happens in a nested iframe. Frame IDs are unique for a given tab and process.
+
timeStamp
+
number. The time at which DOMContentLoaded was fired, in milliseconds since the epoch.
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.webNavigation.onDOMContentLoaded")}}

+ +

Examples

+ +

Logs the target URLs for onDOMContentLoaded, if the target URL's hostname contains "example.com" or starts with "developer".

+ +
var filter = {
+  url:
+  [
+    {hostContains: "example.com"},
+    {hostPrefix: "developer"}
+  ]
+}
+
+function logOnDOMContentLoaded(details) {
+  console.log("onDOMContentLoaded: " + details.url);
+}
+
+browser.webNavigation.onDOMContentLoaded.addListener(logOnDOMContentLoaded, filter);
+
+
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.webNavigation API. This documentation is derived from web_navigation.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +
为发出的HTTP请求在不同阶段添加事件监听器。事件监听器可以接收到请求的详细信息,也可以修改或取消请求。
+ +

概况

+ +

每个事件都会在请求的特定阶段触发。事件的顺序大概是这样的:

+ +

在请求过程中的任意时间,{{WebExtAPIRef("webRequest.onErrorOccurred", "onErrorOccurred")}} 可以被触发。虽然有时候触发的事件顺序不同,举个例子,在火狐浏览器中的HSTS过程,在onBeforeRequest事件执行后,onBeforeRedirect 事件会被立即触发。

+ +

所有的事件,接受onErrorOccurred事件, addListener()有三个参数 :

+ + + +

这个监听函数接收一个details对象,这个对象包含这个请求的信息。他包含一个请求ID, 在插件中这个ID可以关联唯一个请求事件. 这个ID是浏览器会话和插件上下文中唯一的。他始终在同一个请求中,贯穿着转发和授权等事件中。

+ +

在一个给定的主机上使用webRequest API, 你必须有这个主机的相关权限,包括"webRequest" API permission 和 host permission. 为了使用 "blocking" 特性,你必须有 "webRequestBlocking" API 权限。

+ +

这个webRequest API不能让你进入一些安全敏感的请求,比如update checks and OCSP checks.

+ +

Modifying requests

+ +

在下边这些事件中,你可以修改请求. 比如一些特别的操作:

+ + + +

为了完成这些操作,你需要在extraInfoSpec参数中添加"blocking"的值到事件的addListener()。这将使得监听器变成同步执行。在监听器中,你可以返回一个表明需要作修改的{{WebExtAPIRef("webRequest.BlockingResponse", "BlockingResponse")}}对象:比如说,你想要发送的修改后的请求头。

+ +

从Firefox 52开始,监听器会返回一个resolve(BlockingResponse) 的 Promise,而不是直接返回一个BlockingResponse。这使得监听器可以异步地处理请求。

+ +

Types

+ +
+
{{WebExtAPIRef("webRequest.ResourceType")}}
+
Represents a particular kind of resource fetched in a web request.
+
{{WebExtAPIRef("webRequest.RequestFilter")}}
+
An object describing filters to apply to webRequest events.
+
{{WebExtAPIRef("webRequest.HttpHeaders")}}
+
An array of HTTP headers. Each header is represented as an object with two properties: name and either value or binaryValue.
+
{{WebExtAPIRef("webRequest.BlockingResponse")}}
+
+

An object of this type is returned by event listeners that have set "blocking" in their extraInfoSpec argument. By setting particular properties in BlockingResponse, the listener can modify network requests.

+
+
{{WebExtAPIRef("webRequest.UploadData")}}
+
Contains data uploaded in a URL request.
+
+ +

Properties

+ +
+
{{WebExtAPIRef("webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES")}}
+
The maximum number of times that handlerBehaviorChanged() can be called in a 10 minute period.
+
+ +

Functions

+ +
+
{{WebExtAPIRef("webRequest.handlerBehaviorChanged()")}}
+
This function can be used to ensure that event listeners are applied correctly when pages are in the browser's in-memory cache.
+
+ +

Events

+ +
+
{{WebExtAPIRef("webRequest.onBeforeRequest")}}
+
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.
+
{{WebExtAPIRef("webRequest.onBeforeSendHeaders")}}
+
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.
+
{{WebExtAPIRef("webRequest.onSendHeaders")}}
+
Fired just before sending headers. If your add-on or some other add-on modified headers in {{WebExtAPIRef("webRequest.onBeforeSendHeaders", "onBeforeSendHeaders")}}, you'll see the modified version here.
+
{{WebExtAPIRef("webRequest.onHeadersReceived")}}
+
Fired when the HTTP response headers associated with a request have been received. You can use this event to modify HTTP response headers.
+
{{WebExtAPIRef("webRequest.onAuthRequired")}}
+
Fired when the server asks the client to provide authentication credentials. The listener can do nothing, cancel the request, or supply authentication credentials.
+
{{WebExtAPIRef("webRequest.onResponseStarted")}}
+
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.
+
{{WebExtAPIRef("webRequest.onBeforeRedirect")}}
+
Fired when a server-initiated redirect is about to occur.
+
{{WebExtAPIRef("webRequest.onCompleted")}}
+
Fired when a request is completed.
+
{{WebExtAPIRef("webRequest.onErrorOccurred")}}
+
Fired when an error occurs.
+
+ +

Browser compatibility

+ +

{{Compat("webextensions.api.webRequest")}}

+ + + +

Edge incompatibilities

+ +

Promises are not supported in Edge. Use callbacks instead.

+ +

{{Compat("webextensions.api.webRequest")}} {{WebExtExamples("h2")}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.webRequest API. This documentation is derived from web_request.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

webRequest事件参数

+ +

Type

+ +

该参数值是一个对象,包括以下属性:

+ +
+
urls
+
字符串数组类型,数组内的每个字符串为模式匹配格式。当请求地址符合给定模式时,事件监听器才会响应。需注意的是,仅支持http和HTTPS协议的参数地址,其他协议即使与该给定模式匹配也不会响应。
+
types{{optional_inline}}
+
webRequest.ResourceType类型的数组,表示资源类型列表。例如:stylesheets、images、scripts。事件监听器仅响应出现在该指定列表的资源类型。
+
tabId{{optional_inline}}
+
数值类型,与{{WebExtAPIRef("tabs.Tab", "tab")}}关联,事件监听器仅响应指定了该tabId的请求。
+
windowId{{optional_inline}}
+
数值类型,与{{WebExtAPIRef("windows.Window", "window")}}关联,事件监听器仅响应指定了该windowId的请求。
+
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.api.webRequest.RequestFilter")}}

+ +

{{WebExtExamples}}

+ +
告知信息 + +

该API基于Chromium的 chrome.webRequest API. 该文档来源于Chromium代码中的 web_request.json

+ +

Microsoft Edge兼容性数据由Microsoft Corporation提供,并包含在Creative Commons Attribution 3.0 United States License下。

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

创建一个新的窗口.

+ +

当你创建一个窗口时,你可以:

+ + + +

这是一个异步的方法返回一个 Promise.

+ +

语法

+ +
var creating = browser.windows.create(
+  createData            // optional object
+)
+
+ +

参数

+ +
+
createData{{optional_inline}}
+
object.
+
+
+
url{{optional_inline}}
+
字符串或字符串数组. 一个URL或都URL数组要在该窗口中打开成标签页的. 完整的需要包括scheme (像. http://www.google.com, not www.google.com). 相对路径将相对于该拓展中的当前页. 默认为打开新标签页.
+
tabId{{optional_inline}}
+
integer. 如果设置了该值,将该tab从一个现有的窗口中移到新窗口中.
+
left{{optional_inline}}
+
integer. 窗口左边到屏幕左边缘的距离.如果没有设定,新窗口将按上一个焦点窗口定位水平位置. 对于panel样式窗口,该值不起作用.
+
top{{optional_inline}}
+
窗口顶部到屏幕的顶部距离.如果没有设定,新窗口将按上一个焦点窗口定位垂直位置. 对于panel样式窗口,该值不起作用.
+
width{{optional_inline}}
+
integer. 新窗口的宽度, 包含框架. 未设定则使用默认宽度。.
+
height{{optional_inline}}
+
integer. 新窗口的高度, 包含框架. 未设定则使用默认高度。.
+
focused{{optional_inline}}
+
boolean.如果 为true, 新窗口将获取焦点. 否则新窗口当在后台打开并且当前焦点窗口继续保持焦点.。.默认为true
+
incognito{{optional_inline}}
+
boolean. 是否打开为一个隐私窗口. 如果设定为隐私窗口并且引入了tabId, 则tabId对应的标签必须是一个隐私标签— 即不能把一个不是隐私标签的标签页移动到隐私窗口中。
+
type{{optional_inline}}
+
一{{WebExtAPIRef('windows.CreateType')}} 值,表示创建窗口的类型. panel 或者popup 样式将打开一个没有默认浏览器样式的窗口 (地址栏,工具栏等)。
+
state{{optional_inline}}
+
一个 {{WebExtAPIRef('windows.WindowState')}} 值, 窗口的祲状态。 最小化、最大化、全屏状态不能与left, top, width, or height属性一起使用。
+
+
+
+ +

返回值

+ +

一个 Promise 其中传入一个包含新窗口细节的 {{WebExtAPIRef('windows.Window')}} 对象。 这个{{WebExtAPIRef('windows.Window')}} 有自己的tabs属性集 ,而不像 {{WebExtAPIRef("windows.get()")}}返回的窗口对象和相似的API,  如果传递了populate项其仅仅包含tabs. 如果发生了错误 promise will be rejected with an error message.

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.windows.create", 10)}}

+ +

示例

+ +

打开一个包含两个标签的窗口

+ +
function onCreated(windowInfo) {
+  console.log(`Created window: ${windowInfo.id}`);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+browser.browserAction.onClicked.addListener((tab) => {
+  var creating = browser.windows.create({
+    url: ["https://developer.mozilla.org",
+          "https://addons.mozilla.org"]
+  });
+  creating.then(onCreated, onError);
+});
+ +

当用户点击一个browser action打开一个窗口,并且将当前活跃的标签移动其中

+ +
function onCreated(windowInfo) {
+  console.log(`Created window: ${windowInfo.id}`);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+browser.browserAction.onClicked.addListener((tab) => {
+  var creating = browser.windows.create({
+    tabId: tab.id
+  });
+  creating.then(onCreated, onError);
+});
+ +

打开一个小面板样式的窗口,并且加载一个本地包中的文件到其中

+ +
function onCreated(windowInfo) {
+  console.log(`Created window: ${windowInfo.id}`);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+browser.browserAction.onClicked.addListener((tab) => {
+
+  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);
+
+});
+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.windows API. This documentation is derived from windows.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + 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 +--- +
{{AddonSidebar}}
+ +

与浏览器窗口互动。您可以使用此 API 获取有关已打开窗口的信息,以及打开、修改和关闭窗口。您也可以监听窗口的打开、关闭和其激活事件。

+ +

类型

+ +
+
{{WebExtAPIRef("windows.WindowType")}}
+
浏览器窗口的类型。
+
{{WebExtAPIRef("windows.WindowState")}}
+
浏览器窗口的状态。
+
{{WebExtAPIRef("windows.Window")}}
+
有关一个浏览器窗口的信息。
+
{{WebExtAPIRef("windows.CreateType")}}
+
指定要创建的浏览器窗口的类型。
+
+ +

属性

+ +
+
{{WebExtAPIRef("windows.WINDOW_ID_NONE")}}
+
windowId 值表示不存在浏览器窗口。
+
{{WebExtAPIRef("windows.WINDOW_ID_CURRENT")}}
+
windowId 值表示当前窗口。
+
+ +

函数

+ +
+
{{WebExtAPIRef("windows.get()")}}
+
指定其 ID,获取一个窗口的细节。
+
{{WebExtAPIRef("windows.getCurrent()")}}
+
获取当前窗口。
+
{{WebExtAPIRef("windows.getLastFocused()")}}
+
获取最近获得焦点的窗口,通常它是“顶部”的窗口。
+
{{WebExtAPIRef("windows.getAll()")}}
+
获取所有窗口。
+
{{WebExtAPIRef("windows.create()")}}
+
+

创建新窗口。

+
+
{{WebExtAPIRef("windows.update()")}}
+
更新一个窗口的属性。使用此项对移动、调整大小、聚焦/取消聚焦等。
+
{{WebExtAPIRef("windows.remove()")}}
+
关闭一个窗口及其所有标签页。
+
+ +

事件

+ +
+
{{WebExtAPIRef("windows.onCreated")}}
+
一个窗口创建时触发。
+
{{WebExtAPIRef("windows.onRemoved")}}
+
一个窗口关闭时触发。
+
{{WebExtAPIRef("windows.onFocusChanged")}}
+
当前有焦点的窗口改变时触发。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.windows")}}

+ + + +

Edge 的不兼容

+ +

Edge 中不支持 Promises。需使用回调。

+ +

{{WebExtExamples("h2")}}

+ +
声明 + +

此 API 基于 Chromium 的 chrome.windows API。此文档基于 Chromium 代码中的 windows.json

+ +

Microsoft Edge 兼容性数据由微软公司提供,并包含在创作共用 署名 3.0美国许可证下。

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

浏览器窗口的状态。

+ +

类型

+ +

类型的值是字符串类型。 可能的值如下:

+ + + +

浏览器适配

+ + + +

{{Compat("webextensions.api.windows.WindowState")}}

+ +

{{WebExtExamples}}

+ +
致谢 + +

此API基于谷歌浏览器 chrome.windows API。此文档源于谷歌源码 windows.json .

+ +

微软Edge浏览器兼容性数据由微软公司提供,并包含在美国Creative Commons Attribution 3.0许可证下。

+
+ + 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 +--- +
{{AddonSidebar()}}
+ +

浏览器窗口的类型。

+ +

Type

+ +

类型的值是字符串类型。 可能的值如下:

+ + + +

浏览器适配

+ + + +

{{Compat("webextensions.api.windows.WindowType")}}

+ +

{{WebExtExamples}}

+ +
Acknowledgements + +

This API is based on Chromium's chrome.windows API. This documentation is derived from windows.json in the Chromium code.

+ +

Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.

+
+ + diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/index.html" new file mode 100644 index 0000000000..5fecb4334f --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/index.html" @@ -0,0 +1,36 @@ +--- +title: clipboard +slug: Mozilla/Add-ons/WebExtensions/API/剪切板 +tags: + - 剪切板 + - 扩展 + - 附加组件 +translation_of: Mozilla/Add-ons/WebExtensions/API/clipboard +--- +
{{AddonSidebar}}
+ +

WebExtention 的 clipboard API 增加了一个将图像复制到剪贴板的函数。目前,这个 API 仅支持复制图像,但我们期望它未来支持复制文本和 HTML(译者注:原文如此,可能是指被支持复制富内容之后的标准剪贴板 API 取代)。

+ +

这个  WebExtension API 之所以存在,主要是因为标准的 Web 剪贴板 API Clipboard API 不支持将图像写入剪贴板。一旦标准剪贴板 API 对非文本剪贴板内容的支持进入通用状态,则此 API 可能会被弃用。

+ +

Reading from the clipboard is not supported by this API, because the clipboard can already be read using the standard web platform APIs. See Interacting with the clipboard.

+ +

This API is based on Chrome's clipboard API, but that API is only available for Chrome apps, not extensions.

+ +

To use this API you need the "clipboardWrite" extension permission.

+ +

函数

+ +
+
{{WebExtAPIRef("clipboard.setImageData()")}}
+
复制图像到剪切板。
+
+ +

浏览器兼容性

+ +

{{Compat("webextensions.api.clipboard")}} {{WebExtExamples("h2")}}

+ +
说明 + +

 此 API 基于 Chromium 的 chrome.clipboard API.

+
diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/setimagedata/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/setimagedata/index.html" new file mode 100644 index 0000000000..3cdaf45b08 --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/api/\345\211\252\345\210\207\346\235\277/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 +--- +
{{AddonSidebar()}}
+ +

将图像复制到剪贴板。在将图像写入剪贴板之前,会对图像进行重新编码。如果图像无效,则不会修改剪贴板。

+ +

图像被作为包含经过编码的图像的 ArrayBuffer 提供。支持 JPEG 和 PNG 格式。

+ +

基于 Chrome 的 clipboard.setImageData() API,但存在一些差异:

+ + + +

这是一个返回 Promise 的异步函数。

+ +

语法

+ +
browser.clipboard.setImageData(imageData, imageType)
+
+ +

参数

+ +
+
imageData
+
An ArrayBuffer containing the encoded image data to copy to the clipboard.
+
imageType
+
A {{domxref("DOMString")}} indicating the type of image contained in imageData: "png" or "jpeg".
+
+ +

返回值

+ +

A Promise 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).

+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.api.clipboard.setImageData", 10)}}

+ +

示例

+ +

Copy a remote image:

+ +
// requires:
+// * the host permission for "https://cdn.mdn.mozilla.net/*"
+// * the API permission "clipboardWrite"
+
+fetch('https://cdn.mdn.mozilla.net/static/img/favicon144.png')
+.then(response => response.arrayBuffer())
+.then(buffer => browser.clipboard.setImageData(buffer, 'png'));
+ +

Copy an image that was bundled with the extension:

+ +
// requires the API permission "clipboardWrite"
+
+fetch(browser.runtime.getURL('image.png'))
+.then(response => response.arrayBuffer())
+.then(buffer => browser.clipboard.setImageData(buffer, 'png'));
+ +

{{WebExtExamples}}

+ +
说明 + +

 此 API 基于 Chromium 的 chrome.clipboard API.

+
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 +--- +
{{AddonSidebar}}
+ +
{{WebExtAllCompatTables}}
+ + + +
致谢 + +

Microsoft Edge 的兼容性数据由 Microsoft 公司提供,依照知识共享署名 3.0 美国协议授权。

+
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 +--- +
{{AddonSidebar}}
+ +

使用WebExtension API构建的扩展旨在与Chrome和Opera扩展兼容:尽可能为这些浏览器编写的扩展应该在Firefox上运行,并且只需进行极少的更改。

+ +

但是,Firefox目前仅支持Chrome和Opera支持的有限功能和API。 我们正在努力增加更多的支持,但许多功能尚未得到支持,我们可能永远不会支持某些功能。

+ +

JavaScript APIs

+ +

回调与 chrome.* 命名空间

+ +

在 Chrome 中,扩展通过使用 chrome 命名空间来访问私有 JavaScript API:

+ +
chrome.browserAction.setIcon({path: "path/to/icon.png"});
+ +

WebExtensions 通过使用 browser 命名空间来访问等价的 API:

+ +
browser.browserAction.setIcon({path: "path/to/icon.png"});
+ +

许多 API 是异步的。在 Chrome 中,异步的 API 使用回调来返回值,使用 {{WebExtAPIRef("runtime.lastError")}} 来与传达错误:

+ +
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
+);
+ +

在 WebExtensions 中应使用 promises 来访问等价的 API:

+ +
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);
+
+ +

Firefox 支持 chrome 和 browser 命名空间

+ +

为了帮助移植,Firefox 的 WebExtension 实现支持 chrome 与回调和 browser 与 promise。这意味着许多 Chrome 扩展无须修改就能在 Firefox 上运行。然而并不是 WebExtension 标准的一部分,也许不会被所有兼容 WebExtension的浏览器支持。

+ +

如果你在编写 WebExtension 时确实要用到 browser 和 promise,我们也开发了polyfill 来保证扩展可以在 Chrome 里运行:https://github.com/mozilla/webextension-polyfill.

+ +

部分受支持的 API

+ +

页面 JavaScript API 的浏览器支持情况 包含了介绍受 Firefox 任意程度支持的 API 的兼容性表格。若对 API 的支持存在须要注意的事项,并标有星号“*”,且在 API 的参考页面会介绍注意事项。

+ +

这些表格由 在 GitHub 上以 JSON 文件存储的兼容性数据生成。

+ +

本节剩余部分介绍了表格未涵盖的兼容性问题。

+ +

notifications

+ + + +

proxy

+ + + +

tabs

+ + + +

webRequest

+ + + +

windows

+ + + +

其他不兼容情况

+ +

CSS 中的 URL

+ +

Firefox 解析 CSS 中嵌入的 URL  时,若 URL 时相对地址,将是相对 CSS 文件,而不是被嵌入的网页文件。

+ +

更多不兼容情况

+ +

Firefox 不支持从后台标签页使用 alert()、confirm() prompt()

+ +

web_accessible_resources

+ +

在 Chrome 中,若资源在 web_accessible_resources 中列出,即可通过 chrome-extension://<your-extension-id>/<path/to/resource> 访问。每个扩展的 ID 都是固定的。

+ +

Firefox 以不同方式进行实现。它使用一个随机的 UUID,在每个 Firefox 实例中都不同:moz-extension://<random-UUID>/<path/to/resource>。这一随机性可能会让你无法实现某些东西,例如你无法将特定扩展的 URL 添加到另一个域名的 CSP 策略中。

+ +

Manifest "key" 属性

+ +

对于解包了的扩展,Chrome 允许将 "key" 属性添加到 manifest,以确保在不同机器上的扩展 ID 不变。这主要在使用 web_accessible_resources 时有用。鉴于 Firefox 为 web_accessible_resources 使用随机的 UUID,此属性不受支持。

+ +

Content script requests happen in the context of extension, not content page

+ +

In Chrome when request is called (for example, using fetch()) to relative URL like /api from content script, it will be sent to https://example.com/api. In Firefox you have to provide absolute URLs. 

+ +

manifest.json 键

+ +

The main manifest.json 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.

+ +

These tables are generated from compatibility data stored as JSON files in GitHub.

+ +

Native messaging

+ +

Command-line arguments

+ +

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: chrome-extension://[extensionID]. This enables the app to identify the extension.

+ +

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.

+ +

allowed_extensions

+ +

In Chrome, the allowed_extensions key in the app manifest is called allowed_origins instead.

+ +

App manifest location

+ +

Chrome expects to find the app manifest in a different place. See Native messaging host location in the Chrome docs. 

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 +--- +
{{AddonSidebar}}
+ +

Content script 是你扩展的一部分,运行于一个特定的网页环境(而并不是后台脚本,后台脚本是扩展的一部分,也不是该网页利用 {{HTMLElement("script")}} 加载的一个脚本,{{HTMLElement("script")}} 加载的脚本是网页的一部分)。

+ +

后台脚本可以访问所有WebExtension JavaScript APIS,但是他们不能直接访问网页的内容,所以如果你需要Content Scripts来做到这点。

+ +

就像通常的网页加载的脚本一样,Content Scripts 可以使用standard DOM APIS 读取和修改页面内容。

+ +

Content Script 只能访问WebExtension APIS 的一个小的子集,但是它们可以使用通信系统与后台脚本进行通信,从而间接的访问WebExtension APIS。

+ +
+

注意content scripts 在addons.mozilla.org现在已被禁止,如果你在这个域名尝试插入一个Content script将会失败而这个页面会LOG一个CSP错误。

+
+ +

加载Content scripts

+ +

你可以通过两种方法之一在一个页面加载Content script:

+ + + +

在每一个extension的每一个frame中,只有一个全局作用域。所以在一个content script中的变量可以被另外的content script访问到,而与content script如何被加载无关。

+ +

Content script 环境

+ +

DOM 访问

+ +

Content scripts 可以访问和修改页面的DOM,就像普通的页面脚本一样。他们也可以察觉页面脚本对页面做出的任何修改。

+ +

不过,content scripts 得到的是一个“干净的DOM视图”,这意味着:

+ + + +

在 Gecko(译者注:Gecko是由 Mozilla 工程开发出的布局引擎的名字), 这种行为被称为射线视觉。

+ +

举个例子,考虑一个网页如下:

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+  </head>
+
+  <body>
+    <script src="page-scripts/page-script.js"></script>
+  </body>
+</html>
+ +

脚本文件“page-script.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'");
+}
+ +

现在一个扩展插入一个content script 如下:

+ +
// 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()
+ +

相反的情况也是成立的:页面脚本不能察觉到通过content scripts 添加的JavaScript 属性。

+ +

这意味着content script 可以依靠DOM属性获取可预期的行为

+ +

这种行为造成的一个结果是content script不能获取任何通过页面加载的Javascript 库。所以,如果这个页面包含JQuery,content script 将不会在意它。

+ +

如果一个content script 想要使用Javascript库,这个库本身就必须像一个content script一样在这个content script旁被插入:

+ +
"content_scripts": [
+  {
+    "matches": ["*://*.mozilla.org/*"],
+    "js": ["jquery.js", "content-script.js"]
+  }
+]
+ +

WebExtension APIs

+ +

除了standard DOM APIS,content script还能使用以下WebExtension APIS:

+ +

From extension:

+ + + +

From runtime:

+ + + +

From i18n:

+ + + +

所有 storage.

+ +

跨域名权限

+ +

content scripts 拥有与扩展剩余部分一致的权限:所以如果这个扩展已在manifest.json文件中使用permission关键字请求跨域权限,其content script将能很好获取某些跨域权限。

+ +

后台脚本通信

+ +

尽管content scripts 不能直接使用大部分WebExtension APIS,但他们可以通过使用messaging APIS 与扩展的后台脚本通信,然后便能够间接地调用所有的后台脚本能够调用的APIS。

+ +

在background script和content script中有两种基本的通讯方式:你可以发送带有可选回复的一次性的消息,或者在两者之间建立一个长期活动的连接并用这个连接来进行信息交换。

+ +

一次性消息

+ +

为了发送一个带有可选回复选项的一次性消息,你能使用以下APIS:

+ + + + + + + + + + + + + + + + + + + + + +
 In content scriptIn background script
Send a messagebrowser.runtime.sendMessage()browser.tabs.sendMessage()
Receive a messagebrowser.runtime.onMessagebrowser.runtime.onMessage
+ +

举例,这里是一个监听点击事件的content script,如果点击发生在一个链接上,他将会将该链接的地址发送给后台脚本:

+ +
// content-script.js
+
+window.addEventListener("click", notifyExtension);
+
+function notifyExtension(e) {
+  if (e.target.tagName != "A") {
+    return;
+  }
+  browser.runtime.sendMessage({"url": e.target.href});
+}
+ +

后台脚本监听这个消息然后使用notifications API 显示一个通知:

+ +
// 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
+  });
+}
+
+ +

这个示范代码从Github上的 notify-link-clicks-i18n 例子 修改而来.

+ +

Connection-based messaging

+ +

如果你将在一个content script 和 后台脚本间交换大量的消息,一次性消息会变得笨重而缓慢。所以一个更好的方案是在两个脚本间建立一个长久连接,然后使用该连接交换消息。

+ +

每个脚本都有一个 runtime.Port 对象用以交换消息。

+ +

建立过程::

+ + + +

每个脚本都拥有一个port,两个脚本可以使用runtime.Port.postMessage()来发送消息,runtime.Port.onMessage 来接收消息

+ +

比如,当加载该content script时:

+ + + +
// 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!"});
+});
+ +

对应的后台脚本:

+ + + +
// 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!"});
+});
+
+ +

 inpage-toolbar-ui 例子使用了 connection-based messaging.

+ + + +

网页通信

+ +

尽管content script 通常不能获取由网页脚本创建的对象,但他们可以通过 window.postMessagewindow.addEventListener APIs 与网页脚本进行通信.

+ +

比如:

+ +
// 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"
+  }, "*");
+ +
// content-script.js
+
+window.addEventListener("message", function(event) {
+  if (event.source == window &&
+      event.data.direction &&
+      event.data.direction == "from-page-script") {
+    alert("Content script received message: \"" + event.data.message + "\"");
+  }
+});
+ +

完整的例子请访问该链接, visit the demo page on GitHub 并且观看以下介绍.

+ +
+

需要注意的是当你用该方法与一些不被信任的网页进行交互式需要特别小心。WebExtensions拥有高等级权限,而一些恶意页面可以很轻松的获取这些权限。

+ +

做一个微小的示范,假定有如下content script 代码:

+ +
// content-script.js
+
+window.addEventListener("message", function(event) {
+  if (event.source == window &&
+      event.data.direction &&
+      event.data.direction == "from-page-script") {
+    eval(event.data.message);
+  }
+});
+ +

现在网页脚本可以在content script 权限范围内运行任何代码。

+
+ +

与页面脚本共享对象

+ +
+

这个部分的技术描述只适用于49版本后的Firefox

+
+ +
+

作为一个插件开发者你必须考虑脚本运行在任何伺机偷取用户个人隐私,破坏他们的电脑,或者使用其他方式攻击的网页上。

+ +

隔离content script 和 页面脚本 便是为了使恶意网页的攻击变得更加困难。

+ +

这部分的技术打破了这个隔离,它们从根本上是危险的而应该被谨慎使用。

+
+ +

我们在 DOM access 中看到content scripts不会察觉到通过网页脚本修改的某些属性. 这意味着,如果一个网页加载了一个库比如JQuery,content script 将不会使用它,而不得不加载它自己的一个复制。相反的,网页加载的脚本也不能获知content script的修改。

+ +

然而,Firefox提供了一些APIS 可以使得content script能够:

+ + + +

Xray vision in Firefox

+ +

在Firefox中,隔离content script 和页面脚本通过使用一种称为“Xray vision”的功能实现。 当一个处于更高权限的脚本访问一个被定义于一个更低权限版本的域中时,它将只能看见这个对象的原始版本。

+ +

任何 expando 属性都是不可见得, 而且如果对象的任何属性被重定义,他也只能能看见原始的实现而不是重定义的实现。

+ +

这个功能的目的是为了让低权限的脚本不至于因为重定义原始对象属性而使高权限脚本行为异常。

+ +

让我们来举个例子,当一个content script 访问一个页面的 window 类,他不会看见任何该页面脚本对这个window 添加的任何属性, 如果页面脚本重定义了任何已存在的属性,content script将只能看见该属性的原始版本。

+ +

更多信心请查看 Xray visionScript security.

+ +

从content script 中访问 页面脚本对象

+ +

在Firefox中,content script中的DOM对象会获得一个额外的属性 wrappedJSObject。这是一个会包含任何由页面脚本所造成修改的”未包裹“对象。

+ +

让我们来看一个简单的例子,假定一个页面载入脚本如下:

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+  </head>
+  <body>
+    <script type="text/javascript" src="main.js"></script>
+  </body>
+</html>
+ +

这个脚本添加一个全局的属性到全局window:

+ +
// main.js
+
+var foo = "I'm defined in a page script!";
+ +

Xray vision 意味着 如果一个content script 尝试访问foo,它将是未定义的:

+ +
// content-script.js
+
+console.log(window.foo); // undefined
+ +

在Firefox,content script 可以使用window.wrappedJSObject来看见全局属性:

+ +
// content-script.js
+
+console.log(window.wrappedJSObject.foo); // "I'm defined in a page script!"
+ +

注意因为这个原因,你最好不在依赖该对象的任何属性或方法 建立或执行某些操作,你所期望的,它们,甚至setter和getter 都可能被不被信任的代码重定义。

+ +

同时注意unwarapping是及物的:当你使用wrappedJSObject,该未包裹对象的任何属性都是未包裹的(同时都是不可靠的),所以 一个好的建议是只在你需要时获取这个对象,重新包裹他,你能这样做:

+ +
XPCNativeWrapper(window.wrappedJSObject.foo);
+ +

查看 Xray vision   文档获取更多.

+ +

与页面脚本共享content script 对象

+ +

Firefox 同样提供APIS允许content scripts 是对象对于页面脚本可用。这里是两个主要的APIS:

+ + + +

exportFunction

+ +

给予一个定义于content script中的方法,exportFunction()导出他至页面脚本域,然后脚本可以调用它。

+ +

比如,让我们考虑一个WebExtension有一个后台脚本如下:

+ +
/*
+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) => {
+  browser.notifications.create({
+    type: "basic",
+    title: "Message from the page",
+    message: message.content
+  });
+});
+ +

该脚本做了两件事:

+ + + +

content script 如下:

+ +
/*
+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'});
+ +

该脚本定义了一个函数notify()用以发送其参数到后台脚本,而后他导出了这个函数至页面脚本域。现在页面脚本可以调用该函数:

+ +
window.notify("Message from the page script!");
+ +

更详细的信息请看, Components.utils.exportFunction.

+ +

cloneInto

+ +

给予一个定义于content script的对象, 该技术可以创建该对象的一个复制到页面脚本域,从而使该复制可以被页面脚本访问.通常使用 structured clone algorithm 复制对象, 这意味着该对象中的方法不会被复制为了复制方法,需要传递cloneFunction选项.

+ +

比如,这里有一个content script 定义了一个包含方法的对象,然后复制他们至页面脚本域:

+ +
/*
+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});
+ +

现在页面脚本将看到新的含有notify方法的属性:

+ +
window.messenger.notify("Message from the page script!");
+ +

详情请看 Components.utils.cloneInto.

+ +

在content script中使用 eval()

+ +

在 Chrome中,eval() 总是在content script的上下文环境中运行, 而不是在页面的上下文环境中运行.

+ +

在Firefox中:

+ + + +

比如,有一个content script如下:

+ +
// content-script.js
+
+window.eval('window.x = 1;');
+eval('window.y = 2');
+
+console.log(`In content script, window.x: ${window.x}`);
+console.log(`In content script, window.y: ${window.y}`);
+
+window.postMessage({
+  message: "check"
+}, "*");
+ +

这段代码仅仅通过调用window.eval()eval()创建了变量x和y。然后记录它们的值并通知页面更新.

+ +

接收到消息后页面的脚本记录下这些变量:

+ +
window.addEventListener("message", function(event) {
+  if (event.source === window && event.data && event.data.message === "check") {
+    console.log(`In page script, window.x: ${window.x}`);
+    console.log(`In page script, window.y: ${window.y}`);
+  }
+});
+ +

在Chrome中,输出类似下面所示:

+ +
In content script, window.x: 1
+In content script, window.y: 2
+In page script, window.x: undefined
+In page script, window.y: undefined
+ +

在Firefox中,输出类似下面所示:

+ +
In content script, window.x: undefined
+In content script, window.y: 2
+In page script, window.x: 1
+In page script, window.y: undefined
+ +

上述内容同样适用于 setTimeout(), setInterval(), and Function().

+ +

当在页面的上下文中运行代码时, 适用于上面所提到的"Sharing content script objects with page scripts" 这一部分的警告: 页面的环境可能会被恶意的网页所控制,这可能会导致你所交互的对象会有意想不到的行为:

+ +
// page.js redefines console.log
+
+var original = console.log;
+
+console.log = function() {
+  original(true);
+}
+ +
// content-script.js calls the redefined version
+
+window.eval('console.log(false)');
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 +--- +
{{AddonSidebar}}
+ +
+

使用WebExtension API 开发的插件默认应用了内容安全策略(Content Security Policy, 缩写CSP)。这限制了可以加载的 <script><object> 的资源来源,并且禁止了潜在的不安全用法如 eval().

+ +

这篇文章简单地解释了CSP是什么,默认的策略是什么,这对插件来说意味着什么,以及插件如何改变默认CSP。

+
+ +

Content Security Policy (CSP) 是一种避免网站意外执行包含有恶意的内容的机制。网站通过使用服务端发送的HTTP头指定CSP。CSP主要关注指定各种内容的合法来源,如脚本和嵌入式插件。例如,网站可以使用它来告诉浏览器应该只执行来自网站自身的JavaScript,而不腻执行其他来源的脚本。CSP还可以指导浏览器禁止潜在危险行为,如eval()的使用。

+ +

和网页一样,插件可以加载其他来源的内容。例如浏览器的弹出窗口可以指定为一个HTML文档,它同样可以包含不同来源的JavaScript和CSS,就像一个普通的网页一样。

+ +
<!DOCTYPE html>
+
+<html>
+  <head>
+    <meta charset="utf-8">
+  </head>
+
+  <body>
+
+    <!--Some HTML content here-->
+
+    <!--
+      Include a third-party script.
+      See also https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity.
+    -->
+    <script
+      src="https://code.jquery.com/jquery-2.2.4.js"
+      integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI="
+      crossorigin="anonymous">
+    </script>
+
+    <!-- Include my popup's own script-->
+    <script src="popup.js"></script>
+  </body>
+
+</html>
+ +

和网站相比,插件可以访问特权API,因此一旦它们被恶意代码破坏,风险就更大。因此:

+ + + +

默认内容安全策略

+ +

对插件的默认内容安全策略如下:

+ +
"script-src 'self'; object-src 'self';"
+ +

这会被应用在任何没有明确在manifest.json中的content_security_policy 项设置自己的内容安全策略的插件中。它有以下几种效果:

+ + + +

script 和 object资源的位置

+ +

在默认CSP下你只能加载相对插件来说本地的 <script><object> 资源。例如假设插件文档中存在这样一条语句:

+ +
 <script src="https://code.jquery.com/jquery-2.2.4.js"></script>
+ +

这不会加载请求的资源:它会安静地失败,并且你所期望看到的任何来自该资源的对象都不会出现。对于这种情况有两种解决办法:

+ + + +

eval() 和friends

+ +

默认CSP下插件不被允许像JavaScript一样执行字符串。这意味着以下情况都被禁止:

+ +
eval("console.log('some output');");
+ +
window.setTimeout("alert('Hello World!');", 500);
+ +
var f = new Function("console.log('foo');");
+ +

内联 JavaScript

+ +

默认CSP下内联JavaScript不被执行。这不仅不允许将JavaScript直接放在 <script> 标签中间,也不允许内联事件句柄。即以下内容被禁止:

+ +
<script>console.log("foo");</script>
+ +
<div onclick="console.log('click')">Click me!</div>
+ +

如果你正在使用类似 <body onload="main()"> 的代码在页面加载时运行你的脚本,请使用监听器监听DOMContentLoaded 或者 load 代替。

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 +--- +
{{AddonSidebar}}
+ +
+

嵌入一个 WebExtension 需要使用 Firefox 51 或更高版本。在 SDK 附加组件中嵌入一个 WebExtension 还需要 jpm 1.2.0

+
+ +

从 Firefox 51 开始,你可以在传统附加组件类型中嵌入一个 WebExtension。

+ +

传统附加组件可以是经典的自举扩展或者Add-on SDK 附加组件。嵌入式 WebExtension 的文件打包在传统附加组件中。嵌入式 WebExtension 并不直接与嵌入的附加组件共享范围,但可以使用 {{WebExtAPIRef("runtime")}} API 中定义的消息函数交换消息。

+ +

+ +

这意味着您可以一次性迁移传统附加组件到 WebExtensions,并且在此期间附加组件的功能完全保留。尤其是它可以让您从旧版附加组件迁移存储数据到 WebExtension,通过撰写一个中间的混合式附加组件,使用旧版 API 读取数据(例如 simple-prefs 或 preferences 服务)并使用 WebExtension API 写入它(例如 {{WebExtAPIRef("storage")}})。

+ +

连同本指南,我们撰写了两个例子展示如何使用嵌入式 WebExtensions 来帮助从传统附加组件迁移。如何从自举式附加组件迁移以及如何从 SDK 附加组件迁移

+ +

嵌入 WebExtension

+ +

如果传统附加组件是一个带有install.rdf 的自举式扩展,在该 RDF 中加入 "hasEmbeddedWebExtension" 并设为 "true":

+ +
<em:hasEmbeddedWebExtension>true</em:hasEmbeddedWebExtension>
+ +
如果旧式附加组件是一个 SDK 附加组件,在 package.json 中包含 "hasEmbeddedWebExtension" 并设为 true
+ +
 
+ +
"hasEmbeddedWebExtension": true
+
+ +
WebExtension 本身放在附加组件中的 "webextension" 顶层目录。例如:
+ +
 
+ +
my-boostrapped-addon/
+    chrome/
+    webextension/
+        manifest.json
+        background.js
+        ...
+    bootstrap.js
+    chrome.manifest
+    install.rdf
+ +
 
+ +
+
my-sdk-addon/
+    index.js
+    package.json
+    webextension/
+        manifest.json
+        background.js
+        ...
+
+ +

Firefox 不将嵌入式 WebExtension 视为一个独立的附加组件。因此,您不应该为它指定一个附加组件 ID。如果你这样做,那只会被忽略。

+ +

但是,在您完成附加组件的迁移并移除旧式嵌入代码后,您必须添加一个 applications 键,设置 ID 为旧式附加组件的 ID。通过此方式,addons.mozilla.org 可以识别 WebExtension 是旧式附加组件的一个更新。

+ +

启动 WebExtension

+ +

嵌入式 WebExtension 必须由被嵌入的附加组件明确启动。

+ +

如果被嵌入的附加组件是一个自举式附加组件,那么传递到自举式扩展的 startup() 函数的 data 将获得一个明确的 webExtension

+ +
// bootstrapped add-on
+
+function startup({webExtension}) {
+
+...
+ +

如果被嵌入的附加组件是一个 SDK 附加组件,它可以使用 sdk/webextension 模块访问一个 WebExtension 对象:

+ +
// SDK add-on
+
+const webExtension = require("sdk/webextension");
+ +

无论哪种方式,此对象都有一个 startup() 函数,它返回一个 Promise。该 promise 使用一个 browser 属性解决一个对象:这包括 {{WebExtAPIRef("runtime")}} API,被嵌入的附加组件可以用它来与嵌入式 WebExtension 交换消息:

+ + + +

例如:

+ +
// bootstrapped add-on
+
+function startup({webExtension}) {
+  webExtension.startup().then(api => {
+    const {browser} = api;
+    browser.runtime.onMessage.addListener(handleMessage);
+  });
+}
+ +
// SDK add-on
+
+const webExtension = require("sdk/webextension");
+
+webExtension.startup().then(api => {
+  const {browser} = api;
+  browser.runtime.onMessage.addListener(handleMessage);
+});
+
+ +

应注意的是,嵌入的附加组件不能启动通信,它可以使用 onMessage 接收(并可选响应)一次性消息,并可以使用 onConnect 接受连接请求。

+ +

如果嵌入式 WebExtension 缺少一个 manifest,或者如果 manifest 无效,该 promise 会被拒绝。这种情况下,您可以在浏览器工具箱的控制台中看到更多细节。

+ +

交换消息

+ +

一旦嵌入式 WebExtension 处在运行,它可以使用 {{WebExtAPIRef("runtime")}} API 的子集与旧式附加组件交换消息:

+ + + +

无需连接的消息

+ +

要发送一条消息,WebExtension 可以使用 {{WebExtAPIRef("runtime.sendMessage()")}}。您可以省略 extensionId 参数,因为浏览器认为嵌入式 WebExtension 是被嵌入附加组件的一部分:

+ +
browser.runtime.sendMessage("message-from-webextension").then(reply => {
+  if (reply) {
+    console.log("response from legacy add-on: " + reply.content);
+  }
+});
+ +

被嵌入的附加组件可以使用 {{WebExtAPIRef("runtime.onMessage")}} 对象接收消息(并可选响应):

+ +
// bootstrapped add-on
+
+function startup({webExtension}) {
+  // Start the embedded webextension.
+  webExtension.startup().then(api => {
+    const {browser} = api;
+    browser.runtime.onMessage.addListener((msg, sender, sendReply) => {
+      if (msg == "message-from-webextension") {
+        sendReply({
+          content: "reply from legacy add-on"
+        });
+      }
+    });
+  });
+}
+ +

基于连接的消息

+ +

要在 WebExtension 与传统附加组件间设置一个长寿命连接,WebExtension 可以使用 {{WebExtAPIRef("runtime.connect()")}}。

+ +
var port = browser.runtime.connect({name: "connection-to-legacy"});
+
+port.onMessage.addListener(function(message) {
+  console.log("Message from legacy add-on: " + message.content);
+});
+
+ +

旧式附加组件可以使用 {{WebExtAPIRef("runtime.onConnect")}} 监听连接尝试,双方可以使用得到的 {{webExtAPIRef("runtime.Port")}} 来交换消息:

+ +
function startup({webExtension}) {
+  // Start the embedded webextension.
+  webExtension.startup().then(api => {
+    const {browser} = api;
+    browser.runtime.onConnect.addListener((port) => {
+      port.postMessage({
+        content: "content from legacy add-on"
+      });
+    });
+  });
+}
+ +

从传统附加组件迁移数据

+ +

嵌入式 WebExtensions 的一项主要用途是迁移附加组件的存储数据。

+ +

人们从旧式附加组件类型迁移的一个主要问题是存储数据,因为旧式附加组件不能使用 WebExtension 存储 API,WebExtensions 也不能使用旧式存储 API。例如,如果一个 SDK 附加组件使用了 SDK 的 simple-prefs API 来存储首选项,WebExtension 版本不可能访问这项数据。

+ +

使用嵌入式 WebExtensions,您可以创建一个嵌入了 WebExtension 的附加组件中间版本来迁移数据。中间版本使用旧式 API 读取存储的数据,然后使用 WebExtension API 写入数据。

+ + + +

我们提供了两个例子说明此模式:"embedded-webextension-bootstrapped" 展示了从一个自举式附加组件迁移,而 "embedded-webextension-sdk" 展示了从一个 SDK 附加组件迁移。

+ +

限制

+ +

调试

+ +

如果您有一个嵌入了 WebExtension 的旧式附加组件,您不能使用新的附加组件调试器来调试它。您必须使用基于浏览器工具箱的旧版调试工具

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 +--- +
{{AddonSidebar}}
+ +

为帮助了解如何开发扩展,我们维护了一个包含简单扩展示例的代码仓库在https://github.com/mdn/webextensions-examples. 本文描述了仓库代码中所使用的 WebExtension APIs。

+ +

这些示例工作在 Firefox Nightly 下: 大部分示例在 Firefox 的早期版本中也能够运行, 请检查扩展 manifest.json 文件中的 strict_min_version 键。

+ +

如果你想尝试这些示例,有下面三个选择:

+ +
    +
  1. 克隆代码库,通过 "临时载入附加组件" 功能直接从源文件夹中载入扩展组件。再重启浏览器前该扩展将一直存在。
  2. +
  3. 克隆代码库,使用 web-ext 命令行工具运行安装了扩展的 Firefox。
  4. +
  5. 克隆代码库,进入 build 文件夹。该文件夹包含所有示例的已构建、带签名版本。你可以在Firefox中打开(菜单栏->文件->打开文件)并且永久安装这些扩展。这些扩展和直接从 addons.mozilla.org 安装的扩展别无二致。
  6. +
+ +
+

重要:不要提交这些关于 WebExtension 例子的示例到 AMO (addons.mozilla.org)  上去,你无需为附加组件签名就能运行 WebExtension 的示例。只要按照上面的步骤来就可以了。

+
+ +

如果你想对代码仓库贡献,给我们发送 pull request!

+ +

{{WebExtAllExamples}}

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 +--- +
{{AddonSidebar}}
+ +
+

本页介绍了火狐 Firefox 55中存在的开发工具接口(dectools APIs)。 虽然该接口Api基于 Chrome 开发工具Api,仍有许多功能尚未实现在火狐中实现,因此未记录在本页内容中。产看当前缺失的功能,请参阅链接开发工具Api的限制.

+
+ +

您可以使用WebExtensions API扩展浏览器的内置开发人员工具。要创建devtools扩展,请在manifest.json中包含“ devtools_page”键:

+ +
"devtools_page": "devtools/devtools-page.html"
+ +

此项的值是指向与您的扩展程序捆绑在一起的HTML文件的URL。该URL应相对于manifest.json文件本身。

+ +

HTML文件在扩展中定义了一个特殊页面,称为devtools页面。

+ +

devtools页面

+ +

当打开浏览器devtools时,将加载devtools页面,并在关闭浏览器时将其卸载。请注意,由于devtools窗口与单个选项卡相关联,因此很可能同时存在多个devtools窗口-因此有多个devtools页面。

+ +

devtools页面没有任何可见的DOM,但可以包含使用<script>标记的JavaScript源。源必须与扩展本身捆绑在一起。来源可以访问::

+ + + +

请注意,devtools页面无法访问任何其他WebExtension API,并且后台页面无法访问devtools API。相反,devtools页面和后台页面必须使用运行时消息传递API进行通信。这是一个例子:

+ +
<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+  </head>
+  <body>
+    <script src="devtools.js"></script>
+  </body>
+</html>
+ +

devtools.js文件将保存创建您的dev工具扩展的实际代码。

+ +

创建面板

+ +

devtools窗口中包含许多单独的工具-JavaScript调试器,网络监视器等。顶部的一排标签可让用户在不同的工具之间切换。承载每个工具的用户界面的窗口称为“面板”

+ +

使用devtools.panels.create()API,可以在devtools窗口中创建自己的面板:

+ +
browser.devtools.panels.create(
+  "My Panel",                      // title
+  "icons/star.png",                // icon
+  "devtools/panel/panel.html"      // content
+).then((newPanel) => {
+  newPanel.onShown.addListener(initialisePanel);
+  newPanel.onHidden.addListener(unInitialisePanel);
+});
+ +

这需要三个必选参数:面板的标题,图标和内容。它返回一个Promise,该Promise解析为代表新面板的devtools.panels.ExtensionPanel对象。

+ +

与目标窗口互动

+ +

开发人员工具始终附加到特定的浏览器选项卡。这称为开发人员工具的“目标”或“检查的窗口”。您可以使用devtools.inspectedWindow API与检查的窗口进行交互。

+ +

Running code in the target window

+ +

devtools.inspectedWindow.eval()提供了一种在检查的窗口中运行代码的方法。

+ +

这有点像使用{{WebExtAPIRef("tabs.executeScript()")}}注入内容脚本,但有一个重要区别:

+ + + +
+

请注意,DOM的清晰视图是一项安全功能,旨在通过重新定义本机DOM功能的行为来帮助防止恶意页面欺骗扩展。这意味着您需要非常小心地使用eval(),并应尽可能使用普通的内容脚本。

+
+ +

devtools.inspectedWindow.eval()加载的脚本也看不到内容脚本定义的任何JavaScript变量。

+ +

Working with content scripts

+ +

devtools文档无法直接访问{{WebExtAPIRef("tabs.executeScript()")}},因此,如果需要注入内容脚本,devtools文档必须向后台脚本发送一条消息,要求其注入剧本。 devtools.inspectedWindow.tabId提供目标选项卡的ID:devtools文档可以将其传递给后台脚本,而后台脚本又可以将其传递给{{WebExtAPIRef("tabs.executeScript()")}}:

+ +
// devtools-panel.js
+
+const scriptToAttach = "document.body.innerHTML = 'Hi from the devtools';";
+
+window.addEventListener("click", () => {
+  browser.runtime.sendMessage({
+    tabId: browser.devtools.inspectedWindow.tabId,
+    script: scriptToAttach
+  });
+});
+ +
// background.js
+
+function handleMessage(request, sender, sendResponse) {
+  browser.tabs.executeScript(request.tabId, {
+    code: request.script
+  });
+}
+
+browser.runtime.onMessage.addListener(handleMessage);
+ +

如果您需要在目标窗口中运行的内容脚本和devtools文档之间交换消息,则最好使用{{WebExtAPIRef("runtime.connect()")}}和{{WebExtAPIRef("runtime.onConnect()")}},以在后台页面和devtools文档之间建立连接。然后,后台页面可以维护选项卡ID和{{WebExtAPIRef("runtime.Port")}}对象之间的映射,并使用此映射在两个作用域之间路由消息。

+ +

+ +

devtools API的局限性

+ +

这些API基于Chrome devtools API,但与Chrome相比,许多功能仍缺失。本节列出了从Firefox 54开始尚未实现的功能。请注意,devtools API正在积极开发中,我们希望在将来的版本中增加对其中大多数功能的支持。

+ +

devtools.inspectedWindow

+ +

The following are not supported:

+ + + +

None of the options to inspectedWindow.eval() are supported.

+ +

使用inspectedWindow.eval()注入的脚本不能使用控制台的所有命令行帮助器功能,但是都支持$ 0和inspect(...)(从Firefox 55开始)。

+ +

devtools.panels

+ +

The following are not supported:

+ + + +

Examples

+ +

The webextensions-examples repo on GitHub, contains several examples of extensions that use devtools panels:

+ + 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 +--- +
{{AddonSidebar}}
+ +

Extensions「扩展」 可以扩展和修改一个浏览器的能力。用于 Firefox 的 扩展使用 WebExtensions API 「一种开发扩展的跨浏览器系统」构建。该系统与 Google Chrome、Opera 和 W3C 草案社区组织 所支持的 扩展 API 在很大程度上兼容。大多数情况下为这些浏览器编写的扩展只需少许修改即可在 Firefox 或 Microsoft Edge 中运行。这种 API 与也完全兼容 多进程 Firefox

+ +

如果你有想法或问题,或者在使用 WebExtensions APIs 迁移旧式附加组件时需要帮助,可以在 dev-addons 邮件列表 或者 IRC 上的 #extdev 与我们联系。

+ +
+ + +
+

参考资料

+ +

JavaScript APIs

+ + + +
{{ ListSubpages ("/zh-CN/Add-ons/WebExtensions/API") }}
+ +

Manifest 关键信息

+ + + +
{{ ListSubpages ("/zh-CN/Add-ons/WebExtensions/manifest.json") }}
+
+
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 +--- +
{{AddonSidebar}}
+ +

有两种方式可以让浏览器扩展与系统剪贴板交互: {{domxref("Document.execCommand()")}} 方法以及现代的异步的 Clipboard API.

+ +

{{domxref("Document.execCommand()")}} 方法常通过以下指令使用:

+ + + +

Clipboard API 提供了异步的连接来直接读写剪贴板内容. 例, 如此从剪贴板读取文本:

+ +
navigator.clipboard.readText().then(text => outputElem.innerText = text);
+ +

这将请求剪贴板内容, 并且当接收到响应时存储剪贴板文本到一个元素的 {{domxref("Node.innerText", "innerText")}}.

+ +
+

注意: 异步的 Clipboard API 方法是一个近期新增的规范, 并且这个规范可能不适用于所有浏览器. 请在使用前测试了每一种方法的兼容性, 以确保支持满足您的需求.

+
+ +

写入系统粘贴板

+ +

有两种向剪贴板写入数据的方法. 你可以使用 {{domxref("Document.execCommand", "document.execCommand()")}}  来触发 "剪切" 和 "复制" 行为, 这将用选择的数据覆盖剪贴板的当前内容. 另一个选项是使用 Clipboard API 的 {{domxref("Clipboard.writeText()")}} 或 {{domxref("Clipboard.write()")}} 方法来用指定数据覆盖剪贴板内容.

+ +

使用 execCommand()

+ +

{{domxref("Document.execCommand", "document.execCommand()")}}  方法的 "cut""copy" 命令可以被用于以选中素材代替剪贴板的当前内容. 这些命令无需任何特别的权限就可以使用, 如果你在一个用于用户操作的短生存期的事件处理程序中使用他们(例如, 一次点击事件).

+ +

例如,假设你有一个下面的弹出菜单页面:

+ +
<input id="input" type="text"/>
+<button id="copy">Copy</button>
+
+ +

使 "copy"按钮能复制 "input"中的文本,代码如下:

+ +
function copy() {
+  var copyText = document.querySelector("#input");
+  copyText.select();
+  document.execCommand("Copy");
+}
+
+document.querySelector("#copy").addEventListener("click", copy);
+ +

由于execCommand()命令在单击事件中,所以不需要特别的权限。

+ +

此外,如果用警报(alarm)替换上面的命令来触发复制事件:

+ +
function copy() {
+  var copyText = document.querySelector("#input");
+  copyText.select();
+  document.execCommand("Copy");
+}
+
+browser.alarms.create({
+  delayInMinutes: 0.1
+});
+
+browser.alarms.onAlarm.addListener(copy);
+ +

这种触发不一定成功,它取决于浏览器是否支持。Firefox浏览器就不支持该功能,你会在浏览器控制台中看到以下信息:

+ +
"document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler."
+ +

为了能够在这种情形下使用,你需要拥有"clipboardWrite"的权限( permission)。 因此,"clipboardWrite"权限能使你不通过临时事件处理程序就可以写入系统粘贴板中。

+ +

使用 Clipboard API

+ +

Clipboard API 更加灵活, 因为你不仅可以将当前选择复制到剪贴板中, 还可以直接指定要放入剪贴板的信息.

+ +

要使用 Clipboard API 需要在你的 manifest.json 文件中申请 clipboardReadclipboardWrite 权限.

+ +

对于页面脚本, 需要权限 API 的 clipboard-write 权限. 你可通过 {{domxref("Permissions.query", "navigator.permissions.query()")}} 来检查这个权限:

+ +
navigator.permissions.query({name: "clipboard-write"}).then(result => {
+  if (result.state == "granted" || result.state == "prompt") {
+    /* write to the clipboard now */
+  }
+});
+ +

这个函数使用一个字符串作为输入并且用它更新剪贴板:

+ +
function updateClipboard(newClip) {
+  navigator.clipboard.writeText(newClip).then(function() {
+    /* clipboard successfully set */
+  }, function() {
+    /* clipboard write failed */
+  });
+}
+ +

特定浏览器注意事项

+ +

 这里涉及的剪贴板和其他API正在快速发展, 因此浏览器在工作方式上存在差异.

+ +

在Chrome中:

+ + + +

在Firefox中:

+ + + +

读取系统粘贴板

+ +

execCommand() 方法提供了 "paste" 指令,能让你粘贴内容。你可以使用 Clipboard API 的更灵活的方法: {{domxref("Clipboard.read()")}} 和 {{domxref("Clipboard.readText()")}}。

+ +

使用 execCommand()

+ +

首先,你需要为扩展申请 "clipboardRead" permission 。即便你在用户生成的事件处理程序 ( 例如 {{event("click")}} 或 {{event("keypress")}} ) 中使用 "paste" 指令也是如此。

+ +

假设你的HTML页面内容如下:

+ +
<input id="output" type="text"/>
+<button id="paste">粘贴</button>
+
+ +

要在用户单机 id 为 "paste" 的 {{HTMLElement("button")}} 时从剪贴板设置 id 为 "output" 的 {{HTMLElement("textarea")}} 的内容,可以使用这样的代码:

+ +
function paste() {
+  var pasteText = document.querySelector("#output");
+  pasteText.focus();
+  document.execCommand("paste");
+  console.log(pasteText.textContent);
+}
+
+document.querySelector("#paste").addEventListener("click", paste);
+ +

使用 Clipboard API

+ +

剪贴板 API 的 {{domxref("Clipboard.readText", "navigator.clipboard.readText()")}} 和 {{domxref("Clipboard.read", "navigator.clipboard.read()")}} 方法让你从剪贴板读取任意文本或二进制数据。这让你从剪贴板访问数据无需将它们粘贴至一个可编辑的元素中。

+ +

一旦你通过 Permissions API 获取了 "clipboard-read" 权限,你就可以轻松读取剪贴板:

+ +
navigator.clipboard.readText().then(clipText =>
+  document.getElementById("outbox").innerText = clipText);
+ +

这个代码片段从剪贴板提取文本并且用该文本替换 ID 为 "outbox" 的元素的当前内容。

+ +

特定浏览器注意事项

+ +

Firefox 在 54 版本提供了 "clipboardRead" permission ,但是仅支持向处于 内容可编辑模式 的元素粘贴,对于内容脚本,只能在 {{HTMLElement("textarea")}} 工作。对于后台脚本,任何元素都可被设置为内容可编辑模式。

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 +--- +
{{AddonSidebar}}
+ +

使用 {{WebExtAPIRef("webRequest")}} API可以拦截HTTP请求。该API允许开发者植入一个侦听器用以侦听各个阶段的HTTP请求。在侦听器中,你能:

+ + + +

本文将探究webRequest模型的三种用法:

+ + + +

记录请求的 URL

+ +

新建一个名为requests的目录,在其中新建一个名为manifest.json的文件,文件包含如下 内容 :

+ +
{
+  "description": "Demonstrating webRequests",
+  "manifest_version": 2,
+  "name": "webRequest-demo",
+  "version": "1.0",
+
+  "permissions": [
+    "webRequest",
+    "<all_urls>"
+  ],
+
+  "background": {
+    "scripts": ["background.js"]
+  }
+}
+ +

接着新加一个名为background.js的文件,包含如下内容:

+ +
function logURL(requestDetails) {
+  console.log("Loading: " + requestDetails.url);
+}
+
+chrome.webRequest.onBeforeRequest.addListener(
+  logURL,
+  {urls: ["<all_urls>"]}
+);
+
+
+ +

这里我们在请求开始之前用{{WebExtAPIRef("webRequest.onBeforeRequest", "onBeforeRequest")}}调用logURL()函数。logURL()函数抓取从事件对象发出的请求中的URL,然后将其打印到浏览器的控制台窗口中。参数{urls: ["<all_urls>"]}表示拦截发往所有URL的HTTP请求。

+ +

测试方法是:安装该WebExtension打开浏览器的控制台,然后开启某个网页即可。在浏览器控制台中就能见到浏览器请求所有资源的URL:

+ +

{{EmbedYouTube("X3rMgkRkB1Q")}}

+ +

重定向请求

+ +

现在让我们用webRequest来重定向HTTP请求。首先将manifest.json文件内容替换如下:

+ +
{
+
+  "description": "Demonstrating webRequests",
+  "manifest_version": 2,
+  "name": "webRequest-demo",
+  "version": "1.0",
+
+  "permissions": [
+    "webRequest",
+    "webRequestBlocking",
+    "https://mdn.mozillademos.org"
+  ],
+
+  "background": {
+    "scripts": ["background.js"]
+  }
+
+}
+ +

这里唯一的变化是权限里 新增了webRequestBlocking项。新增这个权限是为了随时都能修改请求。

+ +

下一步替换background.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"]
+);
+ +

此外在请求构造出来之前我们用{{WebExtAPIRef("webRequest.onBeforeRequest", "onBeforeRequest")}}事件侦听器来实现URL替换。侦听器将会用redirectUrl指定的内容替换原有的URL。

+ +

这次我们不拦截所有的请求:{urls:[pattern], types:["image"]}选项告诉浏览器必须同时满足如下两点的请求才会被拦截:(1)在 https://mdn.mozillademos.org/之下的URL; (2)图片资源。该功能的更多说明参见{{WebExtAPIRef("webRequest.RequestFilter")}}。

+ +

刚才我们忽略了“blocking选项。要修改请求就要用到“blocking选项,该选项让侦听器函数阻塞住发往网络请求,浏览器将会等待侦听器返回才会继续处理。阅读{{WebExtAPIRef("webRequest.onBeforeRequest")}}以了解更多有关“blocking 的细节。.

+ +

测试时打开MDN上的一个包含诸多图片的页面(如https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor ),重新加载WebExtension,然后重新加载这个页面:

+ +

{{EmbedYouTube("ix5RrXGr0wA")}}

+ +

修改请求报头

+ +

最后我们将使用webRequest修改请求报头。在这个例子中我们将修改 "User-Agent"报头,使得在浏览" http://useragentstring.com/"网站下的网页时可以识别浏览器Opera 12.16。

+ +

"manifest.json" 可以与上一个例子相同。

+ +

修改"background.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"]
+);
+ +

在请求报头被发送前,我们使用 {{WebExtAPIRef("webRequest.onBeforeSendHeaders", "onBeforeSendHeaders")}} 事件监听器来运行一个函数。

+ +

只有在向匹配的URL格式的网页发送请求时,这个监听函数才会运行。 还需注意的是,我们再次使用了"blocking"选项。我们还使用了"requestHeaders"选项,使监听器可以传递我们希望的请求报头数组。了解更多{{WebExtAPIRef("webRequest.onBeforeSendHeaders")}}的信息。

+ +

侦听函数在请求报头数组中寻找 "User-Agent" 报头,用ua变量替换它的值,然后返回修改后的报头数组 。现在这个修改后的数组会被发送到服务器。

+ +

要测试它,先打开 useragentstring.com网址,检查标识浏览器是否为火狐浏览器 。然后加载附加组件, 刷新网址,再次检查标识浏览器,你会发现火狐浏览器被定义为 Opera了:

+ +

{{EmbedYouTube("SrSNS1-FIx0")}}

+ +

了解更多

+ +

学习你能使用的所有webRequest API,查看 reference documentation

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 +--- +
{{AddonSidebar}}
+ +

WebExtensions API 有一个相当方便的模块可用于附加组件的国际化(i18n)。我们将在本文中探讨其功能,并为它的运作方式提供一个实例。WebExtensions 的 i18n 系统类似常见的 i18n 用途 JavaScript 库,例如 i18n.js

+ +
+

本文中的 WebExtension 实例 notify-link-clicks-i18n 可在 GitHub 上查阅。在您阅读下列章节时,可参照它的代码。

+
+ +

剖析一个国际化的 WebExtension

+ +

一个国际化的 WebExtension 与其他 WebExtension 一样可以包含各类功能,如后台脚本内容脚本等,但它也有些额外的部分,从而允许它适应不同的语言区域。目录树大致如下:

+ + + +

让我们逐项探讨这些新特性,因为下列每个章节都是你在国际化 WebExtension 时所要遵循的步骤。

+ +

在 _locales 中提供本地化的字符串

+ +
+
你可以使用Language subtag lookup page上的查找工具查询语言子标签。请注意,你需要搜索语言的英语名称。
+
+ +

每个 i18n 系统都需要你提供想支持的各语言区域的已翻译字符串。 在 WebExtensions 中,这些字符串放在一个名为 _locales 的目录中,_locales 目录则位于扩展的根目录。每个语言区域都有一个名叫 messages.json 的文件,其中包含相应的字符串(在 WebExtension 中称作“消息”),这个文件放在 _locales 的子目录下,子目录以对应语言区域的语言子标签来命名。

+ +

注意,如果子标签包含一个基本语言和一个区域变种,那么语言与变种之间通常会以连字号隔开,例如 "en-US"。但作为 _locales 的子目录,它必须采用下划线来分隔,如 "en_US"。

+ +

因此在我们这个示例应用中,我们有如下几个目录:"en"(英语)、"de"(德语)、"nl"(荷兰语)以及 "ja"(日语)。每个目录都包含一个 messages.json 文件。

+ +

现在我们来看其中一个文件(_locales/en/messages.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"
+      }
+    }
+  }
+}
+ +

这个文件是一个标准的 JSON — 其中每个成员都是一个带有名称的对象,里面包含一个 message(消息)和一个 description(描述)。这些项目都是字符串。$URL$ 是一个占位符,在 WebExtension 调用 notificationContent 成员时将被一个子字符串替换。你将在接下来的{{anch("从 JavaScript 检索消息字符串")}}章节中了解如何使用。

+ +
+

注意:你可以在 Locale-Specific Message reference 里找到更多有关  messages.json 文件中内容的信息。

+
+ +

国际化 manifest.json

+ +

要国际化你的 manifest.json,有几项任务要完成。

+ +

在 manifests 中检索本地化的字符串

+ +

你的 manifest.json 包含显示给用户的字符串,例如附加组件的名称和描述。如果你将这些字符串国际化,并将合适的翻译放到 messages.json 中,则用户将根据当前语言区域看到适当的字符串翻译。

+ +

要将这些字符串国际化,按如下格式指定:

+ +
"name": "__MSG_extensionName__",
+"description": "__MSG_extensionDescription__",
+ +

我们在在这里检索到消息字符串依赖于浏览器的语言区域,而不仅仅是一个静态字符串。

+ +

要这样调用消息字符串,你需要用的方式为:

+ +
    +
  1. 两个下划线,接着是
  2. +
  3. 字符串 "MSG",接着是
  4. +
  5. 一个下划线,接着是
  6. +
  7. 你想调用的在 messages.json 中定义的消息名称,接着是
  8. +
  9. 两个下划线
  10. +
+ +
__MSG_ + messageName + __
+ +

指定默认语言区域

+ +

你还必须在你的 manifest.json 中指定另一个字段,它就是 default_locale

+ +
"default_locale": "en"
+ +

如果扩展没有包含浏览器当前语言区域的本地化字符串,则会使用该字段所指定的默认语言区域。任何浏览器语言区域下不可用的消息字符串都将用默认语言区域的字符串替换。有关浏览器如何选择字符串,还有一些细节需要注意 — 详见{{anch("选择本地化的字符串")}}。

+ +

依赖语言区域的 CSS

+ +

您还可以在扩展的 CSS 文件中检索本地化的字符串。例如,您可能想构建一个依赖于语言区域的 CSS 规则,如下所示:

+ +
header {
+  background-image: url(../images/__MSG_extensionName__/header.png);
+}
+ +

这很有用,不过在这种情况下使用{{anch("预定义消息")}}来处理或许会更好。

+ +

从 JavaScript 检索消息字符串

+ +

所以,您应该已经建立起您的消息字符串和 manifest。现在只需开始从 JavaScript 调用这些消息字符串,以便你的扩展尽可能多地表述适合的语言。实际上 i18n API 相当简单,只需包含以下四个主要的方法(method):

+ + + +

在我们的 notify-link-clicks-i18n 示例中,后台脚本包含下列代码:

+ +
var title = browser.i18n.getMessage("notificationTitle");
+var content = browser.i18n.getMessage("notificationContent", message.url);
+ +

第一行是从最适合当前语言区域的可用 messages.json 文件中检索 notificationTitle message 字段。第二行与第一行类似,但它被传递了一个 URL 作为第二参数。怎么一回事?它就是你所指定的要替代 notificationContent 消息字段里 $URL$ 占位符的内容:

+ +
"notificationContent": {
+  "message": "您点击了 $URL$。",
+  "description": "告诉用户点击了哪个链接。",
+  "placeholders": {
+    "url" : {
+      "content" : "$1",
+      "example" : "https://developer.mozilla.org"
+    }
+  }
+}
+
+ +

"placeholders" 这个成员定义了所有的占位符,以及它们所检索的来源。"url" 这个占位符指定了其内容取自 $1,它就是 getMessage() 第二个参数里的第一个值。由于占位符就叫做 "url",我们就在实际的消息字符串中用 $URL$ 调用它("name" $NAME$ 调用也是一样的,以此类推)。对于多个占位符,你可以将其置于数组内,并作为第二个参数传递到 {{WebExtAPIRef("i18n.getMessage()")}} — [a, b, c] 可替换为 $1, $2, and $3,以此类推,并置于 messages.json 内。

+ +

接下来我们看一个例子:在 en/messages.json 文件中原始的 notificationContent 消息字符串如下: in the en/messages.json file is

+ +
您点击了 $URL$。
+ +

我们可以看到链接点击后会打开 https://developer.mozilla.org。在 {{WebExtAPIRef("i18n.getMessage()")}} 调用后,第二个参数的内容就变成了 messages.json 里的 $1,并替换定义在 "url" 占位符里的 $URL$ 这个占位符。所以最后的消息字符串就变成了:

+ +
您点击了 https://developer.mozilla.org。
+ +

直接占位符的使用

+ +

你可以直接将变量($1, $2, $3 等)插入消息字符串,例如我们可以将上述的 "notificationContent" 成员重写为:

+ +
"notificationContent": {
+  "message": "你点击了 $1。",
+  "description": "告诉用户点击了哪个链接。"
+}
+ +

这么做看起来似乎更快捷,也没那么复杂,但另一种方法(使用 "placeholders")更切实际,因为提供一个占位符名(例如 "url")和 example 可帮你记住占位符是什么 — 在你代码写了一个礼拜后,你很可能忘了 $1$8 表示什么,但你或许记得起来占位符名表示什么。

+ +

替换硬编码

+ +

也可以在占位符中包含硬编码的字符串,从而每次都使用相同的值,而不是从代码中的变量获取值。例如:

+ +
"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/"
+    }
+  }
+}
+ +

在本例中我们只是硬编码了占位符的内容,而不是从 $1 这样的变量值中获取它。有时候你会遇到消息文件非常复杂,或者如果你想将文件里的不同值分离开来以便字符串可读性更好,这种情况下它会很有用,这些值可通过编程来访问。

+ +

此外,你可使用这样的替代方式指定不想被翻译的一部分字符串,例如人名或公司名。

+ +

选择本地化的字符串

+ +

语言区域可以仅使用语言代码指定,例如 fren,也可以进一步限定区域代码,例如 en_USen_GB,其描述了使用相同基础语言的区域变体。当您向 i18n 系统询问一个字符串时,它将使用以下算法选择一个字符串:

+ +
    +
  1. 如果有精确匹配当前语言区域的 messages.json 文件,并且它包含该字符串,则返回它。
  2. +
  3. 否则,如果当前语言区域有合格区域(例如 en_US)并且有一个无区域限定的 messages.json 文件(例如 en)且包含该字符串,则返回它。
  4. +
  5. 否则,如果 manifest.json 里包含 default_locale 所对应的 messages.json 文件且包含该字符串,则返回它。
  6. +
  7. 否则,返回一个空字符串。
  8. +
+ +

参见下列示例:

+ + + +

假设 default_locale 是设为 fr,而浏览器的语言环境为 en_GB

+ + + +

预定义消息

+ +

i18n 模块为我们提供了一些预定义的消息,我们可以用之前在 {{anch("Calling message strings from manifests and extension CSS")}} 中看到的相同的方式调用。例如:

+ +
__MSG_extensionName__
+ +

预定义的消息使用完全相同的语法,例如在消息名称之前使用 @@

+ +
__MSG_@@ui_locale__
+ +

下表显示了各个可用的预定义消息。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
消息名描述
@@extension_id扩展或应用的 ID;你可以使用该字符串构建 URL,用于扩展内部的资源。甚至未本地化的扩展也可以使用该消息。
+ 注意:该消息无法在 manifest 文件中使用。
@@ui_locale当前的语言区域;你可以使用该字符串构建语言区域特有的 URL。
@@bidi_dir当前语言区域对应的文本书写方向,可以是 "ltr",例如英语这样的从左到右书写的语言,或"rtl",例如阿拉伯语这样的从右到左书写的语言。
@@bidi_reversed_dir如果 @@bidi_dir 是 "ltr",则是 "rtl",否则是 "ltr"。
@@bidi_start_edge如果 @@bidi_dir 是 "ltr",则是 "left",否则是 "right"。
@@bidi_end_edge如果 @@bidi_dir 是 "ltr",则是 "right",否则是 "left"。
+ +

回到我们之前的例子,像下面这样写更有意义:

+ +
header {
+  background-image: url(../images/__MSG_@@ui_locale__/header.png);
+}
+ +

现在我们可以保存本地指定的图片,目录则可以根据所支持的不同语言区域进行匹配,例如 en、de 等 — 这样显得更有意义多了。

+ +

让我们看看一个在 CSS 文件中使用 @@bidi_* 消息的例子:

+ +
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;
+}
+ +

对于从左到右语言(例如英语、中文),该 CSS 声明调用在上面预定义的消息,最终转换为下列代码:

+ +
direction: ltr;
+padding-left: 0;
+padding-right: 1.5em;
+
+ +

而对于从右到左语言(如阿拉伯语),则将得到:

+ +
direction: rtl;
+padding-right: 0;
+padding-left: 1.5em;
+ +

测试你的 WebExtension

+ +

从 Firefox 45 开始,你可以临时安装磁盘上的 WebExtensions  — 另见从磁盘加载。按上述步骤操作,然后尝试我们的 notify-link-clicks-i18n WebExtension。访问你喜欢的任何网站,然后点一下链接,查看是否有通知出现来显示所点击的链接网址。

+ +

接下来,将 Firefox 的语言区域更改为你想测试的扩展支持的某个语言区域。

+ +
    +
  1. 在 Firefox 中打开 "about:config",找到 general.useragent.locale 首选项。
  2. +
  3. 双击该首选项(或按回车)以选择它,输入你想测试的语言环境的语言代码,然后点击“确定”(或按回车)。我们的示例扩展支持“en”(英语)、“de”德语()、“nl”(荷兰语)和“ja”日语。
  4. +
  5. 重启你的浏览器以完成更改。
  6. +
+ +
+

Note: 这个方法可以用来修改浏览器的语言区域,即使你未安装过该语言区域对应的语言包。这样的话你就可以将浏览器用户界面调整显示为你的默认语言。

+
+ +
    +
+ +

再次从磁盘临时加载该扩展,然后测试你的新语言区域:

+ + + +

{{EmbedYouTube("R7--fp5pPGg")}}

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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
值类型字符串(String)
强制性非强制
示例 +
+"author": "小明"
+
+ +

附加组件的作者, 用于在浏览器用户界面上显示, 这样别人下载安装使用该附加组件的时候, 就能看见你的大名了.

+ +

示例

+ +
"author": "小明"
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.author")}}

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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
TypeObject
强制性不强制
示例 +
+"background": {
+  "scripts": ["background.js"]
+}
+
+ +

通过background 键来给您的扩展程序引入一个或者多个后台脚本文件,以及一个可选的后台页面文件。

+ +

后台脚本放置的是需要长期保持状态,或者需要执行长期的操作,并且与任意特定网页或者浏览器窗口的生命周期无关的代码。

+ +

后台脚本会在扩展程序被加载后立即被加载,并且一直保持被加载状态,只有在扩展程序被禁止或者卸载的时候才停止运行。只要您获得了必要的许可permissions,您可以在该脚本中使用任意的扩展程序API。

+ +

浏览Anatomy of a WebExtension中的Background pages部分以获取更多的细节。

+ +

background 键最多只能拥有以下的两个属性,两个属性都是可选属性:

+ + + + + + + + + + + + +
"scripts" +

一个字符串数组,数组中的每个字符串都是JavaScript源文件相对于manifest.json的相对路径,JavaScript源文件便是些被包含在扩展程序中的后台脚本文件。

+ +

脚本共享相同的全局窗口

+ +

脚本按照在数组中的顺序进行加载

+ +

注意在低于Firefox 50版本的浏览器下会出现一个问题:当Firefox debugger已经打开时,脚本并不能总是按照数组中定义的顺序进行加载。若要解决这个问题,您可以使用page属性,用<script>标签将后台脚本文件从页面中加载进来。这个问题已经在Firefox 50中被修复。

+
"page" +

如果您仅仅指定了“scripts”属性,将生成一个空白的页面来运行指定的脚本。

+ +

如果您需要在页面中显示某些特定的内容,您可以使用“page”属性来定义自己的页面。

+ +

如果您使用此属性,您仍然可以使用“script”属性来指定后台脚本,但您也可以就像在普通网页中一样在页面中包含自己的脚本。

+
+ +

示例

+ +

加载2个后台脚本文件.

+ +
  "background": {
+    "scripts": ["jquery.js", "my-background.js"]
+  }
+ +

加载1个自定义的后台页面文件.

+ +
  "background": {
+    "page": "my-background.html"
+  }
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.background", 10)}}

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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
类型Object
是否必须
示例 +
+"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"
+}
+
+ +

浏览器按钮(browser action)指您的扩展在浏览器工具栏上所添加的按钮。该按钮有个图标,并可可选地拥有一个使用 HTML,CSS,和 JavaScript 指定内容的弹出窗口。

+ +

如果您使用弹窗(popup),则该弹窗将在用户点击该按钮时打开,并且弹窗中你所提供的运行中的 JavaScript 将可处理用户与其的交互。如果您不使用弹窗,则会在用户点击该按钮时将点击事件传递给你扩展的 background scripts 中。

+ +

您同样可以使用 browserAction API 以编程的方式创建及控制浏览器按钮。

+ +

语法

+ +

browser_action 键是一个可能有以下任何属性的对象,均是可选:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型详细描述
browser_styleBoolean +
Firefox 48 中新出现
+ +

可选,默认为 false

+ +

使用此项来包含一个样式表以使其与浏览器 UI 和其它使用了 browser_style 属性的扩展外观上保持一致。虽然此键值默认为 false,还是建议您将其包含并设其为 true

+ +

在 Firefox 中,该样式表详阅 chrome://browser/content/extension.css,OS X 系统或见于 chrome://browser/content/extension-mac.css。

+ +

Firefox Style Guide 记述了为获得特定样式您所能为弹窗中元素应用的 class。

+ +

latest-download 中的示例扩展的弹窗使用了 browser_style

+
default_areaString +
Firefox 54 中新出现
+ +

定义浏览器最初放置该按钮的位置。该字符串可能是以下四个值中的一个:

+ +
    +
  • "navbar":按钮会被放置到浏览器主工具栏中,与 URL 栏并肩。
  • +
  • "menupanel":按钮会被放置到弹出面板中。
  • +
  • "tabstrip":按钮会被放置到包含浏览器选项卡的工具栏中。
  • +
  • "personaltoolbar":按钮会被放置到书签工具栏中。
  • +
+ +

该属性只有 Firefox 支持。

+ +

这个属性是可选的,并默认为 "navbar"。

+ +

扩展不能在其被安装后主动更改其按钮的位置,但用户可以使用浏览器内置的界面定制机制来移动按钮。

+
default_iconObjectString +

使用此项以指定一个或多个 browser action 之图标。该图标默认显示在浏览器工具栏里。

+ +

图标使用相对于 manifest.json 文件本身的 URL 指定。

+ +

你可以通过提供一个字符串以指定单个的图标文件:

+ +
+"default_icon": "path/to/geo.svg"
+ +

要指定多个不同大小的图标,则在此指定一个对象。每个属性的名字是以像素记的该图标的高,且其必须被转换为一个整数。值为其 URL。示例:

+ +
+    "default_icon": {
+      "16": "path/to/geo-16.png",
+      "32": "path/to/geo-32.png"
+    }
+ +

参阅 选择图标大小 以获得此项的更多指引。

+
default_popupString +

指向包含弹窗信息的 HTML 文件之路径

+ +

该 HTML 文件可能会使用 <link> and <script> 元素来包含 CSS 和 JavaScript,就像普通网页一样。

+ +

与普通网页不同,弹窗中运行的 JavaScript 能访问所有的 WebExtension APIs(当然,仅对于拥有适当权限的扩展)。

+ +

这是一个可本地化属性

+
default_titleString +

按钮的工具提示,在用户将鼠标移到其上时显示。

+ +

这是一个可本地化属性

+
+ +

选择图标大小

+ +

浏览器按钮的图标在不同上下文中可能需要以不同大小显示:

+ + + +

如果浏览器在给定的情况下找不到正确尺寸的图标,它就会选最匹配的并对其缩放。缩放可能会使图标模糊,所以一件很重要的事情就是小心地选择图标尺寸。

+ +

对此有两种常用方法。你可以以 SVG 文件的形式提供单个图标,然后它就会被正确地缩放:

+ +
"default_icon": "path/to/geo.svg"
+ +

或者,您可以提供几个不同尺寸的图标,浏览器将选择最佳匹配。

+ +

Firefox 中:

+ + + +

所以你可以选定精确匹配的图标,不论普通屏还是 Retina 屏的显示,都仅需要提供三个图标文件,并把它们像这样确定下来:

+ +
    "default_icon": {
+      "16": "path/to/geo-16.png",
+      "32": "path/to/geo-32.png",
+      "64": "path/to/geo-64.png"
+    }
+ +

如果 Firefox 找不到其需要的精确匹配的尺寸,则它会选择大于理想尺寸的已指定的最小图标。如果所有图标都小于理想尺寸,它就将选择已指定的最大图标。

+ +

示例

+ +
"browser_action": {
+  "default_icon": {
+    "16": "button/geo-16.png",
+    "32": "button/geo-32.png"
+  }
+}
+ +

只有一个图标的浏览器按钮,指定了 2 种不同大小。其扩展的 background scripts 能接收用户点击其图标时的点击事件代码大概像这样:

+ +
 browser.browserAction.onClicked.addListener(handleClick);
+ +
"browser_action": {
+  "default_icon": {
+    "16": "button/geo-16.png",
+    "32": "button/geo-32.png"
+  },
+  "default_title": "Whereami?",
+  "default_popup": "popup/geo.html"
+}
+ +

浏览器按钮具有一个图标,一个标题,还有一个弹窗。弹窗会在用户点击按钮时出现。

+ +

对于一个简易,但是完整,使用了浏览器按钮的扩展,参见演练教程

+ +

浏览器兼容性

+ +

{{Compat("webextensions.manifest.browser_action", 10)}}

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 +--- +
{{AddonSidebar}}
+ +
+

注意这个key不被Blink-based浏览器(Google Chrome和Opera)支持。如果你在插件中包含了这个key,当在这些浏览器中调用时虽然能用但是会显示警告。

+
+ + + + + + + + + + + + + + + + +
类型Object
强制性通常不做强制性要求(详细参见When do you need an Add-on ID?)。在Firefox 48版本之前为强制要求。
示例 +
+"applications": {
+  "gecko": {
+    "id": "addon@example.com",
+    "strict_min_version": "42.0"
+  }
+}
+
+ +

applications key包含特定于主机应用程序的键。

+ +

目前只包含了一个key:gecko,其中包含了4个attributes:

+ + + +

Chrome不兼容性

+ +

你不能在Chrome附加组件中使用这个key。

+ +

示例

+ +

示例中包含了所有可能的key。注意你通常不会包含strict_max_versionupdate_urlkey在大部分附加组件中。

+ +
"applications": {
+  "gecko": {
+    "id": "addon@example.com",
+    "strict_min_version": "42.0",
+    "strict_max_version": "50.*",
+    "update_url": "https://example.com/updates.json"
+  }
+}
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 +--- +

{{AddonSidebar}}

+ + + + + + + + + + + + + + + + +
类型数组(Array)
必要
示例 +
+"content_scripts": [
+  {
+    "matches": ["*://*.mozilla.org/*"],
+    "js": ["borderify.js"]
+  }
+]
+
+ +

让浏览器将content scripts加载到匹配网址的网站上

+ +

此键(content_scripts)是一个数组,每个项目都是一个满足下列条件的对象:

+ + + +

下面表格列出了所有与你可以使用的键:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型描述
all_framesBoolean +

true: 将jscss注入该页面所有的框架(frame)中

+ +

false: 仅注入到顶层

+ +

默认为false

+
cssArray +

一个数组,包含将会被注入到匹配页面的CSS文件的路径(路径相对于manifest.json)。

+ +

在加载DOM之前,文件将会按指定的顺序注入。

+
exclude_globsArray +
Firefox 自48版本开始支持globs
+ +

包含通配符的字符串数组。 请参阅下面的匹配URL格式

+
exclude_matchesArray一个match patterns的数组,请参阅下面的匹配URL格式
include_globsArray +
Firefox 自48版本开始支持globs
+ 包含通配符的字符串数组。 请参阅下面的匹配URL格式
jsArray +

一个数组,包含将会被注入到匹配页面的JS文件的路径(路径相对于manifest.json)。

+ +

文件将会按指定的顺序注入。这意味着如果你想在另一个脚本中包含jQuery,可以这样做:

+ +
+"js": ["jquery.js", "my-content-script.js"]
+ +

接下来,"my-content-script.js"可以使用jQuery.

+ +

文件将在run_at指定的时间注入。

+
matchesArray +

一个match patterns的数组,请参阅下面的匹配URL格式

+ +

这是唯一的必须键。

+
run_atString +

此选项指定在“js”键中的脚本何时被注入。您可以使用下列的三个字符串之一,每个字符串都代表加载文档过程中的不同状态。状态直接对应于{{domxref("Document/readyState", "Document.readyState")}}:

+ +
    +
  • document_start”:对应于正在加载。 DOM仍在加载中。
  • +
  • document_end”:对应于可交互。 DOM已完成加载,但脚本和图像等资源可能仍在加载。
  • +
  • document_idle”:对应完成。 文档及其所有资源已完成加载。
  • +
+ +

默认值为“document_idle”。

+ +

在所有情况下,js键中的文件都会在css键中的文件之后注入。

+
+ +

匹配URL格式

+ +

“content_scripts”键基于URL匹配将content scripts注入到网页上:如果网页的URL与键中的规则匹配,则将注入脚本。“content_scripts”中有四个属性,可以用于此规则:

+ + + +

要匹配这些属性之一,网址必须与其数组中的至少一个项匹配。例如,指定一个属性:

+ +
"matches": ["*://*.example.org/*", "*://*.example.com/*"]
+ +

"http://example.org/"和"http://example.com/"都将会匹配

+ +

由于matches是唯一的强制性键,其他三个键用于进一步限制匹配的URL。要匹配作为一个整体的键,网址必须:

+ +
    +
  1. 匹配matches属性
  2. +
  3. 并且,匹配include_globs属性(如果有)
  4. +
  5. 并且,不匹配exclude_matches属性(如果有)
  6. +
  7. 并且,不匹配exclude_globs属性(如果有)
  8. +
+ +

globs

+ +
Firefox 自48版本开始支持globs
+ +

glob只是一个可以包含通配符的字符串。 有两种类型的通配符,您可以在一个glob中组合使用它们:

+ + + +

例如,"*na?i"会匹配"illuminati"和"annunaki",但不会匹配"sagnarelli".

+ +

示例

+ +
"content_scripts": [
+  {
+    "matches": ["*://*.mozilla.org/*"],
+    "js": ["borderify.js"]
+  }
+]
+ +

这会将content脚本“borderify.js”插入到“mozilla.org”或其任何子域下的所有页面,无论是HTTP还是HTTPS。

+ +
  "content_scripts": [
+    {
+      "exclude_matches": ["*://developer.mozilla.org/*"],
+      "matches": ["*://*.mozilla.org/*"],
+      "js": ["jquery.js", "borderify.js"]
+    }
+  ]
+ +

这会将两个content脚本插入到“mozilla.org”及其任何子域(除“developer.mozilla.org”外)的所有页面中,无论是通过HTTP还是HTTPS。

+ +

content脚本有相同的DOM视图,并按照它们在数组中出现的顺序注入,因此“borderify.js”可以访问由“jquery.js”添加的全局变量。

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.content_scripts")}}

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 +--- +

{{AddonSidebar}}

+ + + + + + + + + + + + + + + + +
TypeString
强制性可能发生的:如果存在_locales子目录,必须存在,否则不存在。
例子 +
+"default_locale": "en"
+
+ +

如果扩展名包含_locales目录,则该key必须存在,否则不得存在。它标识 _locales的一个子目录,该子目录将用于查找扩展名的默认字符串。

+ +

见 国际化 。

+ +

范例

+ +
"default_locale": "en"
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.default_locale")}}

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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
值类型字符串
强制性不强制
示例 +
+"description": "附加组件的主要功能特性的简短描述."
+
+ +

用于在用户下载安装使用界面中显示的一段简短的关于该附加组件的描述.

+ +

关于本地化, 可查看 localizable property.

+ +

示例

+ +
"description": "附加组件的主要功能特性的简短描述."
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.description")}}

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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
值类型对象
强制性非强制
示例 +
+"developer": {
+  "name": "Walt Whitman",
+  "url": "https://en.wikipedia.org/wiki/Walt_Whitman"
+}
+
+ +

插件开发者的名字和主页地址,用于显示在浏览器的用户界面中。

+ +

该对象的两个属性都是可选的。如果存在“name”和“url”属性,将会分别覆盖authorhomepage_url键。这个对象仅仅允许指定一个开发者名字的主页地址。

+ +

示例

+ +
"developer": {
+  "name": "Walt Whitman",
+  "url": "https://en.wikipedia.org/wiki/Walt_Whitman"
+}
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.developer")}}

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 +--- +
{{AddonSidebar}}
+ +
+

本文描述的是适用于 WebExtensions 的 manifest.json。若您正在寻找适用于 PWA 的 manifest.json 的有关信息,请参考这篇文章:Web App Manifest

+
+ +
manifest.json 是每个 WebExtension 唯一必须包含的元数据文件。
+ +

通过使用 manifest.json,您可以指定扩展的基本元数据,例如名称和版本,还可以指定扩展各个方面的功能(例如后台脚本,内容脚本和某些浏览器行为)。

+ + +

它是一个允许使用 "//" 撰写单行注释的、特殊的 JSON 文件。

+ +

manifest.json 键列表

+ +

支持的 manifest.json 键如下所示:

+ +

简体中文内容

+ +
{{ListSubpages("/zh-CN/Add-ons/WebExtensions/manifest.json")}}
+ +

英文内容

+ +
{{ListSubpages("/en-US/Add-ons/WebExtensions/manifest.json")}}
+ + + +

在运行时访问 manifest.json 键

+ +

你可以在拓展的 JavaScript 代码中通过 {{WebExtAPIRef("runtime.getManifest()")}} 函数访问拓展的 manifest 数据:

+ +
browser.runtime.getManifest().version;
+ +

示例

+ +

The block below shows the basic syntax for some common manifest keys.

+ +
+

Note: 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.

+
+ +

For complete example extensions, see Example extensions.

+ +
{
+  "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"]
+}
+ +

浏览器兼容性

+ +

For a full overview of all manifest keys and their sub-keys, see the full manifest.json browser compatibility table.

+ + + +

{{Compat("webextensions.manifest")}}

+ +

参见

+ +

{{WebExtAPIRef("permissions")}} JavaScript API

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 +--- +

{{AddonSidebar}}

+ + + + + + + + + + + + + + + + +
值类型Number
强制性强制
示例 +
+"manifest_version": 2
+
+ +

此键指定扩展使用的 manifest.json 的版本。

+ +

目前,此值必须为 2。

+ +

示例

+ +
"manifest_version": 2
+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.manifest.manifest_version")}}

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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
值类型字符串(String)
强制性强制
示例 +
+"name": "附加组件的名称"
+
+ +

附加组件的名称. 用于在用户界面和 addons.mozilla.org 网站上显示标识名称.

+ +

关于本地化, 可查看 localizable property.

+ +

示例

+ +
"name": "插件的名称"
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.name")}}

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 +--- +

{{AddonSidebar}}

+ + + + + + + + + + + + + + + + +
值类型数组
强制性不强制
示例 +
+"permissions": [
+  "*://developer.mozilla.org/*",
+  "webRequest"
+]
+
+ +

使用permissions 关键字为你的扩展请求特殊的权限。该关键字为一个字符串数列,每个字符串请求一项权限。

+ +

如果你使用该关键字请求权限,浏览器可能会在安装该扩展时通知用户该扩展需求某些权限,并询问他们是否愿意给予这些权限。在插件安装之后浏览器也可能允许用户检查扩展的权限。因为要求授予权限可能会影响用户安装你的扩展的意愿,所以请求权限需要特别小心的考虑。举个例子,你想要避免请求不必要的权限,而且可以在你的扩展描述中提供你为何需要某些权限的信息。更多关于这个话题的描述你可以参考这篇提供的文章 请求正确的权限

+ +

该关键字能够包含三种类型的权限:

+ + + +

主机权限

+ +

 主机权限使用 match patterns 指定,扩展在每一个表达式指定的网址上请求额外权限。

+ +

额外权限包括:

+ + + +

Firefox浏览器,自56以后的版本,扩展都会自动获取其源的主机权限,如以下形式:

+ +
moz-extension://60a20a9b-1ad4-af49-9b6c-c64c98c37920/
+ +

60a20a9b-1ad4-af49-9b6c-c64c98c37920 是扩展内部ID。编程时可使用 extension.getURL() 来返回此URL路径:

+ +
    +
  1. +
    browser.extension.getURL("");
    +// moz-extension://60a20a9b-1ad4-af49-9b6c-c64c98c37920/
    +
  2. +
+ +

API 权限

+ +

API 权限有关键字指定,每个关键字标志着一类WebExtension API 能够被使用。

+ +

如下关键字是当前可用的:

+ + + +

在大部分情况下这种权限仅仅允许你访问API,除了以下情况:

+ + + +

活动标签权限

+ +

该权限被指定为“activeTab”。如果一个扩展拥有activeTab权限,当用户跟该扩展交互时,扩展仅在活动标签被赋予额外权限。

+ +

“用户交互”包括:

+ + + +

额外特权包括:

+ + + +

改权限的目的是为了在不给予扩展太多权限的情况下,使得扩展能够应付大部分情况。很多扩展需要在用户要求时,在当前页面做一些处理,比如,考虑一个扩展想要在用户点击一个浏览器按钮时在当前页面运行一个脚本,如果 activeTab 权限不存在,扩展将需要请求主机权限<all_urls>,但是这给予了扩展超过其需要的权限:现在它可以在任何任何时间标签页执行脚本任何次,而不是仅仅在活动标签而且仅仅回应用户的行为。

+ +

剪贴板访问

+ +

有两种权限使得WebExtentsion可以跟剪贴板交互:

+ + + +

查看 Interact with the clipboard 获取更多

+ +

无限制存储

+ +

unlimitedStorage 权限:

+ + + +
+
+ +

示例

+ +
 "permissions": ["*://developer.mozilla.org/*"]
+ +

请求 developer.mozilla.org 下的权限访问.

+ +
  "permissions": ["tabs"]
+ +

请求tabs API的权限需要部分的访问。

+ +
  "permissions": ["*://developer.mozilla.org/*", "tabs"]
+ +

请求以上两种访问。

+ +

浏览器兼容性

+ +

本页的兼容列表是从结构化数据生成的。如果你想参与修改此数据,请参考 https://github.com/mdn/browser-compat-data 并发送pull 请求。

+ +

{{Compat("webextensions.manifest.permissions")}}

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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
TypeString
强制性不强制
示例 +
+"short_name": "附加组件的短名称"
+
+ +

附加组件的短名称. 一般用在 name 特性太长的情况下. 建议短名称的长度不要超过12个字符. 如果没有在 manifest.json 主文件中声明 short_name, 并且 name 特性的值又比较长的话, 用户界面显示的时候可能只会显示一部分. 

+ +

关于本地化, 可查看 localizable property.

+ +

示例

+ +
"short_name": "附加组件的短名称"
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.short_name")}}

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 +--- +

{{AddonSidebar}}

+ + + + + + + + + + + + + + + + +
TypeString
强制性强制
示例 +
+"version": "0.1"
+
+ +

附加组件的版本, 一般格式设置为由点分隔开来数字的ASCII字符串. 关于版本格式的详细信息, 请查看 Version format .

+ +

需要注意的是 Chrome 浏览器的 version 格式要求(the syntax defined for Chrome's version)比 Firefox 浏览器的 version 格式更严格一些, 这意味这:

+ + + +

示例

+ +
"version": "0.1"
+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.version")}}

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 +--- +

{{AddonSidebar}}

+ + + + + + + + + + + + + + + + +
类型Array
是否必需No
示例 +
+"web_accessible_resources": [
+  "images/my-image.png"
+]
+
+ +

描述

+ +

你有时想将资源(如图片、HTML、CSS 或 JavaScript)与你的扩展应用合并打包,让网页能够访问它们。

+ +

举个例子,Beastify example extension 将用户选择的野兽图片来替换网页,这些图片与应用是经过合并打包的。该应用添加 <img>,其 src 指向图片,这样就使选中的图片可见了。网页要载入图片的话,这些图片就必须可经访问。

+ +

通过 web_accessible_resources, 你列出资源,让它们可经网页访问。这些资源路径相对于 manifest.json 文件.

+ +

注意,这其中不必包括 content scripts。

+ +

如果你的应用要用 {{WebExtAPIRef("webRequest")}} 来重定向公共 URL(如 HTTPS) 到一个该应用中的页面, 那么应用必须将该页面列入web_accessible_resources

+ +

使用 web_accessible_resources

+ +

例如,如果你的应用含有图片,路径为 images/my-image.png,如下所示:

+ +
my-extension-files/
+    manifest.json
+    my-background-script.js
+    images/
+        my-image.png
+ +

如果要使网页能够从元素 <img> 的属性 src 指向该图片,你得写明web_accessible_resources,如下所示:

+ +
"web_accessible_resources": ["images/my-image.png"]
+ +

之后,图片可通过 URL 来访问,如下所示:

+ +
moz-extension://<extension-UUID>/images/my-image.png"
+ +

<extension-UUID> 不是应用 ID,它随机生成,对应每个浏览器实例,以防网页查看浏览器安装的扩展应用来获取信息。

+ +
+

Chrome 的 <extension-UUID> 是不变的。某资源如果由web_accessible_resources 写明,那么它可通过 chrome-extension://<your-extension-id>/<path/to/resource> 来访问。  

+
+ +

要获得资源的 URL,推荐用 runtime.getURL 向参数传递 manifest.json 的相对路径,比如:

+ +
browser.runtime.getURL("images/my-image.png");
+// something like:
+// moz-extension://944cfddf-7a95-3c47-bd9a-663b3ce8d699/images/my-image.png
+ +

这会返回正确的 URL,不受应用运行的浏览器影响。

+ +

通配符

+ +

web_accessible_resources  中的条目还可以有通配符。比如,下面的条目匹配“images/my-image.png”:

+ +
  "web_accessible_resources": ["images/*.png"]
+ +

安全

+ +

注意,如果你部署了一个页面,那么任一网页可能会链接或重定向至该页面,因而它应认为任意输入(比如 POST data)的来源不可信任,这与通常网页的做法一样。

+ +

Example

+ +
"web_accessible_resources": ["images/my-image.png"]
+ +

Make the file at "images/my-image.png" web accessible.

+ +

Browser compatibility

+ + + +

{{Compat("webextensions.manifest.web_accessible_resources")}}

diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/\344\270\273\351\241\265\345\234\260\345\235\200/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/\344\270\273\351\241\265\345\234\260\345\235\200/index.html" new file mode 100644 index 0000000000..01749d5ff3 --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/\344\270\273\351\241\265\345\234\260\345\235\200/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 +--- +
{{AddonSidebar}}
+ + + + + + + + + + + + + + + + +
值类型字符串(String)
强制性非强制
示例 +
+"homepage_url": "https://example.org/my-addon"
+
+ +

该扩展的主页地址。

+ +

如果 developer 键存在且包含“url”属性,它将会覆盖 homepage_url 键。

+ +

这是一个 localizable property.

+ +

示例

+ +
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify"
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.manifest.homepage_url")}}

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 +--- +
{{AddonSidebar}}
+ +

匹配模式是一种指定网址组的方法:: 一个匹配模式匹配特定的一组URL。 它们由WebExtensions 在几个地方使用,最明显的是指定要将内容脚本加载到哪些文档中,并指定要向其中添加 webRequest 侦听器的URL。

+ +

使用匹配模板的API通常接收一个匹配模板的列表,当URL匹配任何模式时会恰当的运行. 看个例子 在manifest.json中的 content_scripts 关键字。

+ +

匹配模式结构

+ +

所有的匹配模式用一个字符串来定义,而且都是"<all_urls>" 模板的一部份, 匹配模板包含三个部分: scheme, host, 和 path.  scheme  host 用 "://" 分隔。

+ +
<scheme>://<host><path>
+ +

方案

+ +

 scheme  可能以下两种格式之一:

+ + + + + + + + + + + + + + + + + + +
FormMatches
"*"Only "http" and "https".
One of "http", "https", "file", "ftp", "app".Only the given scheme.
+ +

主机

+ +

 host 组件可以采取三种形式之一::

+ + + + + + + + + + + + + + + + + + + + + + +
FormMatches
"*"Any host.
"*." followed by part of the hostname.The given host and any of its subdomains.
A complete hostname, without wildcards.Only the given host.
+ +

只有当 scheme 是 "file" 是 host 可选的

+ +

值得注意的是通配符可能只会在开头显示。

+ +

路径

+ +

path 组件必须以“/”开头。

+ +

之后,它可能随后包含“*”通配符和网址路径中允许的任何字符的任意组合。 与 host 不同, path 组件可能在中间或末尾包含“*”通配符,并且“*”通配符可以多次出现。

+ +

<all_urls>

+ +

特殊值“<all_urls>”匹配任何受支持方案下的所有URL:即, "http", "https", "file", "ftp", "app"。

+ +

范例

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PatternExample matchesExample non-matches
+

<all_urls>

+ +

Match all URLs.

+
+

http://example.org/

+ +

ftp://files.somewhere.org/

+ +

https://a.org/some/path/

+
+

resource://a/b/c/
+ (unsupported scheme)

+
+

*://*.mozilla.org/*

+ +

Match all HTTP and HTTPS URLs that are hosted at "mozilla.org" or one of its subdomains.

+
+

http://mozilla.org/

+ +

https://mozilla.org/

+ +

http://a.mozilla.org/

+ +

http://a.b.mozilla.org/

+ +

https://b.mozilla.org/path/

+
+

ftp://mozilla.org/
+ (unmatched scheme)

+ +

http://mozilla.com/
+ (unmatched host)

+ +

http://firefox.org/
+ (unmatched host)

+
+

*://mozilla.org/

+ +

Match all HTTP and HTTPS URLs that are hosted at exactly "mozilla.org/".

+
+

http://mozilla.org/

+ +

https://mozilla.org/

+
+

ftp://mozilla.org/
+ (unmatched scheme)

+ +

http://a.mozilla.org/
+ (unmatched host)

+ +

http://mozilla.org/a
+ (unmatched path)

+
+

ftp://mozilla.org/

+ +

Match only "ftp://mozilla.org/".

+
ftp://mozilla.org +

http://mozilla.org/
+ (unmatched scheme)

+ +

ftp://sub.mozilla.org/
+ (unmatched host)

+ +

ftp://mozilla.org/path
+ (unmatched path)

+
+

https://*/path

+ +

Match HTTPS URLs on any host, whose path is "path".

+
+

https://mozilla.org/path

+ +

https://a.mozilla.org/path

+ +

https://something.com/path

+
+

http://mozilla.org/path
+ (unmatched scheme)

+ +

https://mozilla.org/path/
+ (unmatched path)

+ +

https://mozilla.org/a
+ (unmatched path)

+ +

https://mozilla.org/
+ (unmatched path)

+
+

https://*/path/

+ +

Match HTTPS URLs on any host, whose path is "path/".

+
+

https://mozilla.org/path/

+ +

https://a.mozilla.org/path/

+ +

https://something.com/path/

+
+

http://mozilla.org/path/
+ (unmatched scheme)

+ +

https://mozilla.org/path
+ (unmatched path)

+ +

https://mozilla.org/a
+ (unmatched path)

+ +

https://mozilla.org/
+ (unmatched path)

+
+

https://mozilla.org/*

+ +

Match HTTPS URLs only at "mozilla.org", with any path.

+
+

https://mozilla.org/

+ +

https://mozilla.org/path

+ +

https://mozilla.org/another

+ +

https://mozilla.org/path/to/doc

+
+

http://mozilla.org/path
+ (unmatched scheme)

+ +

https://mozilla.com/path
+ (unmatched host)

+
+

https://mozilla.org/a/b/c/

+ +

Match only this URL.

+
https://mozilla.org/a/b/c/Anything else.
+

https://mozilla.org/*/b/*/

+ +

Match HTTPS URLs hosted on "mozilla.org", whose path contains a component "b" somewhere in the middle.

+
+

https://mozilla.org/a/b/c/

+ +

https://mozilla.org/d/b/f/

+ +

https://mozilla.org/a/b/c/d/

+
+

https://mozilla.org/b/*/
+ (unmatched path)

+ +

https://mozilla.org/a/b/
+ (unmatched path)

+
+

file:///blah/*

+ +

Match any FILE URL whose path begins with "blah".

+
+

file:///blah/

+ +

file:///blah/bleh

+
file:///bleh/
+ (unmatched path)
+ +

无效匹配模式

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Invalid patternReason
resource://path/Unsupported scheme.
https://mozilla.orgNo path.
https://mozilla.*.org/"*" in host must be at the start.
https://*zilla.org/"*" in host must by the only character or be followed by ".".
http*://mozilla.org/"*" in scheme must be the only character.
file://*Empty path: this should be "file:///*".
+ +

测试匹配模式

+ +

当制作扩展时你通常不会跟直接使用匹配模板: 通常你讲一个匹配模式传递给API,然后API构造一个匹配模式并且使用他来测试url。不过如果你正在尝试哪一种匹配模式可以被使用,或者调试一个匹配问题,那么直接创建和测试匹配模板的能力将变得有用,这个模块将解释如何做到这点。

+ +

首先,打开开发者工具设置,并且检查 "Enable browser chrome and add-on debugging toolboxes" 被打开:

+ +

{{EmbedYouTube("JDEe2fyFpHE")}}

+ +

然后打开 "Browser Console":

+ +

{{EmbedYouTube("mfuBMje6dA4")}}

+ +

它给了你一个命令行以使你可以执行一些特权javascript代码。

+ +
+

因为运行在浏览器控制台的代码拥有系统特权,在任何时候都请你小心理解你的代码做了什么

+
+ +

现在粘贴以下代码到命令行然后按下 enter:

+ +
Cu.import("resource://gre/modules/MatchPattern.jsm");
+Cu.import("resource://gre/modules/BrowserUtils.jsm");
+ +

这做了两件事:

+ + + +

现在你可以构造MatchPattern对象,构造URIs,并检查URIs 是否匹配:

+ +
var match = new MatchPattern("*://mozilla.org/");
+
+var uri = BrowserUtils.makeURI("https://mozilla.org/");
+match.matches(uri); //        < true
+
+uri = BrowserUtils.makeURI("https://mozilla.org/path");
+match.matches(uri); //        < false
+ +

 

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 +--- +
{{AddonSidebar}}
+ +

浏览器附加组件( add-on )常被用于修改网页。例如更改页面的样式,隐藏特定的DOM节点或把DOM节点注入到页面中。

+ +

使用WebExtensions有两种方式:

+ + + +

无论使用上面何种方式,它们都被称为内容脚本, 与其他脚本的区别:

+ + + +

在本文中,我们将看下加载脚本的两种方式。

+ +

修改匹配URL的页面

+ +

首先,创建一个名为“ modify-page ”的文件夹,并在目录下创建“ manifest.json ”文件,内容如下:

+ +
{
+
+  "manifest_version": 2,
+  "name": "modify-page",
+  "version": "1.0",
+
+  "content_scripts": [
+    {
+      "matches": ["https://developer.mozilla.org/*"],
+      "js": ["page-eater.js"]
+    }
+  ]
+
+}
+ +

"content_scripts"指出符合 URL 格式的页面地址,然后让浏览器加载脚本(“ page-eater.js“)到匹配的URL页面(https://developer.mozilla.org/ )。

+ +
+

由于 content_scripts "js" 属性是一个数组,因此可以使用它将多个脚本注入匹配的页面。 如果这样做,页面将按照数组中列出的顺序加载多个脚本。

+
+ +
+

content_scripts 键还具有一个 "css" 属性,可以使用它来注入CSS样式表。

+
+ +

在 "modify-page" 文件夹下创建“ page-eater.js ”文件,内容如下:

+ +
document.body.textContent = "";
+
+var header = document.createElement('h1');
+header.textContent = "This page has been eaten";
+document.body.appendChild(header);
+ +

现在安装这个WebExtension, 然后浏览 https://developer.mozilla.org/

+ +

{{EmbedYouTube("lxf2Tkg6U1M")}}

+ +
+

请注意,虽然此视频显示在 addons.mozilla.org 工作的 content scripts ,但目前该网站已禁止 content scripts

+
+ +

通过程序修改页面

+ +

如何修改程序使其在用户要求时才吞页面。现在修改上面的例子,在点击右键菜单项时才注入内容脚本。

+ +

修改 "manifest.json" 内容如下:

+ +
{
+
+  "manifest_version": 2,
+  "name": "modify-page",
+  "version": "1.0",
+
+  "permissions": [
+    "activeTab",
+    "contextMenus"
+  ],
+
+  "background": {
+    "scripts": ["background.js"]
+  }
+
+}
+ +

这里我们要移除"content_scripts"键值,并添加两个键:

+ + + +

在 "modify-page" 文件夹下创建名为 "background.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"
+    });
+  }
+});
+
+ +

在该脚本中我们创建了一个右键菜单项, 给了它一个具体的 id 和标题 (将在菜单中显示的文本)。 然后又设置了一个事件侦听器,当用户点击菜单项时,检查该菜单项是否就是我们的吞页菜单项。 如果是, 就通过tabs.executeScript() 接口,把"page-eater.js" 注入到活动标签页中。 这个接口用标签ID做为参数:如果省略标签ID参数,就默认把脚本注入当前活动标签。

+ +

现在,附加组件看起来像这样:

+ +
modify-page/
+    background.js
+    manifest.json
+    page-eater.js
+ +

重新加载WebExtension, 打开页面 (这次可以是任何一个页面) 激活右键菜单,然后选择 "Eat this page":

+ +

{{EmbedYouTube("zX4Bcv8VctA")}}

+ +
+

请注意,虽然此视频显示在 addons.mozilla.org 工作的 content scripts ,但目前该网站已禁止 content scripts

+
+ +

消息

+ +

内容脚本和后台脚本不能直接相互访问,但可以通过发送消息进行通信。当一端设置一个消息侦听器时,另一个端就可以发送消息了。下面的表格总结了通信时的api接口:

+ + + + + + + + + + + + + + + + + + + +
 在内容脚本中在后台脚本中
发送消息browser.runtime.sendMessage()browser.tabs.sendMessage()
接收消息browser.runtime.onMessagebrowser.runtime.onMessage
+ +

修改上面的示例,使得可以通过后台脚本来发送消息。

+ +

首先,修改 "background.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);
+  }
+});
+
+ +

 注入 "page-eater.js"后, 通过使用 tabs.query() 获取当前活动标签页, 然后使用tabs.sendMessage() 将消息发送到该标签页中的内容脚本。 该消息的内容 {replacement: "Message from the add-on!"}。

+ +

接下来,修改 "page-eater.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);
+
+ +

现在,不再立即执行吞页,内容脚本将先通过使用 runtime.onMessage来监听消息。当监听到消息时, 内容脚本才开始运作,除了来自request.replacement的替换文本不一样以外,其他的脚本运作本质上与之前的相同 。

+ +

如果我们想将消息从内容脚本发送到后台页面,除了在内容脚本中使用 runtime.sendMessage() ,其他与上面的过程相反。

+ +
+

这些例子注入的都是JavaScript;注入CSS可以使用 tabs.insertCSS() 函数。

+
+ +

了解更多

+ + + +

 

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 +--- +
{{AddonSidebar}}
+ +

 

+ +

原生应用清单是一个符合特定规则的JSON文件,它应该使用与 extension 不同的安装方式存放在用户的计算机上。举个例子,原生应用清单是由设备管理员或者通过原生应用安装器提供的。

+ +

有三种不同的原生应用清单:

+ + + + + + + + + + + + + + + + +
原生应用通信清单 +

定义关于 与本地应用通信 的功能:哪一个 extension 可以与本机的原生应用交换信息。

+
存储管理清单 +

定义一些 extension 可以用 {{WebExtAPIRef("storage.managed")}} 读取的只读数据。

+
PKCS #11 清单 +

定义了 extension 使用 {{WebExtAPIRef("pkcs11")}} API 去枚举 PKCS #11 安全模型 并在Firefox安装它们。

+
+ +

对于所有的原生应用清单,你需要做一些工作以便于浏览器可以找到它们。这些规则在 清单路径 章节。

+ +

原生应用通信清单

+ +

原生应用通信清单中包含单个JSON对象,对象具有如下属性:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
nameString +

原生应用的名字

+ +

它必须与 extension 调用 {{WebExtAPIRef("runtime.connectNative()")}} 和 {{WebExtAPIRef("runtime.sendNativeMessage()")}} 时传入的名称保持一致。

+ +

在 OS X 和 Linux 中,它必须和清单文件的文件名保持一致(除.json文件扩展名外)。

+ +

在 Windows 中,它必须和你创建的包含原生应用清单路径的注册表一致。

+ +

它必须符合正则表达式  "^\w+(\.\w+)*$"。这意味着它只能包含小写字母、数字、下划线和 . ,并且不允许开头或结束是 . ,并且 . 后面不能是 .

+
descriptionString +

关于这个原生应用的描述。

+
pathString +

到原生应用的路径。

+ +

在 Windows 中,这可以是一个相对路径。在 OS X 和 Linux 中,必须是绝对路径。

+
typeString +

定义 extension 和原生应用的连接方法。

+ +

目前只支持一种值,那就是 stdio。该值表示应用使用标准输入(stdin)来接受消息,用标准输出(stdout)来发送消息。

+
allowed_extensionsArray of String +

Add-on ID 组成的数组。每个值代表允许ID为该值的 extension 与这个原生应用通信。

+ +
+

这意味着你可能需要在你 extension 的 manifest.json 中包含 applications 字段,并为 extension 设置一个显示的ID,哪怕是在开发时

+
+
+ +

举个例子,这是 ping_pong 原生应用的原生应用通信清单:

+ +
{
+  "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" ]
+}
+ +

清单表示:它允许ID为 ping_pong@example.org 的 extension 通过传入 ping_pong 给 {{WebExtAPIRef("runtime")}} 与自己连接。原生应用自身在 /path/to/native-messaging/app/ping_pong.py 中。

+ +

存储管理清单

+ +

存储管理清单中包含单个JSON对象,对象具有如下属性:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
nameString +

一个 extension 的 ID,表示这个 extension 可以读取这个仓库。

+ +

给出这个ID需要你的 extension 的 manifest.json 文件包含 applications 字段。

+
descriptionString +

人类可读的描述,Firefox会忽略它。

+
typeString +

该值只能是storage

+
dataObject +

一个JSON对象,其中可以包含任何合法的JSON值(string、number、boolean、array、object),他们将成为browser.storage.managed可访问的数据。

+
+ +

举个例子:

+ +
{
+  "name": "favourite-colour-examples@mozilla.org",
+  "description": "ignored",
+  "type": "storage",
+  "data":
+  {
+    "colour": "management thinks it should be blue!"
+  }
+}
+ +

在给出的清单文件中,ID 为 favourite-colour-examples@mozilla.org 的 extension 有权限使用清单中的 data 字段中的数据,代码如下:

+ +
var storageItem = browser.storage.managed.get('colour');
+storageItem.then((res) => {
+  console.log(`Managed colour is: ${res.colour}`);
+});
+ +

PKCS #11 清单

+ +

PKCS #11 清单中包含单个JSON对象,对象具有如下属性:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
nameString +

PKCS #11 模块的名字。

+ +

它必须和你使用 pkcs11 API 时的名字一致。

+ +

在 OS X 和 Linux 中,它必须和清单文件的文件名保持一致(除文件扩展名外)

+ +

在 Windows 中,它必须和你创建的包含原生应用清单路径的注册表一致。

+ +

它必须符合正则表达式  "^\w+(\.\w+)*$"。这意味着它只能包含小写字母、数字、下划线和 . ,并且不允许开头或结束是 . ,并且 . 后面不能是 .

+
descriptionString +

关于该模块的描述。

+ +

它将被用在浏览器界面中为模块设置一个友好的名字(比如,在Firefox的“安全设备”对话框中)

+
pathString +

到模块的路径。

+ +

在 Windows 中,这可以是一个相对路径。在 OS X 和 Linux 中,必须是绝对路径。

+
typeString该值只能是pkcs11。 This must be "pkcs11".
allowed_extensionsArray of String +

Add-on ID 组成的数组。每个值代表允许ID为该值的 extension 与这个模块通信。

+ +
+

这意味着你可能需要在你 extension 的 manifest.json 中包含 applications 字段,并为 extension 设置一个显示的ID,哪怕是在开发时

+
+
+ +

举个例子:

+ +
{
+  "name": "my_module",
+  "description": "My test module",
+  "type": "pkcs11",
+  "path": "/path/to/libpkcs11testmodule.dylib",
+  "allowed_extensions": ["my-extension@mozilla.org"]
+}
+ +

给出的这个JSON清单,保存为 my_module.json,ID为 my-extension@mozilla.org 的 extension 就能够使用类似于如下代码安装 /path/to/libpkcs11testmodule.dylib 安全模块:

+ +
browser.pkcs11.installModule("my_module");
+ +

清单路径

+ +

在 Linux 和 Mac OS X 中,你需要将清单文件存在特定的位置。在 Windows 中,你需要创建一个注册表来指向清单文件。

+ +

所有类型的清单的详细规则都是相同的,除了倒数第二个的 type 字段表示了清单的类型。下面的例子展示了三种不同类型的清单。在例子中,<name> 代表清单中的 name 字段值。

+ +

Windows

+ +

如果想要全局可见,使用下面的路径创建注册表:

+ +
HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\NativeMessagingHosts\<name>
+
+HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\ManagedStorage\<name>
+
+HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\PKCS11Modules\<name>
+ +

注册表应该有单个默认值,值里存放“到清单文件的路径”。比如为原生应用通信清单建立的注册表差不多是这样:

+ +

为原生应用通信清单建立的注册表

+ +
+

对于原生应用清单,即使原生应用是32位的,也不能在 Wow6432Node 下创建注册表。浏览器将总会在 native 视图下寻找注册表的,而不是32位放在环境。确保注册表的创建在原生视图中,你可以键入KEY_WOW64_64KEY 或 KEY_WOW64_32KEY  到 RegCreateKeyEx。请参考:Accessing an Alternate Registry View

+
+ +

如果想要用户级别的可见,使用下面的路径创建注册表:

+ +
HKEY_CURRENT_USER\SOFTWARE\Mozilla\NativeMessagingHosts\<name>
+
+HKEY_CURRENT_USER\SOFTWARE\Mozilla\ManagedStorage\<name>
+
+HKEY_CURRENT_USER\SOFTWARE\Mozilla\PKCS11Modules\<name>
+ +

注册表应该有单个默认值,值里存放“到清单文件的路径”。

+ +

Mac OS X

+ +

如果想要全局可见,将清单文件存放在:

+ +
/Library/Application Support/Mozilla/NativeMessagingHosts/<name>.json
+
+/Library/Application Support/Mozilla/ManagedStorage/<name>.json
+
+/Library/Application Support/Mozilla/PKCS11Modules/<name>.json
+ +

如果想要用户级别的可见,将清单文件存放在:

+ +
~/Library/Application Support/Mozilla/NativeMessagingHosts/<name>.json
+
+~/Library/Application Support/Mozilla/ManagedStorage/<name>.json
+
+~/Library/Application Support/Mozilla/PKCS11Modules/<name>.json
+
+ +

Linux

+ +

如果想要全局可见,将清单文件存放在:

+ +
/usr/lib/mozilla/native-messaging-hosts/<name>.json
+
+/usr/lib/mozilla/managed-storage/<name>.json
+
+/usr/lib/mozilla/pkcs11-modules/<name>.json
+
+ +

或者:

+ +
/usr/lib64/mozilla/native-messaging-hosts/<name>.json
+
+/usr/lib64/mozilla/managed-storage/<name>.json
+
+/usr/lib64/mozilla/pkcs11-modules/<name>.json
+ +

如果想要用户级别的可见,将清单文件存放在:

+ +
~/.mozilla/native-messaging-hosts/<name>.json
+
+~/.mozilla/managed-storage/<name>.json
+
+~/.mozilla/pkcs11-modules/<name>.json
+ +

 

+ +

 

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 +--- +
{{AddonSidebar}}
+ +

Native messaging 可以让 extension 与安装在用户计算机上的原生应用交换信息。 原生应用仅需给 extension 提供服务,而无需在网页中可访问。 一个常见的例子是密码管理器: 原生应用负责存储和加密你的密码,并且和 extension 通信来填充网页中的表单字段。Native messaging 可以让 extension 拥有那些WebExtensions APIs 所没有的功能,比如访问某些特定的硬件。

+ +

原生应用的安装与管理并不是在浏览器当中的: 它应该是使用操作系统进行安装,和其他的原生应用一样。然后你需要将你的原生应用安装在指定位置,并提供一个清单。清单中描述了浏览器如何连接到你的原生应用。

+ +

extension 必须在 manifest.json 中获得"nativeMessaging" 权限。 同时,原生应用也需要在其清单中的 "allowed_extensions" 字段中包含 extension 的ID来表示允许该 extension 与自己进行通信。

+ +

经过上述操作,extension 就可以通过 {{WebExtAPIRef("runtime")}} API 与原生应用进行JSON数据通信了。原生应用可以通过标准输入/输出来接受/返回数据与 extension 通信。

+ +

+ +

和 Chrome 相比,WebExtensions 所支持的 native messaging 有2个主要区别:

+ + + +

Github 中的 webextensions-examples 仓库有一个完整的关于 native messaging 的例子,文章中的大部分代码片段均出于此。

+ +

安装

+ +

Extension 的 manifest.json

+ +

如果你想让你的 extension 与原生应用进行通信,你需要:

+ + + +

这有一个 manifest.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"]
+
+}
+ +

原生应用清单

+ +

原生应用清单描述了浏览器如何与原生应用进行连接。

+ +

原生应用清单需要与原生应用一起安装,浏览器仅会查阅清单而不会安装或管理原生应用。因此,何时采用何种方式来安装或更新这些文件的安全模型比起使用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.)

+ +

关于原生应用清单的详细语法和路径规则,可参考 原生应用清单

+ +
+
+

除清单外,原生应用还必需配置路径规则,你可以参考 原生应用清单 来配置路径。

+
+
+ +

这有一个例子,是关于 "ping_pong" 原生应用的清单:

+ +
{
+  "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" ]
+}
+ +

上面的清单代表:

+ + + +
+

对于Windows: 在上面的例子中,原生应用是一个Python脚本,它在Windows下可能是无法运行的。一个代替方案是提供一个 .bat 文件,并且在清单中指向这个 .bat 文件:

+ +
{
+  "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" ]
+}
+ +

在 .bat 文件中调用 Python 脚本:

+ +
@echo off
+
+python -u "c:\\path\\to\\native-messaging\\app\\ping_pong.py"
+ +

 

+
+ + + +

交换信息

+ +

根据上面的配置,extension已经可以和原生应用交换JSON信息了。

+ +

Extension 端

+ +

你使用过 messaging APIs 与 content script 通信,与原生应用通信你应该非常熟悉,有2种方式:

+ + + +

基于连接的通信

+ +

在这种方式下,你需要调用 {{WebExtAPIRef("runtime.connectNative()")}} 并传入原生应用的名称(名称在原生应用清单中的 "name" 字段定义)。这个操作将会运行原生应用(如果它之前没在运行的话)并返回一个 {{WebExtAPIRef("runtime.Port")}} 。

+ +

当原生应用启动后,它被会传入2个参数:

+ + + +

原生应用会一直保持运行,直到 extension 调用 Port.disconnect() 或连接它的记录被结束。

+ +

使用 Port ,调用 postMessage() 传入一个JSON来发送消息,使用 onMessage.addListener() 来接收消息。

+ +

下面是一个例子:background script 建立与 ping_pong 原生应用的链接,并监听原生应用发来的消息。每当browser action 点击时,发送一个 ping 的消息给原生应用。

+ +
/*
+启动,连接 ping_pong 原生应用
+*/
+var port = browser.runtime.connectNative("ping_pong");
+
+/*
+监听从原生应用发来的消息
+*/
+port.onMessage.addListener((response) => {
+  console.log("Received: " + response);
+});
+
+/*
+每当 browser action 被点击时,发送一条消息给原生应用
+*/
+browser.browserAction.onClicked.addListener(() => {
+  console.log("Sending:  ping");
+  port.postMessage("ping");
+});
+ +

无连接的通信

+ +

在这种模式下你需要调用 {{WebExtAPIRef("runtime.sendNativeMessage()")}} 传入如下参数:

+ + + +

每个消息都会创建一个新的原生应用实例。当原生应用启动时会被传入2个参数:

+ + + +

原生应用发送的第一条消息将会被作为对 sendNativeMessage() 响应,将会被传入回调函数中。

+ +

这有一个例子,对在上方的代码片段进行重写,改成使用 runtime.sendNativeMessage() 的方式:

+ +
function onResponse(response) {
+  console.log("Received " + response);
+}
+
+function onError(error) {
+  console.log(`Error: ${error}`);
+}
+
+/*
+每当 browser action 被点击时,发送一条消息给原生应用
+*/
+browser.browserAction.onClicked.addListener(() => {
+  console.log("Sending:  ping");
+  var sending = browser.runtime.sendNativeMessage(
+    "ping_pong",
+    "ping");
+  sending.then(onResponse, onError);
+});
+
+ +

原生应用端

+ +

在原生应用端,使用标准输入来接受消息,使用标准输出来发送消息。

+ +

每条消息将会被序列化成UTF-8格式的JSON数据,并且在消息前面有一个32位的值来表示该条消息使用本地字节序的长度。

+ +

发送给原生应用的单条消息最大是1MB,总消息不得超越4GB。

+ +

下面是一个用 Python 写的原生应用例子。监听 extensions 发送的消息,如果消息是 ping,则回复 pong:

+ +
#!/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"))
+
+ +

关闭原生应用

+ +

如果你通过 runtime.connectNative() 连接原生应用,则原生应用会一直保持运行,直到 extension 调用 Port.disconnect() 或连接它的记录被结束。 如果你通过 runtime.sendNativeMessage() 向原生应用发消息,原生应用会在回复消息后被关闭。

+ +

关闭原生应用的过程:

+ + + +

常见问题 Troubleshooting

+ +

如果有什么地方出错,可以检查浏览器控制台。原生应用发送的任何 stderr 都会被反应在浏览器控制台中。所以如果你已经运行了原生应用,你可以看到原生应用发出的所有错误信息。

+ +

如果你没有配置好原生应用,你应该会看到一些错误信息。

+ +
"No such native application <name>"
+ + + +
"Error: Invalid application <name>"
+ + + +
"'python' is not recognized as an internal or external command, ..."
+ + + +
"File at path <path> does not exist, or is not executable"
+ + + +
"This extension does not have permission to use native application <name>"
+ + + +
"TypeError: browser.runtime.connectNative is not a function"
+ + + +
"[object Object]       NativeMessaging.jsm:218"
+ + + +

与 Chrome 的兼容问题

+ +

{{Page("Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities", "Native_messaging")}}

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 +--- +

打包你的扩展

+ +

Firefox 扩展应打包为 XPI 文件。它只是一个 ZIP 文件,但采用 .xpi 作为扩展名。

+ +

最重要的一点,ZIP 文件必须是扩展文件的 ZIP 打包,不能包含一层根目录。

+ +

Windows

+ +
    +
  1. 打开你的扩展文件所在的文件夹。
  2. +
  3. 选择所有文件。
  4. +
  5. 右击并选择 发送到 → 压缩(zipped)文件夹。
  6. +
  7. 将得到的文件从 文件名.zip 重命名为 文件名.xpi
  8. +
+ +

Screenshot of the Windows Explorer context menu showing Send to compressed (zipped) folder

+ +

Mac OS X

+ +
    +
  1. 打开你的扩展文件所在的文件夹。
  2. +
  3. 选择所有文件。
  4. +
  5. 右击并选择 压缩 n 项。
  6. +
  7. 将得到的文件从 Archive.zip 重命名为  文件名.xpi
  8. +
+ +

Screenshot of the Finder context menu showing the Compress 15 Items option

+ +

Linux / Mac OS X 终端

+ +
    +
  1. cd path/to/my-extension/
  2. +
  3. zip -r ../my-extension.xpi *
  4. +
+ +

安装你的扩展

+ +
    +
  1. 导航到 about:addons
  2. +
  3. 拖拽 XPI 到页面上,或者打开齿轮菜单,选择“从文件安装附加组件...”
  4. +
  5. 点击弹出的对话框中的“安装”
  6. +
+ +

在 Firefox OS 上安装你的扩展

+ +

你可以使用 WebIDE 提供的 USB 或者 Wifi 进行安装

+ +

故障排除

+ +

下面是几种你可能会遇到的常见问题:

+ +

"此附加组件无法安装,因为它未经验证。"

+ + + +

"该附加组件无法安装,因为它似乎已损坏。"

+ + + +

完全没反应

+ + 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 +--- +
{{AddonSidebar}}
+ +

使用 WebExtension API 开发的扩展是专为跨浏览器兼容而设计的:很大程度上,该技术与 Google Chrome 和 Opera 支持的扩展 API 代码直接兼容。为这些浏览器编写的扩展,在大多数情况下,只需少数修改就能在 Firefox 中运行。几乎所有的扩展 API 都支持使用 chrome 命名空间下的回调函数,跟 Chrome 一样。那些仅有的 chrome 命名空间不支持的 API 是故意不与 Chrome 兼容的。这些情况下,API 文档页将明确声明它仅在 browser 命名空间中受支持。从 Chrome 或者 Opera 移植一个扩展的过程大概这样:

+ +
    +
  1. 检查你 manifest.json 使用的功能并了解 WebExtension API 对应的 Chrome 不兼容参考表。如果你在使用的功能或者 API 还未被 Firefox 支持,那你可能还不能移植你的扩展。Mozilla 提供了一个服务可助您自动执行此步:https://www.extensiontest.com/
  2. +
  3. 安装你的扩展至 Firefox 并对其进行测试。
  4. +
  5. 如有任何问题,可通过 dev-addons 邮件列表IRC 上的 #webextensions 联系我们。
  6. +
  7. 提交您的附加组件至 AMO 以供签名及分发
  8. +
+ +

如果您依赖 Chrome 命令行选项来加载解压的扩展,请参看 Firefox 中进行临时安装的 web-ext 工具以便开发。

+ + 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 +--- +

要使用 WebExtension API 进行开发,你需要进行一些最基本的设置。

+ + 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_ +--- +
{{AddonSidebar}}
+ +

一般当你完成了基于WebExtension技术的附加组件的代码编写和测试, 你可能会想与其他人分享这成果(不管出于什么目的...). Mozilla旗下有一个网站: addons.mozilla.org (简称AMO), 开发者们可以在这里发布附加组件, 而其他用户可以在这里找到这些附加组件并安装使用, 通过在AMO上发布你的附加组件, 你可以加入到我们的社区里来, 这里有一群用户和创造者, 说不准会发现几个使用你的附加组件的人哦.

+ +

你编写的附加组件并不一定需要发布在AMO上, 但是、即使你不打算在AMO上发布你的附加组件, 你也必须提交你的附加组件到AMO上来进行审核以获得签名。因为火狐浏览器会拒绝安装没有AMO签名的附加组件。

+ +

所以发布一个附加组件的流程, 可概述为:

+ +
    +
  1. 压缩你所创建的附加组件文件
  2. +
  3. AMO上创建一个属于你的账户
  4. +
  5. 上传你的压缩文件到AMO来进行签名和审核, 并选择是否在AMO上进行发布
  6. +
  7. 修复在审核中发现的任何问题
  8. +
  9. 如果你选择不在AMO上发布, 可以恢复已签名的附件组件, 并自行发布
  10. +
+ +

当你准备发布附加组件的新版本时, 你可以访问 addons.mozilla.org 的附加组件页来更新它, 并上传新的版本.
+ 需要注意的是: 你必须在这个附加组件页进行更新, 否则AMO没法知道你是要更新一个已经存在的附加组件呢, 还是要上传一个全新的附加组件呢.

+ +

如果你选择在AMO上发布你的附加组件, 之后火狐浏览器会自动检查更新. 如果你选择自行发布,  你需要在你的manifest.json中手动设置一个applications 唯一标识, 并且需要手动设置update_url属性指向你的update manifest file.

+ +
+
+

火狐浏览器把附加组件包的后缀叫做或改为".xpi", 这只是".zip"的一个扩展.

+ +

在上传附加组件到AMO的时候, 你不需要把压缩包的后缀改为".XPI".

+
+
+ +

1. 使用zip压缩你的附加组件文件

+ +

首先你的附加组件文件夹应该包含一个manifest.json和其他一些需要的文件 - javascript文件, icons文件, HTML文件等等. 你需要使用zip把它们压缩成一个文件以便上传到AMO.

+ +

注意: 请将你的附加组件目录的的所有文件压缩为zip包,而 不要直接对附加组件根目录进行压缩(见下图所示).

+ +

Windows

+ +
    +
  1. 打开你的附加组件所在的文件夹.
  2. +
  3. 选中所有文件.
  4. +
  5. 右键并选择发送到 → 压缩到(zipped)文件夹.
  6. +
+ +

+ +

Mac OS X

+ +
    +
  1. 打开你的附加组件所在的文件夹.
  2. +
  3. 选中所有文件.
  4. +
  5. 右键并选择压缩n项.
  6. +
+ +

+ +

Linux / Mac OS X Terminal

+ +
    +
  1. cd path/to/my-addon/
  2. +
  3. zip -r ../my-addon.zip *
  4. +
+ +

2. 在AMO上创建一个账户

+ +

访问https://addons.mozilla.org/. 如果你已经有一个火狐账户, 你可以直接使用它来登录. 否则, 点击"注册"并按要求创建一个火狐账户.

+ +

3. 上传你的zip压缩文件

+ +

接下来, 上传压缩后的附加组件到AMO进行签名和审查, 并选择是否发布到AMO, 更多细节, 可查看Submitting to AMO.

+ +
+

需要注意的是一旦你上传了你的附加组件(基于WebExtension技术)到AMO, 你不能使用Add-on SDK或过时的XUL/XPCOM技术来更新该附加组件. 如果你切换到了这些技术平台之一, 必须把它做为新的附加组件并重新提交.

+ +

总而言之: 像Add-on SDK和XUL/XPCOM等过时的技术体系在不久的将来都将被淘汰, WebExtensions才是唯一.

+ +

在上传你的附加组件之前,请再次检查你的zip包内没有包含其他不相关的文件.

+
+ +

4. 修复审查中出现的问题

+ +

当你上传了附加组件, AMO服务器将运行一些基本的检查并立即通知你有关的一切问题. 这些问题分为2种类型: "错误"和"警告". 如果你有错误, 你必须修复它们并重新提交, 如果只是警告, 你最好也搞定它们(当可以也忽略警告): 然后可以继续提交.

+ +

如果自动检查器没有报告任何错误, 该附件组件将进行更为详细的审核(复查). 你同样会收到审查结果并且需要修复所有问题, 然后重新提交.

+ +

5. 发布你的附加组件

+ +

如果你选择了在AMO上托管你的附加组件, 这意味着发布过程的结束. AMO会对该附加组件进行签名和发布, 之后其他用户就能下载并安装使用了.

+ +

如果你选择不在AMO上进行发布, 可以恢复已签名的附加组件, 并自行发布(比如把附件组件的压缩包直接发给别人).

+ +

 

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 +--- +

{{AddonSidebar}}

+ +

很多时候你需要从外部资源引入内容到你的插件。但是,源可能被嵌入了恶意的源代码,这些恶意的源代码可能由源的开发者或者恶意的第三方所编写。

+ +

以RSS读取器为例子。你不知道你的插件将会打开什么RSS源也无法控制那些RSS源的内容。所以,可能用户可能订阅到一个RSS源里面包含了带有恶意脚本的标题。可能就是简单的JavaScript代码标签<script></script>。如果你在提取标题的时候,当作一般文本添加到一个页面的DOM,用户可能加载未知的脚本。因此,需要注意避免直接把一般文本加载为HTML。

+ +

你还需要记住扩展有授权的上下文,例如后台的脚本backgroup scrips以及内容脚本content scripts。最坏的情况里,一个内嵌的洁白你可能运行在一个或多种上下文中,导致一些提取操作。这种情况会导致用户的浏览器暴露在远程攻击下,被注入代码访问用户的重要数据,例如密码、浏览器历史或者浏览器行为等。

+ +

这篇文章说明如何安全的对待远端数据并添加到DOM。

+ + + +

处理任意字符串

+ +

当处理字符串时,有很多推荐的策略来安全添加他们到页面:标准的DOM节点创建方法或jQuery。

+ +

DOM节点创建方法/函数

+ +

一个轻量级的方法来插入字符串到页面是使用原生的DOM操纵方法/函数: document.createElement, Element.setAttribute, 以及Node.textContent. 安全的方法是分别创建节点并使用textContent属性赋值:

+ +
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);
+ +

这种方法安全原因是使用.textContent 时会自动消除 data.color.中的任何远程 HTML代码。

+ +

但是要注意,使用原生方法不能保证绝对安全,例如下面的代码:

+ +
var data = JSON.parse(responseText);
+addonElement.innerHTML = "<div class='" + data.className + "'>" +
+                         "Your favorite color is now " + data.color +
+                         "</div>";
+ +

在其中,Here, the contents of data.className 或 data.color 的内容可能包含HTML代码使得标签提早关闭,并插入更多的HTML内容,之后关闭另一个标签。

+ +

jQuery

+ +

当使用jQuery的方法如 attr() 和 text() ,会清洗添加到DOM的内容。所以,上面“favorite color”例子采用jQuery实现会形如:

+ +
var node = $("</div>");
+node.addClass(data.className);
+node.text("Your favorite color is now " + data.color); 
+ +

处理HTML内容

+ +

当你知道处理外部源的内容是HTML的时候,添加到页面之前净化HTML是很关键的。净化HTML的最好办法是使用HTML净化的库或者一个带有HTML净化特性的模板引擎。在这一节,我们来看一些合适的工具以及使用方法。

+ +

HTML 净化

+ +

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. DOMPurify,是一个HTML净化的库,可以脱离任意会导致脚本执行的元素,以便安全注入远端源到HTML节点,这个库被很多不同的安全专家评估过,是很适合这种任务扩展的库。

+ +

DOMPurify 有一个简约版用于生产环境,purify.min.js. 你可以使用这个版本来适配你的扩展,例如你可以这样添加:

+ +
"content_scripts": [
+  {
+    "matches" : ["<all_urls>"],
+    "js": ["purify.min.js", "myinjectionscript.js"]
+  }
+]
+ +

之后,在myinjectionscript.js中你可以读取外部HTML并净化,之后添加到页面的DOM中:

+ +
var elem = document.createElement("div");
+var cleanHTML = DOMPurify.sanitize(externalHTML);
+elem.innerHTML = cleanHTML;
+ +

你可以使用任何方法添加净化后的HTML到DOM,例如jQuery’s .html() 方法。注意这种情况需要使用 Remember though that the SAFE_FOR_JQUERY 标记:

+ +
var elem = $("<div/>");
+var cleanHTML = DOMPurify.sanitize(externalHTML, { SAFE_FOR_JQUERY: true });
+elem.html(cleanHTML);
+ +

模板引擎

+ +

另一个常见的模式是对一个页面创建本地HTML模板并通过远端的值来填空。这种方法被广泛应用,应该注意去避免构造函数的使用,可能会导致执行代码的注入。当模板引擎使用构造函数插入HTML到文档的时候会发生这种情况,如果用来注入原始HTML的变量是远端代码,这就属于上面介绍中的安全风险。

+ +

例如,当使用mustache templates 你必须使用两个花括号\{{variable}},来去掉任何HTML。使用三个花括号\{\{{variable}}} 必须避免注入原始HTML字符串到模板。

+ +

Handlebars 工作原理也是类似, \{{variable}} 。同时,如果创造了Handlebars helper使用 Handlebars.SafeString 使用Handlebars.escapeExpression() 来消除任何传给helper的动态参数。Handlebars.SafeString 的结果被认为是安全的,当插入到双handlebars的时候就不会做消除动作。

+ +

在其他模板系统中也有类似的构造函数,需要有同样的考虑。

+ +

其他参考

+ +

关于这个主题更多的信息,可以查看下面的文章

+ + + +
+
+
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 +--- +
{{AddonSidebar}}
+ +

常说的 浏览器动作(browser action), 指通过在工具栏上上添加新按钮,提供用户互动选项,用户可点击按钮与你的扩展进行互动。
+

+ +

工具栏按钮(browser action)与地址栏按钮(page action)极为相似。区分其不同点及使用,请参看 Page actions and browser actions.

+ +

指定浏览器动作

+ +

通过manifest.json里的关键字browser_action 来定义浏览器动作的属性:

+ +
"browser_action": {
+  "default_icon": {
+    "19": "button/geo-19.png",
+    "38": "button/geo-38.png"
+  },
+  "default_title": "Whereami?"
+}
+ +

必须定义的键是 default_icon.

+ +

有两种方法来指定浏览器动作:带弹出框(popup)和不带弹出框(popup)。

+ +

如果不指定弹出框,当用户点击按钮时,点击事件将被发送至扩展,而扩展可用以下函数来捕获 browserAction.onClicked:

+ +
browser.browserAction.onClicked.addListener(handleClick);
+ +

如果指定了弹出框,当用户点击按钮时,点击事件将不会被发送,而是显示出弹出框。用户能够通过弹出框进行互动,并且点击框外区域时弹出框会自动关闭。请参看文章 Popup 来了解更多关于创建和管理弹出框的细节。

+ +

注意一个扩展只能指定一个浏览器动作。

+ +

可通过browserAction API在程序里更改你的浏览器动作的属性。

+ +

图标

+ +

想了解更多关于如何创建浏览器动作图标信息,请参看Photon Design System 文档里的 Iconography 部分.

+ +

范例

+ +

在Github上的扩展范例库 webextensions-examples 中有两个实现浏览器动作的例子:

+ + 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 +--- +
{{AddonSidebar}}
+ +

扩展程序包含的某些UI组件,例如: popups, sidebarsoptions pages ,实际上可以用如下方式统一定义:

+ +
    +
  1. 创建一个HTML文件用于描述该UI组件的页面结构
  2. +
  3. 在manifest.json中添加字段 (browser_action, page_action, sidebar_action, 或 options_ui) 以指向其对应的页面
  4. +
+ +

这种方式面临的一个挑战是如何使用浏览器自带的样式,以使得组件的UI表现与浏览器的UI风格相符。要解决这个问题,可以在该字段的配置中增加一个可字段 browser_sytle ,如果设置了这个字段并且值为 true ,  那么该UI组件的HTML将会被插入一个或多个样式表,样式表会使你的扩展程序的UI表现与浏览器的风格一致 (并且与其它同样应用了这个字段的扩展程序一致)。

+ +

若使用了 browser_style: true , 你需要在不同的浏览器主题中测试你的扩展程序,以确保其UI表现和期望的一致。 

+ +
+

谷歌浏览器Google Chrome 和 欧朋浏览器 Opera 使用字段名 chrome_style 而非browser_style, 因此如果要适配它们,你需要同时添加这两个字段。

+
+ +

在火狐浏览器中,这个样式文件可以在 chrome://browser/content/extension.css查看。为Mac OS X系统额外准备的样式文件也可以在  chrome://browser/content/extension-mac.css 查看。

+ +

大多数样式是自动应用的,但是某些元素需要添加非标准的类名 browser-style 来获得其样式,如下表所示:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ElementExample
<button> +
+<button class="browser-style">Click me</button>
+
+

<select>

+
+
+<select class="browser-style" name="select">
+  <option value="value1">Value 1</option>
+  <option value="value2" selected>Value 2</option>
+  <option value="value3">Value 3</option>
+</select>
+
<textarea> +
+<textarea class="browser-style">Write here</textarea>
+
Parent of an <input> +
+<div class="browser-style">
+  <input type="radio" id="op1" name="choices" value="op1"/>
+  <label for="op1">Option 1</label>
+
+  <input type="radio" id="op2" name="choices" value="op2"/>
+  <label for="op2">Option 2</label>
+</div>
+
+ +
+

查看 {{bug(1465256)}} 以了解相关修订

+
+ +

浏览器兼容性

+ + + +

{{Compat("webextensions.browser_style")}}

+ +

火狐面板组件Firefox Panel Components

+ +
+

非标准
+ 此功能不是通用标准,仅支持在firefox中使用

+
+ +

chrome://browser/content/extension.css 样式文件中也包含了火狐面板组件的样式

+ +

legacy Firefox Style Guide 使用示例

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ElementExample
Header +
+<header class="panel-section panel-section-header">
+  <div class="icon-section-header"><img src="image.svg"/></div>
+  <div class="text-section-header">Header</div>
+</header>
+
Footer +
+<footer class="panel-section panel-section-footer">
+  <button class="panel-section-footer-button">Cancel</button>
+  <div class="panel-section-footer-separator"></div>
+  <button class="panel-section-footer-button default">Confirm</button>
+</footer>
+
Tabs +
+<div class="panel-section panel-section-tabs">
+  <button class="panel-section-tabs-button selected">Tab</button>
+  <div class="panel-section-tabs-separator"></div>
+  <button class="panel-section-tabs-button">Tab</button>
+  <div class="panel-section-tabs-separator"></div>
+  <button class="panel-section-tabs-button">Tab</button>
+</div>
+
Form +
+<div class="panel-section panel-section-formElements">
+  <div class="panel-formElements-item">
+    <label for="name01">Label:</label>
+    <input type="text" value="Name" id="name01" />
+  </div>
+  <div class="panel-formElements-item">
+    <label for="picker01">Label:</label>
+    <select id="picker01">
+      <option value="value1" selected="true">Dropdown</option>
+      <option value="value2">List Item</option>
+      <option value="value3">List Item</option>
+    </select>
+  </div>
+  <div class="panel-formElements-item">
+    <label for="placeholder01">Label:</label>
+    <input type="text" placeholder="Placeholder" id="placeholder01" />
+    <button name="expander" class="expander"></button>
+  </div>
+</div>
+
Menu +
+<div class="panel-section panel-section-list">
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut">Ctrl-L</div>
+  </div>
+
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+
+  <div class="panel-section-separator"></div>
+
+  <div class="panel-list-item disabled">
+    <div class="icon"></div>
+    <div class="text">Disabled List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+
+  <div class="panel-section-separator"></div>
+
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+</div>
+
+ +

Example

+ +

HTML

+ +
<header class="panel-section panel-section-header">
+  <div class="icon-section-header"><!-- An image goes here. --></div>
+  <div class="text-section-header">Header</div>
+</header>
+
+<div class="panel-section panel-section-list">
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut">Ctrl-L</div>
+  </div>
+
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+
+  <div class="panel-section-separator"></div>
+
+  <div class="panel-list-item disabled">
+    <div class="icon"></div>
+    <div class="text">Disabled List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+
+  <div class="panel-section-separator"></div>
+
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+
+  <div class="panel-list-item">
+    <div class="icon"></div>
+    <div class="text">List Item</div>
+    <div class="text-shortcut"></div>
+  </div>
+</div>
+
+<footer class="panel-section panel-section-footer">
+  <button class="panel-section-footer-button">Cancel</button>
+  <div class="panel-section-footer-separator"></div>
+  <button class="panel-section-footer-button default">Confirm</button>
+</footer>
+ + + +

Result(若查看失败,请切回英文版查看)

+ +

{{EmbedLiveSample("Example","640","360")}}

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 +--- +
{{AddonSidebar}}
+ +
+

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 browser.menus API.

+ +

Example of content menu items added by a WebExtension, from the context-menu-demo example

+ +

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")}}.

+ +

Specifying context menu items

+ +

You manage context menu items programmatically, using the {{WebExtAPIRef("contextMenus")}} API. However, you need to request the contextMenus permission in your manifest.json to be able to take advantage of the API.

+ +
"permissions": ["contextMenus"]
+ +

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:

+ +
browser.contextMenus.create({
+  id: "log-selection",
+  title: browser.i18n.getMessage("contextMenuItemSelectionLogger"),
+  contexts: ["selection"]
+}, onCreated);
+ +

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.

+ +
browser.contextMenus.onClicked.addListener(function(info, tab) {
+  switch (info.menuItemId) {
+    case "log-selection":
+      console.log(info.selectionText);
+      break;
+    ...
+  }
+})
+ +

Examples

+ +

The webextensions-examples repo on GitHub, contains several examples of extensions that use context menu items:

+ + +
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 +--- +
{{AddonSidebar}}
+ +
+

This feature is available since Firefox 54.

+
+ +

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.

+ +

Simple example showing the addition of "My panel" to the Developer Tools tabs.

+ +

Specifying a developer tools panel

+ +

A developer tools panel is added using the devtools.panels API, which in turn needs to be run from a special devtools page.

+ +

Add the devtools page by including the devtools_page key in extension's manifest.json and provide the location of the page's HTML file in the extension:

+ +
"devtools_page": "devtools-page.html"
+ +

From the devtools page, call a script that will add the devtools panel:

+ +
<body>
+  <script src="devtools.js"></script>
+</body>
+ +

In the script, create the devtools panel by specifying the panel's title, icon, and HTML file that provides the panel's content:

+ +
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) => {
+  newPanel.onShown.addListener(handleShown);
+  newPanel.onHidden.addListener(handleHidden);
+});
+ +

The extension can now run code in the inspected window using devtools.inspectedWindow.eval() 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 Extending the developer tools.

+ +

Developer panel design

+ +

For details on how to design your developer panel's web page to match the style of Firefox, see the Photon Design System documentation.

+ +

Icons

+ +

For details on how to create icons to use with your developer tools panel, see Iconography in the Photon Design System documentation.

+ +

Examples

+ +

The webextensions-examples repository on GitHub includes the devtools-panels example which implements a devtools panel.

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 +--- +
{{AddonSidebar}}
+ +

为了能给用户提供在不同场景下都具有价值的功能, WebExtensions 提供了许多的用户界面选项。下面是这些选项的摘要,在本章中将会对每个选项做出更详细的说明。

+ +
+

想要使你的扩展能提供良好的用户体验吗? 请查看文章用户体验的最佳实践 .

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
UI 选项描述实例
浏览器工具栏按钮(浏览器行为)工具栏上一个可点击的按钮,点击时将事件派发到附件组件上。默认情况下,这个按钮在栏位中是可见的。Example of a WebExtension toolbar button
带有弹出面板的工具栏按钮当这个在工具栏上的按钮被点击时,它会弹出一个面板。这个面板使用 HTML 文档编写,用于处理与用户的交互行为。Example of a WebExtension toolbar button with a popup
地址栏菜单按钮(页面行为)这个按钮位于浏览器地址栏菜单条,按钮被点击的时候可以派发一个事件出来。默认情况下,这个按钮在所有tab上都是隐藏的.Example showing an address bar button (page action)
带有弹出面板的地址栏菜单按钮地址栏菜单按钮被点击时,会弹出一个面板,这个面板通过HTML文档定义,用于处理用户交互。Example of a popup on the address bar button
上下文菜单项在一个或多个网页上下文菜单中的菜单项,复选框和单选按钮.菜单项也可以通过添加分隔栏进行分组,当一个菜单项被点击时,一个事件将会被派发至附加组件.
侧边栏 +

一个在网页边显示的HTML文档,每页都有其特定的内容. 每当扩展安装时侧边栏将会打开,但最终还是遵循用户的侧边栏可见性设置. 侧边栏内的用户交互通过HTML文档处理.

+
Example of a WebExtension's sidebar
选项页面一个可以使你定义可以更改的扩展首选项的页面. 用户可以从浏览器的附加组件管理器中访问此页面.Example showing the options page content added in the favorite colors example.
扩展页面 +

在单独的窗口或页面中使用扩展提供的页面来提供表单,帮助或其他任何需要的内容.

+
Example of a simple bundled page displayed as a detached panel.
通知通过底层操作系统的通知机制向用户显示的短暂通知. 当用户点击或者通知关闭时(用户关闭或超时关闭)派发事件到扩展程序.Example notification from a WebExtension
地址栏建议当用户输入关键词时提供自定义的地址栏建议.Example showing the result of the firefox_code_search WebExtension's customization of the address bar suggestions.
开发者工具面板在浏览器的开发者工具中显示的一个关联了HTML文档的标签.New panel tab in the Developer Tools tab bar
+ +

以下的操作指南提供了一些创建用户界面选项的指导;

+ + 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 +--- +
{{AddonSideBar}}
+ +
通常来说的page action,是添加到浏览器地址栏中的按钮。用户通过点击这个按钮与你的扩展进行交互。
+ +

+ +

地址栏按钮(Page actions)和工具栏按钮( browser actions)

+ +

地址栏按钮(或 page action) 与工具栏按钮(或 browser action)非常相似。

+ +

其不同之处为:

+ + + +

当动作(行为)与当前页面关联时,使用地址栏按钮,而当动作(行为)与浏览器相关或与多个页面相关时使用工具栏按钮。例如:

+ + + + + + + + + + + + + + + + + + + + + + + + +
类型书签动作内容动作标签操作
page action将本页面保存到书签Reddit enhancementSend tab
browser action显示所有书签使能ad-blocking同步所有打开的标签
+ +

 

+ +

定义地址栏按钮

+ +

你可以在manifest.json中使用page_action键定义地址栏按钮的属性:

+ +
"page_action": {
+  "browser_style": true,
+  "default_icon": {
+    "19": "button/geo-19.png",
+    "38": "button/geo-38.png"
+  },
+  "default_title": "Whereami?"
+}
+ +

仅default_icon是强制(必需)的。

+ +

有两种方式定义地址栏按钮:带popup窗口和无popup窗口。如果你没有指定一个popup,则当用户点击此按钮时,事件被派送到使用pageAction.onClicked侦听器的扩展:

+ +
browser.pageAction.onClicked.addListener(handleClick);
+ +

如果你指定了一个popup,则点击事件不被派送,在用户点击按钮时显示popup。用户可以与popup进行交互,并且当用户点击popup以外区域时,popup自动关闭。参见Popup可获得创建和管理popups更详细内容。

+ +

注意你的扩展只能有一个地址栏按钮。

+ +

通过使用pageAction API,你可以以编程方式修改地址栏按钮的任何属性。

+ +

Icons

+ +

如何创建用于地址栏按钮的ICONS的详细内容,请参见Photon Design System文档中的Iconography节。

+ +

示例

+ +

GitHub上的 webextensions-examples 库中包括了实现无popup地址栏按钮的例子 chill-out

diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/\344\276\247\350\276\271\346\240\217/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/\344\276\247\350\276\271\346\240\217/index.html" new file mode 100644 index 0000000000..8d13bfaf2c --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/\344\276\247\350\276\271\346\240\217/index.html" @@ -0,0 +1,53 @@ +--- +title: 侧边栏 +slug: Mozilla/Add-ons/WebExtensions/user_interface/侧边栏 +translation_of: Mozilla/Add-ons/WebExtensions/user_interface/Sidebars +--- +
{{AddonSidebar}}
+ +
+

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 > Sidebar" menu. Only one sidebar can be shown at a time, and that sidebar will be displayed for all tabs and all browser windows.

+ +

The browser may include a number of built-in sidebars. For example, Firefox includes a sidebar for interacting with bookmarks:

+ +

Using the sidebar_action 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.

+ +

就像浏览器的弹出页面,侧边栏也是一个HTML文档。当用户打开侧边栏时,HTML文档载入打开的浏览器窗口。每个窗口有一个该文档的实例。打开一个新窗口时,该窗口获得自己的文档实例

+ +

可以使用函数{{WebExtAPIRef("sidebarAction.setPanel()")}}指定侧边栏仅用于指定的某个标签,使用{{WebExtAPIRef("windows.getCurrent()")}} 侧边栏知道自己属于哪一个标签。

+ +
// sidebar.js
+browser.windows.getCurrent({populate: true}).then((windowInfo) => {
+  myWindowId = windowInfo.id;
+});
+ +

不同的窗口使用不同的侧边栏是非常有用的,这是一个实例 ,见"annotate-page" example.

+ +

侧边栏俱有和后台程序以及弹出窗口相同的API权限,在非隐藏模式下,侧边栏使用API {{WebExtAPIRef("runtime.getBackgroundPage()")}} 可以直接访问后台页面,使用 API 如{{WebExtAPIRef("tabs.sendMessage()")}} 与content scripts交互,使用API 如 {{WebExtAPIRef("runtime.sendNativeMessage()")}} 与原生应用交互。

+ +

关闭窗口或关闭侧边栏时,侧边栏文档退出。这意味着和后台页面不同,侧边栏文档不是一直住留,也不像弹出窗口,只要用户与页面交互 ,它就一直存在。

+ +

使用侧边栏的扩展载入时,侧边栏自动打开。这是为了帮助用户知道扩展俱有侧边栏。注意不能通过编程的方式打开侧边栏:侧边栏只能由用户打开。

+ +

声明侧边栏

+ +

声明侧边栏,只需在manifest.json中指 定关键字  sidebar_action    并同时指定title 和 icon:

+ +
"sidebar_action": {
+  "default_title": "My sidebar",
+  "default_panel": "sidebar.html",
+  "default_icon": "sidebar_icon.png"
+}
+ +

使用API {{WebExtAPIRef("sidebarAction")}} ,你可以用编程的方式修改title panel icon。

+ +

浏览器提供的显示侧边栏的UI中,title和icon显示给用户,如Firefox菜单栏的"View > Sidebar"

+ + + +

For details on how to design your sidebar's web page to match the style of Firefox, see the Photon Design System documentation.

+ +

Example

+ +

The webextensions-examples repository on GitHub includes the annotate-page example which implements a sidebar.

+
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 +--- +

{{AddonSidebar}}

+ +

如果你已经阅读了 你的第一个扩展,那么你现在已经知道如何写一个扩展了。在这篇文章,我们将写一个稍微复杂一点点的扩展来为你展示更多的一些API 。

+ +

这个扩展会添加一个新按钮到 Firefox 的工具栏。在用户点击该按钮时,我们会显示一个弹出窗(popup)来让他们选择一种动物。在他们选择之后,我们会将当前网页替换为他所选动物的图片。

+ +

要实现这点,我们将:

+ + + +

你可以想象这样的扩展的整体结构:

+ +

+ +

这是一个非常简单的扩展,但也展示了 WebExtensions API 的许多基本概念:

+ + + +

你可以在 GitHub 找到该扩展的完整的源代码

+ +

写这个扩展,你需要45或更高版本的firefox。

+ +

编写扩展

+ +

创建一个新目录,并切换到该目录:

+ +
    +
  1. +
    mkdir beastify
    +cd beastify
    +
  2. +
+ +

manifest.json

+ +

现在创建一个名为 "manifest.json" 的文件,并对其添加下列内容:

+ +
    +
  1. +
    {
    +
    +  "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"
    +  ]
    +
    +}
    +
  2. +
+ + + +

需要注意,所有路径是相对于 manifest.json 。

+ +

图标

+ +

插件应该有一个图标。这个图标被用于显示在附加组件管理器中(可以通过"about:addons"来访问)。当前插件中manifest.json指定了我们插件的图标位于"icons/beasts-48.png"。

+ +

创建“icons”文件夹,并将图标命名为“beasts-48.png”。你可以使用我们例子中的图标,它是从 Aha-Soft’s Free Retina iconset 截取的,使用需要遵循该网站的许可证

+ +

如果你使用自己的图标,它的尺寸应该是48×\times48像素的。同时,对于高分辨率的设备,可以提供96×\times96像素的图片。此时,manifest.json应当这样配置:

+ +
    +
  1. +
    "icons": {
    +  "48": "icons/beasts-48.png",
    +  "96": "icons/beasts-96.png"
    +}
    +
  2. +
+ + + +

工具栏按钮

+ +

工具栏按钮也需要一个图标,并且我们的 manifest.json 承诺我们会为该工具栏在 "icons/beasts-32.png" 提供一个图标。

+ +

将一个图标命名为为 "beasts-32.png"并保存到"icons"文件夹。你可以使用例子中的图片,它是取自 IconBeast Lite 图标集并按其许可协议授权使用。

+ +

如果你没有弹出窗,用户点击的事件会直接分派到你的插件中。如果你制作了弹出窗,用户点击会直接打开这个弹出窗,而不会被分派给插件。本例中我们需要弹出窗,因此我们现在开始写它。

+ +

弹出窗

+ +

该弹出窗的函数是让用户选择三种动物的其中一种。

+ +

在根目录下创建“popup”文件夹,用于存放弹出窗的代码。弹出窗由以下文件组成:

+ + + +
mkdir popup
+cd popup
+touch choose_beast.html choose_beast.css choose_beast.js
+ +

choose_beast.html

+ +

HTML 文件就像这样:

+ +
    +
  1. +
    <!DOCTYPE html>
    +
    +<html>
    +  <head>
    +    <meta charset="utf-8">
    +    <link rel="stylesheet" href="choose_beast.css"/>
    +  </head>
    +
    +<body>
    +  <div id="popup-content">
    +    <div class="button beast">Frog</div>
    +    <div class="button beast">Turtle</div>
    +    <div class="button beast">Snake</div>
    +    <div class="button reset">Reset</div>
    +  </div>
    +  <div id="error-content" class="hidden">
    +    <p>Can't beastify this web page.</p><p>Try a different page.</p>
    +  </div>
    +  <script src="choose_beast.js"></script>
    +</body>
    +
    +</html>
    +
  2. +
+ +

我们有一个ID为 "popup-content" 的<div>元素包含了每个动物选择。我们还有另外一个<div> 元素,它的ID为 "error-content" ,class为"hidden"。我们将会使用它以防初始化弹窗的时候出问题。

+ +

注意我们引入了CSS和JS文件,就像网页一样。

+ +

choose_beast.css

+ +

CSS 固定了弹出窗的大小,确保3个选择填充满空间,并给了他们基本点样式。同时隐藏了class="hidden"的元素,这意味着我们的"error-content" <div> 将会被默认隐藏:

+ +
    +
  1. +
    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;
    +}
    +
  2. +
+ +

choose_beast.js

+ +

我们在弹出窗的脚本中监听点击事件。 如果用户选择其中一个动物,我们在当前标签页中插入一段内容脚本。一旦内容脚本加载,我们发送一条有关动物选择的信息:

+ +
    +
  1. +
    /**
    + * CSS to hide everything on the page,
    + * except for elements that have the "beastify-image" class.
    + */
    +const hidePage = `body > :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) => {
    +
    +    /**
    +     * 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(() => {
    +        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(() => {
    +        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);
    +
  2. +
+ +

从96行开始。只要弹出窗加载完,popup scrpit 就会使用 browser.tabs.executeScript() API在活跃标签页执行 content script。如果执行 content scrpit成功,content script会在页面中一直保持,直到标签被关闭或者用户导航到其他页面。

+ +

browser.tabs.executeScript()调用失败的常见原因是你不能在所有页面执行content scripts。例如,你不能在特权浏览器页面执行,像about:debugging,你也不能在addons.mozilla.org域执行。如果调用失败,reportExecuteScriptError()会隐藏"popup-content" <div>,并展示"error-content" <div>, 然后打印一个错误到控制台

+ +

如果成功执行 content script ,我们会调用 listenForClicks()。这个监听了弹窗上的点击事件。

+ + + +

beastify() 函数做了三件事:

+ + + +

reset() 函数实际上就是撤销 beastify :

+ + + +

The content script

+ +

在扩展的根目录下创建一个新的文件夹,叫做"content_scripts",然后在里面新建一个新的名为 "beastify.js" 的文件,内容如下:

+ +
    +
  1. +
    (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) => {
    +    if (message.command === "beastify") {
    +      insertBeast(message.beastURL);
    +    } else if (message.command === "reset") {
    +      removeExistingBeasts();
    +    }
    +  });
    +
    +})();
    +
  2. +
+ +

content script做的第一件事是检查全局变量 window.hasRun:如果它被设置了,脚本直接返回,否则设置window.hasRun并继续。原因是每次用户打开弹出窗,弹出窗就会在活跃页面执行一个content script ,所以我们可能会在单个页面运行多个脚本实例。如果是这样的话,我们需要保证只有一个实例在做所有事情。

+ +

然后,从第40行开始,content script 监听来自弹出窗的信息,使用browser.runtime.onMessage API。在上面我们看到弹出窗脚本能够发送两种不同的信息:"beastify" and "reset"。

+ + + +

动物们

+ +

最后,我们要加入包含动物们的图像。

+ +

创建"beasts"文件夹,之后将图片放入并命名。你可以从 the GitHub repository,或这里下载图片:

+ +

+ +

测试

+ +

请仔细确认项目目录如下所示:

+ +
    +
  1. +
    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
    +
  2. +
+ +

Firefox 45开始,你可以临时从硬盘中安装扩展

+ +

在Firefox地址栏中输入:about:debugging,单击“临时载入附加组件”,然后选择你的manifest.json文件。

+ +

然后你应该已经看到扩展图标出现在了Firefox的工具条上:

+ +

{{EmbedYouTube("sAM78GU4P34")}}

+ +

打开一个网页,然后点击图标,选择一个动物,然后观察网页的变化

+ +

{{EmbedYouTube("YMQXyAQSiE8")}}

+ +

用命令行开发

+ +

你可以通过使用 web-ext 工具来将临时安装的工作自动化,试试这个:

+ +
    +
  1. +
    cd beastify
    +web-ext run
    +
  2. +
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 +--- +
{{AddonSidebar}}
+ +

扩展为浏览器添加特性与功能。它通过熟悉的 web 技术——HTML,CSS 还有 JavaScript 来创建。扩展可以利用网页上的 JavaScript 使用同一批 API,但扩展也可以访问扩展自己专用的 JavaScript API。这意味着,和在网页里编码相比,在扩展中,可以做到更加多的事情。以下是其中一些你可以做的事情的示例:

+ +

提升或补充网站功能:用扩展来实现额外的浏览器内的特性或者来自于你网站的信息。它允许用户搜集他们访问过的页面细节来提升你所提供的服务。

+ +

+ +

示例: 亚马逊助手, OneNote Web Clipper, 和 Grammarly for Firefox

+ +

让用户展现他们的个性:浏览器扩展可以操控网页的内容;例如,让用户在每个页面上添加他们最喜欢的徽标或者图片。扩展也可以让用户更新火狐浏览器的界面,就像独立的主题扩展一样。

+ +

+ +

示例: MyWeb New Tab, Tabliss, 和 VivaldiFox

+ +

从网页中添加或删除内容:你可能想要帮助用户从网页中阻止一些侵扰的广告,当网页中提到一个国家或者城市时提供旅游指南,或者重组页面内容来提供一个统一的阅读体验。有了可以访问和更新一个页面里的 HTML 和 CSS的能力,扩展可以帮助用户以他们想要的形式来查看网页。

+ +

+ +

示例: uBlock Origin, Reader, 和 Toolbox for Google Play Store™

+ +

添加工具和新的浏览特性:给任务面板添加新特性,或者从URL地址,超链接,或者页面文字生成二维码。有了灵活的界面选择和 WebExtensions APIs 你可以轻松的添加新的特性到浏览器。并且,你可以提升几乎任何网站的特性或者功能,不必是你自己的网站。

+ +

+ +

示例: Swimlanes for TrelloTomato Clock

+ +

游戏:通过线下游戏的特性,或者探索新游戏的可能性来提供传统计算机游戏功能;例如,把游戏合并入每天网页浏览中。

+ +

+ +

示例:Solitaire Card Game New Tab, 和 2048 Prime.

+ +

添加开发工具:你可以提供网站开发工具给你的公司或者开发一个有用的技术或者你想分享的网站开发技术。无论哪种方式,你可以通过对开发者工具栏添加一个新的标齐那也来提升内置的 Firefox 开发者工具。

+ +

+ +

示例: Web Developer, Web React Developer Tools, 和 aXe Developer Tools

+ +

Firefox 扩展使用 WebExtensions API,一种跨浏览器的扩展开发系统,构建而成。 在很大程度上,它与 Google Chrome 和 Opera 所支持的扩展 API 兼容。 在大多数情况下,为这些浏览器所写的扩展只需少量修改便可在 FireFox 和 Microsoft Edge 上运行。这些 API 也完全兼容多线程 Firefox

+ +

如果你有想法或问题,或者在使用 WebExtensions API 迁移旧式附加组件时需要帮助,您可以在 dev-addons 邮件列表或者Matrix 上的 Add-ons room 与我们联系。

+ +

接下来呢?

+ + 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_ +--- +
{{AddonSidebar}}
+ +

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.

+ +

你的开发环境

+ +

你不需要任何特殊的开发或构建环境工具来创建浏览器扩展:只需要一个简单的文本编辑器就可以创建出很好的浏览器扩展。当然,你可能一直在做web开发有一套你想去配置的开发工具和环境。如果是这样,你需要意识到一些事情。

+ +

如果你使用了打包压缩工具来交付你最终的代码,你需要提交你的源码到 AMO 审查。此外,用于压缩、混淆、构建的工具需要是开源的(或提供无限的免费使用), 并且可以在审阅者的计算机(Windows、Mac或Linux)上运行。主要是,我们的审阅者无法使用商业或基于Web的工具。

+ +

 

+ +

学习更多关于构建工具

+ +

Third-party libraries

+ +

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 AMO review process, 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.

+ +

Learn more about submitting source code

+ +

The Firefox Add-on Distribution Agreement

+ +

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.

+ +

Read the agreement

+ +

Learn more about signing

+ +

The review process

+ +

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.

+ +

Check out the review policy and guidelines

+ + + +

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.

+ +

Learn more about getting your add-ons featured

+ +

Continue your learning experience

+ +

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:

+ + 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 +--- +

{{AddonSidebar}}

+ +

选项卡允许用户在其浏览器窗口中打开多个网页,然后在这些网页之间切换。 使用Tabs API,您可以使用和操作这些选项卡来创建实用程序,为用户提供使用选项卡或提供扩展功能的新方法。

+ +

在这篇how-to文章中我们将看到:

+ + + +

最后,我们通过查看API提供的其他一些其他功能。

+ +
+

注意:其他地方有一些Tab API功能。 这些是可用于使用脚本操作选项卡内容的方法{{WebExtAPIRef("tabs.connect")}},{{WebExtAPIRef("tabs.sendMessage")}}和{{WebExtAPIRef("tabs.executeScript")}}如果您需要有关这些方法的更多信息,请参阅概念文章内容脚本和操作指南修改网页

+
+ +

权限和选项卡API

+ +

对于大多数Tabs API函数,您不需要任何权限; 但是,有一些例外:

+ + + +

以下是您可以在扩展程序的manifest.json文件中请求"tabs"权限的方法:

+ +
"permissions": [
+  "<all_urls>",
+  "tabs"
+],
+
+ +

此请求允许您在用户访问的所有网站上使用所有标签API功能。 还有一种替代方法可以请求权限使用{{WebExtAPIRef("tabs.executeScript")}}或{{WebExtAPIRef("tabs.insertCSS")}},其中您不需要主机权限,形式为"activeTab"。 此权限与<all_urls>提供与"tabs"相同的权限,但有两个限制:

+ + + +

这种方法的好处是用户不会收到权限警告,也就是说您的扩展程序可以“访问所有网站的数据”。 这是因为<all_urls>权限使扩展能够在任何选项卡中随时执行脚本,而"activeTab"仅限于允许扩展在当前选项卡中执行用户请求的操作。

+ +

Discovering more about tabs and their properties

+ +

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.

+ +

This is where {{WebExtAPIRef("tabs.query")}} comes in. Used alone to get all tabs or taking the queryInfo 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.

+ +

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")}}.

+ +
+

Note:

+ + +
+ +

How to example

+ +

To see how {{WebExtAPIRef("tabs.query")}} and {{WebExtAPIRef("tabs.Tab")}} are used, let’s walk through how the tabs-tabs-tabs example adds the list of “switch to tabs” to its toolbar button popup.

+ +

The tabs tabs tabs toolbar menu showing the switch to tap area

+ +

manifest.json

+ +

Here is the manifest.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"
+}
+
+ +
+

Note the following:

+ + +
+ +

tabs.html

+ +

tabs.html defines the content of the extension’s popup:

+ +
<!DOCTYPE html>
+
+<html>
+
+ <head>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="tabs.css"/>
+ </head>
+
+<body>
+
+ <div class="panel">
+    <div class="panel-section panel-section-header">
+     <div class="text-section-header">Tabs-tabs-tabs</div>
+    </div>
+
+    <a href="#" id="tabs-move-beginning">Move active tab to the beginning of the window</a><br>
+
+
+…
+
+Define the other menu items
+…
+
+    <div class="switch-tabs">
+
+     <p>Switch to tab</p>
+
+     <div id="tabs-list"></div>
+
+    </div>
+ </div>
+
+ <script src="tabs.js"></script>
+
+</body>
+
+</html>
+
+ +

Here is a summary of the above does:

+ +
    +
  1. The menu items are declared.  
  2. +
  3. An empty div with the ID tabs-list is declared to contain the list of tabs.
  4. +
  5. tabs.js is called.
  6. +
+ +

tabs.js

+ +

In tabs.js, we’ll see how the list of tabs is built and added to the popup.  

+ +

Creating the popup

+ +

First, an event handler is added to execute listTabs() when tabs.html is loaded:

+ +
document.addEventListener("DOMContentLoaded", listTabs);
+ +

The first thing that listTabs() does is to call getCurrentWindowTabs(). This is where {{WebExtAPIRef("tabs.query")}} is used to get a {{WebExtAPIRef("tabs.Tab")}} object for the tabs in the current window:

+ +
function getCurrentWindowTabs() {
+  return browser.tabs.query({currentWindow: true});
+}
+
+ +

Now, listTabs() is ready to create the content for the popup.

+ +

To start with:

+ +
    +
  1. Grab the tabs-list div.
  2. +
  3. Create a document fragment (into which the list will be built).
  4. +
  5. Set counters.
  6. +
  7. Clear the content of the tabs-list div.
  8. +
+ +
function listTabs() {
+ getCurrentWindowTabs().then((tabs) => {
+    let tabsList = document.getElementById('tabs-list');
+    let currentTabs = document.createDocumentFragment();
+    let limit = 5;
+    let counter = 0;
+
+    tabsList.textContent = '';
+
+ +

Next, we’ll create the links for each tab:

+ +
    +
  1. Loops through the first 5 items from the {{WebExtAPIRef("tabs.Tab")}} object.
  2. +
  3. For each item, add a hyperlink to the document fragment. +
      +
    • The link’s label—that is, its text—is set using the tab’s title (or the ID, if it has no title).
    • +
    • The link’s address is set using the tab’s ID.
    • +
    +
  4. +
+ +
    for (let tab of tabs) {
+     if (!tab.active && counter <= 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;
+
+    }
+
+ +

Finally, the document fragment is written to the tabs-list div:

+ +
    tabsList.appendChild(currentTabs);
+  });
+}
+
+ +

Working with the active tab

+ +

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:

+ +
 else if (e.target.id === "tabs-alertinfo") {
+   callOnActiveTab((tab) => {
+     let props = "";
+     for (let item in tab) {
+       props += `${ item } = ${ tab[item] } \n`;
+     }
+     alert(props);
+   });
+ }
+
+ +

Where callOnActiveTab() finds the active tab object by looping through the {{WebExtAPIRef("tabs.Tab")}} objects looking for the item with active set:

+ +
document.addEventListener("click", function(e) {
+ function callOnActiveTab(callback) {
+   getCurrentWindowTabs().then((tabs) => {
+     for (var tab of tabs) {
+       if (tab.active) {
+         callback(tab, tabs);
+       }
+     }
+   });
+ }
+}
+
+
+ +

Creating, duplicating, moving, updating, reloading, and removing tabs

+ +

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.

+ +

The following functions are available:

+ + + +
+

NOTE: 

+ +

These functions all require the ID (or IDs) of the tab they are manipulating:

+ + + +

Whereas the following functions will act on the active tab (if no tab ID is provided): 

+ + +
+ +

How to example

+ +

The tabs-tabs-tabs 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.

+ +

But first, here is a demonstration of the feature in action:

+ +

{{EmbedYouTube("-lJRzTIvhxo")}}

+ +

manifest.json

+ +

None of the functions require a permission to operate, so there are no features in the manifest.json file that need to be highlighted.

+ +

tabs.html

+ +

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 <a> 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.

+ +
    <a href="#" id="tabs-move-beginning">Move active tab to the beginning of the window</a><br>
+    <a href="#" id="tabs-move-end">Move active tab to the end of the window</a><br>
+
+    <div class="panel-section-separator"></div>
+
+
+    <a href="#" id="tabs-duplicate">Duplicate active tab</a><br>
+
+    <a href="#" id="tabs-reload">Reload active tab</a><br>
+    <a href="#" id="tabs-alertinfo">Alert active tab info</a><br>
+ +

tabs.js

+ +

To implement the “menu” defined in tabs.html, tabs.js includes a listener for clicks in tabs.html:

+ +
document.addEventListener("click", function(e) {
+ function callOnActiveTab(callback) {
+
+   getCurrentWindowTabs().then((tabs) => {
+     for (var tab of tabs) {
+       if (tab.active) {
+         callback(tab, tabs);
+       }
+     }
+   });
+}
+}
+
+ +

A series of if statements then look to match the ID of the item clicked.

+ +

This code snippet is for the “Move active tab to the beginning of the window list” option:

+ +
 if (e.target.id === "tabs-move-beginning") {
+   callOnActiveTab((tab, tabs) => {
+     var index = 0;
+     if (!tab.pinned) {
+       index = firstUnpinnedTab(tabs);
+     }
+     console.log(`moving ${tab.id} to ${index}`)
+     browser.tabs.move([tab.id], {index});
+   });
+ }
+
+ +

It's worth noting the use of console.log(). This enables you to output information to the debugger console, which can be useful when resolving issues found during development.

+ +

Example of the console.log output, from the move tabs feature, in the debugging console

+ +

The move code first calls callOnActiveTab() which in turn calls getCurrentWindowTabs() 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:

+ +
 function callOnActiveTab(callback) {
+   getCurrentWindowTabs().then((tabs) => {
+     for (var tab of tabs) {
+       if (tab.active) {
+         callback(tab, tabs);
+       }
+     }
+   });
+ }
+
+ +
Pinned tabs
+ +

A feature of tabs is that the user can pin 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, firstUnpinnedTab() is called to find the position of the first unpinned tab by looping through the tabs object:

+ +
function firstUnpinnedTab(tabs) {
+ for (var tab of tabs) {
+   if (!tab.pinned) {
+     return tab.index;
+   }
+ }
+}
+
+ +

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:

+ +
     browser.tabs.move([tab.id], {index});
+ +

The remaining functions to duplicate, reload, create, and remove tabs are implemented similarly.

+ +

Manipulating a tab’s zoom level

+ +

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.

+ +

The level of zoom can be between 30% and 300% (represented as decimals 0.3 to 3).

+ +

In Firefox the default zoom settings are:

+ + + +

How to example

+ +

The tabs-tabs-tabs example includes three demonstrations of the zoom feature: zoom in, zoom out, and reset zoom. Here is the feature in action:

+ +

{{EmbedYouTube("RFr3oYBCg28")}}

+ +

Let’s take a look at how the zoom in is implemented.

+ +

manifest.json

+ +

None of the zoom functions require permissions, so there are no features in the manifest.json file that need to be highlighted.

+ +

tabs.html

+ +

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.

+ +

tabs.js

+ +

tabs.js starts by defining several constants used in the zoom code:

+ +
const ZOOM_INCREMENT = 0.2;
+const MAX_ZOOM = 3;
+const MIN_ZOOM = 0.3;
+const DEFAULT_ZOOM = 1;
+
+ +

It then uses the same listener we discussed earlier so it can act on clicks in tabs.html.

+ +

For the zoom in feature, this runs:

+ +
 else if (e.target.id === "tabs-add-zoom") {
+   callOnActiveTab((tab) => {
+     var gettingZoom = browser.tabs.getZoom(tab.id);
+     gettingZoom.then((zoomFactor) => {
+       //the maximum zoomFactor is 3, it can't go higher
+       if (zoomFactor >= 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 > MAX_ZOOM ? MAX_ZOOM : newZoomFactor;
+         browser.tabs.setZoom(tab.id, newZoomFactor);
+       }
+     });
+   });
+ }
+
+ +

This code uses callOnActiveTab() 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 (MAX_ZOOM) 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")}}.

+ +

Manipulating a tab’s CSS

+ +

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")}}).

+ +

This can be useful, for example, if you want to highlight certain page elements or change the default layout of the page.

+ +

How to example

+ +

The apply-css example uses these features to add a red border to the web page in the active tab. Here is the feature in action:

+ +

{{EmbedYouTube("bcK-GT2Dyhs")}}

+ +

Let’s walk through how it’s set up.

+ +

manifest.json

+ +

To use the CSS features you need either:

+ + + +

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.

+ +
{
+  "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"
+ ]
+
+}
+
+ +

You will note that "tabs" permission is requested in addition to "activeTab". 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.

+ +

The other main features in the manifest.json file are the definition of:

+ + + +

background.js

+ +

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:

+ +
const CSS = "body { border: 20px solid red; }";
+const TITLE_APPLY = "Apply CSS";
+const TITLE_REMOVE = "Remove CSS";
+const APPLICABLE_PROTOCOLS = ["http:", "https:"];
+
+ +

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 initializePageAction().

+ +
var gettingAllTabs = browser.tabs.query({});
+
+gettingAllTabs.then((tabs) => {
+ for (let tab of tabs) {
+   initializePageAction(tab);
+ }
+});
+
+ +

initializePageAction uses protocolIsApplicable() to determine whether the active tab’s URL is one the CSS can be applied to:

+ +
function protocolIsApplicable(url) {
+ var anchor =  document.createElement('a');
+ anchor.href = url;
+ return APPLICABLE_PROTOCOLS.includes(anchor.protocol);
+}
+
+ +

Then, if the example can act on the tab, initializePageAction() sets the tab’s pageAction (navigation bar) icon and title to use the “off” versions before making the pageAction visible:

+ +
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);
+ }
+}
+
+ +

Next, a listener on pageAction.onClicked waits for the pageAction icon to be clicked, and calls toggleCSS when it is.

+ +
browser.pageAction.onClicked.addListener(toggleCSS);
+ +

toggleCSS() gets the title of the pageAction and then takes the action described:

+ + + +
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);
+}
+
+ +

Finally, to ensure that the pageAction is valid after each update to the tab, a listener on {{WebExtAPIRef("tabs.onUpdated")}} calls initializePageAction() each time the tab is updated to check that the tab is still using a protocol to which the CSS can be applied.

+ +
browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
+ initializePageAction(tab);
+});
+
+ +

Some other interesting abilities

+ +

There are a couple of other Tabs API features that don’t fit into one of the earlier sections:

+ + + +

Learn more

+ +

If you want to learn more about the Tabs API, check out:

+ + 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 +--- +
{{AddonSidebar}}
+ +

在这篇文章中,我们将为 Firefox 创建一个扩展。这个扩展只是给从 "firefox.org" 或其任意子域名加载的任何页面添加一个红色边框。

+ +

该示例的源代码位于 GitHub:https://github.com/mdn/webextensions-examples/tree/master/borderify

+ +

首先,你需要 Firefox 45 或更高版本。

+ +

编写扩展

+ +

创建一个新的目录并切换到该目录。例如,在你的命令行/终端,你可以这么做:

+ +
mkdir borderify
+cd borderify
+ +

manifest.json

+ +

现在,在 "borderify" 目录内直接创建文件 "manifest.json"。文件内容如下:

+ +
{
+
+  "manifest_version": 2,
+  "name": "Borderify",
+  "version": "1.0",
+
+  "description": "Adds a red border to all webpages matching mozilla.org.",
+
+  "icons": {
+    "48": "icons/border-48.png"
+  },
+
+  "content_scripts": [
+    {
+      "matches": ["*://*.mozilla.org/*"],
+      "js": ["borderify.js"]
+    }
+  ]
+
+}
+ + + +

这里最有意思的键是 content_scripts,它告诉 Firefox 加载脚本到其 URL 匹配特定模式的网页。本例中,我们要求 Firefox 加载脚本 "borderify.js" 到任何来自 "mozilla.org" 或其子域的 HTTP 或 HTTPS 页面。

+ + + +
+

某些情况下,你需要给你的扩展指定一个 ID。如果你需要指定一个附加组件 ID,请在 manifest.json 中添加 browser_specific_settings 键,并设置其 gecko.id 属性:

+ +
"browser_specific_settings": {
+  "gecko": {
+    "id": "borderify@example.com"
+  }
+}
+
+ +

icons/border-48.png

+ +

扩展应该有一个图标。这将显示在附加组件管理器加载项的列表中。我们的 manifest.json 保证了会有一个图标 "icons/border-48.png"。

+ +

在 "borderify" 目录下直接创建 "icons" 目录,并在 "icons" 目录下保存一个名为 "border-48.png"的图标. 你可以使用我们的示例中的,来自谷歌材料设计中的图标,遵循 Creative Commons Attribution-ShareAlike 协议。

+ +

如果您选择使用自己的图标,它也应该是 48×48 像素。你也可以为高分辨率显示器提供一个 96x96 的像素图标,在 manifest.json 的 icons 对象中添加 96 属性即可:

+ +
"icons": {
+  "48": "icons/border-48.png",
+  "96": "icons/border-96.png"
+}
+ +

或者,也可以在这里提供一个 SVG 文件,它会被正确地缩放。(不过:如果你正在使用 SVG 并且你的图标包含文字,有可能想要用你的 SVG 编辑器的“转换为路径”工具来拼和文字,这样图标会以一个恒定的大小/位置来缩放。)

+ + + +

borderify.js

+ +

最后,在 "borderify" 目录下直接创建 "borderify.js" 文件,并写入下面的内容:

+ +
document.body.style.border = "5px solid red";
+ +

manifest.json 文件中 content_scripts 的键给出了一条模式匹配,该脚本便会被加载到匹配的页面中。该脚本会像页面加载自己的脚本一样被加载,可以直接访问该文档。

+ + + +

测试一下

+ +

首先,仔细检查文件是否在正确的位置:

+ +
borderify/
+    icons/
+        border-48.png
+    borderify.js
+    manifest.json
+ +

安装

+ +

打开 Firefox 的 about:debugging 页面,点击”This Firefox" (在新版本的Firefox里),点击 "临时加载附加组件(Load Temporary Add-on)" 按钮,并选择你的附加组件目录:

+ +

{{EmbedYouTube("cer9EUKegG4")}}

+ +

附加组件将会被安装,直到下次重启浏览器失效。

+ +

或者,你可以通过 web-ext 工具从命令行来运行扩展。

+ +

测试

+ +

现在尝试访问"mozilla.org", 你将会在页面上看到有个红色的边框

+ +

{{EmbedYouTube("rxBQl2Z9IBQ")}}

+ +
+

不要在 addons.mozilla.org 上尝试!内容脚本(Content Script) 当前在那个域名下是被限制的。

+
+ +

尝试一下编辑内容脚本更改边框的颜色,或做页面内容别的修改,保存内容脚本,然后通过单击 about:debugging 页面下的 “刷新” 按钮重新加载附加的文件。你可以马上看到的变化:

+ +

{{EmbedYouTube("NuajE60jfGY")}}

+ + + +

打包和发布

+ +

为了给其他人使用你的插件,您需要打包,并将其提交给 Mozilla 进行签名。要了解更多有关,请参考 "发布你的扩展"

+ +

下一步

+ +

现在,你已经在开发 Firefox 的一个 Web 扩展的过程中得到了一些想法,尝试:

+ + + +
+ + + + + +
diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/\345\256\236\347\216\260\344\270\200\344\270\252\350\256\276\347\275\256\351\241\265\351\235\242/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/\345\256\236\347\216\260\344\270\200\344\270\252\350\256\276\347\275\256\351\241\265\351\235\242/index.html" new file mode 100644 index 0000000000..fe8ac2e0a7 --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/\345\256\236\347\216\260\344\270\200\344\270\252\350\256\276\347\275\256\351\241\265\351\235\242/index.html" @@ -0,0 +1,203 @@ +--- +title: 实现一个设置页面 +slug: Mozilla/Add-ons/WebExtensions/实现一个设置页面 +translation_of: Mozilla/Add-ons/WebExtensions/Implement_a_settings_page +--- +
{{AddonSidebar}}
+ +

设置页面可以让用户查看,修改扩展的一些设置。

+ +

对于WebExtensions,设置通常使用 storage API 保存. 实现一个设置页面通常包含以下三步:

+ + + +
+

你也可以使用 runtime.openOptionsPage() 打开该页面。

+
+ +

简单的 WebExtension

+ +

首先,我们写一个向用户访问的所有页面添加一个蓝色边框的扩展。

+ +

创建一个新的文件夹命名为“setting”,然后创建文件“manifest.json”它包含以下内容:

+ +
{
+
+  "manifest_version": 2,
+  "name": "Settings example",
+  "version": "1.0",
+
+  "content_scripts": [
+    {
+      "matches": ["<all_urls>"],
+      "js": ["borderify.js"]
+    }
+  ]
+
+}
+ +

该扩展指示浏览器在用户访问的网站上加载一个名为"borderify.js“的Content Script。

+ +

接下来,在"setting"目录下创建"borderify.js",然后给予他以下内容:

+ +
document.body.style.border = "10px solid blue";
+ +

这只是向网页加入了一一个蓝色边框

+ +

现在 安装该扩展 并测试它——打开任意一个网页:

+ +

{{EmbedYouTube("E-WUhihF8fw")}}

+ +

添加设置页面

+ +

现在让我们创建一个设置页面来允许用户设置边框的颜色。

+ +

首先更新 "manifest.json" 使他拥有如下内容:

+ +
{
+
+  "manifest_version": 2,
+  "name": "Settings example",
+  "version": "1.0",
+
+  "content_scripts": [
+    {
+      "matches": ["<all_urls>"],
+      "js": ["borderify.js"]
+    }
+  ],
+
+  "options_ui": {
+    "page": "options.html"
+  },
+
+  "permissions": ["storage"]
+
+}
+
+ +

我们加入了两个manifest 关键字:

+ + + +

接下来,因为我们承诺提供"options.html",让我们来创建他,在"setting"目录创建一个该文件并具有以下内容:

+ +
<!DOCTYPE html>
+
+<html>
+  <head>
+    <meta charset="utf-8">
+  </head>
+
+  <body>
+
+    <form>
+        <label>Border color<input type="text" id="color" ></label>
+        <button type="submit">Save</button>
+    </form>
+
+    <script src="options.js"></script>
+
+  </body>
+
+</html>
+
+ +

这里定义了一个带有标记文字{{htmlelement("input")}}的 {{htmlelement("form")}} 和一个 提交 {{htmlelement("button")}}. 也包含了一个名为"options.js"的脚本。

+ +

仍然在"settting"目录下创建 "options.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);
+
+ +

它做了两件事:

+ + + +

最后,更新"borderify.js" 来读取边框颜色:

+ +
+

因为 browser.storage.local.get() 在火狐52版本之前的一个漏洞 ,以下代码没法起作用。为了使它生效,onGot()中的 item.color 必须改为 item[0].color。

+
+ +
 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);
+
+ +

最后,完整的扩展看起来是这样:

+ +
settings/
+    borderify.js
+    manifest.json
+    options.html
+    options.js
+ +

现在:

+ + + +

在火狐中你可以通过访问"about:addons"点击扩展旁边的"Preferences"按钮访问设置页面。

+ +

{{EmbedYouTube("ECt9cbWh1qs")}}

+ +

进一步了解

+ + diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/\346\236\204\345\273\272\344\270\200\344\270\252\350\267\250\346\265\217\350\247\210\345\231\250\347\232\204\346\211\251\345\261\225\346\217\222\344\273\266/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/\346\236\204\345\273\272\344\270\200\344\270\252\350\267\250\346\265\217\350\247\210\345\231\250\347\232\204\346\211\251\345\261\225\346\217\222\344\273\266/index.html" new file mode 100644 index 0000000000..6d1a21497c --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/\346\236\204\345\273\272\344\270\200\344\270\252\350\267\250\346\265\217\350\247\210\345\231\250\347\232\204\346\211\251\345\261\225\346\217\222\344\273\266/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 +--- +

{{AddonSidebar()}}

+ +

浏览器扩展 API 的引入为浏览器扩展的开发创造了 “一次开发跨浏览器” 的前景。然而,在使用扩展 API 的浏览器中(主要是 Chrome、 Firefox、 Opera 和 Edge) ,API 的实现和覆盖范围都存在差异。除此之外,Safari 使用了它自己的 Safari 扩展脚本系统。

+ +

最大化兼容浏览器扩展意味着至少在两个不同的浏览器上兼容同一个扩展。本文探讨了在创建跨浏览器扩展时所面临的六个主要挑战,并在每种情况下提出了如何应对这些挑战。

+ +

本文不讨论为 Safari 构建浏览器扩展。您可以通过 Safari 扩展共享一些资源,比如图片和 HTML 内容。然而,如果您要进行 JavaScript 部分的编程则需要作为一个单独的开发项目进行,除非您希望创建自己的 polyfill。

+ +

跨平台扩展的开发障碍

+ +

在开发跨平台扩展时,需要注意以下六个方面:

+ + + +

API 命名空间

+ +

在四大主流浏览器中,有两个 API 命名空间正在使用:

+ + + +

Firefox 也支持 Chrome 浏览器的 chrome.* 名称空间,主要用于协助扩展移植。然而,首选应该使用浏览器 browser.* 命名空间。除了被提议的标准外, browser.* 使用 promises ーー一种现代化且简单的处理异步事件机制。

+ +

只有在非常小的扩展中,命名空间才可能是唯一的跨平台问题。因此,如果你遇到了且试图专门解决这个问题的话,可能很少会有帮助。最好的方法是通过异步事件处理来解决这个问题。

+ +

API 异步事件处理

+ +

在四个主要浏览器中,有两种方法可以处理异步事件:

+ + + +

Firefox 还支持 chrome.* 命名空间中的 callbacks 风格的 API,这主要是为了便于从 Chrome 迁移。然而,应该首选使用 promises(以及 browser.* 命名空间),它已被采纳为拟议标准的一部分。它极大地简化了异步事件处理,特别是在需要将事件链接在一起的情况下。

+ +
+

如果你对这两种方法之间的差异不熟悉,可以看一下 了解异步 JavaScript: Callbacks、 Promises 和 Async/Await 或者 MDN 的 Using promises 页面。

+
+ +

浏览器扩展 API 的垫片(Polyfill)

+ +

那么,当 Firefox 是唯一支持它的浏览器时,你如何轻松地使用 promises 呢?解决方案是使用 promises 为 Firefox 编程,并使用浏览器扩展 API 的垫片(Polyfill)
+
+ 这个 polyfill 解决了跨 Firefox、 Chrome 和 Opera 的 API 名称空间和异步事件处理。在撰写本报告时(2018年11月) ,Edge 的支持正在开发中。
+
+ 要使用 polyfill,可以使用 npm 安装到开发环境中,或者直接从 GitHub Relase 页面下载。

+ +

然后,引入 browser-polyfill.js 到:

+ + + +

例如,这个 manifest.json 代码让你的后台脚本可以使用 polyfill:

+ +
{
+ // ...
+ "background": {
+   "scripts": [
+     "browser-polyfill.js",
+     "background.js"
+   ]
+ }
+}
+ +

您的目标是确保在任何其他扩展脚本执行 browser.* API 前执行 polyfill。

+ +
+

关于如何使用模块打包器使用 polyfill 的更多细节和信息,请参阅 GitHub 上的项目自述文件

+
+ +

还有其他的 polyfill 选项,但是在撰写本文时,没有一个提供浏览器扩展 API polyfill 的覆盖范围。所以,如果你没有把 Firefox 作为你的首选,你的选择就是接受 polyfills 的限制,移植到 Firefox 并添加跨浏览器的支持,或者开发你自己的 polyfill。

+ +

API 函数覆盖率

+ +

这四个主要浏览器提供的 API 函数的实现差异可分为三大类:

+ + + +

你可以在 Mozilla Developer Network 浏览器对 JavaScript API 页面的支持上找到4个主要浏览器对扩展 API 的支持细节,以及 Firefox for Android 对扩展 API 的支持细节。浏览器兼容性信息也包含在每个函数及其方法、类型和事件的 Mozilla Developer Network JavaScript APIs 参考页面中。

+ +

处理 API 差异

+ +

解决这些差异的一个简单方法是将扩展中使用的函数限制在没有 API 差异的函数范围内。在实践中,对于大多数扩展,这种方法可能限制性太强。
+
+ 相反,如果 API 之间存在差异,则应该提供替代实现或降级功能。(请记住: 您可能还需要这样考虑同一浏览器的不同版本之间的 API 支持差异。)

+ +

使用运行时检查函数特性的可用性是实现备选或降级功能的推荐方法。执行运行时检查的好处是,如果函数是可用的,您不需要更新和重新分发扩展来使用它。

+ +

下面的代码使您能够执行运行时检查:

+ +
if (typeof <function> === "function") {
+   // safe to use the function
+}
+ +

Manifest 字段

+ +

4个主要浏览器支持的 manifest.json 文件字段的差异大致可分为三类:

+ + + +

浏览器兼容性信息包含在 Mozilla Developer Network manifest.json 页的每个字段中。

+ +

manifest.json 文件在不同浏览器之间的版本号可能有所不同,为每个浏览器创建和编辑一个静态版本号通常是最简单的方法。

+ +

扩展打包

+ +

通过浏览器扩展商店打包和分发扩展相对简单。

+ + + +

有关打包的详细信息,请参阅相应扩展的开发人员门户网站上的指南。

+ +

扩展发布

+ +

这四种主要浏览器都维护有浏览器扩展商店。每个商店还对扩展进行审核,以检查安全漏洞。

+ +

因此,您需要为每个商店分别添加和更新扩展。在某些情况下,您可以使用脚本上传扩展。

+ +

下表总结了每个商店的做法和特点:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

注册费

+
+

上传模块

+
+

发布审核

+
+

开发者账号需要2FA验证

+
+

Firefox

+
+

+
+

web-ext

+
+

全自动,仅需要几秒钟1

+
+

+
+

Chrome

+
+

+
+

+
+

全自动,短于一小时

+
+

+
+

Opera

+
+

+
+

+
+

人工审核,但不需要提供SLA

+
+

+
+

Edge

+
+

+
+

+
+

人工审核,需要72小时2

+
+

+
+ +

1 在发布后会延期进行一次人工审查,如果发现了需要解决的问题,可能导致扩展被暂停。

+ +

2 在撰写本文时,微软只允许发布预先批准的扩展。

+ +

其他考虑

+ +

扩展命名

+ +

Microsoft 要求扩展具有唯一的名称,并通过 Windows Dev Center 为扩展声明一个或多个名称。因此,即使您不打算立即支持 Edge,为微软保留一个扩展名可能是最谨慎的做法。

+ +

版本号指定

+ +

Firefox 和 Chrome 商店要求每个上传的扩展发布包都有一个单独的版本号。这意味着如果在线上遇到问题,就不能恢复到之前的版本号。

+ +

在不同的实现中共享资源

+ +

即使你要支持的平台中包括 Safari,仍然可以在对于不同浏览器的实现中共享许多资源。其中包括:

+ + + +

总结

+ +

在进行跨平台扩展开发时,可以通过对标 Firefox 和使用 WebExtension API Polyfill 来解决扩展 API 之间的根本差异。遵循这种方法,您将在使用与提议的 WebExtension API 标准紧密结合的 API 特性中受益,并使用 promises 来简单的处理异步事件。

+ +

跨平台工作的主要重点可能是处理主要浏览器支持的 API 特性之间的差异。创建你的 manifest.json 文件应该是相对简单的,你可以手动完成。然后,您将需要考虑扩展包中的打包差异,以及提交到每个扩展商店的过程差异。

+ +

您同时可以使用 browser-extension-template 用于快速设置、生成和发布浏览器扩展项目。

+ +

根据本文中的建议,您现在应该能够创建一个在四种主要浏览器上都运行良好的扩展程序,使您能够将扩展功能交付给更多的人。

diff --git "a/files/zh-cn/mozilla/add-ons/webextensions/\347\224\250\346\210\267\347\225\214\351\235\242\345\205\203\347\264\240/index.html" "b/files/zh-cn/mozilla/add-ons/webextensions/\347\224\250\346\210\267\347\225\214\351\235\242\345\205\203\347\264\240/index.html" new file mode 100644 index 0000000000..1e99cab52c --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/webextensions/\347\224\250\346\210\267\347\225\214\351\235\242\345\205\203\347\264\240/index.html" @@ -0,0 +1,162 @@ +--- +title: 用户界面元素 +slug: Mozilla/Add-ons/WebExtensions/用户界面元素 +translation_of: Mozilla/Add-ons/WebExtensions/user_interface +--- +
{{AddonSidebar}}
+ +

该主题概括了所有你能用来创建你扩展的用户界面的组件。

+ +

浏览器行为

+ +

浏览器行为是一个你能添加至浏览器工具栏的按钮,用户可以点击该按钮来与你的扩展交互。

+ +

+ +

有两种方式定义一个浏览器行为: 有一个 弹出菜单, 或者没有弹出菜单。

+ +

当你没有定义一个弹出菜单时,用户点击按钮会导致一个消息被分发至扩展,而你可以使用 browserAction.onClicked 来监听它:

+ +
browser.browserAction.onClicked.addListener(handleClick);
+ +

如果你定义了弹出菜单,点击事件就不会被分发取而代之的是弹出菜单会显示出来。用户可以跟弹出菜单交互而当用户点击菜单外的区域时它会自动关闭。

+ +

值得注意的是你的扩展只能拥有一个浏览器行为。

+ +

定义浏览器行为

+ +

你通过使用在manifest.json 文件中使用 browser_action 关键字定义浏览器行为的属性 - 图标, 标题, 弹出菜单 :

+ +
"browser_action": {
+  "default_icon": {
+    "19": "button/geo-19.png",
+    "38": "button/geo-38.png"
+  },
+  "default_title": "Whereami?",
+  "default_popup": "popup/geo.html"
+}
+ +

唯一必要的关键字是 default_icon.你可以使用 browserAction API 修改任何属性.

+ +

例子

+ +

在GITHUB上的 webextensions-examples 资源包含了以下使用浏览行为的例子:

+ + + +

页面行为

+ +

页面行为在很多方面类似于 browser actions , 除了:

+ + + +

为了强调页面行为只跟部分页面有联系,他们将其显示在地址栏内而不是工具栏:

+ +

+ +

不像浏览器行为,页面行为默认是关闭的, 调用 pageAction.show()pageAction.hide() 可以显示或隐藏页面行为。

+ +

定义页面行为

+ +

通过在manifest.json中使用page_action 关键字来定义页面行为的属性 —— 图标, 标题, 弹出菜单:

+ +
"page_action": {
+  "browser_style": true,
+  "default_icon": {
+    "19": "button/geo-19.png",
+    "38": "button/geo-38.png"
+  },
+  "default_title": "Whereami?",
+  "default_popup": "popup/geo.html"
+}
+ +

default_icon 是唯一强制要求的关键字. 你可以使用 pageAction API 修改所有的属性或现实或隐藏页面行为。

+ +

例子

+ +

 chill-out 例子使用了一个页面行为。

+ +

弹出菜单

+ +

一个弹出菜单是一个绑定至 browser action 或者 page action  的对话框。

+ +

+ +

当用户点击按钮弹出菜单显示,当用户点击弹出菜单外的任何区域弹出菜单关闭。可以使用  window.close() 来关闭弹出菜单。

+ +

你可以使用专门的在manifest.json中使用"_execute_browser_action" 和 "_execute_page_action" 来定义一个快捷键打开浏览器行为或页面行为. 详情请看 commands manifest.json 关键字。不过你不能在你的扩展脚本中通过编程打开弹出菜单 : 他只能通过用户的行为的被打开。

+ +

弹出菜单像普通网页一样通过HTML文件被定义,你当然也可以在里面包含CSS 和 javascript文件。 而且不像普通网页, 其包含的javascript可以使用所有的已经通过permissions获取了使用权限的 WebExtension APIs

+ +

你可以要求浏览器在你的弹出菜单中包含一个样式表以使其看起来与浏览器UI一致。为了达成这一目的,在你的 browser_actionpage_action  关键字中包含 "browser_style": true

+ +

弹出菜单存在一个限制其可以加载资源的源地址的安全机制, 同时不允许类似 eval() 的做法的使用 查看 Content Security Policy 获取更多细节。

+ +

你可以使用Add-on Debugger来调试弹出菜单标记和脚本,但是你需要一些技巧来设置让弹出菜单不在自动关闭。 阅读关于调试弹出菜单

+ +

弹出菜单尺寸重新计算

+ +

弹出菜单自动根据其内容调整尺寸。其适应算法可能因浏览器而不同。

+ +

在火狐, 尺寸只再弹出菜单显示前被计算,而且在内容变化后至多进行每秒十次的计算。严格来说, 尺寸受 <body> 元素放置尺寸决定。 一种怪异的说法是, 他由 <html> 决定, Firefox 计算该元素的推荐宽度, 重新调整弹出菜单至其宽度, 然后完成尺寸调整所以这里没有上下滚动。 如果适应用户的屏幕他可能会增长到800X600px的尺寸。 如果用户 移动弹出菜单对应按钮到菜单面板 ,而后弹出菜单会在菜单栏内显示并具有合适的尺寸。

+ +

设置页面

+ +

设置页面允许你定义你的扩展可以被用户修改的选项。 用户从浏览器扩展管理器中访问设置页面:

+ +

{{EmbedYouTube("02oXAcbUv-s")}}

+ +

每个浏览器访问该页面的方法存在区别。

+ + + +

你可以通过调用 runtime.openOptionsPage() 打开设置页面

+ +

设置页面存在一个限制其可以加载资源的源地址的安全机制, 同时不允许类似 eval() 的做法的使用 查看 Content Security Policy 获取更多细节。

+ +

定义一个设置页面:

+ +

创建一个设置页面有以下流程:

+ + + +

例子

+ +

 favourite-colour 使用了设置页面。

+ +

上下文菜单项

+ +

使用 {{WebExtAPIRef("contextMenus")}} API, 你可以按你指定的情况向浏览器上下文菜单添加项目, 比如,你可以只在用户点击图片时显示一项,或者在一个可编辑的元素上,或者被选择的页面的一部份。

+ +

指定一个上下文菜单项

+ +

您可以使用{{WebExtAPIRef("contextMenus")}} API来 程序化地管理上下文菜单项。

+ +

例子

+ +

 context-menu-demo 创建了几种不同的上下文菜单项。

+ +

通知

+ +

使用 {{WebExtAPIRef("notifications")}} API,你通过使用操作系统的通知系统可以创建短时通知:

+ +

+ +

定义一个通知

+ +

使用{{WebExtAPIRef("notifications")}} API 可以程序化地管理通知。

+ +

Examples

+ +

notify-link-clicks-i18n 创建了通知。

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 +--- +
+

致 Firefox 开发者:本文描述如何使你开发的扩展能在多进程 Firefox 中运行。

+
+ +

目前,在桌面版 Firefox 中,Chrome 代码(Chrome Code)和内容(Content)运行在同一个进程里。因此扩展可以直接访问网页内容:

+ +
gBrowser.selectedBrowser.contentDocument.body.innerHTML = "replaced by chrome code";
+ +

不过呢,在多进程 Firefox(又称 Electrolysis 或 E10S)中,扩展代码(Add-on Code)和内容则在不同的进程中运行,所以上述直接访问就不一定可行了。

+ +

在多进程 Firefox 中,扩展需要将触及内容的代码分解成单独分离的脚本,也就是所谓的框架脚本(Frame Scripts)。框架脚本在内容进程中运行,可以直接访问内容。框架脚本通过消息传递接口(Message-passing API)与扩展的剩余部分进行通讯。

+ +

运行在 Chrome 进程中的扩展代码必须向框架脚本发送异步消息。这样做可以确保 Firefox 的用户界面不会被内容进程卡死。

+ +

内容进程则可以向 Chrome 进程发送同步或异步消息,不过使用异步消息是再好不过了。

+ +

关于使用消息管理器的更多细节,请参阅:消息管理器指南。接下来,本文将告诉你如何判断你开发的扩展是否会受到这方面的影响,同时简要说明需要如何进行修改。最后,通过对一些简单的样板扩展进行修改,让它们能在多进程 Firefox 中运行。

+ +

检查你的扩展是否受到影响

+ +

总体规则如下:

+ + + +

为了证实是否受到影响,你还需要进一步测试,这个测试过程由两步过程构成:

+ + + +

现在,你可以在多进程 Firefox 中禁用兼容性管理工具来测试你的扩展的兼容性了。可惜你还不能在开启多进程功能的时候安装新扩展,因此你必须先安装好扩展再开启多进程功能。关于这个问题,详见 bug 1055808

+ +

更新你的代码

+ +

更新代码的一般方法是:

+ + + +

更多细节,请参见 message manager 文档。

+ +

新应用程序接口的向前兼容能力

+ +

新的多进程 Firefox 的消息接口在多进程模式没有开启的情况下仍然可用。实际上它们从 Firefox 4开始就在某种程度上可用了。不过呢,最初的应用程序接口和现在的并不相同。一些已知的差异如下:

+ + + +

你不仅应该在开启了多进程支持的每夜版Firefox上测试你的扩展的变化,而且应该在你打算支持的没有开启多进程支持的发行版(Release Build)中测试。

+ +

举几个例子

+ +

这部分将演示修改几种不同的扩展的过程。这些扩展都是很简易的,意在展示基础的扩展模式在多进程Firefox中需要的不同处理方式。

+ +

你可以在 e10s-example-addons GitHub repository 中找到这些例子的所有源代码。

+ +

在所有页面运行一个脚本

+ +
+

查看这个例子的源代码

+
+ +

第一个扩展在每一个页面加载的时候运行一些代码。这些代码不和扩展的其他部分交互,它们只是对页面进行一些预设的修改。在这个例子中,扩展向文档的主体(body)添加了一个边界。

+ +

这个扩展通过将一种“页面加载中”代码碎片("On page load" code snippet)附加于可扩展用户界面语言层来实现此修改。

+ +
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);
+ +

因为这段代码直接访问网络内容,所以它不能在多进程 Firefox 中运行。
+

+ +

移植到消息管理器

+ +

为了使用消息管理器移植这个例子,我们可将这个扩展全部的主体部分放入一个框架脚本:

+ +
// 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";
+});
+
+ +

我们将为这个框架脚本注册一个 chrome:// URL :

+ +
// chrome.manifest
+
+content    modify-all-pages    chrome/content/
+
+ +

我们附加到XUL overlay的主体脚本,只是一个使用全局消息管理器来在每个标签页中加载框架脚本的 stub。

+ +
// 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);
+ +

+ +

移植到 Add-on SDK

+ +

一个好的替代这样的一个扩展的思路是将其移植到 Add-on SDK。Add-on SDK 包括一个名为 page-mod 的设计为在网页中加载脚本的模块。Add-on SDK 称这些脚本为内容脚本。

+ +

这种情况下扩展的主要代码创建一个 page-mod 来加载内容脚本到用户载入的每个页面:

+ +
// main.js
+
+var pageMod = require("sdk/page-mod");
+var self = require("sdk/self");
+
+pageMod.PageMod({
+  include: "*",
+  contentScriptFile: self.data.url("modify-all-pages.js")
+});
+ +

内容脚本可以直接修改页面:

+ +
// modify-all-pages.js - content script
+
+document.body.style.border = "5px solid green";
+ +

在活动标签中运行一个脚本

+ +
+

查看这个例子的代码。

+
+ +

这个例子说明了一个扩展如何:

+ + + +

这个例子是一个无需重启的扩展,它使用 CustomizableUI 模块添加了一个按钮。当用户点击这个按钮,这个扩展运行一些代码来改变当前标签。其基础构造取自 Jorge Villalobos 的 Australis "Hello World" 扩展 .
+
+ 代码实际做的事是:找到任意 <img> 元素并将其 src 替换为从硬编码于扩展中的列表中随机抽取的无意义的 GIF 图像。 无意义的 gifs 从Whimsy extension 获取。

+ +

第一个版本直接访问页面,因此其不是多进程兼容的:

+ +
// 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 < images.length; ++i) {
+        let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)];
+        images[i].src = gif;
+      }
+    },
+ +

+ +

移植到消息管理器

+ +

为了移植这个例子到消息管理器,我们将使 onCommand 加载一个框架脚本到当前的 <browser>,然后监听来自框架脚本的 "request-gifs" 信息。这些 "request-gifs" 信息应当包含我们在此页面上需要的 GIFs :信息监听器取回并返回这个数量的 GIFs。

+ +
// 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 < gifsToReturn.length; i++) {
+      let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)];
+      gifsToReturn[i] = gif;
+    }
+    return gifsToReturn;
+  },
+
+ +

再次地,我们需要为这个框架脚本注册一个 chrome:// URL:

+ +
// chrome.manifest
+
+content gifinate frame-script.js
+ +

在框架脚本中,我们获取所有的 <img> 元素并发送 "request-gifs" 信息给扩展主体代码。 由于这是框架脚本我们可以将其变为一个同步信息,并使用其返回值更新 src 属性:

+ +
// 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 < images.length; ++i) {
+  images[i].src = gifs[i];
+}
+ +

整个扩展的流程现在像这样:
+

+ +

已知问题

+ +

这里是可能影响扩展开发者移植到多进程firefox的开放的bug列表:

+ + diff --git "a/files/zh-cn/mozilla/add-ons/\351\233\267\351\270\237/index.html" "b/files/zh-cn/mozilla/add-ons/\351\233\267\351\270\237/index.html" new file mode 100644 index 0000000000..c46b242f7e --- /dev/null +++ "b/files/zh-cn/mozilla/add-ons/\351\233\267\351\270\237/index.html" @@ -0,0 +1,131 @@ +--- +title: 雷鸟扩展 +slug: Mozilla/Add-ons/雷鸟 +translation_of: Mozilla/Thunderbird/Thunderbird_extensions +--- +
Building a Thunderbird extension
+Step-by-step explanation on how to build an extension for Thunderbird.
+ +
+

{{AddonSidebar}}

+本文档是为Mozilla公司的雷鸟邮件客户端开发扩展的教程。Although there are many similarities with Firefox extensions there are also some differences that may confound the starting developer.
+ +

+Please help! You can add a how-to (a question or an answer or a code snippet), summarize and link to a relevant newsgroup discussion, or create a tutorial. Need help? Contact jenzed.
+ + + + + + + + +
+

Documentation

+ +

Getting started with Thunderbird

+ +

A brave, young developer wants to develop an add-on for Thunderbird. Here's a few links to help them through this journey.

+ +
    +
  • Start by reading the tutorial and learn how to build a Thunderbird extension (Outdated, still talks about overlays and the add-on builder is no longer available but the tutorial has not been updated.)
  • +
  • Read about the main windows so that you know what one means when they say « thread pane », « preview pane », and « folder pane ».
  • +
  • Read an overview of how the various parts of Thunderbird fit together, this really helps get a better understanding of Thunderbird.
  • +
  • Want to do some real stuff? See how to inspect a message (demo add-on included!)
  • +
  • Play with our other demo add-on that exercises some more advanced Thunderbird-specific features
  • +
  • Want to do even more stuff? Don't reinvent the wheel: steal functions from the thunderbird-stdlib project (doc here). Functions for dealing with messages (delete them, archive them, change their tags, etc.) are included.
  • +
  • Haven't found what you're looking for? Read the Thunderbird how-tos; they contain a lot of recipes for things extensions want to do.
  • +
  • Still haven't managed to do what you wanted? See the list of all Thunderbird communication channels so that you know where to ask when you get stuck :-).
  • +
  • Feeling really brave? Read the source using a fancy interface; you can often find tests that demonstrate how to do what you're trying to achieve.
  • +
+ +

The Gloda database

+ +

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 (from field, to field) which are themselves part of a Contact: indeed, a contact has multiple identities.

+ +

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.

+ +

Gloda is extremely powerful and is used heavily by add-ons such as Thunderbird Conversations. Learn more about Gloda:

+ + + + + +

Some of these links may be wildly out of date, but they still provide valuable information on the codebase.

+ + + + + + +
+

Community

+ + + +

{{ DiscussionList("dev-extensions", "mozilla.dev.extensions") }}

+ + + +

Tools

+ + + +

... more tools ...

+ +

View All...

+ + + +
+
XUL, JavaScript, XPCOM, Themes, Developing Mozilla
+
+
+ +

Categories

+ +

{{ languages( { "ja": "ja/Extensions/Thunderbird" } ) }}

diff --git a/files/zh-cn/mozilla/adding_a_new_event/index.html b/files/zh-cn/mozilla/adding_a_new_event/index.html new file mode 100644 index 0000000000..1cd964fe0e --- /dev/null +++ b/files/zh-cn/mozilla/adding_a_new_event/index.html @@ -0,0 +1,186 @@ +--- +title: Adding a new event +slug: Mozilla/Adding_a_new_event +translation_of: Mozilla/Adding_a_new_event +--- +
+

This document is a working draft.

+
+ +

What type of event do you want?

+ +

大体上,有三种类型的事件。 First, you need to choose which type you need.

+ +

Case 1: 简单DOM事件。通过WebIDL、WidgetEvent等机制实现. This type of event is useful if the event isn't handled by C++ code.

+ +

Case 2: DOM事件。表达诸如键盘、鼠标等用户操作的本地事件。这种类型的事件能够方便的使用C++代码来处理。

+ +

Case 3: 非DOM事件。However, C++ 代码需要分派事件到DOM树,然后在使用C++代码来处理。This is useful for widget notifying DOM tree of something or retrieving something from DOM tree.

+ +

How to implement an internal event class

+ +
+

If you're in the case 1, you can skip this section.

+
+ +

Add event messages

+ +

You need to add event messages which are stored by WidgetEvent::message. All messages are defined by macro in "messages" section of BasicEvents.h.

+ +

Define event class name

+ +

You need to add an event class name in EventClassList.h.

+ +

Use NS_EVENT_CLASS macro for adding it. The macro takes two arguments, aPrefix and aName.

+ +

aPrefix defines prefix of event class name which should be Widget or Internal. Widget should be used if the event class is dispatched from widget. Otherwise, i.e., the event class is just used for internal event class of a DOM event class, it should be Internal.

+ +

aName defines its event class specific name and it must end with "Event" or "EventBase". The latter is used only for abstruct super event class whose instance will never be created.

+ +

Please note that aName must not be same as other event classes even if aPrefix is different. I.e., defining both WidgetFooEvent and InternalFooEvent is invalid.

+ +

Define and implement an event class

+ +

Then, you need to define and implement an event class. You should choose a good header file from what your event class represents.

+ +
+
BasicEvents.h
+
This header file should be used only for defining generic purpose event class such as a common super class of various event classes. Probably, you shouldn't use this for your class.
+
ContentEvents.h
+
This header file should be used for defining internal event classes which are dispatched in content and do not represent user action. Typically, events in this header file never cross process boundary.
+
MouseEvents.h
+
This header file should be used for defining input events from pointing devices such as mouse.
+
TextEvents.h
+
This header file should be used for defining input events from keyboard or IME and also other text edit related events like querying focused content information.
+
TouchEvents.h
+
This header file should be used for defining input events from touch devices.
+
MiscEvents.h
+
If the new event class isn't proper any header files above, you should use this.
+
+ +

Each event class should implement following methods manually.

+ +
+
virtual InternalFooEvent* AsFooEvent() MOZ_OVERRIDE
+
This method should just return this. This method is used for retrieving sub class pointer avoiding to use static_cast.
+
virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
+
This method should create a new instance with copying its members except widget. For copying the members, this should use AssignFooEventData() with true for aCopyTargets. And also, mFlags should be just copied since AssignFooEventData() doesn't copy mFlags. This method is basically used for duplicating an internal event class instance of a DOM event when the DOM event is stored by content.
+
void AssignFooEventData(const InternalFooEvent* aEvent, bool aCopyTargets)
+
This method should copy members from aEvent. First, this method should call its super class's this method. Then, copy the additional members which are defined in the class. If aCopyTargets is false, don't copy its event target related members.
+
+ +

All new member variables of event classes must be with "m" prefix. Although, a lot of existing members don't have "m" prefix, but you shouldn't use the legacy local rules.

+ +

If you need to add methods, it's okay to implement them as inline methods. I.e., you can implement new methods in the header files directly.

+ +

However, if implementing method isn't small and called from a lot of places, implementing it as inline causes to increase binary size. In this case, you should implement the method in WidgetEventImple.cpp. And also, if implementing a method needs to include other header files, you should implement it in WidgetEventImple.cpp too for avoiding include hell.

+ +

Make new event class IPC aware

+ +

For example, new class is caused by native user input event and needed to be dispatch to content, the class should be able to cross process boundary. In such cases, you may need to add new ParamTraits for the new event class in nsGUIEventIPC.h.

+ +

Modify utility methods of WidgetEvent

+ +

WidgetEvent class has some utility mehtods and all of them are implemented in WidgetEventImple.cpp. E.g., if your event shouldn't cause DOM event, you need to modify WidgetEvent::IsAllowedToDispatchDOMEvent(). If your event should be fired on focused node, you need to modify WidgetEvent::IsTargetedAtFocusedContent().

+ +

How to implement a DOM event class

+ +
+

If you're in the case 3, you can skip this section.

+
+ +

Create WebIDL of the event

+ +

Write a DOM event definition with WebIDL. It should be created under dom/webidl/. See WebIDL bindings for the detail.

+ +

If your new event shouldn't be created with event constructor such as:

+ +
var event = new FooEvent("bar", { bubbles: true, cancelable: true, detail: 5 });
+ +

you shouldn't define construnctor in it.

+ +

Create XPCOM interface for the DOM event

+ +

If your event class should be accessible via XPCOM interface, you should create a new nsIDOMFooEvent interface in dom/interfaces/events/. However, in these days, this is not necessary. If all information of the event is stored by its internal event, C++ event handlers can acess them with following code:

+ +
NS_IMETHODIMP
+AnEventListener::HandleEvent(nsIDOMEvent* aEvent)
+{
+  InternalFooEvent* internalEvent =
+    aEvent->GetInternalNSEvent()->AsFooEvent();
+  if (NS_WARN_IF(!internalEvent)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  DoSomethingWith(internalEvent->mBar);
+  aEvent->PreventDefault();
+  return NS_OK;
+}
+
+ +

Implement DOM event class

+ +

Generate DOM event implementation if it's possible

+ +

If you're creating simple DOM event class, it might be generated automatically. If it's possible, you just need to add an entry to GENERATED_EVENTS_WEBIDL_FILES in dom/webidl/moz.build.

+ +

Define and create DOM event class manually

+ +

Otherwise, you need to implement a DOM event class yourself. The best place to create FooEvent.h and FooEvent.cpp is in dom/events/. Otherwise, you need to specify the path to the header file in dom/bindings/Bindings.conf.

+ +

When you create a DOM event class, its name should be same as the name defined in its standard specification. And it should be in mozilla::dom namespace. For example, KeyboardEvent which is defined in DOM Level 3 Events should be implemented as mozilla::dom::KeyboardEvent.

+ +

And the header file should be exported as "mozilla/dom/FooEvent.h". Add the header file to EXPORTS.mozilla.dom in dom/events/moz.build.

+ +

You probably need to implement a lot of methods to the event class, but this document doesn't explain all of them. Please refer existing DOM event implementation for example.

+ +

However, there are some hints:

+ +
    +
  1. Set mEventIsInternal in the constructor of the most descendant class because each constructor creates dummy internal event instance at calling constructors of its super class. Therefore, super classes always set it false.
  2. +
  3. Don't override methods of its super classes as far as possible since overriding the method may cause harder to maintain.
  4. +
  5. When you need to check if the caller content or chrome, you can use implicitJSContext attribute in dom/bindings/Bindings.conf. Then, the method can have a pointer of JSContext in its argument.
  6. +
+ +

Create DOM event factory method

+ +
+

If your DOM event implementation is generatable, you can skip this section.

+
+ +

In nsIDOMEvent.idl, you need to define NS_NewDOMFooEvent(). It's last argument should be the most subclass. Then, the implementation of the DOM event can access internal event class instance safer.

+ +

Then, the factory method should be implemented at the bottom of FooEvent.cpp in the global namespace.

+ +

Modify EventDispatcher::CreateEvent()

+ +
+

If your DOM event implementation is generatable or you're in case 3, you can skip this section.

+
+ +

The first half of EventDispatcher::CreateEvent() is a factory to create a DOM event instance from internal event instance. You need to modify this.

+ +

The last half of it is the implementation of legacy event creator of Javascript such as:

+ +
var event = document.createEvent("FooEvent");
+ +

If you support this feature, you need to modify here. However, this feature shouldn't be implemented for compabitility with other browsers since web applications should use event constructor.

+ +

Register each event into EventNameList.h

+ +
+

If you're in case 3, you can skip this section.

+
+ +

EventNameList.h defines mapping between DOM event name, internal event message, event handler attribute owner and internal event class. See the comments of the head of the file for the detail.

+ +

Modify tests

+ +
+

If you're in case 3, you can skip this section.

+
+ +

You need to modify test_all_synthetic_events.html which tests if calling getModifierState() doesn't cause crash.

+ +

You need to modify test_assign_event_data.html which tests if each attribute of DOM event is copied by AssignFooEventData() properly. If your event cannot be fired easy, you should add the test but canRun should return false and call todo().

+ +

If the new DOM event is creatable with constructor, you need to modify test_eventctors.html or test_eventctors.xul which tests the behavior of event constructor.

diff --git a/files/zh-cn/mozilla/bugzilla/index.html b/files/zh-cn/mozilla/bugzilla/index.html new file mode 100644 index 0000000000..83c9832732 --- /dev/null +++ b/files/zh-cn/mozilla/bugzilla/index.html @@ -0,0 +1,58 @@ +--- +title: Bugzilla +slug: Mozilla/Bugzilla +tags: + - Bugzilla + - Developing Mozilla + - 'Developing_Mozilla:Tools' + - NeedsTranslation + - QA + - Tools + - TopicStub +translation_of: Mozilla/Bugzilla +--- +

bugzilla.mozilla.org (often abbreviated b.m.o) is Mozilla.org's bug-tracking system, a database for recording bugs and enhancement requests for Firefox, Thunderbird, SeaMonkey, Camino, and other mozilla.org projects.

+ +
+
+

Documentation about B.m.o.

+ +
+
What to do and what not to do in Bugzilla
+
Tips for how to use Bugzilla, as well as things you should avoid.
+
Bugzilla etiquette
+
A guide to etiquette; this guide will help you understand how best to conduct yourself on b.m.o. and how using proper manners and civility will help ensure your problem gets solved sooner rather than later.
+
How to tell if a bug has already been reported
+
It's useful (but not mandatory) for you to check if the problem you're reporting has been already tracked. This guide will help you do so.
+
Quality assurance
+
Documentation about quality assurance at Mozilla.
+
Bug writing guidelines
+
A guide to writing a good, understandable, bug that will be easily followed by the development team.
+
How to submit a patch
+
If you've fixed a bug, or have implemented a new feature, you'll need to get your patch into the tree so it can become part of the product. This guide will teach you how!
+
+ +

View All...

+
+ +
+

Other materials

+ + + +

Tools

+ +
    +
  • Bugzilla Todos lists review and flag requests, patches to check in, unfulfilled requests you made of other people, and assigned bugs.
  • +
  • Bz Kanban is a board to visualize the status of bugs within a milestone.
  • +
+
+
diff --git a/files/zh-cn/mozilla/bugzilla/testopia/index.html b/files/zh-cn/mozilla/bugzilla/testopia/index.html new file mode 100644 index 0000000000..638ecf9630 --- /dev/null +++ b/files/zh-cn/mozilla/bugzilla/testopia/index.html @@ -0,0 +1,134 @@ +--- +title: Testopia +slug: Mozilla/Bugzilla/Testopia +translation_of: Mozilla/Bugzilla/Testopia +--- +

Testopia 是bugzilla测试用例管理扩展工具。它可以帮助测试人员跟踪管理测试用例,并将测试用例运行结果整合进bug报告。testopia设计以软件测试为核心,使之可以跟踪软件工程中的几乎任何测试。

+

Testopia 2.5

+

此版本直接支持bugzilla4.2,并且不在需要bugzilla 补丁。如果用户需要升级至2.5

+

在安装前,请卸载已安装的bugzilla补丁。安装之需要直接将tar包解压在bugzilla的根目录下,并运行checksetup即可。感谢来自bugzilla团队的LpSolit,没有它就没有这些变化。

+

Testopia 2.4 - 重要通知!

+

如果用户在大小写敏感的文件系统中升级,请一定要从扩展目录中删除已有的testopia文件夹。

+

如果用户已经修改了testopia 的源代码,用户需要将他们合并到Testopia文件夹(capital T)。如果用户使用windows系统或其它大小写不敏感的文件系统,用户仅需要重命名已有文件夹即可,例如:testopia-old ,然后解压缩tar包。在删除老版本前,用户可以合并两个文件夹。

+

API USERS 请注意: 不再赞成使用Positional parameters。所有参数变量现在都应形成哈希对 (struct, dict, hashmap or whatever your language of choice calls key, value pairs).

+

虽然,努力尝试继续支持positional parameters,但请注意有些api直到用户调用时才会失败。在后续版本中也许会完全去除对它的支持。

+

一如既往,请在安装或升级前备份你已安装的系统。

+

Integration Points

+ +

Features for version 2.4 (Bugzilla 3.6.x)

+ +

Features for version 2.3 (Bugzilla 3.4.x)

+ +

Features for version 2.2 (Bugzilla 3.2 and 3.0.x)

+

此版本主要是修复了一些bug,使之更好的兼容bugzilla 3.2 和 3.0.6。请确认根据自己的bugzilla版本下载正确的安装包。

+

To install, do the following (see the README for more detailed instructions):

+
    +
  1. 解压Testopia 2.4 tar包到用户的Bugzilla目录.
  2. +
  3. 打Bugzilla补丁.
    + On Linux systems it should look something like: +

    patch -p0 -i extensions/testopia/patch-3.6

    +
  4. +
  5. Run checksetup.pl
  6. +
+

升级Testopia步骤同上。只是需要先卸载以前的老补丁即可。如果同时升级bugzilla,请先升级bugzilla,再升级testopia。

+

patch -p0 -R -i extensions/testopia/patch-<version>

+

命令中<version> 代表Bugzilla版本号

+

Requirements

+

我们决定尝试紧跟bugzilla最新稳定版本3.4,来完成自己的开发。这给我们提供稳定的代码。为任何软件开发插件或扩展,就像射击移动目标一样。这个决定使得我们可以集中更多时间在新特性上,而不是旧特性。因此,这就意味着新特性不会再支持早先的版本,除非我们有时间这么做。当然,任何想这么做的人,都是无上欢迎的。

+ +

TODO

+ +

See the Roadmap and Bug List for more details.

+ + +

Downloads

+ +

Developers

+

Greg Hendricks
+ Vance Baarda (former developer)
+ Ed Fuentetaja (former developer)

diff --git a/files/zh-cn/mozilla/chrome_registration/index.html b/files/zh-cn/mozilla/chrome_registration/index.html new file mode 100644 index 0000000000..8e7fd85b41 --- /dev/null +++ b/files/zh-cn/mozilla/chrome_registration/index.html @@ -0,0 +1,229 @@ +--- +title: Chrome Registration +slug: Mozilla/Chrome_Registration +tags: + - NeedsEditorialReview + - Toolkit API +translation_of: Mozilla/Chrome_Registration +--- +

 

+ +

Chrome是什么?

+ +

Chrome 是应用程序内容窗口以外一系列用户接口元素。工具栏,如菜单栏,进度栏和标题栏这些都是chrome典型的元件。

+ +

Chrome Providers

+ +

A supplier of chrome for a given window type (e.g. for the browser window) is called a chrome provider. The providers work together to supply a complete set of chrome for a particular window, from the images on the toolbar buttons to the files that describe the text, content and appearance of the window itself.

+ +

There are three basic types of chrome providers:

+ +

Content

+ +

The main source file for a window description comes from the content provider, and it can be any file type viewable from within Mozilla. It will typically be a XUL file, since XUL is designed for describing the contents of windows and dialogs. The JavaScript files that define the user interface are also contained within the content packages, as well as most XBL binding files.

+ +

Locale

+ +

Localizable applications keep all their localized information in locale providers. This allows translators to plug in a different chrome package to translate an application without altering the rest of the source code. The two main types of localizable files are DTD files and Java-style properties files.

+ +

Skin

+ +

A skin provider is responsible for providing a complete set of files that describe the visual appearance of the chrome. Typically a skin provider will provide CSS files and images.

+ +

Note: Scripts (including those found in XBL) loaded from skin packages will not execute.

+ +

The Chrome Registry

+ +

The gecko runtime maintains a service known as the chrome registry that provides mappings from chrome package names to the physical location of chrome packages on disk.

+ +

This chrome registry is configurable and persistent, and thus a user can install different chrome providers, and select a preferred skin and locale. This is accomplished through xpinstall and the extension manager.

+ +

In order to inform the chrome registry of the available chrome, a text manifest is used: this manifest is "chrome.manifest" in the root of an extension, or theme, and chrome/*.manifest in a XULRunner application.

+ +

The plaintext chrome manifests are in a simple line-based format. Each line is parsed individually; if the line is parseable the chrome registry takes the action identified by that line; otherwise the chrome registry ignores that line (and prints a warning message in the runtime error console).

+ +
locale packagename localename path/to/files
+skin packagename skinname path/to/files
+
+ +

Manifest Instructions

+ +

comments

+ +

A line is a comment if it begins with the character '#'; any other characters on the line are ignored.

+ +
# this line is a comment - you can put whatever you want here
+
+ +

content

+ +

A content package is registered with the line

+ +
contentpackagenameuri/to/files/[flags]
+
+ +

This will register a location to use when resolving the URI chrome://packagename /content/.... The URI may be absolute or relative to the location of the manifest file. Note, that it must end with an '/'.

+ +

locale

+ +

A locale package is registered with the line

+ +
localepackagenamelocalenameuri/to/files/[flags]
+
+ +

This will register a locale package when resolving the URI chrome://packagename /locale/... . Thelocalename is usually a plain language identifier "en" or a language-country identifier "en-US". If more than one locale is registered for a package, the chrome registry will select the best-fit locale using the user's preferences.

+ +

skin

+ +

A skin package is registered with the line

+ +
skinpackagenameskinnameuri/to/files/[flags]
+
+ +

This will register a skin package when resolving the URI chrome://packagename/skin/... . Theskinname is an opaque string identifying an installed skin. If more than one skin is registered for a package, the chrome registry will select the best-fit skin using the user's preferences.

+ +

style

+ +

Style overlays (custom CSS which will be applied to a chrome page) are registered with the following syntax:

+ +
style chrome://URI-to-style chrome://stylesheet-URI[flags]
+
+ +
Note that only stylesheets at chrome URIs can be applied in this way.
+ +

override

+ +

In some cases an extension or embedder may wish to override a chrome file provided by the application or XULRunner. In order to allow for this, the chrome registration manifest allows for "override" instructions:

+ +
override chrome://package/type/original-uri.whatevernew-resolved-URI[flags]
+
+ +

Note: overrides are not recursive (so overriding chrome://foo/content/bar/ with file:///home/john/blah/ will not usually do what you want or expect it to do).

+ +
+

There is a currently a bug in the Firefox 2.0.0.* series, as well as previous builds, where if you use a relative URL for thenew-resolved-URI parameter, the override will not work. You need to provide a fully qualified URL (ie, one that is resolvable anywhere, not just in the directory the chrome manifest resides in). Given that the extension or application developer usually is unable to predict what the full path to such a file might be, currently one would normally only use this directive using another chrome:// URL as thenew-resolved-URI parameter. See {{ Bug(323455) }}.

+
+ +

resource

+ +

{{ Fx_minversion_inline(3) }}

+ +

When using JavaScript code modules it may be necessary to create resource protocol aliases so extensions and applications can load modules using Components.utils.import. Aliases can be created using the resource instruction:

+ +
resourcealiasnameuri/to/files/[flags]
+
+ +

This will create an mapping for the res://<aliasname>/ to the path given.

+ +
+

Note that there are no security restrictions preventing web content from including content at resource uris so take care with what you make visible there.

+
+ +

Manifest Flags

+ +

Manifest lines can have multiple, space-delimited flags added at the end of the registration line. These flags mark special attributes of chrome in that package, or limit the conditions under which the line is used.

+ +

application

+ +

Extensions may install into multiple applications. There may be chrome registration lines which only apply to one particular application. The flag

+ +
application=app-ID
+
+ +

indicates that the instruction should only be applied if the extension is installed into the application identified byapp-ID is running. Multiple application flags may be included on a single line, in which case the line is applied if any of the flags match.

+ +

appversion

+ +

Extensions may install into multiple versions of an application. There may be chrome registration lines which only apply to a particular application version. The flag

+ +
appversion=version
+appversion<version
+appversion<=version
+appversion>version
+appversion>=version
+
+ +

indicates that the instruction should only be applied if the extension is installed into the application version identified. Multiple appversion flags may be included on a single line, in which case the line is applied if any of the flags match. The version string must conform to the Toolkit version format.

+ +
+

Versions of Gecko before 1.8.0.13 and 1.8.1.5 contained a bug where if you use the comparisons <, > or = then the version string had be 2 characters or more long. If not you would get a message in the error console that the appversion flag was not recognized. See {{ Bug(380398) }}.

+
+ +

contentaccessible

+ +

{{ Fx_minversion_inline(3) }} Untrusted content is no longer allowed to reference resources in chrome packages. If this needs to be explicitly allowed, set the contentaccessible flag to yes for behavior as found in older versions.

+ +

The contentaccessible flag applies only to content packages: it is not recognized for locale or skin registration. However, the matching locale and skin packages will also be exposed to content. Changed for Firefox 3 RC 1 for {{ bug(292789) }}.

+ +

os

+ +

{{ Fx_minversion_inline(3) }} Extensions (or themes) may offer different features depending on the operating system on which Firefox is running. The value is compared to the value of OS_TARGET for the platform.

+ +
os=WINNT
+os=Darwin
+
+ +

See OS_TARGET for a more complete list of os names. The os name is case insensitive.

+ +

osversion

+ +

{{ Fx_minversion_inline(3) }} An extension or theme may need to operate differently depending on which version of an operating system is running. For example, a theme may wish to adopt a different look on Mac OS X 10.5 than 10.4:

+ +
osversion>=10.5
+
+ +

platform (Platform-specific packages)

+ +

Some packages are marked with a special flag indicating that they are platform specific. Some parts of content, skin, locales may be different based on the platform being run. These packages contain three different sets of files, for Windows and OS/2, Macintosh, and Unix-like platforms. For example, the order of the "OK" and "Cancel" buttons in a dialog is different, as well as the names of some items.

+ +

The "platform" modifier is only parsed for content registration, it is not recognized for locale or skin registration. However it applies to content, locale, and skin parts of the package, when specified.

+ +

To indicate that a package is platform-specific, add the "platform" modifier to the "content" line after the path, for example:

+ +
content global-platform jar:toolkit.jar!/toolkit/content/global-platform/ platform
+
+ +

Once that is specified in your manifest you then ensure that under the directory global-platform are subdirectories win (Windows/OS2), mac (OS9/OSX), or unix (Everything Else). Anything residing outside of these subdirectories will be ignored.

+ +

xpcnativewrappers

+ +

Chrome packages can decide whether to use the xpcnativewrappers security mechanism to protect their code against malicious content that they might access. See Safely accessing content DOM from chrome for details.

+ +

As of Firefox 1.5 alpha releases (Deer Park alphas), this flag is *off* by default, and must be explicitly enabled by specifying xpcnativewrappers=yes.

+ +

As of the first Firefox 1.5 beta release, this flag will be enabled by default, and extensions that need insecure access to the content objects will be required to specify xpcnativewrappers=no.

+ +

The xpcnativewrappers flag applies only to content packages: it is not recognized for locale or skin registration.

+ +

 

+ +

Example Chrome Manifest

+ +
content       necko                   jar:comm.jar!/content/necko/ xpcnativewrappers=yes
+locale	       necko       en-US       jar:en-US.jar!/locale/en-US/necko/
+content       xbl-marquee             jar:comm.jar!/content/xbl-marquee/
+content       pipnss                  jar:pipnss.jar!/content/pipnss/
+locale        pipnss      en-US       jar:en-US.jar!/locale/en-US/pipnss/
+# Firefox-only
+overlay chrome://browser/content/pageInfo.xul           chrome://pippki/content/PageInfoOverlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
+overlay chrome://communicator/content/pref/preftree.xul chrome://pippki/content/PrefOverlay.xul
+overlay chrome://navigator/content/pageInfo.xul         chrome://pippki/content/PageInfoOverlay.xul application=seamonkey@applications.mozilla.org
+content       pippki                  jar:pippki.jar!/content/pippki/ xpcnativewrappers=yes
+locale        pippki      en-US       jar:en-US.jar!/locale/en-US/pippki/
+content       global-platform         jar:toolkit.jar!/content/global-platform/ platform
+skin          global      classic/1.0 jar:classic.jar!/skin/classic/global/
+override chrome://global/content/netError.xhtml jar:embedder.jar!/global/content/netError.xhtml
+content       inspector               jar:inspector.jar!/content/inspector/ xpcnativewrappers=no
+
+ +

Debugging a Chrome Manifest file

+ +

The Chrome List extension shows all registered chrome. This is very helpful when trying to write a chrome.manifest file as you can inspect where the files are being mapped from (jar files, local directory, etc.)

+ +

Old-style contents.rdf manifests

+ +

Before the plaintext manifests were introduced (which happened in Firefox 1.5, Toolkit 1.8), RDF manifests named "contents.rdf" were used to register chrome. This format is deprecated; however, the Mozilla Suite (SeaMonkey) does not support the plaintext manifest format yet, so contents.rdf manifests are required for extensions that wish to maintain backwards compatibility with Firefox 1.0 or the suite.

+ +

Official References for Toolkit API

+ +

{{ page("zh-CN/docs/Toolkit_API/Official_References") }}

diff --git a/files/zh-cn/mozilla/command_line_options/index.html b/files/zh-cn/mozilla/command_line_options/index.html new file mode 100644 index 0000000000..347a35bdb1 --- /dev/null +++ b/files/zh-cn/mozilla/command_line_options/index.html @@ -0,0 +1,407 @@ +--- +title: 命令行选项 +slug: Mozilla/Command_Line_Options +translation_of: Mozilla/Command_Line_Options +--- +

命令行选项用于为 Mozilla 应用程序指定各种启动选项。例如,您可以使用命令行配置选项来绕过配置档管理器并打开一个特定的配置档(如果您有多个配置档)。您也可以控制 Mozilla 应用程序如何打开,初始打开哪个组件以及当组件打开时要做什么。这个页面描述常用的选项和如何使用它们。

+ +

语法规则

+ +

首先,让我们描述一下适用于所有选项的语法规则。

+ + + +

使用命令行选项

+ +

命令行选项在启动应用程序的命令后输入。某些选项选项有参数。它们在命令行选项后输入。某些选项有缩写替代。例如,命令行选项 "-editor" 可以缩写为 "-edit"。(其中可用的缩写将会在下面的文本中阐述) 在某些情况下,选项参数必须用引号括起。(这会在以下的选项描述中注明。) 可以指定多个命令行选项。通常,语法如下:

+ +
应用程序 -选项 -选项 "参数" -选项 参数
+
+ +

示例

+ +

下列示例显示 "-ProfileManager" 命令的使用,它将会在启动 Firefox 或 Thunderbird 前打开配置档管理器:

+ +
Windows
+ +

从 Windows 开始菜单中选择运行,输入:

+ +
firefox -ProfileManager
+
+ +
Mac OS X
+ +

转到 Applications > Utilities,打开终端并输入:

+ +
cd /Applications/Firefox.app/Contents/MacOS
+./firefox -ProfileManager
+
+ +
Linux
+ +

打开终端并输入:

+ +
cd Thunderbird 安装目录
+./thunderbird -ProfileManager
+
+ +

以上示例调用 "-ProfileManager" 命令行选项用于 Mozilla 的 Thunderbird 邮件客户端。

+ +

用户配置档

+ +

-CreateProfile profile_name

+ +

创建一个名为profile_name 的配置档,而不启动程序。profile_name 一定不能包含空格( )。

+ +
firefox -CreateProfile JoelUser
+
+ +

-CreateProfile "profile_name profile_dir"

+ +

在目录 profile_dir 中创建一个名为 profile_name 的配置档而不启动应用程序。注意 profile_nameprofile_dir 必须括在一起。(在 SeaMonkey1.x 中未有)

+ +

注: profile_dir 必须存在而且您必须还未有称为 profile_name 的配置档。

+ +
firefox -CreateProfile "JoelUser c:\internet\moz-profile"
+
+ +

-ProfileManager

+ +

使用配置档管理器启动。

+ +

-SelectProfile

+ +

使用配置档选择对话框启动。仅用于 SeaMonkey1.x

+ +

-ProfileWizard

+ +

使用配置档向导启动。仅用于 SeaMonkey1.x

+ +

-P "profile_name"

+ +

绕过配置档管理器并使用名为profile_name 的配置档启动。对于处理多个配置档很有用。注意profile_name 是区分大小写的。如果您未指定一个配置档名称,那么就会打开配置档管理器。在 L:inux 上,您必须使用大写字母 P,因为小写调用 Purify 模式(内存和泄露探测)。其它平台大小写都接受。

+ +
firefox -P "Joel User"
+
+ +

-profile "profile_path"

+ +

使用给出路径的配置档启动。仅用于 FirefoxThunderbirdSeaMonkey2.x

+ +

"profile_path" 可以是一个绝对路径("/path/to/profile") 或一个相对路径("path/to/profile").

+ +
在 Mac OS X 上,从 Firefox 4.0 和以上,由于 regression 的原因,不在支持给出相对路径,查看{{ bug(673955) }}.
+ +

-no-remote

+ +

允许同一事件打开多个应用程序副本。(在 SeaMonkey1.x 中无效,它仅支持 MOZ_NO_REMOTE=1)。

+ +
firefox -no-remote -P "另一个配置档"
+
+ +

-migration

+ +

使用导入向导启动。(SeaMonkey1.x 中无效)

+ +

-installer

+ +

使用 Netscape 4.x 迁移窗口启动。仅用于 SeaMonkey1.x

+ +

-resetPref preference

+ +

重置指定的首选项(逗号间隔)为默认值。仅用于 SeaMonkey1.x

+ +
seamonkey -resetPref browser.startup.homepage
+
+ +

-override /path/to/override.ini

+ +

加载指定的 override.ini 文件以覆盖 application.ini ({{ Source("browser/app/application.ini") }})中的配置。通过加载下列 override.ini 可以抑制在启动时的迁移向导。仅用于 Firefox

+ +
[XRE]
+EnableProfileMigrator=0
+
+ +

浏览器

+ +

-browser

+ +

使用 browser(浏览器)组件启动。仅用于 FirefoxSeaMonkey

+ +

-url URL

+ +

根据浏览器选项,在新标签页或窗口中打开 URL-url 可以省略。仅用于 FirefoxSeaMonkey。注: 当打开多个 URLs 时,Firefox 总是把它们打开为一个新窗口中的选项页。

+ +
firefox www.mozilla.com
+
+ +

-private

+ +

以私密浏览模式打开 Firefox,而不考虑当前的用户首选项。仅用于 Firefox 3.6 和以后版本。

+ +

-new-tab URL

+ +

在新标签页中打开 URL。仅用于 FirefoxSeaMonkey2.x

+ +

-new-window URL

+ +

在新窗口中打开 URL。仅用于 FirefoxSeaMonkey2.x

+ +

-search term

+ +

使用您的默认搜索引擎搜索 term。仅用于 FirefoxSeaMonkey2.x 及以后的版本。

+ +

-preferences

+ +

打开选项/首选项窗口。仅用于 FirefoxSeaMonkey2.x

+ +

-setDefaultBrowser

+ +

设置应用程序为默认的浏览器。仅用于 Firefox

+ +

邮件/新闻

+ +

-mail

+ +

使用邮件客户端启动。仅用于 ThunderbirdSeaMonkey

+ +

-mail mailto_URL

+ +

为给出的 mailto_URL 启动撰写消息的窗口。仅用于 Thunderbird

+ +
thunderbird -mail mailto:me@isp.net?subject=hi
+
+ +

-news news_URL

+ +

使用新客户端启动。如果给出了 news_URL (可选),则打开指定的新闻组。仅用于 ThunderbirdSeaMonkey

+ +
thunderbird -news news://server/group
+
+ +

-compose message_options

+ +

使用邮件撰写器启动。查看语法规则。仅用于 ThunderbirdSeaMonkey

+ +
thunderbird -compose "to=foo@nowhere.net"
+
+ +

-addressbook

+ +

使用地址簿启动。仅用于 ThunderbirdSeaMonkey

+ +

-options

+ +

打开选项/首选项窗口。仅用于 Thunderbird

+ +

-offline

+ +

以离线模式启动。仅用于 ThunderbirdSeaMonkey

+ +

-setDefaultMail

+ +

设置应用程序为默认的邮件客户端。仅用于 Thunderbird

+ +

日历

+ +

-calendar

+ +

使用日历客户端启动。仅用于 Sunbird

+ +

-subscribe URL-url URL

+ +

订阅到给出的 URL。仅用于 Sunbird

+ +

-showdate 日期

+ +

显示给出的日期的您的计划安排。仅用于 Sunbird

+ +
sunbird -showdate 08/04/2008
+
+ +

其它组件

+ +

-editor URL-edit URL

+ +

为给出的 URL 使用编辑器(撰写器)启动(其中 URL 是可选的)。仅用于 SeaMonkey

+ +
seamonkey -edit www.mozilla.org
+
+ +

-jsconsole

+ +

使用错误控制台启动应用程序.

+ +

-inspector URL

+ +

使用 DOM Inspector 启动(如果已安装的话),并观察给出的 URL (其中 URL 是可选的)。

+ +

-venkman

+ +

使用 JavaScript 调试器 Venkman 启动(如果已安装的话)。

+ +

-chat

+ +

使用 IRC 客户端 ChatZilla 启动(如果已安装的话)。

+ +

XULRunner

+ +

-app /path/to/application.ini

+ +

启动一个新进程运行在指定路径 path/to 处的 XULRunner 应用程序。仅用于 Firefox 版本 3 和以上。

+ +

Chrome

+ +

-chrome chrome_URL

+ +

加载指定的 chrome。

+ +
firefox -chrome chrome://inspector/content
+
+ +

-register chrome_URL

+ +

注册指定的 chrome,而不启动应用程序。

+ +

扩展附件

+ +

{{ gecko_minversion_note("1.9.2", "-install-global-extension 和 -install-global-theme 已经从 Gecko 1.9.2 和以上的版本移除。") }}

+ +

-install-global-extension /path/to/extension

+ +

安装扩展到应用程序目录。参数是扩展的路径。您必须有管理权限。(在 SeaMonkey1.x 中无效,但是某些扩展已经把这个作为一个安装时的选项)。

+ +

-install-global-theme /path/to/theme

+ +

和上面类似,但是只用于主题。您必须有管理权限。(在 SeaMonkey1.x 中无效,但是某些扩展已经把这个作为一个安装时的选项)。

+ +
+

从 Firefox 2.0.0.7 开始,-install-global-extension-install-global-theme 命令行参数选项的使用被限制为只允许安装在本地磁盘或映射的驱动器上的附加组件。从网络共享直接安装将不再成功。

+
+ +

-safe-mode

+ +

禁用所有的扩展启动应用程序,仅用于启动。(扩展不会加载,但是不会在扩展管理器数据源中永久禁用)。(在 SeaMonkey1.x 中无效)

+ +

语种

+ +

-UILocale locale

+ +

locale 资源作为用户界面的语种。

+ +
firefox -UILocale en-US
+
+ +

启动

+ +

-turbo

+ +

Launch application in Quick Launch mode. SeaMonkey1.x only.

+ +

-nosplash or -quiet

+ +

Suppresses display of the splash screen. To show splash screen, use the -splash command. Note the splash screen is disabled by default on some systems. SeaMonkey1.x only.

+ +

远程控制

+ +

-remote 远程命令

+ +

在一个已经运行的应用程序进程中执行远程命令(查看远程控制)。注: Unix/Linux 仅适用于 SeaMonkey1.x

+ +
firefox -remote "openURL(www.mozilla.org, new-tab)"
+
+ +

其它

+ +

-silent

+ +

不打开默认窗口。对于那些打开它们自己窗口但是未防止默认窗口打开的那些命令行参数很有用。仅适用于 FirefoxThunderbird3.xSeaMonkey2.x

+ +

-console

+ +

使用一个调试控制台启动应用程序。注:仅适用于 Windows。

+ +

-h-help-?

+ +

显示所有可用的命令行参数的列表。注意,在 Windows 上仅对调试构建版本({{ Bug(355889) }})有效。这个选项仅在命令行控制台中可用。

+ +

-v-version

+ +

打印应用程序版本。注意,在 Windows 上仅对调试构建版本({{ Bug(355889) }})有效。

+ +

-osint

+ +

告诉应用程序它是被 OS SHell 启动的。这个不应该指定,除非调用者在启动应用程序时,提供了 OS  Shell 的所有功能。({{ Bug(384384) }}).

+ +

-requestPending

+ +

Tells the application that there will be a Windows DDE request to open the same url specified on the command line. This should not be specified unless the caller provides all of the functionality provided by the OS shell when launching the application ({{ Bug(354005) }}).

+ +

X11 options

+ +

These options are only available for an application build for and running atop the X11/X.org display and window system to be found on Linux and other Unices.

+ +
--display=DISPLAY
+ +

设置要使用的 X display

+ +
--sync
+ +

使 X 调用同步

+ +
--g-fatal-warnings
+ +

使所有警告视为严重

+ +

其它需要编写文档的选项

+ + + +

参考

+ + + +
+

原始文档信息

+ + +
+ +

{{ languages( { "ja": "ja/Command_Line_Options" } ) }}

diff --git a/files/zh-cn/mozilla/connect/index.html b/files/zh-cn/mozilla/connect/index.html new file mode 100644 index 0000000000..7e75bb5c62 --- /dev/null +++ b/files/zh-cn/mozilla/connect/index.html @@ -0,0 +1,122 @@ +--- +title: Mozilla 开发者计划 +slug: Mozilla/Connect +translation_of: Mozilla/Connect +--- +
+

采取行动、互相激励并共同协作,使网络成为创建跨联网设备体验的主要平台。

+
+ +
+
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+

联系Mozilla

+ +

开发商为全世界的人们创造未来的建筑服务和应用程序。Mozilla开发者关系的目标是帮助开发人员使用开放标准的Web技术,成功实现自己的目标。除了文件在MDN,我们提供的帮助和其他资源来实现这一目标,通过各种渠道。我们邀请您来连接、学习和分享自己的知识。

+ +

我们提供的帮助下通过Stack Overflow的Q&A解决你可能有的特定技术问题和挑战。我们也有一个简讯让您了解在Web场景周围的Web应用程序的最新动态和更多资讯。订阅 Apps & Hacks newsletter

+ +

If you share Mozilla's mission and principles and want to help spread them to more developers, check out the ways you can get involved with technical evangelism, and join our evangelism discussion group.

+ +

我们有很多计划和点子去反复扩展我们的开发者关系,我们希望你也参与我们!因此,在Stack Overflow上关注这个标签订阅这个Hacks博客,和订阅邮件

+ +

Join Mozilla

+ +

If you want to go beyond connecting with Mozilla, you can join Mozilla and help realize Mozilla's mission of building a better Internet. As a developer, you have skills to contribute in many areas, as well as the opportunity to enhance your skills. Mozilla is an open source project, so we "default to open." You can "view source" and contribute to our software development projects, like the Firefox browser for desktop and Android, Firefox OS, and Mozilla's websites. You can become part of an international community and get recognition for your efforts. Here are some of the advantages of contributing to the Mozilla project.

+ +

Opportunity to learn something new

+ +
+

In writing code for an open source project, you may face problems you have not encountered before, which present learning opportunities for you. You can try out new tools and techniques in an open source project. If for example, if you have never done unit testing, and cannot get permission to do so at work then coding for an open source project would be an excellent place to learn more about it. Contributing to open source gives you the opportunity to collaborate with and get to know many people around the world who have similar interests. Moreover, an open source organization like Mozilla has many contributors who can help you in solving problems you encounter. If you're just getting started contributing, you can look for "mentored" bugs, where an experienced contributor has offered to help a newcomer fix them.

+ +

What can I get by contributing?

+ +

Exploring many things and gaining recognition in the community -- these are the intangible benefits of contributing to Mozilla. While we can't guarantee specific tangible benefits, many valued contributors receive free Mozilla gear and invitations to Mozilla-related events, and are first in line to be considered for internships. Moreover, your experience in contributing to an open source project might help you find a job. More and more employers of developers are looking at open source contributions. They like to see that you're blogging and contributing to mailing lists, and they like to see you listed as a contributor to an open source project. It may also help with the work experience section of your CV/resumé.

+ +

How you can contribute to Mozilla

+ +

There are many project area for which you can contribute to Mozilla. You can find a current, complete list on the main Mozilla Get Involved page. Some areas that may interest you as a developer include:

+ + +
+
+
+ +
+
+

Stack Overflow 上的常见问题解答 查看所有问与答...

+ +

在开发时我们有问与答去讨论挑战和问题,特别是Firefox OS和移动开放的互联网。在堆栈溢出上可用的简单URL http://stackoverflow.com/r/mozilla.

+ +
+ +

最新常见问题解答主题

+
+ +
 
+
+ +

Developers at a Firefox OS workshop in Madrid.

+ +
+ + + +
diff --git a/files/zh-cn/mozilla/debugging/existing_tools/index.html b/files/zh-cn/mozilla/debugging/existing_tools/index.html new file mode 100644 index 0000000000..055f003c2b --- /dev/null +++ b/files/zh-cn/mozilla/debugging/existing_tools/index.html @@ -0,0 +1,36 @@ +--- +title: Existing Tools +slug: Mozilla/Debugging/Existing_Tools +translation_of: Mozilla/Debugging/Existing_Tools +--- +

下面列出的工具可以帮助你调试Firefox中因性能和内存引发的问题

+

SPS - Built-in profiler

+

profiler.png描述: Add-on that runs the built-in profiler, retrieves the data and parses it on a web service, displaying a call tree and a timeline with responsiveness measurements.
用处: Figuring out where time is being spent in the code / what is hanging Firefox
URL: geckoprofiler.xpi on GitHub
用法: After installing the add-on, click on the icon in the Add-ons bar (status bar) to open an widget with Start/Stop and Analyze buttons. More details at Profiling with the built-in profiler. The profiling build can be used to get accurate call stacks (currently Mac only).

+

 

+

about:jank

+

aboutjank.PNG描述: 运行内置的分析器并将检索到的数据显示在about:jank页面.
用处: 找出哪些代码在消耗时间,哪些代码让Firefox运行受阻.
URL: about:jank AMO下载
用法: 首次打开about:jank页面激活分析器,然后刷新页面查看分析的数据.

+

 

+

 

+

 

+

about:telemetry

+

aboutelemetry.png描述: 显示当前配置文件性能数据:直方图,缓慢的SQL语句和启动时间线.
用处: 获取当前配置文件性能数据.
URL: about:telemetry  AMO下载
用法: 确保选项"提交性能数据"已经开启 (选项 -> 高级 ->提交性能数据)然后打开about:telemetry.

+

 

+

 

+

about:startup

+

aboutstartup.PNG描述: 在about:startup页面显示Firefox的启动计时.
用处: 获取当前配置文件的启动性能信息.
URL: about:startup AMO下载
用法: 安装扩展后打开about:startup.

+

 

+

 

+

about:cc

+

aboutcc.PNG描述: Analyzes the cycle collection graphs and helps find leaks (specially documents) and missing CC optimizations.
用处: 找出内存泄漏的页面.
URL: about:cc bugzilla下载
用法: 安装该扩展,重启, 打开about:cc.首先点击Run Cycle Collector,然后点击 Find Documents.

about:ccdump

+

aboutccdump.png描述: More graphical interface to about:cc. Helps analyze cycle collection graphs and finding leaks
用处: 找出引起内存泄漏的死循环.
URL: about:ccdump  AMO下载
用法: 查看 Jan Odvarko's post 了解更多信息.

+

 

+

about:nosy

+

about-nosy-overview-scaled.png描述: 图形界面的jsprobes,帮助分析哪个标签最消耗资源.
用处: 查看各标签和扩展的内存以及cpu使用情况.
URL: about:nosy Github下载
用法: 查看 Andrew Sutherland's post获得更多详情. 注意: https://clicky.visophyte.org/files/labs/about-nosy/ 上已有的版本只适合Firefox "Aurora" 12的早期版本使用.

MemChaser

+

memchaser.png描述: 在附加组件栏(状态栏)显示GC/CC和内存使用等信息. 还可以切换内存报告记录.
用处: 在一个标准的浏览会话里跟踪记录垃圾回收和内存占用等信息
URL: MemChaser AMO下载
用法: 安装扩展并打开附加组建栏

+

MozRegression

+

描述: Python script that greatly helps you binary-search a regression bug through the nightly builds by automatically downloading and running each build with a fresh profile.
用处: Finding the nightly regression range for a bug that you're not sure when was introduced.
URL: MozRegression on GitHub
用法: First find a nightly build date that you're sure the problem exists, and one where you're sure it doesn't. Then run mozregression --good=yyyy-mm-dd --bad=yyyy-mm-dd and the script will guide you on finding the regression.

+

 

+

Layout painting flash

+

描述: 打开该选项后, Firefox中每次被重绘的元素都会以随机的背景颜色显示出来.
用处: 查找不必要的页面重绘失效问题
URL: 在about:config中将nglayout.debug.paint_flashing 设置为true
用法: 在about:config页面中配置, 更多信息请参考 这篇文章.

Logging GC/CC times

+

描述: 在错误控制台上显示GC/CC运行的时间.
用处: 查看垃圾回收/循环回收是否运行太长时间.
URL: 在about:config中将javascript.options.mem.log 设置为true
用法: 在about:config页面中配置, 打开错误控制台查看记录的信息.

+

{{ languages( { "en": "en/Debugging/Existing_Tools"} ) }}

diff --git a/files/zh-cn/mozilla/debugging/index.html b/files/zh-cn/mozilla/debugging/index.html new file mode 100644 index 0000000000..d3c90b5685 --- /dev/null +++ b/files/zh-cn/mozilla/debugging/index.html @@ -0,0 +1,139 @@ +--- +title: 调试 +slug: Mozilla/Debugging +translation_of: Mozilla/Debugging +--- +

Debugging a project as large as Mozilla can be a daunting task. Fortunately, over the years, Mozilla developers have come up with not just technologies and features to help you debug code, but have devised tips and techniques that can help too. Also available are assorted tools that you can use when debugging.

+ + + + + + + +
+

Documentation topics

+

Debugging on top of the Mozilla platform

+
+
+ Debugging JavaScript code
+
+ How to debug JavaScript code, with a focus on debugging code in the Mozilla project itself.
+
+ Debugging a XULRunner application
+
+ Tips and suggestions that will help you debug your XULRunner based application.
+
+ Debugging on Boot to Gecko
+
+ Debugging Firefox OS (apps and the platform itself)
+
+ Debugging update problems
+
+ Learn how to debug update problems in Mozilla-based applications.
+
+

Debugging the Mozilla platform

+

Using debuggers with Mozilla

+
+
+ Debugging Mozilla on Windows FAQ
+
+ Questions (and answers) about debugging Mozilla on Windows.
+
+ Debugging Mozilla on Mac OS X
+
+ Questions (and answers) about debugging Mozilla on Mac OS X.
+
+ Debugging Mozilla with gdb
+
+ gdb is our primary debugger on Mac and Linux.
+
+ Debugging Mozilla with lldb
+
+ lldb is the new debugger on Mac.
+
+

Advanced debugging techniques

+
+
+ Debugging Mozilla with valgrind
+
+ valgrind is a memory debugger for Mac and Linux. It is slow, but good for tracking down difficult memory safety bugs.
+
+ Replay debugging Firefox with VMWare Workstation
+
+ How to setup record and replay debugging on Firefox, to help debug intermittent mochitest failures.
+
+

Debugging specific parts of the Mozilla codebase

+
+
+ Debugging OpenGL {{gecko_minversion_inline("2.0")}}
+
+ If you're working on code that involves OpenGL calls, and need to debug it, you can turn on a special OpenGL debugging mode.
+
+ Debugging frame reflow and Debugging table reflow
+
+ Notes on debugging issues in Gecko's layout engine.
+
+

Miscellaneous

+
+
+ Debugging Safari
+
+ Some tips for debugging Safari
+
+ Debugging Chrome
+
+ Some tips for debugging Chrome
+
+ Debugging Internet Explorer
+
+ Some tips for debugging Internet Explorer
+
+
+

Providing useful information to the Mozilla developers

+
+
+ How to get a stacktrace for a bug report
+
+ Useful information you can provide about a crash.
+
+ Reporting a Performance Problem
+
+ ...using the Gecko Profiler extension.
+
+ Debugging a hang on Mac OS X
+
+ Collecting "samples" to attach to a bug.
+
+ Remote debugging
+
+ Core dumps and examples of remote debugging. Useful if a developer can't reproduce your crash.
+
+ HTTP logging
+
+ How to log HTTP network traffic for debugging purposes.
+
+

Debugging tools

+
+
+ Tools
+
+ Assorted tools that will help you debug your code or web site.
+
+ Download a debug build
+
+ Recent automatically compiled debug builds are available. Note that these are replaced frequently by our tinderboxes. The debug builds have "-debug" at the end of their file names.
+
+ +
+
+ Performance and profiling
+
+ Troubleshooting performance problems.
+
+ Debugging memory leaks
+
+ Learn about tools and techniques that will help you debug memory leaks.
+
+
+

 

diff --git a/files/zh-cn/mozilla/developer_guide/adding_apis_to_the_navigator_object/index.html b/files/zh-cn/mozilla/developer_guide/adding_apis_to_the_navigator_object/index.html new file mode 100644 index 0000000000..8be46c6439 --- /dev/null +++ b/files/zh-cn/mozilla/developer_guide/adding_apis_to_the_navigator_object/index.html @@ -0,0 +1,34 @@ +--- +title: Adding APIs to the navigator object +slug: Mozilla/Developer_guide/Adding_APIs_to_the_navigator_object +tags: + - chenxk@xi'an +translation_of: Mozilla/Developer_guide/Adding_APIs_to_the_navigator_object +--- +

{{ gecko_minversion_header("9.0") }}

+

Gecko 9.0之后 {{ geckoRelease("9.0") }}, 我们可以很容易的利用Category Manager添加新的APIs 到 {{ domxref("window.navigator") }} 对象。简单地添加一个到 "JavaScript-navigator-property" category 的入口。

+

在程序中添加对象到navigator

+
var categoryManager = Components.classes["@mozilla.org/categorymanager;1"]
+                      .getService(nsICategoryManager);
+
+categoryManager.addCategoryEntry("JavaScript-navigator-property", "myApi",
+                      MY_CONTRACT_ID, false, true);
+
+

这两句添加了一个新的对象, myApi, 到 {{ domxref("window.navigator") }} 对象; 这个新添加的对象是基于由contract ID MY_CONTRACT_ID 所制定的组件的。

+

使用 manifest 文件添加对象到 navigator

+

我们也可以使用chrome manifest 文件添加对象到{{ domxref("window.navigator") }} :

+
component {ffffffff-ffff-ffff-ffff-ffffffffffff} MyComponent.js
+contract @mozilla.org/mycomponent;1 {ffffffff-ffff-ffff-ffff-ffffffffffff}
+category JavaScript-navigator-property myComponent @mozilla.org/mycomponent;1
+
+

这样就添加了一个新的 API, myComponent, 到navigator 对象, 然后就可以通过 navigator.myComponent访问到。

+

实例

+

通过下面两个文件你可以明白接口 mozApps 的实现:

+ +

See also

+ diff --git a/files/zh-cn/mozilla/developer_guide/customizing_firefox/index.html b/files/zh-cn/mozilla/developer_guide/customizing_firefox/index.html new file mode 100644 index 0000000000..b19c860926 --- /dev/null +++ b/files/zh-cn/mozilla/developer_guide/customizing_firefox/index.html @@ -0,0 +1,9 @@ +--- +title: 自定义 Firefox +slug: Mozilla/Developer_guide/Customizing_Firefox +tags: + - Firefox + - Mozilla +translation_of: Mozilla/Developer_guide/Customizing_Firefox +--- +

Firefox 企业版文档 | Firefox 帮助

diff --git a/files/zh-cn/mozilla/developer_guide/index.html b/files/zh-cn/mozilla/developer_guide/index.html new file mode 100644 index 0000000000..4a4f0edd52 --- /dev/null +++ b/files/zh-cn/mozilla/developer_guide/index.html @@ -0,0 +1,106 @@ +--- +title: 开发者手册 +slug: Mozilla/Developer_guide +translation_of: Mozilla/Developer_guide +--- +

有许多方法可以为 Mozilla 项目做出贡献:编码,测试,改进构建过程和工具或为文档做出贡献。 本指南提供的信息不仅可以帮助您以 Mozilla 贡献者的身份入门,而即使您已经是经验丰富的贡献者,本指南也会对您有所帮助。

+ +
+
+

文档主题

+ +
+
入门
+
一步一步引领初学者参与为Mozilla贡献的入门指南。
+
对于新的 Mozilla 开发人员
+
一个对Mozilla新的开发人员的特别有用的文章目录。
+
+ +
+
与 Mozilla 源代码一起工作
+
一个代码概况、如何获取代码和编码风格的指南。
+
编译指南
+
如何编译Firefox、Thunderbird、SeaMonkey或者其他 Mozilla 应用。
+
编辑器配置
+
设置您喜欢的IDE或文本编辑器以此来与Mozilla项目一起工作的提示。
+
开发过程概要
+
Mozilla开发过程的概要。
+
管理多个配置文件
+
作业于 Firefox 先行释出的版本时,通常有数个Firefox文件是有帮助的,例如每个通道配置一个文件,或者针对不同的测试有不同的文件。
+
自动测试
+
如何运行Mozilla的自动测试及如何写新的测试。
+
添加你的patch到树中
+
当你的patch完成后,你需要把它添加到树中。这篇文章解释了review过程和如何使你的patch得到支持。
+
Mozilla模块及模块所有权
+
这篇文章提供关于Mozilla的模块、模块所有者的角色是什么及模块所有者是怎么选择的。
+
探秘Firefox用户接口
+
如何加入到Firefox用户接口及前端软件的开发。
+
代码片段
+
与你需要理解如何工作的许多事物相关的有用的代码示例。
+
Mozilla开发策略
+
关于如何充分利用你的时间参与到Mozilla项目中的提示。
+
调试
+
寻找关于调试Mozilla代码的有帮助的提示和指南。
+
性能
+
性能指南和实用程序可帮助您使代码性能良好(并与他人很好地交流)。
+
Mozilla平台
+
关于 Mozilla 平台成果的信息。
+
Mozilla
+
有关Mozilla编码实践的更多其他信息。
+
将API添加到navigator对象 {{ gecko_minversion_inline("9.0") }}
+
如何和扩展API扩大{{ domxref("window.navigator") }}对象。
+
接口兼容性
+
关于修改Mozilla中脚本的和二进制的应用程序接口的准则。
+
+ +
+
自定义Firefox
+
有关创建Firefox的自定义版本的信息。
+
Task-Graph生成
+
是什么控制在推送到版本控制上运行的工作?你能怎么改变呢?
+
虚拟ARM Linux环境
+
如何设置运行Linux的ARM仿真器以测试特定于ARM的(但不一定特定于平台的)代码。对移动开发人员特别有用
+
过时的构建警告和技巧
+
一个放置构建提示的地方,该构建提示不再与从main构建最新版本的代码相关,而在构建旧代码库时相关。
+
Firefox源文档
+
由mozilla-central源代码构建的Web托管文档。
+
+
+ +
+

工具

+ +
+
Bugzilla
+
Bugzilla数据库用来跟踪Mozilla项目的相关事件。
+
DXR
+
下一代搜索Mozilla的源代码。在积极开发中。
+
SearchFox
+
Mozilla代码搜索的另一种选择。索引JS以及C ++都包含blame功能。在积极开发中。
+
Mercurial
+
用于管理Mozilla的源代码的分布式版本控制系统。
+
Mozilla构建VM
+
与VirtualBox兼容的虚拟机,配置了在Firefox上构建和工作所需的所有软件。
+
Bonsai
+
Bonsai工具帮助你找到谁在何时对代码库进行了什么修改。
+
TaskCluster
+
TaskCluster是支持Mozilla持续集成和发布过程的任务执行框架。
+
Treeherder
+
Treeherder显示树的状态(无论当前是否成功构建)。在签入和签出之前检查此项,以确保您使用的是工作树。
+
Perfherder
+
Perfherder用于汇总针对树的自动性能测试的结果。
+
崩溃跟踪
+
Information about the Socorro 崩溃报告系统。
+
Callgraph
+
通过自动生成调用图来帮助执行Mozilla代码的静态分析的工具。
+
开发者论坛
+
一个有针对性主题的论坛。在这里你可以讨论开发的各种事件。
+
Mozilla平台开发备忘单 (archive.org)
+
Brian Bondy的平台开发人员常用信息列表。 Brian Bondy 记下了 codefirefox.com,但存档的备忘单可能仍然有用。
+
Firefox开发视频教程
+
Brian Bondy的有关Firefox开发的视频教程。
+
+
+
+ +

{{ languages( { "en": "En/Developer_Guide", "ja": "ja/Developer_Guide" } ) }}

diff --git a/files/zh-cn/mozilla/developer_guide/source_code/cvs/index.html b/files/zh-cn/mozilla/developer_guide/source_code/cvs/index.html new file mode 100644 index 0000000000..30cd759598 --- /dev/null +++ b/files/zh-cn/mozilla/developer_guide/source_code/cvs/index.html @@ -0,0 +1,192 @@ +--- +title: 通过CVS获取源码 +slug: Mozilla/Developer_guide/Source_Code/CVS +tags: + - Build documentation + - 所有分类 +translation_of: Mozilla/Developer_guide/Source_Code/CVS +--- + + + + + + +

 

+ +

那些活跃的开发者可以使用CVS来查看最新的源代码。如果你计划提供补丁和修复bug这是你的首选,因为它可以让你得到最新的更新并且作为你自己的。

+ +

如果你想编译发布一款产品,一般最好下载Mozilla源代码

+ +

开始

+ +
CVS"并发版本控制系统"。要想了解更多关于 CVS  通用性欢迎访问 ximbiot.com阅读教程
+ +

 

+ +

任何人都可以通过 CVS的源代码来Check out (也被称为"拉取"或"下载") ,但只有某些人可信任的人能Check in (进行更改,也被称为"提交")。这些人是模块所有者和他们的代表。阅读我们 hacking mozilla  的文档了解如何获得录入信任。同时你也不妨阅读有关使用 SSH 连接到 CVS

+ +
+
+
+
尽管完整的 CVS Checkout可行但并不推荐; mozilla cvs 服务器不应有压力应完全避免除非知道正在做什么和你真正需要
+
+
+
+ +

 

+ +

要求

+ +

要Check out源代码,您需要运行 CVS 1.11 或更高版本。1.12.13版本无法和CVS 服务器一起使用,反而导致挂起,虽然 1.12.9 已知工作正常。此外,您必须使用 GNU make 来Check out和建立 Mozilla。没有其他"make"是程序可以接受的。在 windows、 mac 和周期性的 GNU 系统 (如 GNU/Linux),使用"make"来运行 GNU make;对大多数非 GNU unix (像例如 Solaris, etc.),使用"gmake"。

+ +

CVS 客户端设置

+ +

"Cvsroot"(存储库标识字符串) 用于匿名访问 Mozilla CVS

+ +
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
+
+ +
+
+
开始使用 CVS 前首先要登录运行以下命令:
+
+
+ +
$ cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot login
+# type the password anonymous
+
+ +

如果使用 IDE使用以下服务器数据:

+ + + +

选择一个项目进行拉取

+ +

由于多种不同的应用都基于相同的源代码,您必须通过 MOZ_CO_PROJECT 变量选择对何种应用进行 checkout。当 checkout 真正的源代码时,这一信息(MOZ_CO_PROJECT)是必需的(详见下面对应于您想要checkout的分支的 checkout 部分)。允许的(MOZ_CO_PROJECT)选项有:

+ +
+
browser 
+
独立的 "Firefox" 浏览器。
+
mail 
+
独立的 "Thunderbird" 邮件/新闻客户端。
+
suite 
+
传统的 "Mozilla" SeaMonkey 套件,包括 browser, mail/news, composer 和其他应用。
+
minimo 
+
独立的针对小型设备的浏览器。
+
composer 
+
独立的 HTML 编辑器。
+
calendar 
+
独立的 "Sunbird" 日历应用。
+
xulrunner 
+
下一代的XUL应用启动器。
+
macbrowser 
+
针对 Macintosh 的 "Camino" 本地浏览器。
+
all 
+
Check out 以上所有的项目,以及一些附加组件的代码。
+
+ +

选择多项项目可以用逗号分隔:MOZ_CO_PROJECT=suite,browser,xulrunner.

+ +

注意如果您正在使用一个用户自定义的 .mozconfig 文件,您也可以在这一文件中注明 MOZ_CO_PROJECT 设置,而无需在命令行中添加 MOZ_CO_PROJECT。

+ +

Checking Out 一个新的源代码树

+ +

检查 Tinderbox

+ +

在拉取一个代码树之前,您应该检查相应的Tinderbox来确保代码库的完整性。如果存在红色的tinderboxes,我们总是建议您在等到它们变为绿色后,再进行拉取。

+ +

HEAD 分支

+ +

为了从头开始 check out 一个新的源代码树,需要首先拿到 client.mk 文件。这个文件含有使用 makefile 对剩余的源代码树进行拉取的说明

+ +
$ cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co mozilla/client.mk
+ +

注意:如果您已经设置了一个 .mozconfig 文件,您仍将需要 check out 以下文件:

+ +
+
Firefox 
+
+
cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co mozilla/browser/config/mozconfig
+
+
Thunderbird 
+
+
cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co mozilla/mail/config/mozconfig
+
+
+ +

特定分支

+ +

如果您想要 check out 一个特定 CVS 分支的源代码,使用

+ +
$ cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -r BRANCH mozilla/client.mk
+ +

例如,在拉取 Firefox 1.5 development 分支时,需要用 MOZILLA_1_8_BRANCH 替换上面的 BRANCH。在 CVS Tags 中可以查看 Mozilla 中可用的分支标签。

+ +

当然前面提供的拉取特定项目的 .mozconfig 文件的方法对除 HEAD 外的分支同样适用。

+ +

Checkout

+ +

在选定正确的分支后,运行:

+ +
$ cd mozilla
+$ make -f client.mk checkout MOZ_CO_PROJECT=option,option
+ +

上面已经提到,如果您正在适用已经注明了 MOZ_CO_PROJECT 变量的 .mozconfig 文件,无需在命令行中重复注明。

+ +

特定时刻

+ +

如果您想要 check out 源代码在某一特定时刻的状态,您可以使用 MOZ_CO_DATE 变量。例如 MOZ_CO_DATE="20 Oct 2006 17:00 PDT"。

+ +

这一说明可以加入 .mozconfig 文件中,或者可以在命令行注明,例如

+ +
$ cd mozilla
+$ make -f client.mk checkout MOZ_CO_DATE="20 Oct 2006 17:00 PDT" MOZ_CO_PROJECT=option,option
+ +

将源代码树变更至另一个分支

+ +

HEAD 分支

+ +

更新一个源代码树(无论是 HEAD 分支还是一个特定的分支)至最新的 HEAD 分支,运行:

+ +
$ cd mozilla
+$ cvs up -A client.mk
+ +

-A 选择项会删除任何“黏性分支” ("sticky branch")信息,从而达到更新至 HEAD 分支的效果。

+ +

特定分支

+ +

更新一个从某一特定分支拉取来的源代码树,首先使用

+ +
$ cd mozilla
+$ cvs up -r BRANCH client.mk
+ +

将 BRANCH 替换为您想要更新的分支的标签。

+ +

更新一个源代码树

+ +

只需使用以下方法即可更新您的代码树:

+ +
$ make -f client.mk checkout MOZ_CO_PROJECT=option,option
+ +

同样地,如果您使用了 MOZ_CO_PROJECT 已被定义的用户自定义 .mozconfig 文件,无需在命令行中重复注明。

+ +

创建一个 Diff 文件

+ +

为一个与当前知识库(repository)中相应文件不同的单一本地文件创建 diff,使用:

+ +
$ cvs diff -u8p FILENAME
+ +

更多信息可以查看 Creating a patch

+ +

转换一个已下载的源代码树

+ +

与普通的 checkout 相同,从 mozilla.org (source tarballs) 下载的源代码树已经被设置了 CVS 信息。您可以像普通的源代码树一样更新这些树至最新代码,无需多余操作。有关如何更新源代码树的内容请查看前述章节。

diff --git a/files/zh-cn/mozilla/developer_guide/source_code/index.html b/files/zh-cn/mozilla/developer_guide/source_code/index.html new file mode 100644 index 0000000000..7e23f93adf --- /dev/null +++ b/files/zh-cn/mozilla/developer_guide/source_code/index.html @@ -0,0 +1,48 @@ +--- +title: 与Mozilla源代码一起工作 +slug: Mozilla/Developer_guide/Source_Code +translation_of: Mozilla/Developer_guide/Source_Code +--- +

本文将会帮助你找到Mozilla源代码、学会浏览代码及如何把你建议的改变放到代码树中。

+ +

 

+ + + + + + + + + + + +
+

文档话题

+
+
+
从Mercurial存储库获取代码
+
如果您打算为Mozilla项目做出贡献,获取代码的最佳方式是从版本控制存储库中检查出来。 在这里学习如何做到这一点。
+
使用HTTP或FTP下载代码
+
如果您想获取特定Mozilla产品特定版本的代码,您可能更愿意下载源代码档案。
+
在线查看和搜索Mozilla源代码
+
了解如何使用MXR,Mozilla的在线搜索和浏览工具来访问源代码。 这不是下载代码的好方法,但它是搜索它的好方法。
+
浏览Mozilla源代码
+
了解Mozilla源代码树中的各种文件夹,以及如何找到您要找的内容。
+
Good First Bugs
+
如果你对这个项目不熟悉,并且想要一些工作,请看这里。
+
+
+
+
Mozilla编码风格指南
+
代码风格指南提供了有关如何格式化源代码的信息,以确保您不会被审阅者嘲笑。
+
Try Servers
+
Mozilla产品至少建立在三个平台上。 如果您没有全部访问权限,则可以使用服务器来测试您的修补程序并确保测试通过。
+
创建一个补丁
+
一旦你修改了Mozilla代码,下一步(在确定它能运行之后)就创建一个补丁并提交它进行审查。 这篇文章需要完全更新为Mercurial。
+
获取对源代码的提交访问权限
+
感觉准备加入少数,骄傲的提议者? 了解如何获取Mozilla代码的签入访问权限。
+
从CVS获取较旧的Mozilla代码
+
较旧版本的Mozilla源代码以及当前版本的NSS和NSPR都保存在CVS存储库中。 在本文中了解这一点。
+
+
diff --git a/files/zh-cn/mozilla/developer_guide/source_code/latestpassingsource/index.html b/files/zh-cn/mozilla/developer_guide/source_code/latestpassingsource/index.html new file mode 100644 index 0000000000..a425401edd --- /dev/null +++ b/files/zh-cn/mozilla/developer_guide/source_code/latestpassingsource/index.html @@ -0,0 +1,22 @@ +--- +title: Latest Source Passing Tests +slug: Mozilla/Developer_guide/Source_Code/LatestPassingSource +translation_of: Mozilla/Developer_guide/Source_Code/LatestPassingSource +--- +

This is a supplement to the  general instructions for obtaining Mozilla source code.

+

You can look at tinderboxpushlog to see how green the tree is, though often there are known random failures in play so it can be tricky to identify exactly how good the build is. But in general if it isn't burning it should be mostly usable.

+

On the left hand, you see pushlogs, which means one or more changeset(s) pushed at once.  On the right, you see the results of the tinderbox machines associated with that pushlog.  Each letter shows a machine status type.  Here's a short glossary (tooltips available on hovering the letters):
+
+ B - Build
+ M - Mochitest
+ R - Reftest
+ J - JSReftest
+ T - Talos (performance tests)
+ S - Static analysis tests
+
+ For each pushlog, you can check whether all of the letters associated with it on all platforms are green or not.  Having them all green is a sign of a healthy changeset to pull.  Some failures might be intermittent (or due to machine issues, etc), which are (hopefully) starred.

+

You should note that once you find a healthy pushlog changeset ID, you need to pull its topmost changeset.

+

In case you only care about one platform: "WINNT 5.1" means Windows XP, "WINNT 5.2" means Windows Server 2003, and "WINNT 6.1" means Windows 7. The Mac OS X 10.5 machines test 32-bit; the 10.6 machines test 64-bit.

+

If for example you see that revision 531f60d6cf88 is good enough, you should do the following locally and start a build:

+
hg pull
+hg up 531f60d6cf88
diff --git a/files/zh-cn/mozilla/firefox/australis_add-on_compat/index.html b/files/zh-cn/mozilla/firefox/australis_add-on_compat/index.html new file mode 100644 index 0000000000..0f0031c0f1 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/australis_add-on_compat/index.html @@ -0,0 +1,130 @@ +--- +title: Australis and add-on compatibility +slug: Mozilla/Firefox/Australis_add-on_compat +tags: + - 扩展 +translation_of: Mozilla/Firefox/Australis_add-on_compat +--- +
{{FirefoxSidebar}}
+ +

扩展程序的改变

+ +

我们已经移除了扩展程序的工具栏(包括状态栏)。您不应再依赖它的存在。已有一个填隙片会尝试迁移您的图标,但它可能不起作用或只能部分起作用。 最好的解决方案是更改按钮的位置。 这也许是一个很好的时机去考虑您的扩展程序是否真的需要在默认情况下对所有用户可见的工具栏按钮。使用扩展程序SDK开发的扩展程序不需要注意这次改变。

+ +

我们已经移除了应用(Firefox)菜单。 取而代之的是一个新的基于面板的菜单,可以用导航栏远端的一个按钮打开它。可以将工具栏项目拖进/拖出这个面板。

+ +

一些默认的工具栏按钮ID已更改,我们添加了一些新的ID,并且后退/前进按钮,URL栏,停止/重新加载按钮的顺序将不再可自定义。这也意味着用户不能用常规的自定义流程在这些按钮中添加新的(扩展程序提供的)按钮。

+ +

独立的暂停刷新按钮已被移除

+ +

我们正在更改工具栏按钮的添加方式。 虽然我们尝试保持某种向后兼容性,但是以下的 the following are deprecated and will be removed in the near future: the toolbar.insertItem 方法, toolbar.currentSet 属性, and the currentset 属性 on toolbars. If possible, please stop relying on them. Instead, you should use the CustomizableUI module.

+ +

CustomizableUI introduces a new API to insert, move and remove toolbar buttons and other toolbar items, as well as creating panels that are anchored to these toolbarbuttons. We believe this will be simpler and more powerful than the previous mix of APIs.

+ +

Because of the new customization APIs, your toolbar buttons may not be direct children of a XUL <toolbar>; they might still be in a toolbar, or they might be in the "customization target" of a toolbar (a descendant node in a toolbar), or they might be in the new menu panel. The customization target of any toolbar (whether the target is a child node, or the toolbar itself) via toolbar.customizationTarget.

+ +

Icon sizes in toolbars have changed, and you should ideally provide a larger icon for your add-on's buttons, should they exist, for use in the menu panel and customization area (palette). The new icon sizes are the same on all platforms and are:

+ + + +

When in the customization area (palette), the button will be wrapped in a toolbarpaletteitem with a place attribute set to palette. Putting it all together, your updated CSS might look like this:

+ +
#my-addon-button {
+    list-style-image: url(icon16.png);
+}
+#my-addon-button[cui-areatype="menu-panel"],
+toolbarpaletteitem[place="palette"] > #my-addon-button {
+    list-style-image: url(icon32.png);
+}
+
+/* High-resolution displays */
+@media (min-resolution: 2dppx) {
+    #my-addon-button {
+        list-style-image: url(icon32.png);
+    }
+    #my-addon-button[cui-areatype="menu-panel"],
+    toolbarpaletteitem[place="palette"] > #my-addon-button {
+        list-style-image: url(icon64.png);
+    }
+}
+
+ +

Tab markup and styling have changed. If your add-on affects the tabstrip or provides alternative visualizations of the tabstrip, changes tab colors, or anything else related to the tabstrip, you may want to verify that it still works.

+ +

The navigation toolbar is always visible (except in popup windows where a reduced navigation toolbar with the urlbar is visible) and can no longer be hidden e.g. for update pages or in-content UI. The related Add-on SDK module addon-page has been removed as it no longer has any effect.

+ +

Items in the navigation toolbar can be overflowed if the browser window is made too small. Items in the toolbar will be moved into the new "overflow panel" when this occurs. The overflow panel is anchored to a button that appears in the navigation toolbar when one or more items are overflowed. If your item should never be overflowed, set an overflows attribute to false on the item. The urlbar-container is not overflowable by default, for example. Items that are overflowed have the overflowedItem attribute set to true.

+ +

The menu panel uses a 3-column grid layout. Items should either fit in a single grid column (toolbarbuttons will be styled to do so automatically) or span the entire width of the panel if they wouldn't fit in a single grid column, e.g. for wide toolbaritems. In order to have the latter work correctly, you should use the panel-wide-item class on your toolbaritem.

+ +

If your add-on provides a <toolbarbutton type="menu"/> or <toolbarbutton type="menu-button"/>, consider moving to a subview-based design, which will work much better in the menu panel. There's some documentation you can look at, as well as the implementation of the history widget.

+ +

If your add-on provides a simple toolbarbutton then it should automatically be styled correctly in the menu panel, overflow panel and palette. If it provides a toolbaritem it is likely you will need to do additional work to make it look nice in places other than a toolbar.

+ +

All items will have context menus allowing users to move the items between the palette, panel and the navigation toolbar. If your add-on uses the contextmenu itself, we will not override or change it (see this bug for a lengthy discussion as to why). You are requested, however, to update your menus yourself so that users do have the possibility of using these options even for your add-on's button.

+ +

The class attribute on tab close buttons has been changed. Extensions shouldn't be relying on the class attribute value since it is a list of tokens and should instead look for the anonid attribute with value "close-button".

+ +

The close-icon class now works cross-platform to provide a close icon with a default, hover, and active state. Previously, this wasn't available on Linux and the GTK close icon (gtk-close) was used instead.

+ +

The BrowserToolboxCustomizeDone, BrowserToolboxCustomizeChange, and BrowserCustomizeToolbar global window functions have been removed. The customize events fired from the toolbox are now the preferred mechanism for hooking new logic into the customization feature.

+ +

Add-on SDK Australis APIs

+ +

If you're using the Add-on SDK, there are several new APIs for building your add-on's user interface in Australis. See the reference documentation. Also note that the widget module has been deprecated in favor of the new APIs.

+ +

Changes for themes

+ +

We've changed the tab markup. If you style these differently, you'll need to check whether it still works.

+ +

We'll be drawing tabs in the titlebar and on top, on all platforms (currently implemented on Windows and OS X), except when not showing tabs at all (in popup windows).

+ +

Support for small icons mode as well as text and icons mode have been removed.

+ +

We've changed the default iconsets, and there are new icon sizes for the menupanel. If you're building on the default theme with new icons, you'll need to rearrange your icons in your Toolbar icon files. In both this case and if you supply a complete theme, you will also need to provide icons for the menu panel. The new icon sizes are the same on all platforms and are:

+ + + +

We've removed the add-on bar, but have a shim in place to migrate icons to other places. Any styles pertaining to should be removed so as not to disturb the migration work.

+ +

We've changed a few toolbarbutton IDs, such as those for the bookmark and history buttons. We also added new ones.

+ +

The application (Firefox) menu has been removed.

+ +

The back, forward, stop and refresh buttons will no longer be movable. They will always remain in their current position next to the urlbar. Your CSS rules can probably be simplified now that this is the case.

+ +

The navigation toolbar can no longer be hidden e.g. for update pages or in-content UI.
+  

+ + + + + +

See Also

+ + diff --git a/files/zh-cn/mozilla/firefox/developer_edition/index.html b/files/zh-cn/mozilla/firefox/developer_edition/index.html new file mode 100644 index 0000000000..8764178a14 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/developer_edition/index.html @@ -0,0 +1,57 @@ +--- +title: 开发者版本 +slug: Mozilla/Firefox/Developer_Edition +translation_of: Mozilla/Firefox/Developer_Edition +--- +
{{FirefoxSidebar}}

+ +

一个为网页开发者量身定制的 Firefox。

+ +

下载 Firefox 开发者版本

+ +
+
+
+

最新的 Firefox 特性

+ +

Firefox 开发者版本会在 Firefox 发布流程中取代 Aurora 通道。像 Aurora 通道一样, 每 6 周新特性当它们在 Nightly 版本中稳定后,会登录到开发者版本中。

+ +

通过使用开发者版本,你将会比常规发布的 Firefox 提前至少 12 周体验到新的工具以及平台特性。

+ +

来看看开发者版本中有什么新的内容

+
+ +
+

实验性开发工具

+ +

我们还包含了一系列没有足够测试的实验性工具。

+ +

例如,开发者版本包含了 Firefox Tools Adapter,它可以帮你将 Firefox 开发工具 连接到其他平台的浏览器上,像 Android 上的 Chrome 以及 iOS 上的 Safari。

+
+
+ +
+
+

单独的配置文件

+ +

Firefox 开发版有自己一套单独的配置文件,这就意味着它不会影响你电脑里已经安装了的稳定版或者 Beta 版的 Firefox。

+
+ +
+

专为网页开发者而设

+ +

我们为网页开发者提供了量身的默认设置。例如,默认开启了 Chrome 以及远程调试功能。

+
+
+ +
+
+

一个独特的主题

+ +

这将让你更迅速地进入开发工具中。

+
+ +
 
+
+ +

 

diff --git a/files/zh-cn/mozilla/firefox/enterprise_deployment/index.html b/files/zh-cn/mozilla/firefox/enterprise_deployment/index.html new file mode 100644 index 0000000000..13d68ed3ce --- /dev/null +++ b/files/zh-cn/mozilla/firefox/enterprise_deployment/index.html @@ -0,0 +1,138 @@ +--- +title: 将火狐部署到企业环境下 +slug: Mozilla/Firefox/Enterprise_deployment +tags: + - 发布 企业环境 火狐 管理员手册 +translation_of: Mozilla/Firefox/Enterprise_deployment_before_60 +--- +
{{FirefoxSidebar}}

本页将为您介绍在企业配置环境下针对Mac OS X、Windows系统中火狐管理的整个流程。如您遇有不清楚的地方,请发送邮件至enterprise@mozilla.org

+ +

选择一个火狐的版本

+ +

 

+ +

快速发布版(RR)

+ +

火狐发布的每一个更新都会将主版本号增加,每6周便会发布新功能、Bug修复信息,如有必要,更新中也会加入额外的安全更新信息。当主版本更新后,Mozilla将不再提供上一版本的Bug修复。

+ +

具体更新发布计划请关注Mozilla wiki的版本更新日程表中的”发布日程”。

+ +

稳定版 (ESR)

+ +

火狐每隔7个主版本都会释出一个稳定版的发布内容。这些稳定发布的版本会将54周(9个“六周”一次的更新周期)以来一系列的bug进行修复。这两个版本中都会共同包含第12周(两个发布版本周期)的ESR更新内容。

+ +

到目前为止,扩展支持发布版本的版本号有10、17、24和31。

+ +

绝大多数企业以及组织机构更倾向与选择ESR版本,主要是因为稳定版发布间隔较长,以让各企业用户有充裕的时间对兼容性进行考核(ESR为42周,而RR则仅为6周),一旦在测试期间发现问题,用户也将拥有12周时间建立解决方案(每12周ESR版本会有重复发布)。

+ +

需要注意的是,如果您先使用RR后转为ESR较旧的版本时,将可能受到一些不利因素的影响。即便假设您此前使用的26RR版本火狐,和现改用24.2ESR版本发布于统一天,不同版本差异也会产生不利的因素。这是因为新功能仅会在RR版本发布前加入快速发布版进行评测,但由于一些原因Mozilla决定待功能到某一特定版本后才触发使用,在这之前都会在用户配置文件重将对应功能关闭。一旦您选择了旧版本火狐,用户文档保存的将是最后一次保存的文件,其中即可能设定新功能为启用的状态,进而导致在ESR版中功能失效。如果您执意要从RR过度到ESR版本,您需要等到最新的ESR发布版本释出后再这样做。

+ +

安装

+ +
    +
  1. http://www.mozilla.org/firefox/all/ (RR)或 https://www.mozilla.org/firefox/organizations/all.html (ESR)处获取发布版本安装包,单击“下载”按钮获取软件包或下载器;
  2. +
  3. 根据您选择的安装模式进行安装,命令行下静默安装的参数为 -ms;
  4. +
  5. 您也可以额外指定一个INI文件用以指定建立快捷方式等维护服务;具体请参照命令行安装参数章节中的相关内容.
  6. +
+ +

设置

+ +
    +
  1. 找到火狐的程序主文件夹,(Win7 64位操作系统默认安装位置是 C:\Program Files (x86)\Mozilla Firefox; OSX 10.8 则是默认安装在 /Applications/Firefox.app/Contents/MacOS。下文提到的这些子文件夹都在此程序主文件夹下;
  2. +
  3. 在defaults/pref子文件夹中新建一个Javascript文件 autoconfig.js 或者别的名字,但是建议您还是选用英文字母组合命名文件。该文件将告诉火狐查询对应的配置信息(具体请参考 自定义火狐的默认选项文件章节重的相关内容),您需要至少写入以下两行:
  4. +
  5. +
    pref("general.config.filename", "mozilla.cfg");
    +pref("general.config.obscure_value", 0);
    +
  6. +
  7. 新建.cfg文件,一般命名为mozilla.cfg,同样的它的文件名也可以用其它名字。它用于匹配识别general.config.filename的内容。将第一个语句跳过或注释掉后便可设置您的选项。具体都有哪些选项,您可参考about:config中的内容写入、或者您也可以参考后面的示例配置选项内容。任何about:config选项都可以通过以下函数之一进行设置: +
    +
     
    +
    pref
    +
    此选项可设置每次打开浏览器都按照此配置内容指定用户使用习惯。因此,即便用户在使用过程中可以随意更改偏好,但每次重新启动浏览器,用户之前的配置都将被抹消。如果您需要此方面的相关设置,请在about:config中查找“user set”。
    +
    defaultPref
    +
    此选项可用于修改默认值,但用户通常可以将其更改并将修改内容保存到用户会话中。如果用户偏好被重置,重置的内容将变为此设定值。此项目在about:config的“default”中。
    +
    lockPref
    +
    此选项可用于锁定指定项目,以防止用户在使用过程中通过界面或about:config对指定的配置选项进行修改。 通常锁定项的表现方式是变灰或移除选项内容。在about:config中则显示为“locked”。有一些选项必须通过lockPref设置比如app.update.enabled。如果只用pref设置该内容,该设置无效。
    +
    clearPref
    +
    此选项可以将某些指定的内容“放空”。此选项可以便于跳过某些网站的浏览器版本号检查功能。
    +
    +
  8. +
+ +

相关内容请您参考自定义火狐的自动配置文件以及继续自定义火狐的自动配置文件中的内容。如果您是倾向于零UI操作的狂热者,您可能需要用到CCK2这个扩展。

+ +

配置文件示例

+ +

如果您倾向于配置“极为复杂的用户偏好”,就请跳过这里。自火狐31版发布起,以下示例为您展示了常用的设置选项示例。如果您有某些指定的配置需求,请自行查询知识库中的信息。

+ +
//关闭更新器
+lockPref("app.update.enabled", false);
+//确认更新起已经绝对关闭
+lockPref("app.update.auto", false);
+lockPref("app.update.mode", 0);
+lockPref("app.update.service.enabled", false);
+
+//取消插件兼容性检查
+clearPref("extensions.lastAppVersion");
+
+//第一次运行火狐时不再提示“了解您的权益”
+pref("browser.rights.3.shown", true);
+
+//每次更新后不再显示更新发布注记
+pref("browser.startup.homepage_override.mstone","ignore");
+
+//修改主页地址(用户可改)
+defaultPref("browser.startup.homepage", "http://home.example.com");
+
+//关闭浏览器内默认的PDF阅读器
+pref("pdfjs.disabled", true);
+
+//关闭flash、js转换
+pref("shumway.disabled", true);
+
+//不再提示安装flash插件
+pref("plugins.notifyMissingFlash", false);
+
+//关闭插件提示
+lockPref("plugins.hide_infobar_for_outdated_plugin", true);
+clearPref("plugins.update.url");
+
+//关闭健康诊断报告
+lockPref("datareporting.healthreport.service.enabled", false);
+
+// Disable all data upload (Telemetry and FHR)
+lockPref("datareporting.policy.dataSubmissionEnabled", false);
+
+//关闭崩溃报告
+lockPref("toolkit.crashreporter.enabled", false);
+Components.classes["@mozilla.org/toolkit/crash-reporter;1"].getService(Components.interfaces.nsICrashReporter).submitReports = false; 
+
+ +

扩展包

+ +
    +
  1. 安装扩展,通过about:support找到该拓展对应的GUID;
  2. +
  3. 找到用户配置文件目录 (如win7的是:%APPDATA%\Mozilla\Firefox\Profiles , 在about:support中单击显示文件夹,然后在“扩展”下找到你需要的插件。插件文件可能是单独的xpi文件,或者是一个包含多个文件的目录。
  4. +
  5. 确定如何发布此扩展。最简单的方式是将xpi直接拽到程序主文件夹/distribution/extensions目录下,但是这仅限于用户配置文件已记录该插件的安装情况。您另外还可以手动打开火狐重新安装。具体请参考让插件与火狐合二为一的相关章节。
  6. +
+ +

Also keep in mind: Add-on scopes redux/

+ +

随时变化

+ +

目录结构的变化

+ +

到目前为止,火狐的目录结构已经变更过两次。如果您需要使用21版本以前的火狐,请注意以下的变化:

+ + + +

自动配置general.config.filenamegeneral.config.obscure_value可以在defaults/pref中完成,但文件名应该以英文字母‘a’开头,比如“autoconfig.js”

+ +

如果您的版本defaults/pref与插件设置相悖,您可以尝试将目录结构改为和新版一样。

+ +

ESR 24.x的变化(有Adobe PDF支持)

+ +

火狐RR19.x起将PDF查看器嵌入到自己内部来, 即便您已经将火狐配置了其它PDF视图软件,但嵌入支持直到24.x版本以后才开始启用。而内容类型描述也与Adobe文档的PDF文件不同,若要取消此功能,请您将前面示例中的pdfjs.disabled改为true即可。

diff --git a/files/zh-cn/mozilla/firefox/experimental_features/index.html b/files/zh-cn/mozilla/firefox/experimental_features/index.html new file mode 100644 index 0000000000..390a652feb --- /dev/null +++ b/files/zh-cn/mozilla/firefox/experimental_features/index.html @@ -0,0 +1,623 @@ +--- +title: Experimental features in Firefox +slug: Mozilla/Firefox/Experimental_features +tags: + - 实验的 + - 火狐 + - 特性 + - 设置 +translation_of: Mozilla/Firefox/Experimental_features +--- +
{{FirefoxSidebar}}

Mozilla发布了测试的nightly版本,用于测试新的浏览器特性。 实验性特性,例如所提议的可用的Web平台标准的实现。这个页面列出了Firefox Nightly中的一些新特性和启用方法等信息。在发布这些功能之前,你可以测试Web站点和应用程序,并确保一切都能与最新的Web技术功能协同工作。

+ +

你需要下载隔夜版或是开发者版,来测试下面这些实验性特性。

+ +

HTML

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能Firefox NightlyFirefox 开发者版Firefox 测试版Firefox 发行版Preference
日期和时间输入{{HTMLElement("input")}}为 日期时间 相关的输入类型提供的新用户界面开启
+ (从51开始支持, 从55开始默认开启)
开启
+ (从51开始支持)
关闭
+ (从51开始支持)
---dom.forms.datetime
{{HTMLElement("dialog")}}
+ 包含与之交互的DOM元素的对话框元素。Implementation of modal dialogs and accessibility still missing.
关闭
+ (从53开始支持)
关闭
+ (从53开始支持)
------dom.dialog_element.enabled
+ +

CSS

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能Firefox NightlyFirefox Developer EditionFirefox BetaFirefox ReleasePreference
SubgridsDisabledDisabledDisabledDisabledlayout.css.grid-template-subgrid-value.enabled
Display stray control characters in CSS as hex boxes
+ This feature renders control characters (Unicode category Cc) other than tab (U+0009), line feed (U+000A), form feed (U+000C), and carriage return (U+000D) as a hexbox when they are not expected.
4343DisabledDisabledlayout.css.control-characters.enabled or layout.css.control-characters.visible
Positioned CSS Masks
+ A subset of CSS Masks that includes longhand properties of CSS Masks, as well as a change in the shorthand property
515153DisabledControlled by a compile flag (MOZ_ENABLE_MASK_AS_SHORTHAND).
The font-display descriptor for @font-face
+ To improve Web fonts performance, {{cssxref("@font-face")}} has an experimental {{cssxref("@font-face/font-display", "font-display")}} descriptor.
关闭
+ (available since 46)
关闭
+ (available since 46)
关闭
+ (available since 46)
关闭
+ (available since 46)
layout.css.font-display.enabled
+

font-variation-settings 属性
+ {{cssxref("font-variation-settings")}} 提供了OpenType或TrueType字体印刷特点的低级别的控制, by specifying the four letter axis names of the features you want to vary, along with their variation values.

+
关闭
+ (available since 53)
关闭
+ (available since 53)
关闭
+ (available since 53)
关闭
+ (available since 53)
+

layout.css.font-variations.enabled
+ Functions only in Mac OS Sierra (and later).
+
+ For the downloadable fonts on axis-praxis, you also need gfx.downloadable_fonts.keep_variation_tables (in Firefox 54 and later)

+
touch-action CSS 属性
+ The {{cssxref("touch-action")}} CSS property is part of the {{SpecName("Pointer Events")}} specification and allows you to specify how and in what way the user is able to manipulate an object by touch.
50layout.css.touch_action.enabled
+

The shape-outside CSS property
+ The {{cssxref("shape-outside")}} CSS property is part of the {{SpecName("CSS Shapes")}} specification and allows you to specify a float area causing inline contents to wrap around a shape.

+ +

Firefox currently implements the <shape-box> values ({{bug(1309467)}}) as well as the circle() ({{bug(1311244)}}), ellipse() ({{bug(1326406)}}), and polygon() ({{bug(1326409)}}) functions.

+
关闭
+ (available since 53)
layout.css.shape-outside.enabled
The contain CSS property
+ The {{cssxref("contain")}} CSS property is part of the {{SpecName("CSS Containment")}} specification and allows you to indicate that an element and its contents are independent of the rest of the document tree, allowing {{Glossary("User agent", "user agents")}} to optimize the rendering of a page.
关闭
+ (available since 45)
关闭
+ (available since 45)
关闭
+ (available since 45)
关闭
+ (available since 45)
layout.css.contain.enabled
+

The column-span CSS property
+ The {{cssxref("column-span")}} CSS property is part of the {{SpecName("CSS3 Multicol")}} specification and allows you to specify how many columns an element spans across.

+ +

Firefox currently only parses the property ({{bug(1339298)}}), it's not actually implemented yet ({{bug(616436)}}).

+
关闭
+ (recognized since 55, but not implemented yet)
layout.css.column-span.enabled
The frames() timing function
+ See The frames() class of timing-functions for more details.
开启N/A关闭
+ (available since 55)
关闭
+ (available since 55)
None
+ +

JavaScript

+ +

See also ECMAScript Next support for implemented features of ECMAScript 2016 and later, that are not experimental and thus available without preferences in Firefox Release.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureFirefox NightlyFirefox Developer EditionFirefox BetaFirefox ReleasePreference
Additions to the ArrayBuffer object
+ Adds the {{jsxref("ArrayBuffer.transfer()")}} that returns a new ArrayBuffer whose contents have been taken from the oldBuffer's data (spec).
36DisabledDisabledDisabledNone
TypedObject objects (spec)EnabledDisabledDisabledDisabledNone
SIMD (specification and polyfill)EnabledDisabledDisabledDisabledNone
ECMAScript modules
+ Allows you to use native ECMAScript modules, for example defining modules with <script type="module">, defining fallback scripts with <script nomodule>, and importing code features that have been exported from modules.
DisabledDisabledDisabledDisableddom.moduleScripts.enabled
+ +

APIs

+ +

Canvas & WebGL

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureFirefox NightlyFirefox Developer EditionFirefox BetaFirefox ReleasePreference
WEBGL_debug_renderer_info extension
+ The {{domxref("WEBGL_debug_renderer_info")}} extension allows you to transmit information useful to help debugging problems to the server.
4242DisabledDisabledwebgl.enable-debug-renderer-info
OffscreenCanvas
+ The {{domxref("OffscreenCanvas")}} interface provides a canvas that can be rendered off screen. It is available in both the window and worker contexts.
Disabled
+ (available since 44)
Disabled
+ (available since 44)
Disabled
+ (available since 44)
Disabled
+ (available since 44)
gfx.offscreencanvas.enabled
Hit regions
+ Whether the mouse coordinates are within a particular area on the canvas is a common problem to solve. The hit region API allows you define an area of your canvas and provides another possibility to expose interactive content on a canvas to accessibility tools.
Disabled
+ (available since 30)
Disabled
+ (available since 30)
Disabled
+ (available since 30)
Disabled
+ (available since 30)
canvas.hitregions.enabled
+ +

DOM

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureFirefox NightlyFirefox Developer EditionFirefox BetaFirefox ReleasePreference
Mac上的WebVR API 1.1
+ WebVR API 允许你控制并和使用虚拟现实设备。
EnabledDisabledDisabledDisableddom.vr.enabled
游戏手柄扩展
+ The Gamepad Extensions provide access to additional functionality such as pose information in the case of WebVR controllers, and haptic actuator control (e.g. controller vibration hardware).
EnabledEnabledEnabledDisableddom.gamepad-extensions.enabled
Experimental fetch controller/signal/observer interfaces
+ Also known as "cancellable fetch", these interfaces contain functionality to allow fetch request operations to be observed and controlled during their lifetimes.
Disabled
+ (Available since 55)
DisabledDisabledDisableddom.fetchObserver.enabled and dom.fetchController.enabled (not in about:config by default; you must set them yourself).
FlyWeb
+ FlyWeb is a project at Mozilla focused on bringing a new set of APIs to the browser for advertising and discovering local-area web servers.
51DisabledDisabledDisableddom.flyweb.enabled
HTMLMediaElement.seekToNextFrame()
+ Part of an experimentation process around support non-real-time access to media for tasks including filtering, editing, and so forth, the {{domxref("HTMLMediaElement.seekToNextFrame()")}} advances the the current play position to the next frame in the media.
49
+ (Fundamental update in version 50)
49
+ (Fundamental update in version 50)
DisabledDisabledmedia.seekToNextFrame.enabled
GeometryUtils.getBoxQuads() ({{bug(917755)}})3131DisabledDisabledlayout.css.getBoxQuads.enabled
GeometryUtils.convertPointFromNode(),
+ GeometryUtils.RectFromNode(), and
+ GeometryUtils.convertQuadFromNode()
+ ({{bug(918189)}})
3131DisabledDisabledlayout.css.convertFromNode.enabled
Node.rootNode
+ The {{domxref("Node.rootNode")}} property returns a {{domxref("Node")}} object representing the topmost node in the tree, or the current node if it's the topmost node in the tree.
+ This feature is kept experimental as its naming poses Web compatibility problems. It will be renamed in the future.
4848DisabledDisableddom.node.rootNode.enabled
Performance Observer API
+ The {{domxref("PerformanceObserver")}} interface is used to observe performance measurement events and be notified of new performance entries as they are recorded in the browser's performance timeline.
49DisabledDisabledDisableddom.enable_performance_observer
WebVTT Regions API
+ WebVTT regions are parts of the video viewport that provide a rendering area for WebVTT cues. The {{domxref("VTTRegion")}} is the interface exposing the WebVTT cues.
+ This interface is considered to be in flux and isn't therefore activated in any version by default.
Disabled
+ (Experimental implementation since version 30)
DisabledDisabledDisabledmedia.webvtt.regions.enabled
音频和视频轨道支持
+ Implements {{domxref("HTMLMediaElement.audioTracks")}} and {{domxref("HTMLMediaElement.videoTracks")}}.
+ Firefox doesn't support multiple audio or video tracks, preventing the most common use cases for these properties to work properly. That's why these properties are not activated by default in any version.
Disabled
+ (Experimental implementation since version 33)
DisabledDisabledDisabledmedia.track.enabled
Better value for Event.timestamp
+ The property {{domxref("Event.timestamp")}} is returning a {{domxref("DOMHighResTimeStamp")}}, which is now relative to the Unix epoch.
32 (Windows)
+ 43 (Linux)
32 (Windows)
+ 43 (Linux)
DisabledDisabledmedia.track.enabled
指针事件50DisabledDisabledDisableddom.w3c_pointer_events.enabled
Pointer Events {{domxref("PointerEvent.tangentialPressure")}} and {{domxref("PointerEvent.twist")}}54DisabledDisabledDisableddom.w3c_pointer_events.enabled
Intersection Observer API
+ The {{domxref("Intersection Observer API")}} allows you to configure a callback that is called whenever one item, called a target, intersects either the device viewport or a specified element called.
Disabled
+ (available since 53)
dom.IntersectionObserver.enabled
Web Animations API: KeyframeEffect and KeyframeEffectReadOnly
+ The {{domxref("KeyframEffectReadOnly()", "KeyframeEffectReadOnly.KeyframeEffectReadOnly()")}} and {{domxref("KeyframeEffect()", "KeyframeEffect.KeyframeEffect()")}} constructors can be used to clone existing {{domxref("KeyframeEffectReadOnly")}} object instances by being given the object to clone as their only parameter (see {{bug(1273784)}}.)
5252DisabledDisabledNone
{{domxref("PromiseRejectionEvent")}} and related features
+ Providing a way to monitor and more finely control the rejection of Promises.
+  
Disabled
+ (available since 55)
DisabledDisabledDisableddom.promise_rejection_events.enabled
Payment Request API
+ 为网络支付提供的一个API。
Disabled
+ (available since 55)
Disabled
+ (available since 55)
Disabled
+ (available since 55)
Disabled
+ (available since 55)
dom.payments.request.enabled
+ +

WebRTC

+ + + + + + + + + + + + + + + + + + + + + + +
FeatureFirefox NightlyFirefox Developer EditionFirefox BetaFirefox ReleasePreference
TCP ICE candidates
+ ICE candidates that use TCP rather than UDP are considered during ICE negotiation.
+

Disabled
+ 41

+ +

Enabled
+ 54

+
Disabled
+ 41
Disabled
+ 41
Disabled
+ 41
media.peerconnection.ice.tcp
+ +

开发者工具

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureFirefox NightlyFirefox Developer EditionFirefox BetaFirefox ReleasePreference
Debugger rewrite in HTML5252DisabledDisableddevtools.debugger.new-debugger-frontend
Console rewrite in HTML52DisabledDisabledDisableddevtools.webconsole.new-frontend-enabled
Experimental Performance tool options
+ Enables options in the UI for JIT optimizations, memory, etc.
41DisabledDisabledDisableddevtools.performance.ui.experimental
Layout side panel
+ The Layout side panel allows to inspect and manage different CSS layout types like CSS Grid Layout.
Disabled
+ (available since 52)
Disabled
+ (available since 52)
Disabled
+ (available since 52)
Disabled
+ (available since 52)
devtools.layoutview.enabled
+ +

其他

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureFirefox NightlyFirefox Developer EditionFirefox BetaFirefox ReleasePreference
添加到主屏幕
+ The icons, name, short_name, and theme_color fields of the Web App Manifest (if present) can now be as the source of the homescreen/apps window icons, apps window title, homescreen icon title, and apps window color (respectively) for "Add to home screen" (Firefox Mobile only).
关闭
+ (available since 53)
关闭
+ (available since 53)
关闭
+ (available since 53)
关闭
+ (available since 52)
manifest.install.enabled
TLS 1.3开启开启关闭关闭security.tls.version.max to 4
+ +

See also

+ + diff --git a/files/zh-cn/mozilla/firefox/headless_mode/index.html b/files/zh-cn/mozilla/firefox/headless_mode/index.html new file mode 100644 index 0000000000..855339e6d1 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/headless_mode/index.html @@ -0,0 +1,270 @@ +--- +title: Headless mode +slug: Mozilla/Firefox/Headless_mode +translation_of: Mozilla/Firefox/Headless_mode +--- +
{{FirefoxSidebar}}
+ +

Headless模式是运行Firefox的一种非常有用的方式。就像听起来一样,Firefox正常运行,但没有任何可见UI组件。虽然不太适合浏览网页,但它对自动化测试非常有用。本文提供了有关运行 headless Firefox 的所有知识。

+ +

Using headless mode

+ +

This section provide usage instructions for headless mode.

+ +

Basic usage

+ +

You can run Firefox in headless mode from the command line, by including the -headless flag. For example:

+ +
/path/to/firefox -headless
+ +

Taking screenshots

+ +

Since Firefox 57, the -screenshot flag allows you to take screenshots of websites. The basic usage:

+ +
/path/to/firefox -headless -screenshot https://developer.mozilla.com
+ +

This creates a full-height screenshot of https://developer.mozilla.com, in the active directory called screenshot.png, with a viewport width of 800px.

+ +

You can omit -headless when using -screenshot, as it is implied:

+ +
/path/to/firefox -screenshot https://developer.mozilla.com
+ +

To override the default values, mentioned above, you can use the following flags/features:

+ + + +

For example, the following command creates a screenshot of https://developer.mozilla.com, in the active directory called test.jpg, with a viewport width of 800px, and a height of 1000px:

+ +
/path/to/firefox -screenshot test.jpg  https://developer.mozilla.com --window-size=800,1000
+ +

Browser support

+ +

Headless Firefox works on Fx55+ on Linux, and 56+ on Windows/Mac.

+ +

Automated testing with headless mode

+ +

The most useful way to use headless Firefox, is to run automated tests. You can make your testing process much more efficient.

+ +

Selenium in Node.js

+ +

Here we'll create a Selenium test, using Node.js and the selenium-webdriver package. For this guide, we'll assume that you already have basic familiarity with Selenium, Webdriver, and Node, and you already have a testing environment created. If now, work through our Setting up Selenium in Node guide, and return when you have.

+ +

First, confirm you've installed Node and the selenium-webdriver on your system. Then create a new file, called selenium-test.js, and follow the steps below to populate it with test code.

+ +
+

Note: Alternatively, you could clone our headless-examples repo. This also includes a package file, so you can just use npm install to install necessary dependencies.

+
+ +
    +
  1. +

    Let's add some code. Inside this file, start by importing the main selenium-webdriver module, and the firefox submodule:

    + +
    var webdriver = require('selenium-webdriver'),
    +    By = webdriver.By,
    +    until = webdriver.until;
    +
    +var firefox = require('selenium-webdriver/firefox');
    +
  2. +
  3. +

    Next, we create a new binary object representing Firefox Nightly, and add the -headless argument, so it will run in headless mode:

    + +
    var binary = new firefox.Binary(firefox.Channel.NIGHTLY);
    +binary.addArguments("-headless");
    +
  4. +
  5. +

    Now let's create a new driver instance for Firefox, using setFirefoxOptions() to include an options object, which specifies that we want to run the test using the above binary. This step will be unnecessary on Linux, and after headless mode lands in the release channel on Windows/Mac, but it is still useful if you want to test Nightly-specific features:

    + +
    var driver = new webdriver.Builder()
    +    .forBrowser('firefox')
    +    .setFirefoxOptions(new firefox.Options().setBinary(binary))
    +    .build();
    + +

    Alternatively, you can use options to set the binary and the headless arguments:

    + +
    var firefoxOptions = new firefox.Options();
    +firefoxOptions.setBinary('/path/to/binary');
    +firefoxOptions.headless();
    +
    +const driver = new webdriver.Builder()
    +   .forBrowser('firefox')
    +   .setFirefoxOptions(firefoxOptions)
    +   .build();
    +
    +
  6. +
  7. +

    Finally, add the following code, which performs a simple test on the Google search homepage:

    + +
    driver.get('https://www.google.com');
    +driver.findElement(By.name('q')).sendKeys('webdriver');
    +
    +driver.sleep(1000).then(function() {
    +  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
    +});
    +
    +driver.findElement(By.name('btnK')).click();
    +
    +driver.sleep(2000).then(function() {
    +  driver.getTitle().then(function(title) {
    +    if(title === 'webdriver - Google Search') {
    +      console.log('Test passed');
    +    } else {
    +      console.log('Test failed');
    +    }
    +  });
    +});
    +
    +driver.quit();
    +
  8. +
  9. +

    Finally, run your test with following command:

    + +
    node selenium-test
    +
  10. +
+ +

That's it! After a few seconds, you should see the message "Test passed" returned in the console.

+ +

Headless Firefox in Node.js with selenium-webdriver, by Myk Melez, contains additional useful tips and tricks for running Node.js Selenium tests with headless mode.

+ +

Selenium in Java

+ +
+

Note: Thanks a lot to nicholasdipiazza for writing these instructions!

+
+ +

This guide assumes you already have Geckodriver on your machine, as explained in  Setting up Selenium in Node, and an IDE set up which supports Gradle projects.

+ +
    +
  1. +

    Download our headlessfirefox-gradle.zip archive (see the source here). Extract it, and import the headlessfirefox folder into your IDE, as a gradle project.

    +
  2. +
  3. +

    Edit the build.gradle file, to set selenium to a later version, if needed. At the time of writing, we used 3.5.3.

    + +
    group 'com.mozilla'
    +version '1.0'
    +
    +apply plugin: 'java'
    +
    +sourceCompatibility = 1.8
    +
    +repositories {
    +   mavenCentral()
    +}
    +
    +dependencies {
    +   compile('org.seleniumhq.selenium:selenium-api:3.5.3')
    +   compile('org.seleniumhq.selenium:selenium-remote-driver:3.5.3')
    +   compile('org.seleniumhq.selenium:selenium-server:3.5.3')
    +
    +   testCompile group: 'junit', name: 'junit', version: '4.12'
    +}
    +
  4. +
  5. +

    Edit the webdriver.gecko.driver property, in the HeadlessFirefoxSeleniumExample.java file, to equal the path where you installed geckodriver (see line 15 below).

    + +
    package com.mozilla.example;
    +
    +import org.openqa.selenium.By;
    +import org.openqa.selenium.WebElement;
    +import org.openqa.selenium.firefox.FirefoxBinary;
    +import org.openqa.selenium.firefox.FirefoxDriver;
    +import org.openqa.selenium.firefox.FirefoxOptions;
    +
    +import java.util.concurrent.TimeUnit;
    +
    +public class HeadlessFirefoxSeleniumExample {
    + public static void main(String [] args) {
    +   FirefoxBinary firefoxBinary = new FirefoxBinary();
    +   firefoxBinary.addCommandLineOptions("--headless");
    +   System.setProperty("webdriver.gecko.driver", "/opt/geckodriver");
    +   FirefoxOptions firefoxOptions = new FirefoxOptions();
    +   firefoxOptions.setBinary(firefoxBinary);
    +   FirefoxDriver driver = new FirefoxDriver(firefoxOptions);
    +   try {
    +     driver.get("http://www.google.com");
    +     driver.manage().timeouts().implicitlyWait(4,
    +         TimeUnit.SECONDS);
    +     WebElement queryBox = driver.findElement(By.name("q"));
    +     queryBox.sendKeys("headless firefox");
    +     WebElement searchBtn = driver.findElement(By.name("btnK"));
    +     searchBtn.click();
    +     WebElement iresDiv = driver.findElement(By.id("ires"));
    +     iresDiv.findElements(By.tagName("a")).get(0).click();
    +     System.out.println(driver.getPageSource());
    +   } finally {
    +     driver.quit();
    +   }
    + }
    +}
    +
  6. +
  7. +

    Run the java class, and you should see the HTML content of this page printed in your console/terminal.

    +
  8. +
+ +

Selenium in Python

+ +

This guide assumes you already have geckodriver on your machine, as explained in Setting up Selenium in Node.

+ +
    +
  1. +

    Install the latest version of the Python client for Selenium.

    +
  2. +
  3. +

    Edit the following, to set the executable_path on line 11, to the path where you installed geckodriver:

    + +
    from selenium.webdriver import Firefox
    +from selenium.webdriver.common.by import By
    +from selenium.webdriver.common.keys import Keys
    +from selenium.webdriver.firefox.options import Options
    +from selenium.webdriver.support import expected_conditions as expected
    +from selenium.webdriver.support.wait import WebDriverWait
    +
    +if __name__ == "__main__":
    +    options = Options()
    +    options.add_argument('-headless')
    +    driver = Firefox(executable_path='geckodriver', firefox_options=options)
    +    wait = WebDriverWait(driver, timeout=10)
    +    driver.get('http://www.google.com')
    +    wait.until(expected.visibility_of_element_located((By.NAME, 'q'))).send_keys('headless firefox' + Keys.ENTER)
    +    wait.until(expected.visibility_of_element_located((By.CSS_SELECTOR, '#ires a'))).click()
    +    print(driver.page_source)
    +    driver.quit()
    +
  4. +
  5. +

    Run the Python script, and you should see the HTML content of this page printed in your console/terminal.

    +
  6. +
+ +

Other testing solutions

+ + + +

In addition, you can use headless Firefox to run automated tests written in most other popular testing apps, as long as you are able to set environment variables.

+ +

Troubleshooting and further help

+ +

If you are having trouble getting headless mode to work, then do not worry — we are here to help. This section is designed to be added to as more questions arise, and answers are found.

+ + + +

If you want to ask the engineers a question, the best place to go is the #headless channel on Mozilla IRC. If you are pretty sure you've found a bug, file it on Mozilla Bugzilla.

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/firefox/index.html b/files/zh-cn/mozilla/firefox/index.html new file mode 100644 index 0000000000..b0bc71f5b5 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/index.html @@ -0,0 +1,74 @@ +--- +title: Firefox +slug: Mozilla/Firefox +tags: + - Firefox + - Mozilla + - NeedsTranslation + - TopicStub +translation_of: Mozilla/Firefox +--- +
{{FirefoxSidebar}}
+ +

Firefox(非正式中文名称“火狐”)是Mozilla出品的网页浏览器,可用于Windows、Mac OS X、Linux等桌面操作系统,也可以用于Android等移动操作系统。得益于对最新的网络标准的广泛兼容和强有力的开发工具,Firefox对最终用户和开发者而言都是优秀的浏览器。

+ +

Firefox是一个开源项目,许多代码都是由志愿者社群提供的。在此你将了解如何为Firefox项目做贡献,你也可以找到关于制作附加组件、使用Firefox开发者工具等内容。

+ +
+

了解如何为 Firefox添加附加组件,如何开发和构建Firefox自身,以及了解Firefox以及其他组件内部如何运作。

+
+ + + +

Firefox 发布频道

+ +

Firefox 通过 5 个 发布频道 进行发布。

+ +

Firefox Nightly

+ +

每天晚上,我们都使用 mozilla-central 代码库中的最新代码构建的版本。这些版本适用于开发者或想要尝试最新的、处于活跃开发中的特性的使用者。

+ +

下载 Firefox Nightly

+ +

Firefox Developer Edition

+ +

这是一个为开发者量身定制的版本。每隔六周,我们便选择Firefox Nightly 频道中足够稳定的特性创建一个新版本的Firefox Developer Edition。同时我们还仅仅在该发布频道中为开发者添加一些特有的特性。

+ +

了解关于Firefox Developer Edition的更多信息

+ +

下载 Firefox Developer Edition

+ +

Firefox Beta

+ +

在Firefox Developer Edition停留六周之后,我们将选择足够稳定的特性构建一个新版本的 Firefox Beta 。Firefox Beta 版本适用于热衷于测试将在下一个Firefox 版本中推出的新特性的用户。

+ +

下载 Firefox Beta

+ +

Firefox

+ +

当在Beta频道中稳定六周之后,我们便发布新版本Firefox,将新特性推送至数亿用户。

+ +

下载 Firefox

+ +

Firefox 延长支持版 (ESR)

+ +

Firefox ESR 是在较长周期提供支持的桌面版本Firefox,适用于学校、大学、商业机构等组织以及需要延长支持用以进行大规模部署的用户。

+ +

了解关于 Firefox 延长支持版的更多信息

+ +

下载 Firefox ESR

+ +

Firefox 配置

+ +

如果你在日常中使用多个Firefox发行频道,或者多个不同的配置选项,你应该阅读了解如何通过Firefox的配置管理器与其他管理工具实现使用多个Firefox配置

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/cross_process_object_wrappers/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/cross_process_object_wrappers/index.html new file mode 100644 index 0000000000..38fde2acbf --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/cross_process_object_wrappers/index.html @@ -0,0 +1,114 @@ +--- +title: 跨进程对象包装器 +slug: Mozilla/Firefox/Multiprocess_Firefox/Cross_Process_Object_Wrappers +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Cross_Process_Object_Wrappers +--- +
{{FirefoxSidebar}}
+

本文档介绍了 Cross Process Object Wrappers (CPOWs),这使 chrome 代码能够同步访问多进程 Firefox 中的内容。

+
+ +

在多进程 Firefox 中,chrome 代码运行在与 Web 内容不同的另一个进程中。因此 chrome 代码不能直接与 Web 内容交互;相反,它必须考虑将与 Web 内容交互的脚本放在单独的脚本中,这被称为框架脚本(frame scripts),也称帧脚本。

+ +

Chrome 代码可以使用消息管理器加载框架脚本到内容进程,然后可以使用消息传递 API 与它们通信。有关于此的更多信息,详见 消息管理器 的使用文档。

+ +

Chrome 到内容的通信必须是异步的。这是因为 chrome 进程运行着 Firefox UI,因此如果被内容进程所影响,缓慢的内容进程可能致使 Firefox 对用户无响应。
+
+ 将同步代码转换成异步可能是困难并且耗时的。作为一个迁移的辅助,消息框架使框架脚本变成了内容对象,通过一个被称为 Cross Process Object Wrapper(简称 CPOW)的包装器,使其在 chrome 中可用。但是,尽管 CPOWs 很方便,它们存在严重的局限性并且可能导致响应性问题,因此只应在必要时使用,并仅作为迁移的辅助。

+ +

从框架脚本传递 CPOWs

+ +

框架脚本可以发送消息到 chrome,使用两个全局函数之一:sendAsyncMessage() 或者 sendSyncMessage()。这些函数的第三个可选参数是被包装的属性对象。举例来说,框架脚本在用户点击它时发送一个 DOM 节点到 chrome,并将 clicked 属性作为第三个参数:

+ +
// frame script
+addEventListener("click", function (event) {
+  sendAsyncMessage("my-e10s-extension-message", {}, { clicked : event.target });
+}, false);
+ +

在 chrome 脚本中,DOM 节点现在是通过 Cross Process Object Wrapper 访问,作为该消息的 objects  属性的个属性。chrome 脚本可以获得和设置包装的对象属性,以及调用它的函数:

+ +
// chrome script
+windowMM.addMessageListener("my-e10s-extension-message", handleMessage);
+
+function handleMessage(message) {
+  let wrapper = message.objects.clicked;
+  console.log(wrapper.innerHTML);
+  wrapper.innerHTML = "<h2>已被 chrome 修改!</h2>"
+  wrapper.setAttribute("align", "center");
+}
+ +

自动生成的 CPOWs

+ +

没有自我声明多进程兼容的附加组件会加载一些兼容性垫片。其中一个垫片提供了以下行为:每当 chrome 代码尝试直接访问内容(例如通过 window.content 或者 browser.contentDocument),提供一个包装了内容的 CPOW。这意味着下面这样的例子在多进程 Firefox 中也能正常工作。

+ +
gBrowser.selectedBrowser.contentDocument.body.innerHTML = "被 chrome 代码替换";
+ +

但仍然要记住,这是通过 CPOW 访问,并不是直接访问内容。

+ +

双向 CPOWs

+ +

一个常见的模式是 chrome 代码访问内容对象并添加事件监听器到那里。为了解决这个问题,CPOWs 是双向的。这意味着如果内容传递了一个 CPOW 到 chrome 进程,chrome 进程可以同步传递对象(如事件监听器函数)到 CPOW 中定义的函数。

+ +

这意味着你可以写这样的代码:

+ +
// frame script
+
+/*
+在 mouseover,发送 button 到 chrome 脚本,以一个CPOW形式。
+*/
+
+var button = content.document.getElementById("click-me");
+
+button.addEventListener("mouseover", function (event) {
+  sendAsyncMessage("my-addon-message", {}, { element : event.target });
+}, false);
+ +
// chrome script
+
+/*
+载入框架脚本,然后监听消息。
+在我们得到消息时,提取 CPOW 并添加一个函数作为监听器到按钮的 "click" 事件。
+*/
+
+  browserMM.loadFrameScript("chrome://my-addon/content/frame-script.js", false);
+  browserMM.addMessageListener("my-addon-message", function(message) {
+    let wrapper = message.objects.element;
+    wrapper.addEventListener("click", function() {
+      console.log("被点击了");
+    });
+  });
+
+ +

映射内容文档到 XUL 浏览器

+ +

一个常见的模式是获取 XUL <browser>,它对应一个内容文档。要做到这点, gBrowser.getBrowserForDocument  和 gBrowser.getBrowserForContentWindow 分别可以传递一个内容文档和内容窗口的 CPOW,并且返回这些文档 / 窗口所属的 XUL  <browser>。如果没有找到这样的浏览器,两者都是返回 null。

+ +

CPOWs 的限制

+ +

尽管 CPOWs 可以方便的使用,但它有几个主要的局限性,在下面列出。

+ +

CPOWs 与平台 API

+ +

你不能传递 CPOWs 到预期会收到 DOM 对象的平台 API。举例来说,你不能传递一个 CPOW  nsIFocusManager.setFocus()

+ +

Chrome 响应性

+ +

在 chrome 这边缺少同步 API 是有意的:因为 chrome 进程运行着 Firefox UI,任何响应性问题都将影响整个浏览器。在制成 chrome 进程与内容进程的过程中,CPOWs 打破了这个原则,并且致使内容进程可能使整个浏览器陷入无响应状态。

+ +

性能

+ +

尽管包装器看起来像是一个完全在 chrome 脚本范围下管控的对象,但它实际上只是一个到内容进程中一个对象的引用。在你访问一个包装器的属性时,它发送一个同步消息到内容进程及返回结果。这意味着它比使用一个对象慢很多倍。

+ +

消息顺序

+ +

CPOWs 可能违反你做出的有关消息排序的假设。考虑以下代码:

+ +
mm.addMessageListener("GotLoadEvent", function (msg) {
+  mm.sendAsyncMessage("ChangeDocumentURI", {newURI: "hello.com"});
+  let uri = msg.objects.document.documentURI;
+  dump("收到加载事件: " + uri + "\n");
+});
+
+ +

这发送了一个消息,要求框架脚本更改当前文档的 URI,然后通过一个 CPOW 访问当前的文档 URI。你可能预期 uri 的值得到设置的 "hello.com"。但这不一定:为了避免死锁,CPOW 消息可以绕过正常的消息并且被优先处理。对 documentURI 属性的请求有可能在 "ChangeDocumentURI" 的消息之前被处理,并因而 uri 持有它在更改之前的值。
+
+ 出于这个原因,最好不要混用 CPOWs 和正常的消息管理器消息。还有一个坏主意是将 CPOWs 用于任何安全相关,因为你可能获得不一致的结果,与使用消息管理器的相关代码。

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/debugging_frame_scripts/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/debugging_frame_scripts/index.html new file mode 100644 index 0000000000..57c1b3412a --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/debugging_frame_scripts/index.html @@ -0,0 +1,53 @@ +--- +title: 调试框架脚本 +slug: Mozilla/Firefox/Multiprocess_Firefox/Debugging_frame_scripts +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Debugging_frame_scripts +--- +
{{FirefoxSidebar}}
+

浏览器内容工具箱仅在 Firefox Nightly 中可用,并且仅在多进程模式下可用。

+
+ +

你可以使用浏览器内容工具箱来调试框架脚本。浏览器内容工具箱是一个单独的窗口,它包括一些共享的 Firefox 开发者工具,具体来说:控制台JavaScript 调试器,以及代码草稿纸 —— 但它们着重于浏览器的内容进程。这意味着你可以调试你的附加组件中的框架脚本。

+ +

打开浏览器内容工具箱

+ +

{{EmbedYouTube("Cg6X_zIu7Xk")}}

+ +

要打开浏览器内容工具箱,你需要:

+ + + +

你应该已经在 Firefox 菜单中 ”Web 开发者“的子菜单中看到”浏览器内容工具箱“(或者工具菜单,如果你显示了菜单栏,或者在 OS X)。它会打开一个单独的窗口:

+ +

If you've used the Firefox Developer Tools before, this should look pretty familiar.

+ +

Along the top is a row of tabs that you can use to switch the active tool. Currently we only support the Console, the Debugger, and Scratchpad in the Browser Content Toolbox. At the right of this row are three buttons that activate the split console, open settings, and close the toolbox.

+ +

The rest of the toolbox is taken up with the tool you've currently selected.

+ +

使用

+ +

{{EmbedYouTube("XF0ULNnNOxg")}}

+ +

调试器

+ +

The Debugger lists all the scripts that are loaded into the content process. You'll find your frame scripts listed under the chrome:// URL you registered for them:

+ +

You can set breakpoints, of course, and do all the other things supported by the debugger.

+ +

控制台

+ +

The Console logs output from your frame scripts. If you want to use it to evaluate JavaScript in your frame script's scope, there's a trick you need to know:

+ + + +

Now the console's scope is your frame script's scope, and you can interact directly with it:

+ +

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/faq/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/faq/index.html new file mode 100644 index 0000000000..3299dd0856 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/faq/index.html @@ -0,0 +1,18 @@ +--- +title: FAQ +slug: Mozilla/Firefox/Multiprocess_Firefox/FAQ +translation_of: Mozilla/Firefox/Multiprocess_Firefox/FAQ +--- +
{{FirefoxSidebar}}

使命

+ +

 

+ +

历史

+ +

 

+ +

方式

+ +

 

+ +

影响

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/index.html new file mode 100644 index 0000000000..2936128948 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/index.html @@ -0,0 +1,78 @@ +--- +title: 多进程 Firefox +slug: Mozilla/Firefox/Multiprocess_Firefox +tags: + - NeedsTranslation + - TopicStub +translation_of: Mozilla/Firefox/Multiprocess_Firefox +--- +
{{FirefoxSidebar}}

在目前版本的桌面版 Firefox 中,整个浏览器运行在单个操作系统进程中。尤其是 JavaScript 在同一进程中运行着用户界面(UI,也称 "chrome 代码"),它还搭载着所有网页(也称“内容”,即“标签页”)。
+
+ 未来版本的 Firefox 将在单独的进程中运行浏览器界面,与网页内容的进程分离。这种架构的第一次迭代是所有浏览器标签页在同一个进程中运行,浏览器界面运行在另一个进程中。在未来的迭代中,我们期望有一个以上的内容进程。提供多进程 Firefox 的项目名为 Electrolysis,有时被简称为 e10s。

+ +

普通的网页不会受到多进程 Firefox 的影响。Firefox 本身和 Firefox 附加组件的开发者将受到影响,如果他们的代码依赖于能直接访问 Web 内容。

+ +

不同于此前的直接访问内容,chrome JavaScript 将使用消息管理器来访问内容。为了帮助缓解过渡期,我们实现了跨进程对象包装器(CPOW)和一些面向附加组件开发者的兼容性垫片。如果你是一名附加组件开发者并且想知道自己是否受到影响,参见多进程 Firefox 工作指南

+ +

多进程 Firefox 目前在 开发者版本 默认启用。

+ +
+
+
+
+
技术概述
+
高等层面看待多进程 Firefox 如何被实现。
+
术语表
+
多进程 Firefox 领域相关的术语参考。
+
消息管理器
+
完整的指南,在 chrome 与内容之间通信的对象。
+
基于 SDK 的附加组件
+
如何迁移使用 Add-on SDK 开发的附加组件。
+
各类 URI 在哪里加载
+
各类 URI 的快速指南:chrome:, about:, file:, resource: - 在哪个进程被加载。
+
+
+ +
+
+
动机
+
为什么我们要实现多进程的 Firefox:性能、安全和稳定性。
+
附加组件迁移指南
+
如果你是一名附加组件开发者,看看你的影响,以及如何更新你的代码。
+
跨进程对象包装器(CPOW)
+
Cross Process Object Wrappers 是一个迁移辅助,使 chrome 代码能够访问内容。
+
调试内容进程
+
如何调试运行在内容进程中的代码,包括框架和进程脚本。
+
多进程 Firefox 中的标签选择
+
多进程 Firefox 中如何切换标签页。
+
+
+
+ +
+
+
+
+
chrome 脚本的限制
+
哪些 chrome 代码的做法将不再有效,以及如何解决。
+
+
+ +
+
+
框架脚本的限制
+
哪些框架脚本的做法将不再有效,以及如何代替。
+
+
+
+ +
+

联系我们

+ +

有关此项目的更多信息、参与或提问。

+ + diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_chrome_scripts/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_chrome_scripts/index.html new file mode 100644 index 0000000000..130ce276e3 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_chrome_scripts/index.html @@ -0,0 +1,197 @@ +--- +title: chrome 脚本的限制 +slug: Mozilla/Firefox/Multiprocess_Firefox/Limitations_of_chrome_scripts +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Limitations_of_chrome_scripts +--- +
{{FirefoxSidebar}}

This page describes patterns that used to work in the chrome process that will no longer work in multiprocess Firefox. These are the sorts of things that will break an old add-on in multiprocess Firefox. The fix is generally some variant of "do that in a frame script loaded into the content process".

+ +

This is one of a pair of articles: the other one lists limitations of frame scripts.

+ +

兼容性垫片

+ +

For many of the patterns described here we've implemented compatibility shims so the patterns still work. For example: whenever extensions try to access web content from the chrome process, the browser will return a Cross Process Object Wrapper that gives the chrome code synchronous access to the content.

+ +

You'll get the shims for your add-on by default, unless you set the multiprocessCompatible flag in your add-on's install manifest.

+ +

However, these shims are not a substitute for migrating extensions:

+ + + +

For each pattern we've noted:

+ + + +

gBrowser.contentWindow, window.content...

+ +

如果没有垫片

+ +

所有在 chrome 进程中的 API 提供的直接访问内容对象将不再工作。例如:

+ +
// chrome code
+
+gBrowser.contentWindow;                    // null
+
+gBrowser.contentDocument;                  // null
+
+gBrowser.selectedBrowser.contentWindow;    // null
+
+window.content;                            // null
+
+content;                                   // null
+
+ +

特别说明,docshells 存在于内容进程,因此它们也无法访问:

+ +
gBrowser.docShell;                         // null
+
+gBrowser.selectedBrowser.docShell;         // null
+ +

如果有垫片

+ +

在这些情况下,垫片为你通过一个 CPOW 提供内容对象。

+ +

In some situations, the content process may not be initialized when an add-on asks for access to its content. In this case, the shim will return a JavaScript object that looks somewhat like a window or a document for about:blank. However, this "dummy" object is completely static and only exposes a few of the normal properties that windows and documents have. For this reason, add-ons that try to access content objects in fresh <browser> elements may run into trouble.

+ +

To make the shim unnecessary: factor the code that needs to access content into a separate script, load that script into the content process as a frame script, and communicate between the chrome script and the frame script using the message-passing APIs. See the article on using the message manager.

+ +

CPOW 的限制

+ +

跨进程对象包装器 (CPOWs) 是一个迁移辅助,给 chrome 代码带来同步访问内容对象的能力。但是,在使用它时也有各种限制

+ +

nsIContentPolicy

+ +

如果没有垫片

+ +

在多进程的 Firefox 上,你无法在 chrome  进程中使用 nsIContentPolicy,因为它需要接触网络内容。

+ +

如果有垫片

+ +

The shim enables you to add content policies in the chrome process. It transparently registers an nsIContentPolicy in the content process, whose shouldLoad just forwards to the chrome process. The content to check is forwarded as a CPOW. The chrome process then checks the content against the policy supplied by the add-on, and forwards the response back to the child to be enforced.

+ +

为了使垫片不再必要,在内容进程中定义和注册 nsIContentPolicy。如果你需要确保该政策只注册一次,使用一个 process 脚本 来注册该政策。

+ +

nsIWebProgressListener

+ +

这个 API 在 chrome 进程中工作。有一个垫片让你可以访问传递到 onStateChange nsIWebProgress  对象的 DOMWindow 属性。但是,该 DOMWindow 是异步传递,因此在 chrome 进程收到时,DOM 可能已经改变了(例如,因为代码运行的内容进程已经修改它,或者我们已经导航到另一个页面)。

+ +

还要注意,不同于其他垫片,这个垫片始终有效。

+ +

我们正在努力修复此问题,见 bug 1118880

+ +

另外,你可以在内容进程中使用 nsIWebProgressListener

+ +

chrome 进程中的 Observers

+ +

根据不同的主题,你需要在 chrome 进程或者一个框架脚本中注册 observers。

+ +

对于大多数主题,你需要在 chrome 进程中注册 observers。

+ +

但是,你必须在一个框架脚本中监听 content-document-global-created and document-element-inserted。这些主题的 Observers 获取内容对象并作为 aSubject 参数到 observe(),因此通知不会发送到 chrome 进程。

+ +

有一个垫片会将两个主题转发到 chrome 进程,将 CPOWs 发送为 aSubject 参数。

+ +

HTTP 请求

+ +

你不能观测(observe)内容进程中的 HTTP 请求。如果这样做,你将得到一个错误。
+
+ 如果你在 chrome 进程中这样做,它一般会工作。observer 通知的主题将是一个 nsIHttpChannel,正如你所期望的。

+ +

A common pattern here is to use the notificationCallbacks property of the nsIHttpChannel to get the DOM window that initiated the load, like this:

+ +
observe: function (subject, topic, data) {
+  if (topic == "http-on-modify-request") {
+    var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
+    var domWindow = httpChannel.notificationCallbacks.getInterface(Ci.nsIDOMWindow);
+  }
+}
+ +

或者这样:

+ +
observe: function (subject, topic, data) {
+  if (topic == "http-on-modify-request") {
+    var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
+    var domWindow = httpChannel.notificationCallbacks.getInterface(Ci.nsILoadContext).associatedWindow;
+  }
+}
+ +

In multiprocess Firefox these patterns will no longer work: the getInterface call will fail.

+ +

In multiprocess Firefox, notificationCallbacks is a special object that tries to emulate the single-process notificationsCallbacks object as best it can. It will return a dummy nsILoadContext when asked, but any attempt to get a window out of it will fail.
+
+ There is an outstanding bug (bug 1108827) to implement a shim here that will make notificationCallbacks a CPOW for the objects in the content process.

+ +

The correct way to access the DOM window is through a message manager. In an HTTP observer, you can get the browser message manager for the window using code like this:

+ +
observe: function (subject, topic, data) {
+  if (topic == "http-on-modify-request") {
+    var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
+    var loadContext = httpChannel.notificationCallbacks.getInterface(Ci.nsILoadContext);
+    // topFrameElement is the <browser> element
+    var topFrameElement = loadContext.topFrameElement;
+    var browserMM = topFrameElement.messageManager;
+    console.log("browserMM: " + browserMM);
+  }
+}
+ +

However, before Firefox 38, this technique will not work if multiprocess Firefox is disabled: specifically, topFrameElement will be null. This means that if you need to write code that works before Firefox 38 and on both multiprocess and non-multiprocess variants, you need to implement both paths:

+ + + +

From Firefox 38 onwards, the topFrameElement approach always works.

+ +

DOM 事件

+ +

如果没有垫片

+ +

In multiprocess Firefox, if you want to register an event listener on some content DOM node, that needs to happen in the content process.

+ +

It used to be that if you registered a listener on the XUL <browser>  or <tab> element that hosted some DOM content, then events in the content would bubble up to the XUL and you could handle them there. This no longer happens in multiprocess Firefox.

+ +

如果有垫片

+ +

The shim intercepts chrome process code that adds listeners to XUL elements and sets up listeners in the content process, relaying the result back to the chrome process. The Event object itself is relayed to the chrome process as a CPOW.

+ +

To make the shim unnecessary: register event listeners on the global object inside a frame script. For example:

+ +
addEventListener("load", handler, true) // for example
+ +
如果你需要在这时联系 chrome 进程,发送一个消息。
+ +
 
+ +

沙盒

+ +
You can create sandboxes in the chrome or the content process. Sandboxes are often used as a safe way to manipulate web content, and if that's your goal, create the sandbox in the content process.
+ +
 
+ +
There is a shim for sandboxes: if you make a sandbox in the chrome process and give it content principals (by passing a CPOW as the first argument to Components.utils.Sandbox) then we'll actually make it in the content process.
+ +
 
+ +
+

nsIAboutModule

+ +

By default, custom about: pages registered using nsIAboutModule are loaded in the chrome process. This means that you can't access their content from the content process (via XHR, for example).

+ +

你可以在你注册 about: URI 的代码中改变这个默认值。见 about: 和 chrome: URI

+
+ +

JavaScript 代码模块 (JSM)

+ +
在单进程的 Firefox 中,你可以使用 JavaScript 代码模块 (JSM) 来维持全局状态。在多进程的 Firefox 中,一个加载到某个进程的 JSM 不与加载到另一个进程的同样 JSM 共享状态:因此你不能使用一个 JSM 在 chrome 和内容进程之间共享状态。
+ +
 
+ +
If an add-on wants to use a JSM to share state in this way, it's best to load the JSM in the chrome process, and have frame scripts store and access the JSM's state by sending messages to the chrome process using the message manager.
diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_frame_scripts/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_frame_scripts/index.html new file mode 100644 index 0000000000..d942067bd3 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/limitations_of_frame_scripts/index.html @@ -0,0 +1,101 @@ +--- +title: 框架脚本的限制 +slug: Mozilla/Firefox/Multiprocess_Firefox/Limitations_of_frame_scripts +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Limitations_of_frame_scripts +--- +
{{FirefoxSidebar}}

框架脚本使用系统特权运行,并且能够访问 Components 对象,使它们能够使用 XPCOM 对象和 JSM。许多特权的 API 在内容进程中仍然工作。数据结构的处理仍将工作。XHR 和 Workers 仍将工作。但是,某些 API 在 chrome 进程中工作,但在框架脚本中将不工作。本文列出最重要的那些 API。

+ +

这是一对文章之一,另一篇是:chrome 脚本的限制

+ +

文件 I/O

+ +

你不应该从内容脚本写入或者读取磁盘,特别是配置文件目录。即使这是可能的,你也不应该这样做,应该预期它可能在任何时间停止工作。文件 I/O 应该全部放在 chrome 进程完成。例如:

+ + + +

XUL 和浏览器界面

+ +

任何试图接触界面或者与 XUL 相关的东西都很可能在内容进程中不工作。例如:

+ + + +

Services

+ +

某些服务不能在框架脚本中工作。

+ + + +

Chrome 窗口

+ +

任何需要使用 chrome 窗口的东西都不能在内容进程中工作。例如:

+ + + +

Places API

+ +

Places API 不能在框架脚本中使用。例如:

+ + + +

内容进程中的 Observers

+ +

As noted in Observers in the chrome process, most observers should be registered in the chrome process and will not work in the content process. The exceptions are:

+ + + +

这些必须在内容进程中注册。

+ +

内容窗口到 chrome 窗口的 QI

+ +
There's a particular pattern often used to get from a content window to the associated chrome window. It looks something like this:
+ +
 
+ +
window.QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIWebNavigation)
+                         .QueryInterface(Ci.nsIDocShellTreeItem)
+                         .rootTreeItem
+                         .QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIDOMWindow);
+ +
This will no longer work. In the content process the root tree item is an nsITabChild, that cannot be converted to an nsIDOMWindow, so the second getInterface call here will fail.
+ +
 
+ +

If you want a chrome window: send a message from the content process using the message manager. The target property of the object passed into the message handler in the chrome process is the XUL <browser> receiving the message, and you can get the chrome window from that (Note: I'm not really sure how...).

+ +

nsIAboutModule

+ +

默认情况下,使用 nsIAboutModule  注册的自定义的 about: 页面在 chrome 进程中加载。这意味着你不能从内容进程访问它们的内容(比如通过 XHR)。

+ +

你可以在注册 about: URI 的代码中更改这个默认值。见 about: 和 chrome: URI

+ +

JavaScript 代码模块 (JSM)

+ +
在多进程的 Firefox 中,一个加载到内容进程的 JSM 不予加载到 chrome 进程的同一个 JSM 共享任何状态。参考 chrome 脚本的限制 页面中的内容。
diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/communicating_with_frame_scripts/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/communicating_with_frame_scripts/index.html new file mode 100644 index 0000000000..9c8abfa1c9 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/communicating_with_frame_scripts/index.html @@ -0,0 +1,205 @@ +--- +title: 与框架脚本通信 +slug: >- + Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Communicating_with_frame_scripts +translation_of: >- + Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Communicating_with_frame_scripts +--- +
{{FirefoxSidebar}}

Chrome 的代码与框架脚本的往来通信采用消息 API,它可以包含可 JSON 序列化的对象作为参数。

+ +

这个 API 大多是对称的,但有一个主要的例外:框架脚本可以发送同步或者异步消息到 chrome,但 chrome 只能发送异步消息到内容。这是一种有意的设计,是为了防止内容不响应而导致的 chrome 失去响应。
+
+ 在绝对必要时,框架脚本可以通过被称为 跨进程对象包装器(也称 CPOWs)的东西到达 chrome,并且 chrome 可以使用这些包装器来获得到内容对象的同步访问。

+ +

内容到 chrome

+ +

框架脚本可以选择发送同步消息或者异步消息到 chrome 代码。

+ +

异步消息

+ +

要发送异步消息,内容脚本应使用 sendAsyncMessage() 函数:

+ +
// frame script
+sendAsyncMessage("my-addon@me.org:my-e10s-extension-message");
+ +

sendAsyncMessage() takes one mandatory parameter, which is the name of the message. All messages share the same namespace, so to avoid conflicts with other code, you'll need to ensure that the names you use are unique. If you're using the message manager in an add-on, a good way to do that is to prefix messages with your add-on's ID.

+ +

After the name, you can pass detailed data as a string or a JSON-serializable object, and after that you can pass any objects it wants to pass to content as CPOWs.

+ +

The example below sends a message named "my-e10s-extension-message", with a data payload containing details and tag properties, and exposes the event.target object as a CPOW:

+ +
// frame script
+addEventListener("click", function (event) {
+  sendAsyncMessage("my-addon@me.org:my-e10s-extension-message", {
+    details : "they clicked",
+    tag : event.target.tagName
+  },
+  {
+     target : event.target
+  });
+}, false);
+ +

要接收来自内容的消息,一个 chrome 脚本需要使用消息管理器的 addMessageListener() API 添加消息监听器:
+
+ 传递给监听器的消息是一个对象,包含下列属性:

+ + + + + + + + + + + + + + + + + + + + + + + + +
name字符串,包含消息的名称。
sync布尔值,表示消息是否为同步发送,或者是异步发送。
dataJSON 对象,作为传递给 sendAsyncMessage() 的第二个参数。
target这是 XUL 的 <browser> 元素,来自消息发送的位置。
objectsAn object whose properties are any CPOWs exposed by the sender as the third argument to sendAsyncMessage()
+ +

在下面的例子中,监听器只是记录所有的消息细节;

+ +
// chrome script
+messageManager.addMessageListener("my-addon@me.org:my-e10s-extension-message", listener);
+
+function listener(message) {
+  console.log(message.name);
+  console.log(message.sync);
+  console.log(message.data);
+  console.log(message.target);
+  console.log(message.objects);
+}
+
+ +

So combining this message listener with the message above will give console output somewhat like this, when the user clicks a <div>:

+ +
"my-addon@me.org:my-e10s-extension-message"
+false
+Object { details: "they clicked", tag: "div" }
+<xul:browser anonid="initialBrowser" ... >
+{ target: <div#searchContainer> }
+
+ +

If your code requires access to a window (for example to run window.openDialog), and your message listener is run from somewhere without access to a window (e.g. an XPCOM component), you can access the window of the browser that sent the message with message.target.ownerDocument.defaultView.

+ +

同步消息

+ +

要发送一个同步消息,框架脚本应使用全局的 sendSyncMessage()  函数:

+ +
// frame script
+sendSyncMessage("my-addon@me.org:my-e10s-extension-message");
+ +

在一个 chrome 脚本收到一个同步消息时,它应该从它的消息监听器返回一个值:

+ +
// chrome script
+messageManager.addMessageListener("my-addon@me.org:my-e10s-extension-message", listener);
+
+function listener(message) {
+  return "value from chrome";
+}
+ +

This value is then presented to the frame script in the return value of sendSyncMessage(). Because a single message can be received by more than one listener, the return value of sendSyncMessage() is an array of all the values returned from every listener, even if it only contains a single value:

+ +
// frame script
+addEventListener("click", function (event) {
+  var results = sendSyncMessage("my-addon@me.org:my-e10s-extension-message", {
+    details : "they clicked",
+    tag : event.target.tagName
+  });
+  content.console.log(results[0]);    // "value from chrome"
+}, false);
+ +

Like arguments, return values from sendSyncMessage() must be JSON-serializable, so chrome can't return functions.

+ +

removeMessageListener()

+ +

要停止监听来自内容的消息,使用消息管理器的 removeMessageListener() 方法:

+ +
// chrome script
+messageManager.removeMessageListener("my-addon@me.org:my-e10s-extension-message", listener);
+ +

Chrome 到内容

+ +

要从 chrome 发送一个消息到内容,你需要知道你正在使用什么类型的消息管理器。如果它是一个浏览器消息管理器,你可以使用消息管理器的 sendAsyncMessage  方法:

+ +
// chrome script
+browser.messageManager.sendAsyncMessage("my-addon@me.org:message-from-chrome");
+ +

如果你有一个窗口或者全局消息管理器,你需要使用 broadcastAsyncMessage 方法:

+ +
// chrome script
+window.messageManager.broadcastAsyncMessage("my-addon@me.org:message-from-chrome");
+ +

These methods takes one mandatory parameter, which is the message name. All messages share the same namespace, so to avoid conflicts with other code, you'll need to ensure that the names you use are unique. If you're using the message manager in an add-on, a good way to do that is to prefix messages with your add-on's ID.

+ +

在消息名称后,你可以将详细的数据传递为一个字符串或者一个可 JSON 序列化的对象:

+ +
// chrome script
+messageManager.sendAsyncMessage("my-addon@me.org:message-from-chrome", {
+  details : "some more details"
+});
+ +

To receive a message from chrome, a frame script uses the global addMessageListener() function. This takes two parameters: the name of the message and a listener function. The listener will be passed a message object whose data property is the message payload:

+ +
// frame script
+function handleMessageFromChrome(message) {
+  var payload = message.data.details;      // "some more details"
+}
+
+addMessageListener("my-addon@me.org:message-from-chrome", handleMessageFromChrome);
+ +

message-manager-disconnect

+ +

If you're using a message manager to communicate with a script that may be running in a different process, you can listen for the message-manager-disconnect observer notification to know when the message manager has disconnected from the other end of the conversation, so you can stop sending it messages or expecting to receive messages.

+ +

For example, suppose we load a script into the current <browser> on some event, and keep the browser message manager in an array, so we can send it messages:

+ +
var messageManagers = [];
+
+...
+
+// on some event
+var browserMM = gBrowser.selectedBrowser.messageManager;
+browserMM.loadFrameScript("chrome://my-addon@me.org/content/frame-script.js", false);
+messageManagers.push(browserMM);
+console.log(messageManagers.length);
+ +

We can listen for message-manager-disconnect to update the array when the message managers disconnect (for example because the user closed the tab):

+ +
function myObserver() {
+}
+
+myObserver.prototype = {
+  observe: function(subject, topic, data) {
+    var index = messageManagers.indexOf(subject);
+    if (index != -1) {
+      console.log("one of our message managers disconnected");
+      mms.splice(index, 1);
+    }
+  },
+  register: function() {
+    var observerService = Cc["@mozilla.org/observer-service;1"]
+                          .getService(Ci.nsIObserverService);
+    observerService.addObserver(this, "message-manager-disconnect", false);
+    console.log("listening");
+  },
+  unregister: function() {
+    var observerService = Cc["@mozilla.org/observer-service;1"]
+                            .getService(Ci.nsIObserverService);
+    observerService.removeObserver(this, "message-manager-disconnect");
+  }
+}
+
+var observer = new myObserver();
+observer.register();
diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_environment/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_environment/index.html new file mode 100644 index 0000000000..8d5e9d287b --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_environment/index.html @@ -0,0 +1,104 @@ +--- +title: 框架脚本环境 +slug: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_environment +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_environment +--- +
{{FirefoxSidebar}}

框架脚本的全局是 ContentFrameMessageManager,提供下列环境:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
contentThe DOM window of the content loaded in the browser. may be null (see below)
docShellThe nsIDocShell associated with the browser.
addEventListener()Listen to events from content.
removeEventListener()Stop listening to events from content.
addMessageListener()Listen to messages from chrome.
removeMessageListener()Stop listening to messages from chrome.
sendAsyncMessage()Send an asynchronous message to chrome.
sendSyncMessage()Send a synchronous message to chrome.
dump()Print a message to the console.
atob()Base64 decode.
btoa()Base64 encode.
ComponentsThe usual Components object.
+ +

特别注意,框架脚本使用 content 访问 DOM 窗口,而不是 window

+ +
// frame script
+var links = content.document.getElementsByTagName("a");
+ +

All the frame scripts running in a tab share this global. However, any top-level variables defined by a script are not stored on the global: instead, top-level variables are stored in a special per-script object that delegates to the per-tab global. This means you don't have to worry about global variables you define conflicting with global variables defined by another frame script. You can still access the global directly via this.

+ +

框架脚本使用系统主体运行。如果你想使用其他主题,可以使用 Sandbox

+ +

Frame scripts run with system privileges and have access to the Components object, enabling them to use XPCOM objects and JSMs. However, some APIs  that work in the chrome process will not work in a frame script. See Limitations of frame scripts for more details.

+ +

事件

+ +

Besides the regular DOM events being captured/bubbling up from content the current content object the following additional events get fired in a frame script environment:

+ + + + + + + + + + + + +
unload +
+
Bubbles
+
No
+
+ +

Fires when the frame script environment is shut down, i.e. when a tab gets closed.

+ +

If you use a capturing event listener on the ContentFrameMessageManager, you should verify that its event.target is set to the ContentFrameMessageManager global object in order to avoid handling unload events from content.

+
DOMWindowCreated +

Fires when a new content object is created.
+
+ This can be used if a framescript needs to interact with individual DOM windows instead of simply listening for events bubbling up from content.
+ Another use is to interact with the content very early in the page load process, long before DOMContentLoaded event is fired.
+  

+
+ +

 

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_loading_and_lifetime/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_loading_and_lifetime/index.html new file mode 100644 index 0000000000..ee53fe52e2 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/frame_script_loading_and_lifetime/index.html @@ -0,0 +1,124 @@ +--- +title: 框架脚本的加载与寿命 +slug: >- + Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_loading_and_lifetime +translation_of: >- + Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_loading_and_lifetime +--- +
{{FirefoxSidebar}}

加载框架脚本

+ +

要加载一个框架脚本,使用 loadFrameScript() 函数。

+ +

这行代码加载一个框架脚本到当前选中的标签页。该框架脚本只是将 "foo" 写入到命令行:

+ +
// chrome script
+var mm = gBrowser.selectedBrowser.messageManager;
+mm.loadFrameScript('data:,dump("foo\\n")', true);
+ +

loadFrameScript() 有两个强制性参数:

+ + + +

Note that if the message manager is a global frame message manager or a window message manager then loadFrameScript() may load the script multiple times, once into each applicable frame.

+ +

chrome: URL

+ +

扩展开发者通常会使用 chrome:// URL 来指向一个框架脚本。

+ +

要定义 chrome:// URL 的映射和将一个框架脚本打包到扩展中,使用 "chrome.manifest" 文件来 注册一个chrome URL

+ +
// chrome.manifest
+content my-e10s-extension content.js
+ +
// chrome script
+mm.loadFrameScript("chrome://my-e10s-extension/content/content.js", true);
+ +

allowDelayedLoad

+ +

如果消息管理器是一个 全局框架消息管理器 或者一个 窗口消息管理器,那么:

+ + + +

如果消息管理器是一个 浏览器消息管理器,你应该始终在这里传递 true。因为一个浏览器消息管理器永远只对应一个浏览器标签页,它的 loadFrameScript() 函数只加载框架脚本到一个标签页。因此传递 allowDelayedLoad 仅仅是一个方法来确保脚本被正确加载,在你的标签页在执行后还没有准备好时。

+ +

如果你使用 allowDelayedLoad,你可以使用 removeDelayedFrameScript 取消它:

+ +
var mm = window.messageManager;
+mm.removeDelayedFrameScript("chrome://my-e10s-extension/content/frame-script.js");
+ +

这意味着我们将停止加载脚本到新的标签页。请注意,此函数不会移除已经加载的任何脚本。

+ +

框架脚本的寿命

+ +

框架脚本将在 loadFrameScript() 被调用后尽快加载。如果你设置了 allowDelayedLoad,脚本将加载到一个新的标签页,一旦其已被创建。

+ +

框架脚本与浏览器的标签页相关联,而不是与页面。因此一旦你加载它们,它们就会持续存在,直至标签页被关闭,因此即便你重新加载或者文档重新导航也不会丢失。

+ +

如果你想一个框架脚本在每次新文档被加载后执行操作,你需要监听一个适当的 DOM 事件,通常是 DOMWindowCreated, DOMContentLoaded,  或者 load

+ +

卸载框架脚本

+ +

框架脚本会在托管它们的标签页被关闭时自动卸载。目前还没有办法在已加载它们的标签页之中卸载它们,除了关闭标签页。

+ +

若要监听你的框架脚本被卸载的事件(例如由于标签页被关闭),你必须将 addMessageListener 的第三个参数设置为 true,例如下面的 bootstrap.js 的代码:

+ +
Services.mm.addMessageListener(
+    'my-addon-id',
+    {
+        receiveMessage: function() {
+            console.log('incoming message from frame script:', aMsg.data);
+        }
+    },
+    true // must set this argument to true, otherwise sending message from framescript will not work during and after the unload event on the ContentMessageManager triggers
+);
+ +

and then in your frame script listen for the unload event of the message manager (which is the global this), and then send a message. If you did not set third argument to true in bootstrap.js on Services.mm.addMessageListener, then this send message during and after unload event, will do nothing.

+ +
var gContentFrameMessageManager = this;
+
+addEventListener('unload', function(aEvent) {
+    if (aEvent.target == gContentFrameMessageManager) {
+        sendAsyncMessage('my-addon-id', 'framescript-died'); // if you did not set third argument of `Services.mm.addMessageListener` to `true`, then this will fail to send a message
+    }
+}, false);
+ +

有关卸载/升级操作时的卸载

+ +

在你的附加组件被卸载或禁用时,你应该:

+ + + +
+
+

There is a bug in non-e10s where this oder is not true. In e10s framescripts work fine on updating. For non-e10s waiting for Bug 1202125 - framescripts are not backwards loaded in message order in non-e10s.

+
+ +

Note: you might think that there is a race condition here due to the asynchronous nature of the message passing:

+ + + +

In fact, the message manager guarantees that loadFrameScript and broadcastAsyncMessage are guaranteed to affect frame scripts in the order that they are called, so in this case "disable" will be received and consumed before the new frame scripts are loaded.

+
+ +

At the moment frame scripts are cached until the browser restarts: this problem is tracked as bug 1051238. This is especially a problem for restartless add-ons, because when a new version of the add-on is installed, the old frame scripts will not be unloaded. The workaround here is to randomize the frame script's URL, for example by appending "?" + Math.random() to it.

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/index.html new file mode 100644 index 0000000000..be6ba855c9 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/index.html @@ -0,0 +1,68 @@ +--- +title: 消息管理器 +slug: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager +--- +
{{FirefoxSidebar}}

消息管理器为 chrome 特权的 JavaScript 代码提供了跨进程边界的通信方式。它非常有用,可以允许 chrome 代码(包括浏览器自身的代码和外部代码)访问在单独的进程中运行的网页内容。

+ +

这些指南介绍了如何在多进程 Firefox 中使用消息管理器。

+ +

请注意,多进程 Firefox 的环境并非是必须的:这里描述的一切对单进程 Firefox 也同样有效,所以相同的代码在两个环境下都可以正常工作。

+ +
+

指南

+ +
+ + + +
+ +
+

API 参考资料

+ +
+ + + +
diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/message_manager_overview/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/message_manager_overview/index.html new file mode 100644 index 0000000000..fb85fa5e79 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/message_manager_overview/index.html @@ -0,0 +1,442 @@ +--- +title: 消息管理器概述 +slug: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview +--- +
+

在多进程 Firefox 中有两个进程:

+ + + +

消息管理器的设计目的是使运行在一个进程中的 chrome 特权的 JavaScript 代码能够与不同进程中的 chrome 特权的 JavaScript 代码通信。

+ +

本文介绍了几种类型的消息管理器,如何访问它们,以及在一个较高层面你可以使用什么。

+
+ +

在顶层,有两种不同类型的消息管理器:

+ + + +

框架消息管理器

+ +

在多进程 Firefox 中,当 chrome 代码需要与网页内容交互时,它需要:

+ + + +
+

Some older articles on multiprocess Firefox and the message manager might refer to "content scripts" instead of "frame scripts", but this usage is deprecated because the Add-on SDK uses "content script" to refer to a similar but different kind of script.

+
+ +

因此从根本上,框架消息管理器使 chrome 代码能够:

+ + + +

有多种类型的框架消息管理器,如图所示:

+ +

+ +

This diagram shows the setup when there are 2 browser windows open, one with 2 tabs open and one with 1 tab open.

+ +

Chrome 进程

+ +

In the chrome process, there's a hierarchy of frame message managers: the global frame message manager, window message managers, and browser message managers.

+ +

全局框架消息管理器

+ + + + + + + + + + + + + + + + +
Description +

There's a single global frame message manager in the chrome process.

+ +

This operates on all frames, in all content tabs. If you load a frame script using the global frame message manager, the script gets loaded separately into every open tab: three times, in the diagram above. Similarly, if you send a message using the global frame message manager, it's received by all content tabs, and is then delivered to any frame scripts that are listening for it.

+ +

Its most important functions and attributes are:

+ +

childCount : contains the number of children (typically, browser windows)

+ +

getChildAt() : get the child at the given index

+ +

loadFrameScript() : load a frame script into every tab in the browser

+ +

broadcastAsyncMessage() : send a message to frame scripts

+ +

addMessageListener() : start listening to a specific message from all frame scripts

+ +

removeMessageListener() : stop listening to a specific message

+
Interfaces +

nsIFrameScriptLoader

+ +

nsIMessageListenerManager

+ +

nsIMessageBroadcaster

+
How to access +

Access it using Components.classes:

+ +
+// chrome script
+let globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+  .getService(Ci.nsIMessageListenerManager);
+
+ +

窗口消息管理器

+ + + + + + + + + + + + + + + + +
Description +

There's a window message manager for every browser window: two, in the diagram above.

+ +

It operates on all content tabs in a given window. If you load a frame script using the window message manager it gets loaded separately into each tab open in that particular window. If you send a message using the window message manager, it gets sent to all content tabs in that window.

+ +

Its most important functions and attributes are:

+ +

childCount : contains the number of children (typically, browser tabs)

+ +

getChildAt() : get the child at the given index

+ +

loadFrameScript() : load a frame script into every tab in this window

+ +

broadcastAsyncMessage() : send a message to all frame scripts in this window

+ +

addMessageListener() : start listening to a specific message from frame scripts

+ +

removeMessageListener() : stop listening to a specific message

+
Interfaces +

nsIFrameScriptLoader

+ +

nsIMessageListenerManager

+ +

nsIMessageBroadcaster

+
How to access +

You can access it as a property of the browser window:

+ +
+// chrome script
+let windowMM = window.messageManager;
+
+ +

浏览器消息管理器

+ +
+

Note that in this context, "browser" refers to the XUL <browser> object, which is a frame that hosts a single Web document. It does not refer to the more general sense of a Web browser.

+
+ + + + + + + + + + + + + + + + +
Description +

Finally, there's a browser message manager for every open content tab: three, in the diagram above.

+ +

This corresponds one-to-one with a content tab. Scripts you load using a browser message manager are loaded only into that content tab, and messages you send are delivered only to that content tab.

+ +

You can mix and match: so for example, you could load a script into every tab using the global message manager, but then send a message to the script instance loaded into a specific tab by using the browser message manager.

+ +

Its most important functions are:

+ +

loadFrameScript() : load a frame script into this browser frame (tab)

+ +

sendAsyncMessage() : send a message to all frame scripts in this browser frame

+ +

addMessageListener() : start listening to a specific message from frame scripts

+ +

removeMessageListener() : stop listening to a specific message

+
Interfaces +

nsIProcessChecker

+ +

nsIFrameScriptLoader

+ +

nsIMessageListenerManager

+ +

nsIMessageSender

+
How to access +

The browser message manager can be accessed as a property of the XUL <browser> element:

+ +
+// chrome script
+let browserMM = gBrowser.selectedBrowser.messageManager;
+
+ +

内容进程

+ +

内容框架消息管理器

+ + + + + + + + + + + + + + + + +
Description +

There's a content frame message manager for every open tab. It's the content-side end of frame message manager conversations.

+ +

Frame scripts are loaded into the content frame message manager scope, and messages from chrome message managers end up here.

+ +

The content frame message manager provides the global object for frame scripts (but note that there is trickery to ensure that top-level variables defined by frame scripts are not shared).

+ +

Frame scripts can use this object to send messages to the chrome process, and to receive messages from the chrome process.

+ +

Its most important attributes and functions are:

+ +

content : access the DOM window hosted by the tab

+ +

docShell : access the top-level docshell

+ +

Components : access privileged objects and APIs

+ +

addEventListener() : listen to DOM events

+ +

addMessageListener() : receive messages from the chrome process

+ +

sendAsyncMessage() : send asynchronous messages to the chrome process

+ +

sendSyncMessage() : send synchronous messages to the chrome process

+
Interfaces +

nsIDOMEventTarget

+ +

nsIMessageListenerManager

+ +

nsIMessageSender

+ +

nsISyncMessageSender

+ +

nsIContentFrameMessageManager

+
How to accessThe content frame message manager is the global object in frame scripts.
+ +

进程消息管理器

+ +

Process message managers correspond to process boundaries, and enable code running in different processes to communicate. Multiprocess Firefox has the concept of:

+ + + +

For practical purposes, in multiprocess Firefox the parent process is the chrome process, and child processes are content processes. 

+ +

In each child process, there's a single child process message manager (CPMM). There's also an additional child-in-process message manager (CIPMM) in the parent process.

+ +

For each child process message manager, there's a parent process message manager (PPMM) in the parent process.

+ +

There's also a single global parent process message manager (GPPMM) in the parent process, that provides access to all the parent process message managers. The diagram below shows the setup that would result from having two child processes:

+ +

+ +

With the GPPMM, you can broadcast messages to the CIPMM and all CPMMs. With a PPMM, you can send a message to its corresponding CPMM. With a CPMM, you can send messages to the parent process: these messages are received first by the corresponding PPMM, then by the GPPMM.

+ +

From Firefox 38 onwards, you can also use a parent process message manager to load a script into a child process. This is the recommended way to load a script that executes just once per child process, which is something you might want to do if you are interacting with some global service (for example, adding listeners to observer notifications or registering a content policy).

+ +

父消息管理器

+ +

全局父进程消息管理器

+ + + + + + + + + + + + + + + + +
Description +

The global parent process message manager (GPPMM) is global to the parent process.

+ +
    +
  • Messages sent using the GPPMM get sent to all CPMMs in all child processes.
  • +
  • Process scripts loaded using the GPPMM get loaded in all child processes.
  • +
+ +

Its most important functions and attributes are:

+ +

childCount : contains the number of children (child processes, plus the in-content child)

+ +

getChildAt() : get the child at the given index

+ +

loadProcessScript() : load a process script into every content process

+ +

broadcastAsyncMessage() : send a message to all process scripts

+ +

addMessageListener() : start listening to a specific message from process scripts

+ +

removeMessageListener() : stop listening to a specific message

+
Interfaces +

nsIProcessScriptLoader

+ +

nsIMessageListenerManager

+ +

nsIMessageBroadcaster

+
How to access +

You can access the GPPMM with code like this:

+ +
+// parent process
+let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+           .getService(Ci.nsIMessageBroadcaster);
+ +

You can also access it as the ppmm property of Services.jsm, if you are in the parent process.

+
+ +

父进程消息管理器

+ + + + + + + + + + + + + + + + +
Description +

There's one parent process message manager (PPMM) in the parent process for every child process, and its API is oriented to that one child process.

+ +
    +
  • Messages sent using the PPMM are received only by the corresponding CPMM
  • +
  • Scripts loaded using the PPMM are loaded only into the corresponding child process.
  • +
+ +

Its most important functions are:

+ +

loadProcessScript() : load a process script into the content process

+ +

broadcastAsyncMessage() : send a message to process scripts

+ +

addMessageListener() : start listening to a specific message from process scripts

+ +

removeMessageListener() : stop listening to a specific message

+
Interfaces +

nsIProcessChecker

+ +

nsIProcessScriptLoader

+ +

nsIMessageListenerManager

+ +

nsIMessageSender

+
How to access +

You can access a PPMM using the getChildAt() function in the GPPMM:

+ +
+// parent process
+let ppmm = Services.ppmm.getChildAt(1);
+
+ +

子进程

+ +

子进程消息管理器

+ + + + + + + + + + + + + + + + +
Description +

There's one child process message manager (CPMM) in each child process. Messages sent using the CPMM are sent to the corresponding PPMM and are also relayed to the GPPMM.

+ +

Its most important attributes and functions are:

+ +

Components : access privileged objects and APIs

+ +

addMessageListener() : receive messages from the parent process

+ +

sendAsyncMessage() : send asynchronous messages to the parent process

+ +

sendSyncMessage() : send synchronous messages to the parent process

+
Interfaces +

nsIMessageListenerManager

+ +

nsIMessageSender

+ +

nsISyncMessageSender

+ +

nsIContentProcessMessageManager

+
How to access +

Code running in a child process can access the CPMM with code like this:

+ +
+// child process script
+let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+           .getService(Ci.nsISyncMessageSender);
+ +

You can also access it as the cpmm property of Services.jsm, if you are in the child process.

+
diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/performance/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/performance/index.html new file mode 100644 index 0000000000..3bcb04d88e --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/message_manager/performance/index.html @@ -0,0 +1,292 @@ +--- +title: 性能 +slug: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Performance +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Message_Manager/Performance +--- +
{{FirefoxSidebar}}

着重讲几点框架脚本/消息管理器的使用方式和替代方法,以避免相关的性能缺陷。

+ +

要牢记几点:

+ + + +
+

下面的例子为了简洁,省略了一些样板代码

+ +

“更好”的例子还省略了一些最佳实践。只是为了演示如何解决各子主题中描述的问题。

+
+ +

性能的最佳实践

+ +

每个进程中声明无状态函数

+ +

不良:

+ +
// addon.js
+Services.mm.loadFrameScript("framescript.js", true)
+
+ +
// framescript.js
+
+const precomputedConstants = // ...
+
+function helper(window, action) {
+  // ...  do some work on the window
+}
+
+function doSomething(message) {
+  result = helper(content, message.data)
+  sendAsyncMessage("my-addon:response-from-child", {something: result})
+}
+
+addMessageListener("my-addon:request-from-parent", doSomething)
+
+ +

 

+ +

Why is this bad? Because declared functions are also objects. And since frame scripts get evaluated for each tab this means new function objects get instantiated, new constants get computed, block scopes must be set up etc.

+ +

While it may seem fairly innocencous in this toy example, real scripts often have a lot more functions and initialize some fairly heavyweight objects.

+ +

更好:

+ +

addon.js 如上

+ +
// framescript.js
+Components.utils.import("resource://my-addon/processModule.jsm", {}).addFrame(this)
+
+ +
// processModule.jsm
+
+const EXPORTED_SYMBOLS = ['addFrame'];
+
+const precomputedConstants = // ...
+
+function helper(window, action) {
+  // ... do some work on the window
+}
+
+function doSomething(message) {
+  frameGlobal = message.target
+  result = helper(frameGlobal.content, message.data)
+  frameGlobal.sendAsyncMessage("my-addon:response-from-child", {something: result})
+}
+
+function addFrame(frameGlobal) {
+  frameGlobal.addMessageListener("my-addon:request-from-parent", doSomething)
+}
+
+ +

Javascript modules are per-process singletons and thus all their objects are only initialized once, which makes them suitable for stateless callbacks.
+
+ But care must be taken to not leak references to the frame script global when it is passed into a JSM. Alternatively the frame's unload event or weak maps can be used to ensure that frames can be cleaned up when their respective tab is closed.

+ +

每个进程中存放重量级的状态

+ +

不良:

+ +
// addon.js
+var main = new MyAddonService();
+
+main.onChange(stateChange);
+
+function stateChange() {
+  Services.mm.broadcastAsyncMessage("my-addon:update-configuration", {newConfig: main.serialize()})
+}
+
+ +
// framescript.js
+var mainCopy;
+
+function onUpdate(message) {
+   mainCopy = MyAddonService.deserialize(message.data.newConfig);
+}
+
+addMessageListener("my-addon:update-configuration", onUpdate)
+
+
+// mainCopy used by other functions
+
+ +

The main issue here is that a separate object is kept for each tab. Not only does that increase memory footprint but the deserialization also has to be executed seperately for each tab, thus requiring more CPU time.

+ +

不良:

+ +
// addon.js
+var main = new MyAddonService();
+
+main.onChange(stateChange);
+
+function stateChange() {
+  Services.ppmm.broadcastAsyncMessage("my-addon:update-configuration", {newConfig: main.serialize()})
+}
+ +
// processModule.jsm
+const EXPORTED_SYMBOLS = ['getMainCopy'];
+
+var mainCopy;
+
+Services.cpmm.addMessageListener("my-addon:update-configuration", function(message) {
+  mainCopy = message.data.newConfig;
+})
+
+funtion getMainCopy() {
+  return mainCopy;
+}
+
+
+ +
// framescript.js
+Components.utils.import("resource://my-addon/processModule.jsm")
+
+// getMainCopy() used by other functions
+
+ +

 

+ +

不要在框架脚本中注册观察者(及其他到全局服务的回调)

+ +

不良:

+ +
//framescript.js
+Services.obs.addObserver("document-element-inserted", {
+  observe: function(doc, topic, data) {
+     if(doc.ownerGlobal.top != content)
+        return; // bail out if  this is for another tab
+     decorateDocument(doc);
+  }
+})
+ +

Observer notifications get fired for events that happen anywhere in the browser, they are not scoped to the current tab. If each framescript registers a seperate listener then the observed action will trigger the callbacks in all tabs.

+ +

Additionally the example above does not clean unregister itself, thus leaking objects each time a tab is closed. Frame message manager  message and event listeners are limited in their lifetime to that of the frame itself, this does not apply  to observer registrations.

+ +

更好:

+ +

     

+ +
+
content-document-global-created 通知
+
可以用 DOMWindowCreated 事件取代
+
其他观察者和服务
+
应该在 进程脚本 中注册,或者用 JSM 代替
+
+ +

 

+ +

根据需要加载框架脚本

+ +

不良:

+ +
// addon.js
+Services.mm.loadFrameScript("framescript.js", /*delayed:*/ true)
+
+// stuff communicating with the framescript
+
+ +
// framescript.js
+function onlyOnceInABlueMoon() {
+   // we only need this during a total solar eclipse while goat blood rains from the sky
+   sendAsyncMessage('my-addon:paragraph-count', {num: content.document.querySelectorAll('p').length})
+}
+addMessageListener("my-addon:request-from-parent", onlyOnceInABlueMoon)
+
+ +

更好:

+ +
// addon.js
+function onToolbarButton(event) {
+  let tabMM = gBrowser.mCurrentBrowser.frameLoader.messageManager;
+  let button = event.target;
+  let callback = (message) => {
+    tabMM.removeMessageListener("my-addon:paragraph-count", callback)
+    decorateButton(button, message.data.num)
+  }
+  tabMM.addMessageListener("my-addon:paragraph-count", callback);
+  tabMM.loadFrameScript("data:,sendAsyncMessage('my-addon:paragraph-count', {num: content.document.querySelectorAll('p').length})", false)
+}
+
+function decorateButton(button, count) {
+  // do stuff with result
+}
+
+ +

This executes the script only when it is needed and only in one tab and allows it to be garbage-collected immediately after execution.  As long as it the action does not happen frequently the memory and startup savings should outstrip the added cost of script evaluation.

+ +

Delaying the script registration until the session is restored my provide some middle ground for some addons. It does not provide the same memory footprint reductions but it improves application startup.

+ +

 

+ +

向下推进信息,避免到父进程的调用

+ +

不良:

+ +
// processscript.js
+
+function ContentPolicy() {
+  // ...
+}
+
+Object.assign(ContentyPolicy.prototype, {
+    classDescription: ..., classID: ..., contractID: ...,
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]),
+
+    shouldLoad: function(type, location, origin, context) {
+
+       let resultList = Services.cpmm.sendSyncMessage("my-addon:check-load", {destination: location, source: origin}) // <=== SYNC MESSAGE!
+
+       if(resultList.every((r) => r == true))
+           return Ci.nsIContentPolicy.ACCEPT;
+
+       return Ci.nsIContentPolicy.REJECT_REQUEST;
+    }
+});
+
+// more boilerplate code here
+
+ +

This example is a (somewhat condensed) content policy which gets triggered for every network request in a child process to either allow or deny the request. Since the code calls to the parent process to check whether a specific request can be allowed it would slow down all page loads, as web pages generally issue dozens of requests.

+ +

更好:

+ +

Instead of only keeping the state in the parent an addon can employ a master-slave architecture where the parent has the authoritative state and replicates it to the child processes in advance so they can act based on their local copy.

+ +

See the previous chapter on how to efficiently replicate addon state to each process.

+ +

 

+ +

 

+ +

附加组件卸载时的清理

+ +

 

+ +

不良:

+ +

包括上述所有例子,*包括上述的“更好”*

+ +

If your addon is restartless or uses the SDK then updates or the user turning it off and on will load to unload/reload events. Not handling those properly can lead to duplicate or conflicting code execution, especially when messages are sent. It can also lead to conflicts between the old and new code. Under some circumstances it may even cause exceptions when attempting to register something twice under the same ID.

+ +

更好:

+ +
// addon.js
+function onUnload() {
+  Services.mm.removeDelayedFrameScript("resources://my-addon/framescript.js");
+  Services.ppmm.removeDelayedProcessScript("resources://my-addon/processcript.js");
+  Services.mm.broadcastAsyncMessage("my-addon:unload");
+  Services.ppmm.broadcastAsyncMessage("my-addon:unload");
+}
+
+ +

在框架/进程脚本中:

+ + diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/motivation/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/motivation/index.html new file mode 100644 index 0000000000..7ae3c2aaef --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/motivation/index.html @@ -0,0 +1,44 @@ +--- +title: 动机 +slug: Mozilla/Firefox/Multiprocess_Firefox/Motivation +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Motivation +--- +
{{FirefoxSidebar}}

使 Firefox 在单独的进程中运行内容的主要原因:性能、安全和稳定性。

+ +

性能

+ +

Mozilla 在过去两年对性能的工作重点是浏览器的响应速度。目标是减少 “jank”—在加载大的页面时、表单中输入、或者滚动时,浏览器暂时性失去响应。响应问题在当今较高吞吐量的网络上日益显著。这些工作大部分已被 Snappy 项目完成。主要的重点在:

+ + + +

大部分能轻易做到的事情在这些领域已经完成。剩下的问题比较难以解决。举例来说,JavaScript 执行和布局都发生在主线程,并且阻挡着事件循环。在单独的线程中运行这些组件是困难的,因为它们访问数据,像是 DOM,它们不是线程安全的。作为替代方案,我们已经考虑让事件循环运行在 JavaScript 执行的中间,但这样做会毁掉大量 Firefox 其他地方做出的假设(更不用提附加组件)。

+ +

在一个单独的进程中运行网络内容,是这些方法的一个不错的替代品。类似线程的方式,Firefox 可以在 JavaScript 和布局在内容进程中运行时运行事件循环。但是不同于线程,用户界面(UI)的代码不能访问内容 DOM 或者其他内容的数据结构,因此没有必要进行锁定或者线程安全。而不足之处是,理所当然的,任何在 Firefox UI 进程中运行的需要访问内容数据的代码,都必须明确的通过消息传递的方式来访问内容数据。

+ +

我们觉得这种权衡有道理,有几个原因:

+ + + +

安全

+ +

目前来说,如果某人发现了一个 Firefox 中的可利用漏洞,他们能够接管用户的计算机。有很多种技术来缓解这种问题,但其中最强大的是沙盒。从技术上讲,沙盒不需要多个进程。但是,涵盖沙盒的单进程 Firefox 并不会很有用。沙盒能阻止进程执行,一个乖巧进程绝不会做的操作。遗憾的是,乖巧的 Firefox 进程(尤其是已安装附加组件的 Firefox)会访问很多网络和文件系统。因此,对单进程的 Firefox 沙盒不能限制太多。

+ +

在多进程 Firefox 中,内容进程将被沙盒化。一个乖巧的内容进程不会直接访问文件系统;它必须询问主线程来执行请求。在那时,主进程可以验证请求是否安全和合理。因此,对内容进程的沙盒化可以是相当严格的。我们希望这样的布局可以使 Firefox 更难被安全漏洞所利用。

+ +

稳定性

+ +

目前来说,在网页中运行的代码出现崩溃将导致整个浏览器崩溃。而多进程 Firefox 中,只有崩溃的内容进程会被终止。

+ +
+

此页面整合了很多 Bill McCloskey 的有关多进程 Firefox 的文章: http://billmccloskey.wordpress.com/2013/12/05/multiprocess-firefox/

+
+ +

 

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/tab_selection_in_multiprocess_firefox/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/tab_selection_in_multiprocess_firefox/index.html new file mode 100644 index 0000000000..f396b7dcb5 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/tab_selection_in_multiprocess_firefox/index.html @@ -0,0 +1,21 @@ +--- +title: 多进程 Firefox 中的标签选择 +slug: Mozilla/Firefox/Multiprocess_Firefox/Tab_selection_in_multiprocess_Firefox +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Tab_selection_in_multiprocess_Firefox +--- +
{{FirefoxSidebar}}

在单进程的 Firefox 中,当用户切换标签页时,这是同步操作。当浏览器加载新选择的标签页时,浏览器会阻塞,然后切换到该标签页。这表示标签页选定是通过设置 XUL 的 tab 对象的 selected 属性。代码(包括浏览器代码、扩展或主题)想要更改选定标签页的外观时,可以使用 selected  属性来应用 CSS 到该标签页。

+ +

在多进程的 Firefox 中,标签页切换是异步的。在用户切换标签页时,chrome 进程发送一个请求到内容进程来加载该页面到新选择的标签页。chrome 进程中的函数会立即返回,以便其他代码可以运行。一旦内容进程准备就绪,它发回一个消息到 chrome 进程,然后在用户界面中切换标签页。

+ +

还有 chrome 进程中的计时器:如果内容进程在计时器到期前没有响应,那么浏览器虽然继续切换标签页,但也显示一个包含标识的空标签页,直到目前的内容进程完成页面的加载。目前的计时器被设定为300毫秒。

+ +

还有,相应的,两个属性用于指示标签页选择:

+ + + +

这意味着想要对当前选中标签页应用的样式需要使用 visuallyselected 属性。如果使用 selected 属性,那么在新选择的标签页的样式被更新时会有一个短暂的断层,浏览器仍然在显示旧的标签页的内容。

+ + diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/technical_overview/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/technical_overview/index.html new file mode 100644 index 0000000000..18917fabc4 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/technical_overview/index.html @@ -0,0 +1,164 @@ +--- +title: 技术概述 +slug: Mozilla/Firefox/Multiprocess_Firefox/Technical_overview +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Technical_overview +--- +
{{FirefoxSidebar}}
+

这个页面主要是 Bill McCloskey 的关于多进程 Firefox 的摘要: http://billmccloskey.wordpress.com/2013/12/05/multiprocess-firefox/

+
+ +

从总体上来看,多进程 Firefox 的运行方式如下。当 Firefox 启动时的进程被称为父进程。起初和单程 Firefox 一样:打开一个窗口用于显示browser.xul,它包含主要的 UI 元素。XUL是Firefox的GUI工具箱, 由它提供了类似Web HTML的方式来声明定义UI元素。Firefox 的 UI也有一个window 对象。它有一个document 属性,并含了在 browser.xul 中所有的XML元素。所有的菜单,工具栏,侧边栏和标签页都是 document 下的 XML 元素。每一个标签页(tab)都包含一个 <browser> 元素用来显示网页内容.

+ +

多进程与单进程的最主要区别是每个 <browser> 都有一个remote="true" 的属性。当这个 browser 元素被添加到 document 时,将会启动一个新的内容进程,也称为子进程。同时创建一个跨进程通信的IPC通道。开始时子进程显示 about:blank,父进程通过给子进程发送命令来导航显示的内容。

+ +

绘制

+ +

有时,显示的网页内容需要从子进程传递到父进程然后再显示到屏幕。多进程模式依赖于一个新的特性(off main thread compositing ,OMTC)。简单来说,每个窗口被分成若干层,概念上类似于photoshop中的层。每一次Firefox进行渲染时,这些层被提交到合成线程来构建为一个图片。

+ +

层是树状结构。树的根节点对应一个Firefox窗口。根节点层包其他子层,如绘制菜单和标签页。一个子树对应所有网页内容。网页内容可被分成更多的层,这些层都以同一个内容层为根节点。

+ +

在多进程Firefox中,内容层的子树是一个垫片(shim)。在大多数时间,它包含一个能够简单地保持到子进程的通信链接的引用的占位符节点。内容进程包括网页内容的层树。它构建并且描绘这个层树。当描绘完成时,它通过IPC将层数的结构发送给父进程。当父进程受到这个层树时,它删除这个占位符内容节点并且将其替换为源于内容的实际树。然后它正常地合成并且绘制。当它完成后,它将占位符放回。

+ +

因为Firefox OS的需要,OMTC怎样于多进程一起工作的基本构架已经存在了一段时间。然而,Matt Woodrow和 David Anderson已经完成了大量工作来使得其在Windows,Mac和Linux正常工作。一个巨大的挑战是使多进程Firefox能够在所有平台下都能使OMTC启动。现在,只有Macs默认使用OMTC。

+ +

用户输入

+ +

Events in Firefox work the same way as they do on the web. Namely, there is a DOM tree for the entire window, and events are threaded through this tree in capture and bubbling phases. Imagine that the user clicks on a button on a web page. In single-process Firefox, the root DOM node of the Firefox window gets the first chance to process the event. Then, nodes lower down in the DOM tree get a chance. The event handling proceeds down through to the XUL <browser> element. At this point, nodes in the web page’s DOM tree are given a chance to handle the event, all the way down to the button. The bubble phase follows, running in the opposite order, all the way back up to the root node of the Firefox window.

+ +

With multiple processes, event handling works the same way until the <browser> element is hit. At that point, if the event hasn’t been handled yet, it gets sent to the child process by IPC, where handling starts at the root of the content DOM tree. The parent process then waits to run its bubbling phase until the content process has finished handling the event.

+ +

进程间通信

+ +

所有 IPC 使用 Chromium IPC 程序库。每个子进程都有单独的与父进程的 IPC 链接。子进程之间不能直接通信。为了避免死锁和确保响应能力,父进程不允许坐等子进程的消息。但是,子进程可以阻塞等待父进程的消息。

+ +

相比于人们预期的直接通过 IPC 发送数据包,我们使用代码生成使这个过程更漂亮。IPC 协议在 IPDL 中定义, which sort of stands for “inter-* protocol definition language”. A typical IPDL file is PNecko.ipdl. It defines a set messages and their parameters. Parameters are serialized and included in the message. To send a message M, C++ code just needs to call the method SendM. To receive the message, it implements the method RecvM.

+ +

IPDL is used in all the low-level C++ parts of Gecko where IPC is required. In many cases, IPC is just used to forward actions from the child to the parent. This is a common pattern in Gecko:

+ +
void AddHistoryEntry(param) {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    // If we're in the child, ask the parent to do this for us.
+    SendAddHistoryEntry(param);
+    return;
+  }
+
+  // Actually add the history entry...
+}
+
+bool RecvAddHistoryEntry(param) {
+  // Got a message from the child. Do the work for it.
+  AddHistoryEntry(param);
+  return true;
+}
+
+ +

When AddHistoryEntry is called in the child, we detect that we’re inside the child process and send an IPC message to the parent. When the parent receives that message, it calls AddHistoryEntry on its side.

+ +

For a more realistic illustration, consider the Places database, which stores visited URLs for populating the awesome bar. Whenever the user visits a URL in the content process, we call this code. Notice the content process check followed by the SendVisitURI call and an immediate return. The message is received here; this code just calls VisitURI in the parent.

+ +

The code for IndexedDB, the places database, and HTTP connections all runs in the parent process, and they all use roughly the same proxying mechanism in the child.

+ +

框架脚本

+ +

IPDL takes care of passing messages in C++, but much of Firefox is actually written in JavaScript. Instead of using IPDL directly, JavaScript code relies on the message manager to communicate between processes. To use the message manager in JS, you need to get hold of a message manager object. There is a global message manager, message managers for each Firefox window, and message managers for each <browser> element. A message manager can be used to load JS code into the child process and to exchange messages with it.

+ +

As a simple example, imagine that we want to be informed every time a load event triggers in web content. We’re not interested in any particular browser or window, so we use the global message manager. The basic process is as follows:

+ +
// Get the global message manager.
+let mm = Cc["@mozilla.org/globalmessagemanager;1"].
+         getService(Ci.nsIMessageListenerManager);
+
+// Wait for load event.
+mm.addMessageListener("GotLoadEvent", function (msg) {
+  dump("Received load event: " + msg.data.url + "\n");
+});
+
+// Load code into the child process to listen for the event.
+mm.loadFrameScript("chrome://content/content-script.js", true);
+
+ +

For this to work, we also need to have a file content-script.js:

+ +
// Listen for the load event.
+addEventListener("load", function (e) {
+  // Inform the parent process.
+  let docURL = content.document.documentURI;
+  sendAsyncMessage("GotLoadEvent", {url: docURL});
+}, false);
+
+ +

This file is called a frame script. When the loadFrameScript function call runs, the code for the script is run once for each <browser> element. This includes both remote browsers and regular ones. If we had used a per-window message manager, the code would only be run for the browser elements in that window. Any time a new browser element is added, the script is run automatically (this is the purpose of the true parameter to loadFrameScript). Since the script is run once per browser, it can access the browser’s window object and docshell via the content and docShell globals.

+ +

The great thing about frame scripts is that they work in both single-process and multiprocess Firefox. To learn more about the message manager, see the message manager guide.

+ +

跨进程 API

+ +

There are a lot of APIs in Firefox that cross between the parent and child processes. An example is the webNavigation property of XUL <browser> elements. The webNavigation property is an object that provides methods like loadURI, goBack, and goForward. These methods are called in the parent process, but the actions need to happen in the child. First I’ll cover how these methods work in single-process Firefox, and then I’ll describe how we adapted them for multiple processes.

+ +

The webNavigation property is defined using the XML Binding Language (XBL). XBL is a declarative language for customizing how XML elements work. Its syntax is a combination of XML and JavaScript. Firefox uses XBL extensively to customize XUL elements like <browser> and <tabbrowser>. The <browser> customizations reside in browser.xml. Here is how browser.webNavigation is defined:

+ +
<field name="_webNavigation">null</field>
+
+<property name="webNavigation" readonly="true">
+   <getter>
+   <![CDATA[
+     if (!this._webNavigation)
+       this._webNavigation = this.docShell.QueryInterface(Components.interfaces.nsIWebNavigation);
+     return this._webNavigation;
+   ]]>
+   </getter>
+</property>
+
+ +

This code is invoked whenever JavaScript code in Firefox accesses browser.webNavigation, where browser is some <browser> element. It checks if the result has already been cached in the browser._webNavigation field. If it hasn’t been cached, then it fetches the navigation object based off the browser’s docshell. The docshell is a Firefox-specific object that encapsulates a lot of functionality for loading new pages, navigating back and forth, and saving page history. In multiprocess Firefox, the docshell lives in the child process. Since the webNavigation accessor runs in the parent process, this.docShell above will just return null. As a consequence, this code will fail completely.

+ +

One way to fix this problem would be to create a fake docshell in C++ that could be returned. It would operate by sending IPDL messages to the real docshell in the child to get work done. We may eventually take this route in the future. We decided to do the message passing in JavaScript instead, since it’s easier and faster to prototype things there. Rather than change every docshell-using accessor to test if we’re using multiprocess browsing, we decided to create a new XBL binding that applies only to remote <browser> elements. It is called remote-browser.xml, and it extends the existing browser.xml binding.

+ +

The remote-browser.xml binding returns a JavaScript shim object whenever anyone uses browser.webNavigation or other similar objects. The shim object is implemented in its own JavaScript module. It uses the message manager to send messages like "WebNavigation:LoadURI" to a content script loaded by remote-browser.xml. The content script performs the actual action.

+ +

The shims we provide emulate their real counterparts imperfectly. They offer enough functionality to make Firefox work, but add-ons that use them may find them insufficient. I’ll discuss strategies for making add-ons work in more detail later.

+ +

跨进程对象包装器

+ +

The message manager API does not allow the parent process to call sendSyncMessage; that is, the parent is not allowed to wait for a response from the child. It’s detrimental for the parent to wait on the child, since we don’t want the browser UI to be unresponsive because of slow content. However, converting Firefox code to be asynchronous (i.e., to use sendAsyncMessage instead) can sometimes be onerous. As an expedient, we’ve introduced a new primitive that allows code in the parent process to access objects in the child process synchronously.

+ +

These objects are called cross-process object wrappers, frequently abbreviated to CPOWs. They’re created using the message manager. Consider this example content script:

+ +
addEventListener("load", function (e) {
+  let doc = content.document;
+  sendAsyncMessage("GotLoadEvent", {}, {document: doc});
+}, false);
+
+ +

In this code, we want to be able to send a reference to the document to the parent process. We can’t use the second parameter to sendAsyncMessage to do this: that argument is converted to JSON before it is sent up. The optional third parameter allows us to send object references. Each property of this argument becomes accessible in the parent process as a CPOW. Here’s what the parent code might look like:

+ +
let mm = Cc["@mozilla.org/globalmessagemanager;1"].
+         getService(Ci.nsIMessageListenerManager);
+
+mm.addMessageListener("GotLoadEvent", function (msg) {
+  let uri = msg.objects.document.documentURI;
+  dump("Received load event: " + uri + "\n");
+});
+mm.loadFrameScript("chrome://content/content-script.js", true);
+
+ +

It’s important to realize that we’re send object references. The msg.objects.document object is only a wrapper. The access to its documentURI property sends a synchronous message down to the child asking for the value. The dump statement only happens after a reply has come back from the child.

+ +

Because every property access sends a message, CPOWs can be slow to use. There is no caching, so 1,000 accesses to the same property will send 1,000 messages.

+ +

Another problem with CPOWs is that they violate some assumptions people might have about message ordering. Consider this code:

+ +
mm.addMessageListener("GotLoadEvent", function (msg) {
+  mm.sendAsyncMessage("ChangeDocumentURI", {newURI: "hello.com"});
+  let uri = msg.objects.document.documentURI;
+  dump("Received load event: " + uri + "\n");
+});
+
+ +

This code sends a message asking the child to change the current document URI. Then it accesses the current document URI via a CPOW. You might expect the value of uri to come back as "hello.com". But it might not. In order to avoid deadlocks, CPOW messages can bypass normal messages and be processed first. It’s possible that the request for the documentURI property will be processed before the "ChangeDocumentURI" message, in which case uri will have some other value.

+ +

For this reason, it’s best not to mix CPOWs with normal message manager messages. It’s also a bad idea to use CPOWs for anything security-related, since you may not get results that are consistent with surrounding code that might use the message manager.

+ +

Despite these problems, we’ve found CPOWs to be useful for converting certain parts of Firefox to be multiprocess-compatible. It’s best to use them in cases where users are less likely to notice poor responsiveness. As an example, we use CPOWs to implement the context menu that pops up when users right-click on content elements. Whether this code is asynchronous or synchronous, the menu cannot be displayed until content has responded with data about the element that has been clicked. The user is unlikely to notice if, for example, tab animations don’t run while waiting for the menu to pop up. Their only concern is for the menu to come up as quickly as possible, which is entirely gated on the response time of the content process. For this reason, we chose to use CPOWs, since they’re easier than converting the code to be asynchronous.

+ +

It’s possible that CPOWs will be phased out in the future. Asynchronous messaging using the message manager gives a user experience that is at least as good as, and often strictly better than, CPOWs. We strongly recommend that people use the message manager over CPOWs when possible. Nevertheless, CPOWs are sometimes useful.

diff --git a/files/zh-cn/mozilla/firefox/multiprocess_firefox/which_uris_load_where/index.html b/files/zh-cn/mozilla/firefox/multiprocess_firefox/which_uris_load_where/index.html new file mode 100644 index 0000000000..df24c59988 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/multiprocess_firefox/which_uris_load_where/index.html @@ -0,0 +1,53 @@ +--- +title: 各类 URI 在哪里加载 +slug: Mozilla/Firefox/Multiprocess_Firefox/Which_URIs_load_where +translation_of: Mozilla/Firefox/Multiprocess_Firefox/Which_URIs_load_where +--- +
{{FirefoxSidebar}}

浏览器加载一个页面到 chrome 或者内容进程,基于它的 URI 方案(URI scheme)。对于某些方案,你可以改变默认行为。

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
SchemeBehavior
about: +

默认情况下,about: 页面始终在 chrome 进程加载。但是,在你注册新的 about: 页面时,你可以改变此默认值。

+ +

两个新标志定义在 nsIAboutModule:

+ +
    +
  • URI_CAN_LOAD_IN_CHILD: 页面将加载在加载它的 browser 所在的进程。
  • +
  • URI_MUST_LOAD_IN_CHILD: 页面将始终加载在一个子进程
  • +
+ +

要使用上述任一标志,在你的 注册 about: URI 的代码getURIFlags 实现中返回它。

+
chrome: +

默认情况下,chrome: 页面始终加载在 chrome 进程。但是,在你注册新的 chrome: 页面时,你可以改变此默认值。

+ +

两个新标志定义在 chrome.manifest 文件

+ +
    +
  • remoteenabled: 页面将加载在加载它的 browser 所在的进程。
  • +
  • remoterequired: 页面将始终加载在一个子进程
  • +
+
file:始终在内容进程中加载。
resource:始终在内容进程中加载。
diff --git a/files/zh-cn/mozilla/firefox/privacy/index.html b/files/zh-cn/mozilla/firefox/privacy/index.html new file mode 100644 index 0000000000..e9a4126aa6 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/privacy/index.html @@ -0,0 +1,22 @@ +--- +title: 隐私 +slug: Mozilla/Firefox/Privacy +tags: + - 安全 + - 隐私 +translation_of: Mozilla/Firefox/Privacy +--- +
{{FirefoxSidebar}}
+ +

本文档是所有隐私相关的文档的列表。

+ +

{{ ListSubpages () }}

+ +

参见

+ + diff --git a/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/index.html b/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/index.html new file mode 100644 index 0000000000..a1e1f54a75 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/index.html @@ -0,0 +1,24 @@ +--- +title: Errors +slug: Mozilla/Firefox/Privacy/Storage_access_policy/Errors +tags: + - Cookies + - Errors + - NeedsTranslation + - Storage + - TopicStub + - storage access policy +translation_of: Mozilla/Firefox/Privacy/Storage_access_policy/Errors +--- +
{{FirefoxSidebar}}
+ +

This page lists the errors that can be raised due to Firefox's anti-tracking functionality, governed by the Storage access policy. You can find further information about them by clicking on the links below:

+ +

A request to access cookies or storage was blocked because

+ + diff --git "a/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/\347\246\201\347\224\250\345\244\226\351\203\250cookie/index.html" "b/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/\347\246\201\347\224\250\345\244\226\351\203\250cookie/index.html" new file mode 100644 index 0000000000..d2c05cd375 --- /dev/null +++ "b/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/errors/\347\246\201\347\224\250\345\244\226\351\203\250cookie/index.html" @@ -0,0 +1,39 @@ +--- +title: 禁用:所有第三方存储访问请求 +slug: Mozilla/Firefox/Privacy/Storage_access_policy/Errors/禁用外部Cookie +tags: + - cookie + - 存储 + - 存储访问策略 + - 跟踪 + - 错误 +translation_of: Mozilla/Firefox/Privacy/Storage_access_policy/Errors/CookieBlockedForeign +--- +
{{FirefoxSidebar}}
+ +

消息

+ +

Firefox:

+ +
禁用外部Cookie:由于浏览器禁用第三方内容展示及存储访问请求,Cookie和存储访问被拦截无法使用。
+ +

出现此类情形的原因?

+ +

由于浏览器禁用第三方内容的选项被开启,因此第三方Cookie使用请求和存储请求被拦截了。

+ +

通过以下操作可以修改权限或移除站点:

+ + + +

如果被拦截的资源不需要进行身份验证,你也可以给相关元素添加 crossorigin="anonymous" 属性来达到消除警告的目的。

+ +

相关资料

+ + diff --git a/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/index.html b/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/index.html new file mode 100644 index 0000000000..801d5bfad1 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/privacy/storage_access_policy/index.html @@ -0,0 +1,261 @@ +--- +title: 'Storage access policy: Block cookies from trackers' +slug: Mozilla/Firefox/Privacy/Storage_access_policy +tags: + - NeedsTranslation + - Privacy + - TopicStub + - storage access policy + - tracking protection +translation_of: Mozilla/Firefox/Privacy/Storage_access_policy +--- +
{{FirefoxSidebar}}
+ +

Firefox includes a new storage access policy that blocks cookies and other site data from third-party tracking resources. This policy is designed as an alternative to the older cookie policies, which have been available in Firefox for many years. This policy protects against cross-site tracking while minimizing the site breakage associated with traditional cookie blocking. This article explains how the policy works and how you can test it.

+ +

Testing in Firefox

+ +

This cookie policy has been available in Firefox since version 63. This documentation describes the policy that we intend to ship to Firefox Release users, but may not match what is implemented in the current Release version of Firefox. That's because we document new aspects of the policy as soon as they land in Firefox Nightly, our pre-release channel. Firefox Nightly may also contain experimental features that we don't yet plan to ship to Release users; experimental features will not be included in this documentation, but may nevertheless impact the functionality of domains classified as trackers.

+ +

We recommend sites test with Firefox Nightly, as this includes the newest version of our protections. As described above, note that Nightly may include additional protections that end up getting removed or changed before they reach our Release users. We’ll keep this page updated with the newest information as we strengthen our protections.

+ +

These protections are on by default in Nightly. The cookie policy can be enabled in other versions of Firefox through the Content Blocking settings (these steps will vary by version; the linked documentation includes a dropdown to select the appropriate Firefox version).

+ +

Report Broken Sites

+ +

If you find a website broken as a result of this change, file a bug under the Tracking Protection component within the Firefox product on Bugzilla. Alternatively you can report broken sites directly in Firefox by clicking "Report a Problem" in the Content Blocking section of the Control Center (this shortcut may not be available in all versions of Firefox).

+ +

Tracking protection explained

+ +

How does Firefox determine which resources are tracking resources?

+ +

Firefox uses the Tracking Protection list to determine which resources are tracking resources. The Tracking Protection list is maintained by Disconnect. When the list is applied in Firefox, we make two important changes:

+ + + +

Firefox uses the built-in Tracking Protection URL classifier to determine which resources match the tracking protection list. Domains are matched against the list in accordance with the SafeBrowsing v4 specification. Specifically, we check the exact hostname of the resource against the list, as well as the last four hostnames formed by starting with the last five components and successively removing the leading component. Consider the following examples:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Hostname on the listHostname of resourceMatched
example.comexample.comYes
example.coma.b.example.comYes
blah.example.comexample.comNo
a.b.example.comc.d.example.comNo
blah.example.comfoo.blah.example.comYes
+ +

What does the storage access policy block?

+ +

The storage access policy blocks resources identified as trackers from accessing their cookies and other site storage when they are loaded in a third-party context. This prevents those resources from retrieving tracking identifiers stored in cookies or site storage and using them to identify users across visits to multiple first parties. Specifically, Firefox does this by imposing the following restrictions:

+ +

Cookies:

+ + + +

DOM Storage:

+ + + +

Messaging and Workers:

+ + + +

DOM Cache:

+ + + +

Browser caches:

+ + + +

Network connections:

+ + + +

What is not blocked by the policy?

+ +
    +
  1. This policy does not currently restrict third-party storage access for resources that are not classified as tracking resources. We may choose to apply additional restrictions to third-party storage access in the future.
  2. +
  3. The restrictions applied by the policy will not prevent third-party scripts classified as tracking resources from accessing storage in the main context of the page. These scripts can continue to use storage scoped to the top-level origin.
  4. +
  5. Origins classified as trackers will have access to their own storage when they are loaded in a first-party context.
  6. +
  7. Cross-origin resources loaded from the same eTLD+1 as the top-level context will still have access to their storage.
  8. +
  9. Origins normally classified as trackers will not be blocked if the top-level page origin is determined to be from the same organization as them.
  10. +
+ +

Storage access grants

+ +

In order to improve web compatibility and permit third-party integrations that require storage access, Firefox will grant storage access scoped to the first party for a particular third-party origin as described in this section. Currently, Firefox includes some web compatibility heuristics that grant storage access to third-party resources classified as trackers when a user interacts with those third parties. We do this when we expect that not granting access would cause the web page to break. We also support an initial implementation of the Storage Access API, through which embedded {{htmlelement("iframe")}}s can request storage access by calling {{domxref("Document.requestStorageAccess()")}}. Although both of these approaches provide the same level of storage access, we recommend third parties switch to using the Storage Access API in order to guarantee their access to storage.

+ +

Automatic storage access upon interaction

+ +

In order to improve web compatibility, Firefox currently includes some heuristics to grant storage access automatically to third parties that receive user interaction. These heuristics are intended to allow some third-party integrations that are common on the web to continue to function. They are intended to be temporary and will be removed in a future version of Firefox. They should not be relied upon for current and future web development.

+ +

Third-party storage access may be granted to resources that have been classified as tracking resources when a user gesture triggers a pop-up window that has opener access to the originating document. When that occurs, there are two possible ways a third-party origin can be granted access:

+ + + +

Scope of storage access

+ +

When storage access is granted, it is scoped to the origin of the opener document or subdomains of that origin. Access that is granted on the subdomain of an origin does not extend to the top-level origin. As an example, if a resource from tracker.example is granted storage access on foo.example.com, then tracker.example will be able to access its cookies on bar.foo.example.com but not example.com. Instead, if tracker.example were granted access on example.com it would be able to access its storage on bar.foo.example.com, foo.example.com, and example.com.

+ +

When storage access is granted to tracker.example on example.com, all resources loaded from tracker.example on any top-level document loaded from example.com are immediately given storage access. This includes all resources loaded in the main context of the page, embedded <iframe>s, and resources loaded within embedded <iframe>s. Storage access is not extended to other resources loaded on example.com (e.g. other-tracker.example), nor to other first parties on which tracker.example is embedded (e.g. example.org).

+ +

Storage access grants extend into the first level of nested contexts, but no further. This means that <iframe>s embedded in the main context of the page and loaded from a domain classified as a tracker will have full access to all storage locations accessible through JavaScript. Similarly, requests for resources loaded in <iframe>s embedded in the main context of the page will have access to HTTP cookies. However, further nested contexts, including but not limited to those from the origin classified as a tracker, will not be granted storage access.

+ +

Consider the following embedding scenarios on a top-level page loaded from example.com on which tracker.example has been granted storage access.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Embeddingtracker.example resource storage access
An image is loaded from tracker.example and embedded in the main context of example.com.HTTP: Yes
+ JS: N/A
example.com embeds an <iframe> from example.org. That <iframe> goes on to load an image from tracker.example.HTTP: Yes
+ JS: N/A
example.com embeds an <iframe> from example.org. That <iframe> goes on to embed an <iframe> from tracker.example.HTTP: Yes
+ JS: No
example.com embeds an <iframe> from tracker.example.HTTP: Yes
+ JS: Yes
example.com embeds an <iframe> from example.com (same origin). The nested <iframe> embeds an <iframe> from tracker.example.HTTP: Yes
+ JS: No
+ +

Storage access expiration

+ +

The storage access grant expires after 30 days. Domains classified as tracking resources may be granted third-party storage access on multiple first parties, and the storage permission for each party expires independently. The above heuristics will also serve to extend the lifetime of a third-party storage permission on origins that have already been granted access.  Each time the heuristic is activated, or a success call to the Storage Access API is made, the pre-existing storage access expiration will be extended by 30 days, counting from the time the previous access was granted.

+ +

Please note that in the future we expect to make changes to how long storage access will remain valid for.  As mentioned before, the way to know that you will be able to use storage as a third-party going forward will be using the Storage Access API.

+ +

Debugging

+ +

We encourage site owners to test their sites, particularly those that rely on third-party content integrations. We’ve added several new features to Firefox to make testing easier.

+ +

Developer Tools notifications

+ +

The Network Monitor in Firefox Developer Tools now includes an indicator for all resource requests that have been classified as tracking resources. This indicator is shown as a shield icon in the domain column. In the sample image below, trackertest.org is classified as a tracking resource, while the request to example.com is not.

+ +

network requests in Firefox devtools indicating which ones are tracking resources with a small shield icon

+ +

Adding custom domains to the Tracking Protection list

+ +

Curious how things will work if a third-party domain on your site were classified as a tracker? We’ve added a preference that allows you to add custom domains to the Tracking Protection URL classifier. To do so:

+ +
    +
  1. Type about:config in your address bar. If you are presented with a page that warns you "This may void your warranty!", click "I accept the risk!"
  2. +
  3. Right click on the next page and click "New" > "String".
  4. +
  5. For the preference name enter "urlclassifier.trackingAnnotationTable.testEntries".
  6. +
  7. For the preference value enter comma separated origins that you’d like to have classified as trackers. E.g. "example.net,example.org".
  8. +
+ +
+

Warning: Be sure to remove these entries after you have finished testing.

+
+ +

FAQ

+ +

This cookie policy has the potential to lead to site breakage, but has been designed to allow common third-party integrations to continue to work while preventing cross-site tracking. In this section we describe the functionality you can expect in different integration scenarios.

+ +

Will this storage access policy block ads from displaying on my website?

+ +

No — this feature only restricts access to cookies and site data that can be used to track users across websites. Blocking tracking identifiers does not prevent the display of advertisements.

+ +

I use a third-party analytics service that is classified as a tracker. Will I still receive analytics data?

+ +

This depends on how the third-party analytics service is implemented. Third-party analytics providers will no longer be able to user their third-party storage to collect data. This means that providers using cookies which are scoped to their third-party domain, or local storage and other site data stored under their origin, will no longer have access to those identifiers across other websites.

+ +

If these services are embedded into the main context of the page, they can continue to use first-party cookies and site storage to track users across page visits on that specific first-party domain.

+ +

I use third-party services for social login, like, and share button integration. Will my users still be able to make use of these services?

+ +

This depends on how the social integration is implemented. We expect that many of the popular social integrations will continue to function as they do under Firefox’s current cookie policy with some minor differences in the user experience.

+ +

A social content provider that is classified as a tracker will not have access to their third-party cookies when the user first visits a new first party. Thus, the user may appear logged out to the service despite being logged in when they visit the provider’s website directly. Depending on the type of integration, the user may have to take some action to interact with the social content provider before the provider is given access to their cookies. For example:

+ + + +

After these interactions, the provider will receive third-party storage access if they prompt the user in a way that is captured by the storage access activation heuristics described above. These providers should consider switching to explicitly request storage access through the Storage Access API as soon as possible. An initial implementation of this API is currently available in Nightly.

+ +

I use third-party pixels and other tools to measure the effectiveness of my ad campaigns. Will I still be able to measure the conversion rate of my ads?

+ +

This depends on how the third party has implemented the measurement tool, but generally ad conversion measurement will be more difficult. Consider the following examples:

+ +
    +
  1. You run an ad on a social media website that is seen several times by a user, but never clicked. That user later visits your website, which includes a conversion tracking tag from the same social media website. This type of conversion is often referred to as a “view-through conversion.” Since the social media website does not have access to their third-party storage, they will not recognize the user as the same user that saw the advertisements on their website and the conversion will not be tracked. We expect that most view-through conversion tracking techniques will no longer work, including those offered by display networks.
  2. +
  3. You run an ad on a display network or social media website that is clicked by a user. That user lands on your website, which includes a conversion tracking tag from the same website that displayed your ad. This type of conversion is often referred to as a “click-through conversion.” Since the social media site or display network will not have access to their third-party storage, they will not recognize the user as the same user that saw the advertisements on their website and the conversion will not be tracked. We expect that this version of click-through conversion will no longer work.
  4. +
  5. You run an ad that appears on a social media website. A user clicks on your advertisement and is taken to a landing page that contains a conversion tracking tag from the third-party network. On the social media website, the network annotates the advertisement landing page URL with a query parameter that signals that the visit was the result of a click on an advertisement. On your website, the display network’s tag checks the URL query parameters and saves any ad tracking parameters to first-party storage. If a user later completes a conversion event, the network’s tag checks first-party storage to determine which click (or clicks) was responsible for the visit. We expect that click-through conversion implemented in this way will continue to work.
  6. +
diff --git a/files/zh-cn/mozilla/firefox/privacy/tracking_protection/index.html b/files/zh-cn/mozilla/firefox/privacy/tracking_protection/index.html new file mode 100644 index 0000000000..66620f47d9 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/privacy/tracking_protection/index.html @@ -0,0 +1,87 @@ +--- +title: Tracking Protection +slug: Mozilla/Firefox/Privacy/Tracking_Protection +tags: + - 隐私 +translation_of: Mozilla/Firefox/Privacy/Tracking_Protection +--- +
{{FirefoxSidebar}}
+ +

什么是跟踪保护?

+ +

Firefox 浏览器桌面版和 Android 移动版内置跟踪保护。在隐私窗口或标签页(Android移动版)内,Firefox会阻止跨网站的内容加载。

+ +

如果拦截的内容是网页的一部分,用户可能会注意到网页排版出现问题。如果页面上的其它元素把拦截内容的空位给填补上时,用户完全不会注意到 Firefox 浏览器阻止了一些内容加载。

+ +

当 Firefox 浏览器拦截到内容时,在控制台会有类似这样一条日志消息:

+ +
位于“http://some/url”的资源已被内容拦截功能拦截。
+ +

Firefox 浏览器 Android 移动版需要使用远程调试来看到控制台的输出内容。

+ +

Page information showing possible blocked content.

+ +

点下地址栏左侧这个标志ⓘ 可以查看当前页面的信息。按下第一行的按钮可以关闭对当前网站的跟踪保护。

+ +

如果存在跟踪Cookie,您可以通过单击上图中的“阻止跟踪Cookie”查看以下弹出窗口来查看列表:

+ +

+ +

您可以单击“管理内容阻止”来更改阻止设置:

+ +

+ +

Firefox如何选择要阻止的内容?
+ 基于要从中加载内容的域阻止内容。
+ Firefox将提供一个站点列表,这些站点已经被确定为参与用户的跨站点跟踪。启用跟踪保护后,Firefox将阻止来自列表中站点的内容。
+ 跟踪用户的网站通常是第三方广告和分析网站。

+ +

这对你的网站意味着什么?
+ 最明显的是,这意味着当启用跟踪保护时:
+ 从第三方跟踪服务的内容将对用户不可见
+ 您的网站将无法使用第三方广告或参与跟踪的分析服务
+ 更微妙的是,如果站点的其他部分依赖于正在加载的跟踪器,那么当启用跟踪保护时,这些部分也将被破坏。例如,如果站点包含在加载跟踪站点的内容时运行的回调,则不会执行该回调。
+ 例如,您不应以以下方式使用Google Analytics:

+ +
<a href="http://www.example.com" onclick="trackLink('http://www.example.com', event);">
+  Visit example.com
+</a>
+
+<script>
+function trackLink(url,event) {
+    event.preventDefault();
+    ga('send', 'event', 'outbound', 'click', url, {
+     'transport': 'beacon',
+     'hitCallback': function() {
+       document.location = url;
+     }
+   });
+}
+</script>
+ +

相反,您应该通过检查ga对象是否已初始化来解释Google Analytics丢失的情况:

+ +
<a href="http://www.example.com" onclick="trackLink('http://www.example.com', event);">
+  Visit example.com
+</a>
+
+<script>
+function trackLink(url,event) {
+    event.preventDefault();
+    if (window.ga && ga.loaded) {
+         ga('send', 'event', 'outbound', 'click', url, {
+         'transport': 'beacon',
+         'hitCallback': function() { document.location = url; }
+       });
+    } else {
+        document.location = url;
+    }
+}
+</script>
+
+ +

关于这项技术的更多信息可以在Google分析、隐私和事件跟踪上找到。

+ +
+

注意:以这种方式依赖第三方并不是一个好的做法,因为如果第三方速度慢或不可用,或者跟踪器已被加载项阻止,则站点可能会被破坏。

+
diff --git a/files/zh-cn/mozilla/firefox/releases/1.5/index.html b/files/zh-cn/mozilla/firefox/releases/1.5/index.html new file mode 100644 index 0000000000..a028828a01 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/1.5/index.html @@ -0,0 +1,123 @@ +--- +title: Firefox 1.5 for developers +slug: Mozilla/Firefox/Releases/1.5 +tags: + - Add-ons + - CSS + - DOM + - Extensions + - HTML + - JavaScript + - NeedsTranslation + - RDF + - SVG + - TopicStub + - Web Development + - Web Standards + - XML + - XML Web Services + - XSLT + - XUL +translation_of: Mozilla/Firefox/Releases/1.5 +--- +
{{FirefoxSidebar}}

Based on the Gecko 1.8 engine, Firefox 1.5 improved its already best in class standards support, and provided new capabilities to enable the next generation of web applications. Firefox 1.5 features improved support for CSS2 and CSS3, APIs for scriptable and programmable 2D graphics through SVG 1.1 and <canvas>, XForms and XML events, as well as many DHTML, JavaScript, and DOM enhancements.

+ +

Developer Tools

+ +

Several tools and browser extensions are available to help developers support Firefox 1.5.

+ + + +

Note: Some extensions do not currently support Firefox 1.5, and will be automatically disabled.

+ +

Overview

+ +

Some of the new features in Firefox 1.5:

+ +

Web site and application developers

+ +
+
SVG In XHTML Introduction
+
Learn how to use SVG in XHTML pages and how to use JavaScript and CSS to manipulate the picture in the same way you would script regular XHTML. See also SVG in Firefox to learn about the status and known problems of SVG implementation in Firefox.
+
Drawing Graphics with Canvas
+
Learn about the new <canvas> tag and how to draw graphs and other objects in Firefox.
+
CSS3 Columns
+
Learn about the new support for automatic multi-column text layout as proposed for CSS3.
+
Using Firefox 1.5 caching
+
Learn about bfcache and how it speeds up back and forward navigation.
+
+ +

XUL and Extension Developers

+ +
+
Building an Extension
+
This tutorial will take you through the steps required to build a very basic extension for Firefox. Also see another tutorial on MozillaZine knowledge base, which demonstrates the new features of the Extension Manager in 1.5 that make creating a new extension even easier.
+
XPCNativeWrapper
+
XPCNativeWrapper is a way to wrap up an object so that it's safe to access from privileged code. It can be used in all Firefox versions, though the behavior changed somewhat starting with Firefox 1.5 (Gecko 1.8).
+
Preferences System
+
Learn about the new widgets that allow you to create Options windows easier using less JavaScript code.
+
International characters in XUL JavaScript
+
XUL JavaScript files can now contain non-ASCII characters.
+
Tree API changes
+
The interfaces for accessing XUL <tree> elements have changed.
+
XUL Changes for Firefox 1.5
+
Summary of XUL changes. See also Adapting XUL Applications for Firefox 1.5.
+
+ + + + + +

New End user Features

+ +

User Experience

+ + + +

Security and Privacy

+ + + +

Support for open Web standards

+ +

Firefox support for Web standards continues to lead the industry with consistent cross-platform implementations for:

+ + + +

Firefox 1.5 supports the following data transport protocols (HTTP, FTP, SSL, TLS, and others), multilingual character data (Unicode), graphics (GIF, JPEG, PNG, SVG, and others) and the latest version of the world's most popular scripting language, JavaScript 1.6.

+ +

Changes since Firefox 1.0

+ +

Many changes have been introduced into Firefox since it was first released on November 9, 2004. Firefox has progressed with many new features and bug fixes. A detailed list of changes is available from squarefree.com.

diff --git a/files/zh-cn/mozilla/firefox/releases/1.5/using_firefox_1.5_caching/index.html b/files/zh-cn/mozilla/firefox/releases/1.5/using_firefox_1.5_caching/index.html new file mode 100644 index 0000000000..b062c43ddd --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/1.5/using_firefox_1.5_caching/index.html @@ -0,0 +1,184 @@ +--- +title: Using Firefox 1.5 caching +slug: Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching +translation_of: Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching +--- +
{{FirefoxSidebar}}

介绍

+ +

Firefox 1.5 对整个web页面的一个浏览器会话进行了内存缓存,包括他们对JavaScript状态。在访问过的页面间后退和前进不需要页面加载同时保存JavaScript状态。这个特性,被称为bfcache(“后退前进缓存”),使得页面导航(切换)非常快。这个状态缓存被保存直到用户关闭浏览器。 

+ +

有时候,Firefox不缓存页面。下面是一些页面不被缓存的常见的编程的原因:

+ + + +

这个新的缓存特性改变了页面的加载行为,web作者也许希望: 

+ + + +

两个新的浏览器事件使得用户可以做到这2个要求。

+ +

新的浏览器事件

+ +

如果你使用新的事件,你的页面在其他浏览器依然会正确显示  (我们已经测试了早期版本的Firefox, Internet Explorer, Opera, 和 Safari),而且在 Firefox 1.5加载时将会使用新的缓存功能。

+ +

注意: 直至10-2009 开发版本的Safari 添加了这些新的事件的支持 (见 the webkit bug).

+ +

标准的页面行为是:

+ +
    +
  1. 用户导航至一个页面
  2. +
  3. 当页面加载,行内scripts执行。
  4. +
  5. 一旦页面加载完毕, onload 事件执行。
  6. +
+ +

有些页面包含第四步。如果一个页面使用 unload 或者 beforeunload 处理程序,当从页面导航离开时事件被执行。如果提供了一个unload 处理程序,页面将不会被缓存。

+ +

当一个用户导航至一个被缓存的页面,行内scripts和onload 处理程序将不会执行 (步骤 2 和 3), 因为在大多数情况下,这些scripts的影响(执行效果)已经被保存。

+ +

如果你想在每次用户导航到页面时都执行页面包含的scripts或者其他在页面加载期间执行的行为,或者你想知道什么时候用户导航至一个被缓存的页面,使用新的pageshow 事件.

+ +

如果你拥有当用户导航离页面是执行的行为,但是你想利用这个新的缓存功能,因此不想使用unload处理程序,使用新的 pagehide 事件

+ +

pageshow 事件

+ +

这个事件和 load 事件一样的工作(效果), 除了它每次页面加载是都执行 that it fires every time the page is loaded (然而  load 事件在 Firefox 1.5中当页面从缓存中加载时不执行). 页面第一次加载时, pageshow 事件在 load 事件执行后执行。 pageshow 事件使用一个命名为persisted 的boolean属性,在初始加载时默认设置为 false。如果它不是初始加载,被设置为true(换句话说,但页面被缓存时它被设置为true).

+ +

pageshow 事件执行时,设置每次页面加载时你想要运行的任何的JavaScript。

+ +

如果你将JavaScript函数作为pageshow事件的一部分调用,你可以通过调用pageshow 事件作为load事件的一部分确保在不同于Firefox 1.5的浏览器在页面加载时调用这些函数,如在本文后面所示的示例。

+ +

pagehide 事件

+ +

如果你想定义当用户导航离页面时的行为,但是你不想使用 unload  (这将导致页面不被缓存),你可以使用新的  pagehide 事件。像 pageshow , pagehide 事件使用一个命名为persisted 的属性。 这个属性在页面未被浏览器缓存时设置为 false  ,如果页面被浏览器缓存则设置为 true 。如果这个属性被设置为 false, 如果有设置unload 处理程序的话,unload 事件在pagehide 事件执行后马上执行。

+ +

当页面初次加载,Firefox 1.5 试图按事件会发生相同的顺序模拟load事件。Frames 被作为顶级文档一样对待。如果页面包含frames, 则当缓存当页面被加载:

+ + + +

示例代码

+ +

以下的示例演示了一个页面同时使用 load 和 pageshow 事件。这个示例页面行为如下:

+ + + +

在这个例子中:

+ + + +
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+   "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<head>
+<title>Order query Firefox 1.5 Example</title>
+<style type="text/css">
+body, p {
+	font-family: Verdana, sans-serif;
+	font-size: 12px;
+   	}
+</style>
+<script type="text/javascript">
+function onLoad() {
+	loadOnlyFirst();
+	onPageShow();
+}
+
+function onPageShow() {
+//calculate current time
+	var currentTime= new Date();
+	var year=currentTime.getFullYear();
+	var month=currentTime.getMonth()+1;
+	var day=currentTime.getDate();
+	var hour=currentTime.getHours();
+	var min=currentTime.getMinutes();
+	var sec=currentTime.getSeconds();
+	var mil=currentTime.getMilliseconds();
+	var displayTime = (month + "/" + day + "/" + year + " " +
+		hour + ":" + min + ":" + sec + ":" + mil);
+	document.getElementById("timefield").value=displayTime;
+}
+
+function loadOnlyFirst() {
+	document.zipForm.name.focus();
+}
+</script>
+</head>
+<body onload="onLoad();" onpageshow="if (event.persisted) onPageShow();">
+<h2>Order query</h2>
+
+<form name="zipForm" action="http://www.example.com/formresult.html" method="get">
+<label for="timefield">Date and time:</label>
+<input type="text" id="timefield"><br>
+<label for="name">Name:</label>
+<input type="text" id="name"><br>
+<label for="address">Email address:</label>
+<input type="text" id="address"><br>
+<label for="order">Order number:</label>
+<input type="text" id="order"><br>
+<input type="submit" name="submit" value="Submit Query">
+</form>
+</body>
+</html>
+
+ +

与此相反, 如果以上页面不监听 pageshow 事件,所有的计算作为 load 事件的一部分(取而代之的是如下面的示例代码片段所示的编码),Firefox 1.5 中,当用户导航离页面时,光标位置及date/time会被缓存。当用户返回回该页面,缓存的date/time将会显示。

+ +
<script>
+function onLoad() {
+	loadOnlyFirst();
+
+//calculate current time
+	var currentTime= new Date();
+	var year = currentTime.getFullYear();
+	var month = currentTime.getMonth()+1;
+	var day = currentTime.getDate();
+	var hour=currentTime.getHours();
+	var min=currentTime.getMinutes();
+	var sec=currentTime.getSeconds();
+	var mil=currentTime.getMilliseconds();
+	var displayTime = (month + "/" + day + "/" + year + " " +
+		hour + ":" + min + ":" + sec + ":" + mil);
+	document.getElementById("timefield").value=displayTime;
+}
+
+function loadOnlyFirst() {
+	document.zipForm.name.focus();
+}
+</script>
+</head>
+
+<body onload="onLoad();">
+
+ +

开发Firefox扩展

+ +

Firefox 1.5 extensions 需要允许缓存功能。如果你在开发一个兼容1.5 及以前版本的Firefox扩展,确保它监听事件触发 load 可被缓存,监听的 pageshow 事件触发不应该被缓存。

+ +

例如,Firefox的Google工具栏为了兼容1.5和更早的版本,应该为autolink监听 load 事件函数,为PageRank监听 pageshow 事件函数。

diff --git a/files/zh-cn/mozilla/firefox/releases/12/index.html b/files/zh-cn/mozilla/firefox/releases/12/index.html new file mode 100644 index 0000000000..ee154efbfe --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/12/index.html @@ -0,0 +1,165 @@ +--- +title: Firefox 12 for developers +slug: Mozilla/Firefox/Releases/12 +tags: + - Firefox + - Firefox 12 + - Gecko 12 + - Web Developement +translation_of: Mozilla/Firefox/Releases/12 +--- +
{{FirefoxSidebar}}
+ +

Firefox 12 was shipped on April 24, 2012. This page summarizes the changes in Firefox 12 that affect developers. This article provides information about the new features and key bugs fixed in this release, as well as links to more detailed documentation for both web developers and add-on developers.

+ +

Changes for Web developers

+ +

HTML

+ + + +

CSS

+ + + +

JavaScript

+ + + +

DOM

+ + + +

New WebAPIs

+ + + +

SVG

+ + + +

MathML

+ + + +

Networking

+ + + +

Developer tools

+ + + +

Mozilla has been working on integrating its own Web developer tools that complement the popular Firebug add-on. You can get more information about these tools as well as see a list of resources external to Firefox that will help you with your Web development. The entire list is located at Web developer tools.

+ +

Miscellaneous changes

+ + + +

Changes for Mozilla and add-on developers

+ +

JavaScript code modules

+ +

source-editor.jsm

+ + + +

XUL

+ + + +

XPCOM

+ + + +

XPConnect

+ + + +

Interface changes

+ + + +

SpiderMonkey

+ + + +

Building

+ + + +

Other changes

+ + + +

See also

+ +
{{Firefox_for_developers('11')}}
diff --git a/files/zh-cn/mozilla/firefox/releases/14/index.html b/files/zh-cn/mozilla/firefox/releases/14/index.html new file mode 100644 index 0000000000..8ef207f56e --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/14/index.html @@ -0,0 +1,98 @@ +--- +title: Firefox 14 for developers +slug: Mozilla/Firefox/Releases/14 +tags: + - Firefox + - Firefox 14 + - Gecko + - Gecko 14 +translation_of: Mozilla/Firefox/Releases/14 +--- +
{{FirefoxSidebar}}

Firefox 14 shipped on July 17, 2012. This article lists key changes that are useful for not only Web developers to know about, but also Firefox and Gecko developers as well as add-on developers.

+ +

Changes for Web developers

+ +

HTML

+ + + +

DOM

+ + + +

CSS

+ + + +

JavaScript

+ +

No change.

+ +

MathML

+ + + +

HTTP

+ + + +

Changes for Mozilla and add-on developers

+ +

JavaScript 代码模块

+ +

source-editor.jsm

+ + + +

XUL

+ + + +

接口

+ + + +

拼写检查

+ + + +

相关链接

+ +
{{Firefox_for_developers('13')}}
diff --git a/files/zh-cn/mozilla/firefox/releases/15/index.html b/files/zh-cn/mozilla/firefox/releases/15/index.html new file mode 100644 index 0000000000..1c941836d7 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/15/index.html @@ -0,0 +1,122 @@ +--- +title: Firefox 15 for developers +slug: Mozilla/Firefox/Releases/15 +tags: + - Firefox + - Firefox 15 + - Gecko 15 +translation_of: Mozilla/Firefox/Releases/15 +--- +
{{FirefoxSidebar}}

Firefox 15 shipped on August 28, 2012. This article lists key changes that are useful for not only Web developers to know about, but also Firefox and Gecko developers as well as add-on developers.

+ +

Changes for Web developers

+ +

HTML

+ + + +

CSS

+ + + +

DOM

+ + + +

JavaScript

+ + + +

WebGL

+ + + +

MathML

+ + + +

SVG

+ + + +

Network

+ + + +

附加组件开发变更

+ +

接口变更

+ +
+
{{ interface("nsIDOMWindowUtils") }}
+
aModifiers of sendMouseEvent(), sendTouchEvent(), sendMouseEventToWindow(), sendMouseScrollEvent() and sendKeyEvent() supports all modifier keys which are supported by KeyboardEvent.getModifierState(). Use MODIFIER_* values. And now the 5th parameter of sendKeyEvent() is changed from boolean to unsigned long. For backward compatibility, if caller passes true or false to it, the behavior isn't changed. This change allows callers to specify the key's location.
+
{{ interface("nsIBrowserHistory") }}
+
The hidePage() method was never implemented, and has been removed entirely in this release. The addPageWithDetails() method has also been removed as part of the ongoing work to make all Places APIs asynchronous; use {{ ifmethod("mozIAsyncHistory", "updatePlaces") }} instead. Also, the count attribute was removed; it had not returned an actual count in some time (instead, it was simply indicating whether or not any entries existed). You can use {{ ifattribute("nsINavHistoryService", "hasHistoryEntries") }} instead.
+
{{interface("inIDOMUtils")}}
+
The {{ifmethod("inlDOMUtils", "parseStyleSheet")}} method has been added and allows the (re-)parsing of Cascading Style Sheets.
+
{{interface("nsIINIParserWriter")}}
+
The {{ifmethod("nsIINIParserWriter", "writeFile")}} method now accepts a flagsproperty. This currently offers only one option: you can now tell it to write the file in UTF-16 format instead of UTF-8, for better compatibility with Windows and certain installers.
+
+ +

新增接口

+ +
+
{{ interface("nsISpeculativeConnect") }}
+
Provides a way to hint to the networking layer that you are likely to ask to open a connection to a given URI sometime in the near future. This lets the network layer begin the sometimes high-latency process of opening a new network connection ahead of time.
+
+ +

移除接口

+ +

The following interfaces have been removed.

+ + + +

相关链接

+ +

{{Firefox_for_developers('14')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/16/index.html b/files/zh-cn/mozilla/firefox/releases/16/index.html new file mode 100644 index 0000000000..7d63499c62 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/16/index.html @@ -0,0 +1,114 @@ +--- +title: Firefox 16 for developers +slug: Mozilla/Firefox/Releases/16 +tags: + - Firefox + - Firefox 16 +translation_of: Mozilla/Firefox/Releases/16 +--- +
{{FirefoxSidebar}}

Firefox 16 shipped on October 9, 2012. This article lists key changes that are useful for not only Web developers to know about, but also Firefox and Gecko developers as well as add-on developers.

+ +

Web开发

+ +

HTML

+ + + +

CSS

+ + + +

API/DOM

+ + + +

JavaScript

+ + + +

WebGL

+ +

No change

+ +

SVG

+ +

No change

+ +

MathML

+ +

 

+ + + +

 

+ +

网络

+ +

 

+ +

Developer tools

+ +

 

+ + + +

 

+ +

 

+ +

Changes for Open Web App developers

+ + + +

附加组件开发变更

+ +

修改接口

+ +

{{interface("nsIPrivateDOMEvent")}} has been merged into {{interface("nsIDOMEvent")}}. ({{bug("761613")}})

+ +

新增接口

+ +

废弃接口

diff --git a/files/zh-cn/mozilla/firefox/releases/17/index.html b/files/zh-cn/mozilla/firefox/releases/17/index.html new file mode 100644 index 0000000000..176604bdc7 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/17/index.html @@ -0,0 +1,146 @@ +--- +title: Firefox 17 for developers +slug: Mozilla/Firefox/Releases/17 +tags: + - Firefox + - Firefox 17 +translation_of: Mozilla/Firefox/Releases/17 +--- +
{{FirefoxSidebar}}
+ +

Firefox 17 shipped on November 20, 2012. This article lists key changes that are useful for not only web developers, but also Firefox and Gecko developers as well as add-on developers.

+ +

WEB开发者需要注意的变化

+ +

HTML

+ + + +

CSS

+ + + +

DOM

+ + + +

 

+ +

JavaScript

+ + + +

WebGL

+ +

 

+ + + +

 

+ +

SVG

+ +

No change.

+ +

MathML

+ +

 

+ + + +

 

+ +

XUL

+ + + +

网络

+ +

 

+ + + +

 

+ +

开发者工具

+ +

 

+ + + +

User Agent

+ +

The Gecko part of the user agent string changed. The build date (which hadn't been updated since 2010) was removed, and the Gecko version number was put in its place instead. So Gecko/20100101 -> Gecko/17.0. This may affect you if you are doing user agent sniffing.

+ +

附加组件和Mozilla开发者需要注意的变化

+ +

接口变化

+ +
+
{{ interface("nsIInputStream") }}
+
available() 方法返回一个64位的长度而不是32位的. ({{bug("215450")}})
+
{{ interface("nsIDOMWindowUtils") }}
+
sendMouseScrollEvent()方法被sendWheelEvent()替换. ({{bug("719320")}})
+
{{interface("nsIFilePicker")}}
+
The open() method, to open the file dialog asynchronously, has been added and the show() method has been deprecated ({{bug("731307")}}).
+
{{interface("nsIScriptSecurityManager")}}
+
The checkLoadURIStr() and checkLoadURI() methods have been removed ({{bug("327244")}}).
+
{{interface("nsIRefreshURI")}}
+
The setupRefreshURIFromHeader() method has a added principal parameter ({{bug("327244")}}).
+
+ +

新增接口

+ +

None.

+ +

移除接口

+ +

None removed.

+ +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers('16')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/18/index.html b/files/zh-cn/mozilla/firefox/releases/18/index.html new file mode 100644 index 0000000000..9854df7bf7 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/18/index.html @@ -0,0 +1,82 @@ +--- +title: Firefox 18 for developers +slug: Mozilla/Firefox/Releases/18 +translation_of: Mozilla/Firefox/Releases/18 +--- +
{{FirefoxSidebar}}

Firefox 18已于2013年1月8日发布.

+

WEB开发者需要注意的变化

+

HTML

+ +

CSS

+ +

DOM

+ +

JavaScript

+ +

WebGL

+

SVG

+

MathML

+

XUL

+

网络

+ +

开发者工具

+

附加组件和Mozilla开发者需要注意的变化

+

接口变更

+
+
+ {{ interface("nsIStreamListener") }}
+
+ onDataAvailable()方法的第四个参数(aOffset)类型改为无符号长整型. ({{bug("784912")}})
+
+ {{ interface("nsIUploadChannel") }}
+
+ setUploadStream()支持了超过2GB大小的content-length ({{bug("790617")}})
+
+ {{ interface("nsIEditor") }}
+
+ 删除了addEditorObserver(),使用setEditorObserver()来替代, removeEditorObserver()不再需要一个{{ interface("nsIEditorObserver") }}参数({{bug("785091")}})
+
+
+
+ {{ interface("nsIHttpProtocolHandler") }}
+
+ http-on-modify-request observers are no longer guaranteed to be called synchronously during
+ nsIChannel.asyncOpen(). For observers that need to be called during asyncOpen(), the new http-on-opening-request observer topic has been added. ({{bug("800799")}})
+
+

新增接口

+

移除接口

+

下面的接口已经被移除.

+ +

相关链接

+ +

更早版本

+

{{Firefox_for_developers('17')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/19/index.html b/files/zh-cn/mozilla/firefox/releases/19/index.html new file mode 100644 index 0000000000..670c6f9f18 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/19/index.html @@ -0,0 +1,76 @@ +--- +title: Firefox 19 for developers +slug: Mozilla/Firefox/Releases/19 +translation_of: Mozilla/Firefox/Releases/19 +--- +
{{FirefoxSidebar}}

Firefox 19已于2013年2月19日正式发布.

+ +

Web开发者需要注意的变化

+ +

JavaScript

+ + + +

CSS

+ + + +

DOM

+ + + +

XForms

+ +

删除了对XForms的支持.

+ +

附加组件和Mozilla开发者需要注意的变化

+ +
+

注: A key change in Firefox 19 is that nsresult is now strongly typed. This will help make it easier to detect bugs that are caused by mishandling of return values, but may cause existing code to break if it's making incorrect assumptions in this regard.

+
+ + + +

接口变化

+ +
+
{{interface("nsIImgLoadingContent")}}
+
The parameter (aObserver) of addObserver() method changes from {{interface("imgIDecoderObserver")}} to {{interface("imgINotificationObserver")}}. The notify() method of {{interface("imgINotificationObserver")}} is not scriptable, so you need to use createScriptedObserver() from {{interface("imgITools")}}.
+
{{interface("nsIChannel")}}
+
 contentLength 属性的类型由 long 改成 int64_t.
+
+ +

相关链接

+ + + +

更早版本

+ +
{{Firefox_for_developers('18')}}
diff --git a/files/zh-cn/mozilla/firefox/releases/20/index.html b/files/zh-cn/mozilla/firefox/releases/20/index.html new file mode 100644 index 0000000000..117426208d --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/20/index.html @@ -0,0 +1,47 @@ +--- +title: Firefox 20 for developers +slug: Mozilla/Firefox/Releases/20 +translation_of: Mozilla/Firefox/Releases/20 +--- +
{{FirefoxSidebar}}

Firefox 20正式版发布于

+

Web开发者需要注意的变化

+

HTML

+ +

JavaScript

+ +

CSS

+ +

DOM

+ +

附加组件和Mozilla开发者需要注意的变化

+ +

相关链接

+ +

更早版本

+

{{Firefox_for_developers('19')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/21/index.html b/files/zh-cn/mozilla/firefox/releases/21/index.html new file mode 100644 index 0000000000..9d0788dfa6 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/21/index.html @@ -0,0 +1,107 @@ +--- +title: Firefox 21 for developers +slug: Mozilla/Firefox/Releases/21 +translation_of: Mozilla/Firefox/Releases/21 +--- +
{{FirefoxSidebar}}

Web开发者需要注意的变化

+

HTML

+ +

JavaScript

+ +

CSS

+ +

DOM

+ +

SVG

+ +

网络

+ +

附加组件和Mozilla开发者需要注意的变化

+ +

相关链接

+ +

更早版本

+

{{Firefox_for_developers('20')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/22/index.html b/files/zh-cn/mozilla/firefox/releases/22/index.html new file mode 100644 index 0000000000..32177c38da --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/22/index.html @@ -0,0 +1,89 @@ +--- +title: Firefox 22 for developers +slug: Mozilla/Firefox/Releases/22 +tags: + - Firefox + - Firefox 22 +translation_of: Mozilla/Firefox/Releases/22 +--- +
{{FirefoxSidebar}}

Web开发者需要注意的变化

+ +

HTML

+ + + +

JavaScript

+ + + +

DOM

+ + + +

CSS

+ + + +

附加组件和Mozilla开发者需要注意的变化

+ + + +

Firefox Developer Tools

+ + + +

相关链接

+ + + +

Older versions

+ +

{{Firefox_for_developers('21')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/23/index.html b/files/zh-cn/mozilla/firefox/releases/23/index.html new file mode 100644 index 0000000000..adaf75356f --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/23/index.html @@ -0,0 +1,94 @@ +--- +title: Firefox 23 for developers +slug: Mozilla/Firefox/Releases/23 +tags: + - Firefox + - Firefox 23 +translation_of: Mozilla/Firefox/Releases/23 +--- +
{{FirefoxSidebar}}

Web开发者需要注意的变化

+ +

HTML

+ + + +

JavaScript

+ +

 

+ + + +

HTML

+ + + +

 

+ +

DOM

+ + + +

CSS

+ + + +

WebRTC

+ + + +

MathML

+ + + +

Changes for addon and Mozilla developers

+ +

Firefox developer tools

+ +

Addons that overlay chrome://browser/content/debugger.xul must now overlay chrome://browser/content/devtools/debugger.xul. You may add references to both these files in chrome.manifest for compatibility.

+ +

 

+ +

See also

+ + + +

 

+ +

 

+ +

之前版本

+ +

{{Firefox_for_developers('22')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/24/index.html b/files/zh-cn/mozilla/firefox/releases/24/index.html new file mode 100644 index 0000000000..cd3dd112e2 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/24/index.html @@ -0,0 +1,22 @@ +--- +title: Firefox 24 for developers +slug: Mozilla/Firefox/Releases/24 +translation_of: Mozilla/Firefox/Releases/24 +--- +
{{FirefoxSidebar}}

{{ draft() }}

+

Web开发者需要注意的变化

+

Developer Tools

+

HTML

+

JavaScript

+ +

DOM

+

MathML

+

相关链接

+ +

更早版本

+

{{Firefox_for_developers('23')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/25/index.html b/files/zh-cn/mozilla/firefox/releases/25/index.html new file mode 100644 index 0000000000..a23b1fd7c7 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/25/index.html @@ -0,0 +1,50 @@ +--- +title: Firefox 25 for developers +slug: Mozilla/Firefox/Releases/25 +translation_of: Mozilla/Firefox/Releases/25 +--- +
{{FirefoxSidebar}}

{{ draft() }}

+

Web开发者需要注意的变化

+

CSS

+ +

HTML

+ +

JavaScript

+

下面都是 ECMAScript 6 (Harmony) 中的新特性!

+ +

DOM

+ +

MathML

+

SVG

+

相关链接

+ +

更早版本

+

{{Firefox_for_developers('24')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/25/site_compatibility/index.html b/files/zh-cn/mozilla/firefox/releases/25/site_compatibility/index.html new file mode 100644 index 0000000000..d808bf4007 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/25/site_compatibility/index.html @@ -0,0 +1,40 @@ +--- +title: Firefox 25网站兼容性 +slug: Mozilla/Firefox/Releases/25/Site_Compatibility +translation_of: Mozilla/Firefox/Releases/25/Site_Compatibility +--- +
{{FirefoxSidebar}}

{{ draft() }}

+
+

DOM

+
+

ImageDocument 属性被删除

+ +

非标准的 {{ domxref("ImageDocument") }} 接口在普通页面中不能访问了.

+
+
+

worker 中的所有事件名都加上 Worker 前缀

+ +

为了能让 普通的 DOM 事件 能在 worker 中正常使用, 目前 worker 中的事件 {{domxref("Event") }}, {{ domxref("MessageEvent") }}, {{ domxref("ErrorEvent") }} and {{ domxref("ProgressEvent") }}  被重命名为了 {{ domxref("WorkerEvent") }}, {{ domxref("WorkerMessageEvent") }}, {{ domxref("WorkerErrorEvent") }} and {{ domxref("WorkerProgressEvent") }}.

+
+
+
+

JavaScript

+
+

Proxy 全局变量从对象类型修正到函数类型

+ +

以前, Proxy 是一个对象类型的值. 现在 typeof Proxy 会返回 function ,且不需要在前面加 new 运算符也可以正常调用了.

+
+
+

yield without a value has been deprecated

+ +

yield 运算符不再需要一个操作数, 该变化遵循了 ECMAScript 6 规范草案.

+
+
diff --git a/files/zh-cn/mozilla/firefox/releases/26/index.html b/files/zh-cn/mozilla/firefox/releases/26/index.html new file mode 100644 index 0000000000..621e9f87c9 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/26/index.html @@ -0,0 +1,41 @@ +--- +title: Firefox 26 for developers +slug: Mozilla/Firefox/Releases/26 +translation_of: Mozilla/Firefox/Releases/26 +--- +
{{FirefoxSidebar}}

Web开发者需要注意的变化

+

CSS

+ +

HTML

+

No change.

+

JavaScript

+ +

Interfaces/APIs/DOM

+ +

MathML

+ +

SVG

+

No change.

+

相关链接

+ +

更早版本

+

{{Firefox_for_developers('25')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/26/site_compatibility/index.html b/files/zh-cn/mozilla/firefox/releases/26/site_compatibility/index.html new file mode 100644 index 0000000000..009959b5c0 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/26/site_compatibility/index.html @@ -0,0 +1,104 @@ +--- +title: Site Compatibility for Firefox 26 +slug: Mozilla/Firefox/Releases/26/Site_Compatibility +translation_of: Mozilla/Firefox/Releases/26/Site_Compatibility +--- +
{{FirefoxSidebar}}

{{ draft() }}

+

Firefox 26 Aurora (pre-Beta) will be released on . While it has been developed to maintain compatibility as much as possible, the new version includes some changes affecting backward compatibility aimed at improving interoperability with the other browsers or following the latest Web standards. Here's the list of such changes — hope this helps whenever you test your sites or applications.

+

This article only explains the changes that may affect backward compatibility for Websites. For the other new features and changes, please read the following documents:

+ +

This list may be updated until the release of the final version on , so please check back later. Follow @MozWebCompat on Twitter for further updates.

+
+

CSS

+
+ + +

The non-standard {{ cssxref("-moz-text-blink") }} property has been removed. Instead, the standard, still prefixed {{ cssxref("text-decoration-line") }} property now takes blink as a valid value. Actually it doesn't blink any content on Firefox though, from the perspective of accessibility. Note that the blink effect with text-decoration:blink has been dropped with Firefox 23.

+
+
+
+

DOM

+
+

type 属性不是 image 的 HTMLInputElement 元素的 width 和 height 属性会返回 0

+ +

Previously, the width and height properties of an {{ HTMLElement("input") }} returned the dimension of the element. To comply with the spec, those properties now return 0 if the type property is not image.

+
+
+

Setting document.domain in a sandboxed iframe is no longer allowed

+ +

Setting the {{ domxref("document.domain") }} property on a page embedded in an {{ HTMLElement("iframe") }} with the sandbox attribute will throw a security error from now on.

+
+
+

元素的 id 改变后,旧 id 不再是 window 对象的属性

+ +

An element with id is accessible through window.<id>. Previously, the DOM object remained on {{ domxref("window") }} even after the id of the element is programmatically changed. This odd behavior has been fixed with Firefox 26. The {{ domxref("document.getElementById") }} method, which is recommended to use in general, is not affected by this change.

+
+
+

MessageEvent has been updated

+ +

The {{ domxref("MessageEvent") }} interface has been updated to comply with the latest spec. The initMessageEvent method has been removed while the interface is now a constructor.

+
+
+

HTMLCanvasElement.mozGetAsFile has been deprecated

+ +

The non-standard mozGetAsFile method on the {{ domxref("HTMLCanvasElement") }} interface is now deprecated and will be removed soon. The standard toBlob method can be used instead.

+
+
+

UserDataHandler has been removed

+ +

The deprecated {{ domxref("UserDataHandler") }} interface has been removed. The {{ domxref("Node.setUserData") }} and {{ domxref("Node.getUserData") }} methods have already been removed with Firefox 22.

+
+
+ + +

The following methods on the XBL DOM Interface have been removed from the {{ domxref("Document") }} interface: getAnonymousNodes, getAnonymousElementByAttribute, getBindingParent and loadBindingDocument.

+
+
+

Various non-standard interfaces have been removed

+ +

As part of the ongoing effort to standardize global objects, the following non-standard interfaces have been removed: ChromeWindow, StorageIndexedDB, XULButtonElement, XULCheckboxElement, XULCommandDispatcher, XULCommandEvent, XULControlElement, XULDocument, XULElement, XULLabeledControlElement and XULPopupElement.

+
+
+
+

JavaScript

+
+

The reserved words are no longer allowed as function names

+ +

The reserved words cannot be used for function names. Starting with Firefox 26, such a usage will throw a SyntaxError. For example, function delete() { ... } is illegal.

+
+
+
+

Plug-ins

+
+

All plug-ins except Flash are now defaulted to Click-to-Play

+ +

Starting with Firefox 26, plug-ins require user interaction to be activated. With the exception of the popular Adobe Flash Player, all plug-in content embedded in a Web page is now disabled by default and enabled by user's click. This change has been made in order to improve security and performance of the browser. See the Mozilla Security Blog for details. Web developers are encouraged to leverage modern Web technologies, including HTML5, to provide richer user experience.

+
+
diff --git a/files/zh-cn/mozilla/firefox/releases/27/index.html b/files/zh-cn/mozilla/firefox/releases/27/index.html new file mode 100644 index 0000000000..7f9f6a9028 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/27/index.html @@ -0,0 +1,45 @@ +--- +title: Firefox 27 for developers +slug: Mozilla/Firefox/Releases/27 +translation_of: Mozilla/Firefox/Releases/27 +--- +
{{FirefoxSidebar}}

Web 开发者需要注意的变化

+

开发者工具

+ +

更多详情, 请看这篇文章.

+

CSS

+ +

HTML

+ +

JavaScript

+

EcmaScript 6 (Harmony) 实现了:

+ +

Interfaces/APIs/DOM

+

No change.

+

MathML

+

No change.

+

SVG

+

No change.

+

附加组件和 Mozilla 开发者需要注意的变化

+ +

相关链接

+ +

更早版本

+

{{Firefox_for_developers('26')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/28/index.html b/files/zh-cn/mozilla/firefox/releases/28/index.html new file mode 100644 index 0000000000..1e41a0b20d --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/28/index.html @@ -0,0 +1,117 @@ +--- +title: Firefox 28 for developers +slug: Mozilla/Firefox/Releases/28 +tags: + - Firefox + - Firefox 28 +translation_of: Mozilla/Firefox/Releases/28 +--- +
{{FirefoxSidebar}}

Firefox 28 was released on March 18, 2014. This article lists key changes that are useful not only for web developers, but also Firefox and Gecko developers as well as add-on developers.

+ +

Changes for Web developers

+ +

Developer Tools

+ + + +

More details in this post.

+ +

CSS

+ + + +

HTML

+ + + +

JavaScript

+ + + +

Interfaces/APIs/DOM

+ + + +

MathML

+ + + +

SVG

+ +

No change.

+ +

Audio/Video

+ + + +

Network

+ + + +

Changes for addon and Mozilla developers

+ + + +

Security

+ + + +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers('27')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/28/site_compatibility/index.html b/files/zh-cn/mozilla/firefox/releases/28/site_compatibility/index.html new file mode 100644 index 0000000000..c2a74bad9f --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/28/site_compatibility/index.html @@ -0,0 +1,56 @@ +--- +title: Site Compatibility for Firefox 28 +slug: Mozilla/Firefox/Releases/28/Site_Compatibility +translation_of: Mozilla/Firefox/Releases/28/Site_Compatibility +--- +
{{FirefoxSidebar}}

DOM

+
+
+ + +

{{ domxref("PluginArray") }} 接口, 通常就是指 {{ domxref("window.navigator.plugins") }} 属性, 现在不再是可以枚举的了. 这么做主要是为了防止网站通过某些技术手段窃取用户隐私. 不过开发人员仍然可以使用 {{ domxref("window.navigator.mimeTypes") }} 接口来判断浏览器支持哪些 MIME 类型. 这一变更可能会给一些已有的代码带来兼容性问题.

+
+
+

showModalDialog has been deprecated

+ +

The {{ domxref("window.showModalDialog") }} method, originally from Internet Explorer, is now considered deprecated. The {{ domxref("window.open") }} method should be used instead.

+
+
+

Make sure the deep argument is specified for cloneNode and importNode

+ +

The {{ domxref("Node.cloneNode") }} and {{ domxref("document.importNode") }} methods take the boolean deep argument. It's optional in the DOM4 specification, and if omitted, these methods acted as if the value of deep was true. But this behavior has been changed in the latest spec, and if omitted, the methods will act as if the value was false. Though It's still optional, Firefox now warns developers in console not to omit the argument for the forward compatibility.

+
+
+

History objects now throw if the document is inactive

+ +

The spec of the {{ domxref("History") }} interface has been updated, and the properties and methods now throw a SecurityError exception when those are called on an inactive {{ domxref("document") }}. It would be a problem if you are manipulating {{ domxref("window.history") }} in an {{ HTMLElement("iframe") }}.

+
+
+
+

Networking

+
+

SPDY/2 support has been dropped

+ +

The support of SPDY Protocol Draft 2 has been removed. Web sites should upgrade to SPDY/3 or 3.1.

+
+
+
+

Video/Audio

+
+

canPlayType('video/webm') now returns 'maybe'

+ +

The canPlayType method of the {{ domxref("HTMLMediaElement") }} interface has been updated to comply with the spec. canPlayType('video/webm') and canPlayType('audio/webm') now return 'maybe' instead of 'probably', because media can be encoded with a codec that Firefox doesn't support. If a codec is specified in the type argument, the method returns 'probably' or '' (empty string) depending on the codec. For example, canPlayType('video/webm; codecs=vp8') returns 'probably'.

+
+
diff --git a/files/zh-cn/mozilla/firefox/releases/3.6/index.html b/files/zh-cn/mozilla/firefox/releases/3.6/index.html new file mode 100644 index 0000000000..8bc9182b45 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/3.6/index.html @@ -0,0 +1,305 @@ +--- +title: Firefox 3.6 for developers +slug: Mozilla/Firefox/Releases/3.6 +translation_of: Mozilla/Firefox/Releases/3.6 +--- +

Firefox 3.6 offers support for new and developing web standards, increased performance, and an overall better experience for web users and developers. This page provides links to articles covering the new capabilities of Firefox 3.6.

+ +

For web site and application developers

+ +

CSS

+ +
+
Using gradients
+
Firefox 3.6 adds support for the proposed -moz-linear-gradient and -moz-radial-gradient properties  for background.
+
Multiple backgrounds
+
The background property (as well as background-color, background-image, background-position, background-repeat, and background-attachment) now supports multiple backgrounds. This lets you specify multiple backgrounds that are rendered atop one another in layers.
+
Mozilla-specific media features
+
Media features have been added for Mozilla-specific system metrics, so that media queries can be used to more safely check on the availability of features such as touch support.
+
Scaling background images
+
The background-size property from the CSS 3 Backgrounds and Borders draft is now supported under the name -moz-background-size.
+
WOFF font support
+
@font-face now supports the WOFF downloadable font file format.
+
Pointer events
+
The pointer-events property lets content specify whether or not an element may be the target of mouse pointer events.
+
+ +

Miscellaneous CSS changes

+ + + +

HTML

+ +
+
Using files from web applications
+
Support for the new HTML5 File API has been added to Gecko, making it possible for web applications to access local files selected by the user. This includes support for selecting multiple files using the input type="file" HTML element's new multiple attribute.
+
HTML5 video supports poster frames
+
The poster attribute is now supported for the video element, allowing content to specify a poster frame to be displayed until the video begins to play.
+
Checkboxes and radio buttons support the indeterminate property
+
HTML input elements of types checkbox and radio now support the indeterminate property, which allows a third, "indeterminate" state.
+
Canvas image smoothing can be controlled
+
The new mozImageSmoothingEnabled property can be used to turn on and off image smoothing when scaling in canvas elements.
+
Asynchronous script execution
+
By setting the async attribute on a script element, the script will not block loading or display of the rest of the page. Instead the script executes as soon as it is downloaded.
+
+ +

JavaScript

+ +

Gecko 1.9.2引入了JavaScript 1.8.2, 该版本的JavaScript添加了许多来自ECMAScript 5的新的语言特性:

+ + + +
+
+ +

DOM

+ +
+
Web workers可以自行终止
+
Workers 开始支持nsIWorkerScope.close()方法, 该方法允许它们终止自身的运行.
+
支持文件的拖放
+
DataTransfer对象提供的拖拽监听器现在可以包含一个被拖拽的文件列表.
+
Checking to see if an element matches a specified CSS selector
+
The new element.mozMatchesSelector method lets you determine whether or not an element matches a specified CSS selector. See bug 518003.
+
Detecting device orientation
+
Content can now detect the orientation of the device if it has a supported accelerometer, using the MozOrientation event. Firefox 3.6 supports the accelerometer in Mac laptops.
+
Detecting document width and height changes
+
The new MozScrollAreaChanged event is dispatched whenever the document's scrollWidth and/or scrollHeight properties change.
+
+ +

Miscellaneous DOM changes

+ + + +

XPath

+ +
+
支持choose()方法
+
XPath开始支持choose()方法.
+
+ +

For XUL and add-on developers

+ +

If you're an extension developer, you should start by reading Updating extensions for Firefox 3.6, which offers a helpful overview of what changes may affect your extension. Plug-in developers should read Updating plug-ins for Firefox 3.6.

+ +

New features

+ +
+
Detecting device orientation
+
Content can now detect the orientation of the device if it has a supported accelerometer, using the MozOrientation event. Firefox 3.6 supports the accelerometer in Mac laptops.
+
Monitoring HTTP activity
+
You can now monitor HTTP transactions to observe requests and responses in real time.
+
Working with the Windows taskbar
+
It's now possible to customize the appearance of windows in the taskbar in Windows 7 or later. This has been disabled by default in Firefox 3.6.
+
+ +

Places

+ + + +

Storage

+ +
+
Locale-aware collation of data is now supported by the Storage API
+
Gecko 1.9.2 added several new collation methods to provide optimized collation (sorting) of results using locale-aware techniques.
+
Properties on a statement can now be enumerated
+
You can now use a for..in enumeration to enumerate all the properties on a statement.
+
mozIStorageStatement's getParameterIndex changed behavior between 3.5 and 3.6.
+
See bug 528166 for details.
+
Asynchronously bind multiple sets of parameters and execute a statement.
+
See bug 490085 for details. Documentation coming soon.
+
+ +

Preferences

+ + + +

Themes

+ +

See Updating themes for Firefox 3.6 for a list of changes related to themes.

+ +
+
Lightweight themes
+
Firefox 3.6 supports lightweight themes; these are easy-to-create themes that simply apply a background to the top (URL bar and button bar) and bottom (status bar) of browser windows. This is an integration of the existing Personas theme architecture into Firefox.
+
+ +

Miscellaneous

+ + + +

Firefox/Gecko开发

+ +

Certain changes are only really interesting if you work on the internals of Firefox itself.

+ +

Interfaces merged

+ +

The following interfaces have been combined together:

+ + + +

Interfaces removed

+ +

The following interfaces have been removed entirely because they were unused, unimplemented, or obsolete:

+ + + +

Interfaces moved

+ +

The following interfaces have been relocated from their previous IDL files into new ones:

+ + + +

A large number of interfaces have been moved. See Interfaces moved in Firefox 3.6 for a complete list.

+ +

Other interface changes

+ +

The following assorted changes have been made:

+ + + +

Changes in accessibility code

+ + + +

相关链接

+ + diff --git a/files/zh-cn/mozilla/firefox/releases/3/index.html b/files/zh-cn/mozilla/firefox/releases/3/index.html new file mode 100644 index 0000000000..561c473cd3 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/3/index.html @@ -0,0 +1,310 @@ +--- +title: 致Firefox 3开发者 +slug: Mozilla/Firefox/Releases/3 +tags: + - Firefox 3 +translation_of: Mozilla/Firefox/Releases/3 +--- +
{{FirefoxSidebar}}

如果你是一个Web开发人员,并且希望了解Firefox 3中所有的新特性,这里是一个很好的起点。这篇文章提供了一个覆盖所有Firefox 3新特性的列表。虽然他并不是能够包括所有微小的改动,但他能够帮助你学习到最主要的更新。

+

 

+

Firefox 3 中新的开发人员特性

+

对网站和程序开发者

+
+
+ 更新WEB应用以适应Firefox 3
+
+ 提供了您用于更新WEB应用以受益于Firefox 3新特性所需的信息。
+
+
+
+ 上线与离线事件
+
+ Firefox 3支持WHATWG的上线与离线事件,基于这一特性,程序可以检测当前是否有可用的互联网联接以及何时上线或下线。
+
+
+
+ 跨域的XMLHttpRequest请求
+
+ Firefox 3支持W3C Access Control工作草案,使你有能够使用XMLHttpRequests检索和操作其他站点的数据;使你能够创造令人印象深刻的以浏览器为基础的交互式应用(mashups)。
+
+
+
+ 交错格式样表
+
+ Firefox 3 支持CSS 层叠式样式表 API.
+
+
+ 基于web的协议处理
+
+ 你现在可以使用navigator.registerProtocolHandler()方法注册web应用
+
+
+
+ 在画布(canvas)中“绘”出文字
+
+ 您可以使用Firefox 3支持的非标准API在canvas上绘制文字。
+
+
+
+ 支持画布变换
+
+ Firefox现在的canvas支持transform()setTransform()方法。
+
+
+
+ 使用微格式
+
+ Firefox现在有一组微格式的API。
+
+
+
+ 拖放事件
+
+ Firefox 3 支持新的拖放事件,当拖放开始和结束时,该事件将会被发送至源节点。
+
+ HTML的焦点管理
+
+
+
+ 新的HTML 5 支持activeElement和hasFocus属性
+
+
+
+ 离线浏览
+
+ 在Firefox中,WEB程序现在可以在离线时使用之前被缓存的资源。
+
+ 在Firefox 3中CSS的改进
+
+ Firefox 3 在支持CSS的功能上进行了一些完善。
+
+
+
+ 在Firefox 3中DOM的改进
+
+ Firefox 3 在Firefox3 DOM执行方面提供了一些新的功能,包括支持一些扩展的浏览器的DOM。
+
+
+
+ JavaScript 1.8 的支持
+
+ Firefox 3 提供了 JavaScript 1.8 标准的支持。
+
+
+
+ EXSLT支持
+
+ Firefox 3 提供了对 EXSLTXSLT的扩展)一个基本子集个支持。
+
+
+
+ Firefox 3中SVG的改进
+
+ Firefox 3 对SVG 的支持有了长足的改进:支持二十余个新透镜、一些新元素、一些新属性以及一些其他改进。
+
+
+
+ 对PNG动画的支持
+
+ Firefox 3 提供了对色彩艳丽的 PNG (APNG) 图像格式的支持.
+
+
+
+ <a ping>
+
+  现在可以使用 <a ping> 功能 ping 一个 URL ,并且此功能默认启用.
+
+

对XUL和扩展插件的开发者

+

 

+
+
+

   提供了你需要做的事情的向导,更新您的Firefox 3 扩展。

+
+
+ 更新扩展以兼容Firefox 3
+
+

FUEL 知识库

+
+
+ FUEL 使扩展开发者完成更有成效,更精悍的 XPCOM 规范代码并获得一些 "模式" JavaScript 思想。
+
+

   Firefox 3的提供了一些新的XUL元素,包括新的缩放法,日期和时间获取,以及旋转按钮。

+
+
+ Firefox  3在 XUL 上的改进   
+
+
+
+ Firefox 3的模板
+
+ Firefox 3的模板已显着改善 。关键的改进是,允许使用自定义查询处理器,除数据源之外还可以使用RDF。 
+
+

嵌入的XBL绑定

+
+
+ 现在,您可以使用 data: 网络协议直接嵌入XBL绑定,而不是在单独的XML文件中使用他们。 +

 

+
+
+ 本地化扩展描述
+
+ 这可让本地化的详细信息在附加组件被下载时或被禁用即时生效。 
+
+
+
+ 可靠更新
+
+

In order to provide a more secure add-on upgrade path for users, add-ons are now required to provide a secure method for obtaining updates before they can be installed. Add-ons hosted at

+

AMO

+

automatically provide this. Any add-ons installed that do not provide a secure update method when the user upgrades to Firefox 3 will be automatically disabled. Firefox will however continue to check for updates to the extension over the insecure path and attempt to install any update offered (installation will fail if the update also fails to provide a secure update method).

+
+
+ Idle service
+
+
+
+ Firefox 3 offers the new {{ Interface("nsIIdleService") }} interface, which lets extensions determine how long it's been since the user last pressed a key or moved their mouse.
+
+
+
+ 全屏缩放
+
+
+
+ Firefox 3 improves the user experience by offering full page zoom in addition to text-only zoom.
+
+
+
+ Interfacing with the XPCOM cycle collector
+
+
+
+ XPCOM code can now take advantage of the cycle collector, which helps ensure that unused memory gets released instead of leaking.
+
+
+
+ The Thread Manager
+
+
+
+ Firefox 3 provides the new {{ Interface("nsIThreadManager") }} interface, along with new interfaces for threads and thread events, which provides a convenient way to create and manage threads in your code.
+
+
+
+ JavaScript模块
+
+
+
+ Firefox 3 now offers a new shared code module mechanism that lets you easily create modules in JavaScript that can be loaded by extensions and applications for use, much like shared libraries.
+
+
+
+ Places
+
+
+
+ The history and bookmarks APIs have been completely replaced by the new Places API.
+
+
+
+ Making the transition to Places
+
+
+
+ An article about how to update an existing extension to use the Places API.
+
+
+
+ Firefox 3中下载管理器的改进
+
+
+
+ The Firefox 3 Download Manager features new and improved APIs, including support for multiple progress listeners.
+
+
+
+ Using nsILoginManager
+
+
+
+ 密码管理已经被新的登录管理所代替。
+
+
+
+ Using content preferences
+
+
+
+ Firefox 3 includes a new service for getting and setting arbitrary site-specific preferences that extensions as well as core code can use to keep track of their users' preferences for individual sites.
+
+
+
+ Notable bugs fixed in Firefox 3
+
+
+
+ 文章中所提供的相关Bug信息,已经在Firefox 3中进行了修改。
+
+
+
+ Firefox 3 的界面改动
+
+
+
+ Notes and information of use to people who want to create themes for Firefox 3.
+
+

最终用户将能体验到的新特性

+

用户体验

+ +

安全和隐私

+ + +

性能

+ +

参见

+ +

{{ languages( { "es": "es/Firefox_3_para_desarrolladores", "fr": "fr/Firefox_3_pour_les_d\u00e9veloppeurs", "ja": "ja/Firefox_3_for_developers", "zh-tw": "zh_tw/Firefox_3_for_developers", "zh-cn": "cn/Firefox_3_for_developers", "ko": "ko/Firefox_3_for_developers", "pl": "pl/Firefox_3_dla_programist\u00f3w", "pt": "pt/Firefox_3_para_desenvolvedores" } ) }}

diff --git a/files/zh-cn/mozilla/firefox/releases/3/site_compatibility/index.html b/files/zh-cn/mozilla/firefox/releases/3/site_compatibility/index.html new file mode 100644 index 0000000000..b8b2678b12 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/3/site_compatibility/index.html @@ -0,0 +1,26 @@ +--- +title: Gecko 1.9 Changes affecting websites +slug: Mozilla/Firefox/Releases/3/Site_compatibility +translation_of: Mozilla/Firefox/Releases/3/Site_compatibility +--- +
{{FirefoxSidebar}}

此页设法提供在 Gecko 1.8 和 Gecko 1.9 之间的变动概要,这些变动可能会影响某些网站的行为或网页渲染。

+

参见 Firefox 3 开发者参考

+

事件

+

捕获 load 事件监听

+

在 Gecko 1.8 中,不能在图片上设置 load 事件监听。 在 Gecko 1.9 中,已在 {{ Bug(234455) }} 中修复。 但是在某些网站中,由于捕获 load 事件的事件监听器不正确而导致问题。参见 {{ Bug(335251) }} 中的讨论。 要修复这个问题,出错的页面不再需要设置事件监听器。

+

例如,如下:

+
window.addEventListener('load', yourFunction, true);
+
+

应该更改为:

+
window.addEventListener('load', yourFunction, false);
+
+

事件捕获如何工作的解释,参见 DOM Level 2 事件捕获

+

preventBubble 已被移出

+

少许旧的事件 API 不再被支持

+

DOM

+

WRONG_DOCUMENT_ERR

+

范围

+

intersectsNode 已被移出

+

compareNode 已被移出

+

HTML

+

<object> 中的许多 bug 已经修复

diff --git a/files/zh-cn/mozilla/firefox/releases/31/index.html b/files/zh-cn/mozilla/firefox/releases/31/index.html new file mode 100644 index 0000000000..a22131fe8c --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/31/index.html @@ -0,0 +1,46 @@ +--- +title: Firefox 31 for developers +slug: Mozilla/Firefox/Releases/31 +translation_of: Mozilla/Firefox/Releases/31 +--- +
{{FirefoxSidebar}}

Web 开发者需要关注的变化

+

Developer Tools

+

No change.

+

CSS

+ +

HTML

+

No change.

+

JavaScript

+

实现了如下 ECMAScript 6 新特性:

+ +

Interfaces/APIs/DOM

+ +

MathML

+

No change.

+

SVG

+

No change.

+

Audio/Video

+

No change.

+

Security

+

No change.

+

Changes for add-on and Mozilla developers

+

No change.

+

See also

+ +

Older versions

+

{{Firefox_for_developers('30')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/32/index.html b/files/zh-cn/mozilla/firefox/releases/32/index.html new file mode 100644 index 0000000000..b2bfbc3fd9 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/32/index.html @@ -0,0 +1,154 @@ +--- +title: Firefox 32 for developers +slug: Mozilla/Firefox/Releases/32 +tags: + - Firefox + - Firefox 31 +translation_of: Mozilla/Firefox/Releases/32 +--- +
{{FirefoxSidebar}}

普通 Web 开发者应该注意的变化

+ +

开发者工具

+ +

Highlights:

+ + + +

All devtools bugs fixed between Firefox 31 and Firefox 32.

+ +

CSS

+ + + +

HTML

+ + + +

JavaScript

+ + + +

Interfaces/APIs/DOM

+ + + +

MathML

+ + + +

SVG

+ +

No change.

+ +

WebRTC

+ + + +

Audio/Video

+ +

No change.

+ +

Security

+ + + +

附加组件 和 Mozilla 开发者应该注意的变化

+ +

Xray vision is now applied to JavaScript objects that are not themselves DOM objects: Xrays for JavaScript objects.

+ +

getDataDirectory() method has been added to Addon instances. This method returns the preferred location, within the current profile, for add-ons to store data.

+ +

 

+ +

Add-on SDK

+ +

Highlights

+ + + +

Details

+ +

GitHub commits made between Firefox 31 and Firefox 32. This will not include any uplifts made after this release entered Aurora.

+ +

Bugs fixed between Firefox 31 and Firefox 32. This will not include any uplifts made after this release entered Aurora.

+ +

XPCOM

+ + + +

 

+ +

相关链接

+ + + +

Older versions

+ +

{{Firefox_for_developers('31')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/33/index.html b/files/zh-cn/mozilla/firefox/releases/33/index.html new file mode 100644 index 0000000000..accca764bf --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/33/index.html @@ -0,0 +1,38 @@ +--- +title: Firefox 33 for developers +slug: Mozilla/Firefox/Releases/33 +translation_of: Mozilla/Firefox/Releases/33 +--- +
{{FirefoxSidebar}}

普通 Web 开发者应该注意的变化

+

Developer Tools

+

No change.

+

CSS

+ +

HTML

+

No change.

+

JavaScript

+ +

Interfaces/APIs/DOM

+

No change.

+

MathML

+

No change.

+

SVG

+

No change.

+

Audio/Video

+

No change.

+

Security

+

No change.

+

附加组件 和 Mozilla 开发者应该注意的变化

+

No change.

+

相关链接

+ +

更早版本

+

{{Firefox_for_developers('32')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/35/index.html b/files/zh-cn/mozilla/firefox/releases/35/index.html new file mode 100644 index 0000000000..c7d75e5f94 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/35/index.html @@ -0,0 +1,213 @@ +--- +title: Firefox 35 开发者相关变更清单 +slug: Mozilla/Firefox/Releases/35 +tags: + - Firefox + - Firefox 35 +translation_of: Mozilla/Firefox/Releases/35 +--- +
Firefox 35 was released on January 13th, 2015. This article lists key changes that are useful not only for web developers, but also Firefox and Gecko developers as well as add-on developers.
+ +

Web 开发者相关变更

+ +

开发者工具

+ +

Highlights:

+ + + +

All devtools bugs fixed between Firefox 34 and Firefox 35.

+ +

CSS

+ + + +

HTML

+ + + +

JavaScript

+ + + +

接口/APIs/DOM

+ + + +

 MathML

+ + + +

SVG

+ +

无变化。

+ +

音频/视频

+ +

无变化。

+ +

网络 & 安全

+ + + +

附加组件和 Mozilla 开发者相关的变更

+ +

XUL & 附加组件

+ + + +

Add-on SDK

+ +

Highlights

+ + + +

明细

+ +

Firefox 34 到 Firefox 35 的 GitHub 提交. This will not include any uplifts made after this release entered Aurora.

+ +

Bugs fixed between Firefox 34 and Firefox 35. This will not include any uplifts made after this release entered Aurora.

+ +

 

+ +

See also

+ + + +

 

+ +

以往版本

+ +
+ +
diff --git a/files/zh-cn/mozilla/firefox/releases/41/index.html b/files/zh-cn/mozilla/firefox/releases/41/index.html new file mode 100644 index 0000000000..9e373c6bf7 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/41/index.html @@ -0,0 +1,209 @@ +--- +title: Firefox 41 for developers +slug: Mozilla/Firefox/Releases/41 +tags: + - Firefox + - Firefox 41 +translation_of: Mozilla/Firefox/Releases/41 +--- +
{{FirefoxSidebar}}
To test the latest developer features of Firefox,
+install Firefox Developer Edition
Firefox 41 was released on September 22, 2015. This article lists key changes that are useful not only for web developers, but also Firefox and Gecko developers as well as add-on developers.
+ +

Changes for Web developers

+ +

开发工具

+ +

Highlights:

+ + + +

All devtools bugs fixed between Firefox 40 and Firefox 41: note that many of these bugs, especially those relating to the performance tools, were uplifted to Firefox 40.

+ +

CSS

+ + + +

HTML

+ + + +

JavaScript

+ + + +

Interfaces/APIs/DOM

+ + + +

Events

+ + + +

Web Crypto

+ + + +

Canvas API

+ + + +

Service Workers

+ + + +

WebGL

+ + + +

WebRTC

+ + + +

Miscellaneous

+ + + +

MathML

+ +

新的默认、支持字体处理

+ +

数学公式需要特殊的字体. 到目前为止, 这些字体被硬编码在用户默认样式 mathml.css (使用{{MathMLElement("math")}} 标志设置字体组) 和偏好选项font.mathfont-family (为拉伸和大操作数设置支持字体). Firefox 41 引入一个能够自动设置<math>标志和相应偏好选项的内置x-math 语言 (例如font.name.serif.x-math). 用户默认样式现在将<math>标志字体设置为serif 并且font.mathfont-family 被替换为 font.name.serif.x-math.  所有平台现在基本使用相同列表的支持字体, "Latin Modern Math" 是首选.在标准的 per-language字体偏好菜单中,默认支持字体能够被设置. 更多细节,请参照{{bug(947654)}} 和 {{bug(1160456)}}.

+ +

SVG

+ + + +

音频/视频

+ + + +

Networking

+ + + +

Security

+ + + +

Changes for add-on and Mozilla developers

+ +

XUL

+ +

没有变化。

+ +

JavaScript code modules

+ +

没有变化。

+ +

XPCOM

+ +

没有变化。

+ +

其他

+ + + +

See also

+ + + +

之前版本

+ +

{{Firefox_for_developers('40')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/43/index.html b/files/zh-cn/mozilla/firefox/releases/43/index.html new file mode 100644 index 0000000000..81566a6373 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/43/index.html @@ -0,0 +1,173 @@ +--- +title: Firefox 43 for developers +slug: Mozilla/Firefox/Releases/43 +tags: + - Firefox +translation_of: Mozilla/Firefox/Releases/43 +--- +
{{FirefoxSidebar}}

To test the latest developer features of Firefox,
+ install Firefox Developer Edition
Firefox 43 was released on December 15, 2015. This article lists key changes that are useful not only for web developers, but also Firefox and Gecko developers as well as add-on developers.

+ +

Changes for Web developers

+ +

Developer Tools

+ +

Highlights:

+ + + +

All devtools bugs fixed between Firefox 42 and Firefox 43.

+ +

CSS

+ + + +

HTML

+ + + +

JavaScript

+ +

New APIs

+ + + +

Changes regarding the arguments object

+ + + +

Other changes

+ + + +

Interfaces/APIs/DOM

+ +

DOM & HTML DOM

+ +

No change.

+ +

IndexedDB

+ + + +

Service Workers

+ + + +

WebRTC

+ + + +

Miscellaneous

+ + + +

MathML

+ +

No change.

+ +

SVG

+ +

No change.

+ +

Audio/Video

+ +

No change.

+ +

HTTP

+ +

No change.

+ +

Networking

+ +

No change.

+ +

Security

+ + + +

Changes for add-on and Mozilla developers

+ +

Interfaces

+ +

No change

+ +

XUL

+ +

No change.

+ +

JavaScript code modules

+ +

No change.

+ +

XPCOM

+ +

No change.

+ +

Plugins

+ + + +

Other

+ +

No change.

+ +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers('42')}}

diff --git a/files/zh-cn/mozilla/firefox/releases/44/index.html b/files/zh-cn/mozilla/firefox/releases/44/index.html new file mode 100644 index 0000000000..d18ac693ac --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/44/index.html @@ -0,0 +1,222 @@ +--- +title: Firefox 44 for developers +slug: Mozilla/Firefox/Releases/44 +translation_of: Mozilla/Firefox/Releases/44 +--- +
{{FirefoxSidebar}}

为了测试火狐最新的开发人员特性,请安装火狐开发人员版(Firefox Developer Edition )Firefox 44 于2016年1月26号发布。这个页面列出了对开发人员有用的关键变化。

+ +

对于Web开发人员的变化

+ +

开发者工具

+ +

{{page('/en-US/docs/Tools/Release_notes', 'Firefox_44')}}

+ +

HTML

+ + + +

CSS

+ + + +

JavaScript

+ +

New APIs

+ + + +

Changes

+ + + +

Removals

+ + + +

Interfaces/APIs/DOM

+ +

DOM & HTML DOM

+ + + +

Canvas

+ + + +

WebGL

+ + + +

IndexedDB

+ + + +

Service Workers

+ + + +

WebRTC

+ + + +

New APIs

+ + + +

Miscellaneous

+ + + +

MathML

+ +

No change.

+ +

SVG

+ +

No change.

+ +

Audio/Video

+ +

No change.

+ +

HTTP

+ + + +

Networking

+ +

No change.

+ +

Security

+ + + +

Changes for add-on and Mozilla developers

+ +

Interfaces

+ +

No change

+ +

XUL

+ +

No change.

+ +

JavaScript code modules

+ + + +

XPCOM

+ + + +

Other

+ + + +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers(43)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/45/index.html b/files/zh-cn/mozilla/firefox/releases/45/index.html new file mode 100644 index 0000000000..e288cbacc6 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/45/index.html @@ -0,0 +1,187 @@ +--- +title: Firefox 45 for developers +slug: Mozilla/Firefox/Releases/45 +tags: + - Firefox + - Firefox 45 +translation_of: Mozilla/Firefox/Releases/45 +--- +
{{FirefoxSidebar}}

安装Firefox开发者版本,
+ 以便测试Firefox最新的功能
Firefox 45 was released on March 8, 2016. This article lists key changes that are useful not only for web developers, but also Firefox and Gecko developers as well as add-on developers.

+ +

针对网络开发者的功能更新

+ +

开发工具

+ +

{{page('/en-US/docs/Tools/Release_notes', 'Firefox_45')}}

+ +

HTML

+ + + +

CSS

+ + + +

JavaScript

+ + + +

Interfaces/APIs/DOM

+ +

DOM & HTML DOM

+ + + +

WebGL

+ +

Our implementation of WebGL2 have been extended:

+ + + +

IndexedDB

+ +

No change.

+ +

Service Workers

+ + + +

WebRTC

+ +

No change.

+ +

New APIs

+ +

No change.

+ +

Miscellaneous

+ + + +

MathML

+ +

 

+ +

No change.

+ +

SVG

+ + + +

Audio/Video

+ + + +

HTTP

+ + + +

Security

+ + + +

Changes for add-on and Mozilla developers

+ +

Interfaces

+ +

No change.

+ +

XUL

+ + + +

JavaScript code modules

+ +

No change.

+ +

XPCOM

+ +

No change.

+ +

Search plugins

+ +

Starting in Firefox 45, search plugins located in the user's profile's searchpluginsdirectory are no longer automatically loaded on startup. Instead, a list of user-installed plugins is maintained and only those plugins are loaded. In effect, this means that the only ways to install new search plugins are for the user to do so in the Firefox UX (via OpenSearch discovery, for instance) or for an add-on to install it. Also, when a new search plugin is installed, more information is recorded about where it came from, for future use by profile debugging and cleaning tools.

+ +

 

+ +

Other

+ + + +

 

+ +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers(44)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/49/index.html b/files/zh-cn/mozilla/firefox/releases/49/index.html new file mode 100644 index 0000000000..d1afa7f9a6 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/49/index.html @@ -0,0 +1,348 @@ +--- +title: Firefox 49 for developers +slug: Mozilla/Firefox/Releases/49 +tags: + - Firefox + - Firefox 49 +translation_of: Mozilla/Firefox/Releases/49 +--- +
{{FirefoxSidebar}}

To test the latest developer features of Firefox,
+ install Firefox Developer Edition
Firefox 49 was released on September 20, 2016. This article lists key changes that are useful not only for web developers, but also Firefox and Gecko developers as well as add-on developers.

+ +

对于Web开发者的改变

+ +

开发者工具

+ + + +

HTML

+ + + +

CSS

+ + + +

JavaScript

+ + + +

Interfaces/APIs/DOM

+ +

DOM & HTML DOM

+ + + +

Canvas

+ + + +

WebGL

+ + + +

IndexedDB

+ + + + + + + +

Media Streams

+ + + +

WebRTC

+ + + +

New APIs

+ + + +

Others

+ + + +

MathML

+ +

No change.

+ +

SVG

+ + + +

Audio/Video

+ +

没有改变.

+ +

Plugins and Flash

+ +

Beginning in Firefox 49, Firefox, by default, blocks certain kinds of Flash content that aren't necessary for sites to function well. This behavior, controlled by the preference browser.safebrowsing.blockedURIs.enabled, helps to improve the performance of sites and Firefox in general without having significant impact on site usability. It also helps improve stability of the browsing experience by elminating a major cause of crashes. The blocked Flash modules include several used just for fingerprinting purposes, as well as a number of "supercookie" modules, and in the future may be expanded to include more types of blocked modules. See {{bug(1275591)}} for details.

+ +

This marks the next step in the journey toward a plugin-free future. HTML is very close to the point where plugins will no longer be needed to get the job done.

+ +

HTTP

+ + + +

Networking

+ + + +

Security

+ + + +

Compatibility

+ +

为了增强兼容性对于现在已经存在的内容, Firefox 现在接受一些 webkit 前缀 properties and attributes.

+ + + +

改变对于 add-on and Mozilla developers

+ +

WebExtensions

+ + + +

Interfaces

+ + + +

Other

+ +

没有改变.

+ +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers(48)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/56/index.html b/files/zh-cn/mozilla/firefox/releases/56/index.html new file mode 100644 index 0000000000..e7e2870e37 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/56/index.html @@ -0,0 +1,129 @@ +--- +title: Firefox 56 for developers +slug: Mozilla/Firefox/Releases/56 +translation_of: Mozilla/Firefox/Releases/56 +--- +
{{FirefoxSidebar}}
+

本文介绍了一些在Firefox 56中的一些改进,这些改进会对开发者们产生影响。Firefox 56是当前Firefox的Beta版,预计在2017年9月26日正式发布。

+ +
+

针对网页开发者们的若干改变

+ +

开发者工具

+ +
    +
  • 在CSS格检查器中显示以负号开始的行号({{bug(1369942)}}).
  • +
+ +

HTML

+ +
    +
  • 在打标签的窗体控件中采用labels 属性,比如 {{domxref("HTMLInputElement.labels")}} ({{bug(556743)}}).
  • +
  • 实现了 <link rel="preload">; 更详细的内容,可以参见 Preloading content with rel="preload"  ({{bug(1222633)}}). 需要注意的是,当前的Firefox只支持对可缓存的资源进行预加载。
  • +
+ +

CSS

+ +
    +
  • 实现了Mozilla自有的属性 {{cssxref("<color>")}} 值为 -moz-win-accentcolor 以及 -moz-win-accentcolortext (可以参见 {{bug(1344910)}}), 以及专用的媒体查询语句 -moz-windows-accent-color-in-titlebar (参见{{bug(1379938)}}).
  • +
+ +

SVG

+ +

无修改.

+ +

JavaScript

+ +
    +
  • The Intl API has been enabled on Firefox for Android ({{bug(1344625)}}).
  • +
+ +

APIs

+ +

New APIs

+ +

No changes.

+ +

DOM

+ +
    +
  • On Mac, {{domxref("Document.hidden")}} is now true when the window is behind another non-translucent application {{bug(1236512)}}.
  • +
  • The {{domxref("Gamepad.displayId")}} property has been implemented ({{bug(1375816)}}).
  • +
  • The {{domxref("PerformanceTiming.secureConnectionStart")}} property has been implemented ({{bug(772589)}}).
  • +
  • Firefox used to accept iso-2022-jp-2 sequences silently when an iso-2022-jp {{domxref("TextDecoder.TextDecoder","TextDecoder()")}} was instantiated, however this has now been removed to simplify the API, as no other browsers support it and no pages seem to use it. ({{bug(715833)}}).
  • +
  • The 4ms clamping behaviour of {{domxref("WindowOrWorkerGlobalScope.setTimeout","setTimeout()")}} and {{domxref("WindowOrWorkerGlobalScope.setInterval","setInterval()")}} has been updated to be more in line with other browsers, as described in Timeouts throttled to >=4ms ({{bug(1378586)}}).
  • +
  • The Page Visibility API's {{domxref("Document.onvisibilitychange")}} handler has been added ({{bug("1333912")}}).
  • +
  • The {{domxref("Window.showModalDialog()")}} method has been removed ({{bug(981796)}}).
  • +
+ +

DOM events

+ +
    +
  • {{domxref("GlobalEventHandlers.onwheel")}} is now available on {{domxref("HTMLElement")}} — it wasn't before ({{bug(1370550)}}).
  • +
+ +

WebRTC

+ +
    +
  • Firefox now supports the {{domxref("RTCPeerConnection")}} properties which let you examine the current and pending configurations of the local and remote ends of the connection, to help manage changes in configuration: {{domxref("RTCPeerConnection.currentLocalDescription", "currentLocalDescription")}}, {{domxref("RTCPeerConnection.pendingLocalDescription", "pendingLocalDescription")}}, {{domxref("RTCPeerConnection.currentRemoteDescription", "currentRemoteDescription")}}, and {{domxref("RTCPeerConnection.pendingRemoteDescription", "pendingRemoteDescription")}}.
  • +
+ +

Canvas and WebGL

+ +
    +
  • The {{domxref("CanvasRenderingContext2D.drawImage()")}} method has been updated so that smoothing occurs when downscaling even if imageSmoothingEnabled is false. This is not mandatory as per spec, but follows Chrome's behaviour. See {{bug(1360415)}}.
  • +
  • An {{domxref("SVGImageElement")}} can now be used as a {{domxref("CanvasImageSource")}}, e.g. as the image source in a {{domxref("CanvasRenderingContext2D.drawImage","drawImage()")}} call ({{bug(1382027)}}).
  • +
+ +

Security

+ +

No changes.

+ +

Plugins

+ +

No changes.

+ +

Other

+ +
    +
  • Gecko now encodes URLs internally as punycode, to avoid URL encoding problems (see {{bug("945240")}}, also see discussion in {{bug("942074")}}).
  • +
  • Firefox on Windows and Mac OS X can now be made to run in headless mode using the -headless flag (see {{bug(1355150)}} and {{bug(1355147)}}).
  • +
+ +

Removals from the web platform

+ +

HTML

+ +
    +
  • The {{htmlelement("isindex")}} element has been removed from the HTML parser, and from form submission ({{bug(1266495)}}).
  • +
  • The {{htmlelement("applet")}} element has been removed ({{bug(1279218)}}).
  • +
+ +

APIs

+ +

No changes.

+ +

SVG

+ +

No changes.

+ +

Changes for add-on and Mozilla developers

+ +

WebExtensions

+ +

No changes.

+ +

See also

+ + +
+ + + +

Older versions

+ +

{{Firefox_for_developers(55)}}

+
diff --git a/files/zh-cn/mozilla/firefox/releases/59/index.html b/files/zh-cn/mozilla/firefox/releases/59/index.html new file mode 100644 index 0000000000..aca2ace7c6 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/59/index.html @@ -0,0 +1,130 @@ +--- +title: Firefox 59 for developers +slug: Mozilla/Firefox/Releases/59 +tags: + - '29' + - 发布说明 + - 火狐 +translation_of: Mozilla/Firefox/Releases/59 +--- +
{{FirefoxSidebar}}
{{draft}}
+ +

本文提供了有关Firefox 59中会影响开发人员的更改的信息。 Firefox 59已于2018年3月13日发布。

+ +
+

Web开发者应该注意的变化

+ +

开发工具

+ + + +

HTML

+ + + +

CSS

+ +

无变化。

+ +

SVG

+ +

无变化。

+ +

JavaScript

+ +

无变化。

+ +

APIs

+ +

新增API

+ + + +

DOM

+ +

无变化。

+ +

DOM 事件

+ + + +

多媒体 和 WebRTC

+ +

无变化。

+ +

Canvas 和 WebGL

+ +

无变化。

+ +

HTTP

+ +

无变化。

+ +

安全

+ + + +

插件

+ +

无变化。

+ +

其他

+ +

无变化。

+ +

Web平台的删减

+ +

HTML

+ +

无变化。

+ +

CSS

+ +

无变化。

+ +

APIs

+ + + +

SVG

+ +

无变化

+ +

Mozilla和附加组件开发者应该注意的变化

+ +

WebExtensions

+ +

无变化

+ +

参见

+ + +
+ + + +

历史版本

+ +

{{Firefox_for_developers(58)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/62/index.html b/files/zh-cn/mozilla/firefox/releases/62/index.html new file mode 100644 index 0000000000..10a5c5423a --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/62/index.html @@ -0,0 +1,187 @@ +--- +title: Firefox 62 for developers +slug: Mozilla/Firefox/Releases/62 +translation_of: Mozilla/Firefox/Releases/62 +--- +
{{FirefoxSidebar}}
{{FirefoxSidebar}}
+ +
{{draft}}
+ +

This article provides information about the changes in Firefox 62 that will affect developers. Firefox 62 is the current Beta version of Firefox, and will ship on September 5, 2018.

+ +

Changes for web developers

+ +

Developer tools

+ + + +

HTML

+ +

没有变化。

+ +

CSS

+ + + +

SVG

+ +

No changes.

+ +

JavaScript

+ + + +

APIs

+ +

New APIs

+ + + +

DOM

+ + + +

DOM events

+ +

No changes.

+ +

Service workers

+ +

No changes.

+ +

Media, Web Audio, and WebRTC

+ + + +

Canvas and WebGL

+ +

No changes.

+ + + +

CSSOM

+ + + +

HTTP

+ + + +

Security

+ +

No changes.

+ +

Plugins

+ +

No changes.

+ +

Other

+ +

No changes.

+ +

Removals from the web platform

+ +

HTML

+ +

No changes.

+ +

CSS

+ +

No changes.

+ +

APIs

+ +

No changes.

+ +

SVG

+ +

No changes.

+ +

Other

+ +

No changes.

+ +

Changes for add-on and Mozilla developers

+ +

WebExtensions

+ +

API changes

+ + + +

Manifest changes

+ + + +

Theme changes

+ + + +

Other changes

+ + + +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers(61)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/65/index.html b/files/zh-cn/mozilla/firefox/releases/65/index.html new file mode 100644 index 0000000000..548193494e --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/65/index.html @@ -0,0 +1,128 @@ +--- +title: Firefox 65 for developers +slug: Mozilla/Firefox/Releases/65 +tags: + - '65' +translation_of: Mozilla/Firefox/Releases/65 +--- +
{{FirefoxSidebar}}{{Draft}}
+ +

本文提供了有关 Firefox 65 中将影响开发者的更改信息。 Firefox 65 是当前的 Nightly 版本, 将于2019年1月29日发布。

+ +

为网页开发者带来的改变

+ +

开发者工具

+ +

移除

+ +

HTML

+ +

事件现在可以在禁用状态下的 HTML 元素上进行分发,如设置了 disabled 属性的 {{htmlelement("button")}}, {{htmlelement("fieldset")}}, {{htmlelement("input")}}, {{htmlelement("select")}},和 {{htmlelement("textarea")}} ({{bug(329509)}})。

+ +

移除

+ +

CSS

+ + + +

移除

+ + + +

SVG

+ +

无变化。

+ +

移除

+ +

JavaScript

+ +

移除

+ +

APIs

+ +

无变化。

+ +

新的 APIs

+ +

DOM

+ + + +

DOM events

+ + + +

Service workers

+ + + +

Media, Web Audio, 和 WebRTC

+ + + +

Canvas 和 WebGL

+ +

移除

+ + + +

安全

+ +

无变化。

+ +

移除

+ +

插件

+ +

无变化。

+ +

移除

+ +

其他

+ +

无变化。

+ +

移除

+ +

为附加组件开发者带来的改变

+ +

API 变化

+ +

移除

+ +

Manifest 变化

+ +

移除

+ +

参阅

+ + + +

更早期的版本

+ +

{{Firefox_for_developers(65)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/68/index.html b/files/zh-cn/mozilla/firefox/releases/68/index.html new file mode 100644 index 0000000000..621bd205fb --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/68/index.html @@ -0,0 +1,240 @@ +--- +title: 为开发者的 Firefox 68 文档 +slug: Mozilla/Firefox/Releases/68 +translation_of: Mozilla/Firefox/Releases/68 +--- +

{{FirefoxSidebar}}

+ +

本篇文章将提供关于在Firefox 68版本中,会影响到开发人员的更新的信息。Firefox 68版本发布于2019年7月9日。

+ +

面向开发者的变更

+ +

开发者工具

+ +

浏览器/网页控制台

+ + + +

JavaScript 调试器

+ + + +

网络监视器

+ + + +

页面查看器

+ + + +

存储查看器

+ + + +

其它

+ + + +

移除

+ + + +

HTML

+ + + +

 移除

+ + + +

CSS

+ + + +

Removals

+ + + +

SVG

+ +

No changes.

+ +

JavaScript

+ + + +

APIs

+ +

CSS Object Model (CSSOM)

+ + + +

DOM

+ + + +

DOM events

+ + + +

Media, Web Audio, and WebRTC

+ + + +

Removals

+ + + +

HTTP

+ + + +

Removals

+ + + +

Security

+ + + +

WebDriver conformance (Marionette)

+ +

Bug fixes

+ + + +

Other

+ + + +

Plugins

+ +

No changes.

+ +

Changes for add-on developers

+ +

API changes

+ + + +

显著变更

+ +

无变更。

+ +

还可以看看

+ + + +

更早的版本

+ +

{{Firefox_for_developers(67)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/69/index.html b/files/zh-cn/mozilla/firefox/releases/69/index.html new file mode 100644 index 0000000000..88f1c741aa --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/69/index.html @@ -0,0 +1,185 @@ +--- +title: 面向开发者的Firefox 69 +slug: Mozilla/Firefox/Releases/69 +translation_of: Mozilla/Firefox/Releases/69 +--- +

{{FirefoxSidebar}}

+ +

这篇文章将会围绕Firefox 69对于开发者产生的影响展开。

+ +

Firefox 69 发布于2019年9月3日。

+ +

对于web开发者的变化

+ +

开发者工具

+ +

Debugger(调试器)

+ + + +

Console(控制台)

+ + + +

Network(网络)

+ + + +

Inspector(查看器)

+ + + +

Remote debugging(远程调试)

+ + + +

General(日常)

+ + + +

HTML

+ + + +

 Removals

+ + + +

CSS

+ + + +

SVG

+ + + +

JavaScript

+ + + +

HTTP

+ + + +

APIs

+ +

New APIs

+ + + +

DOM

+ + + +

Media, Web Audio, and WebRTC

+ + + +

Removals

+ + + +

WebDriver conformance (Marionette)

+ +

Other

+ + + +

Changes for add-on developers

+ +

API changes

+ + + +

Other changes

+ + + +

See also

+ + + +

Older versions

+ +

{{Firefox_for_developers(68)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/78/index.html b/files/zh-cn/mozilla/firefox/releases/78/index.html new file mode 100644 index 0000000000..1c28b03a7a --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/78/index.html @@ -0,0 +1,116 @@ +--- +title: 对于开发人员的Firefox 78 +slug: Mozilla/Firefox/Releases/78 +translation_of: Mozilla/Firefox/Releases/78 +--- +

{{FirefoxSidebar}}

+ +

本文提供了有关Firefox 78中将影响开发人员的更改的信息。 Firefox 78发布于2020年6月30日.

+ +

另请参阅Firefox 78中的新增功能:DevTools的改进,新的正则表达式引擎以及Mozilla hacks上大量的Web平台更新。

+ +

对于Web开发人员的更改

+ +

开发者工具

+ +

调试器

+ + + +

网络监控器

+ + + +

其他工具

+ + + +

CSS

+ + + +

JavaScript

+ + + +

一些API

+ +

DOM

+ + + +

服务工作者

+ + + +

Web组装

+ + + +

TLS 1.0和1.1已被移除

+ + + +

对于附加组件开发人员的更改

+ + + +

参见

+ + + +

旧版本

+ +

{{Firefox_for_developers(77)}}

diff --git a/files/zh-cn/mozilla/firefox/releases/index.html b/files/zh-cn/mozilla/firefox/releases/index.html new file mode 100644 index 0000000000..9f16917cdc --- /dev/null +++ b/files/zh-cn/mozilla/firefox/releases/index.html @@ -0,0 +1,12 @@ +--- +title: 与Firefox开发者相关的发行说明 +slug: Mozilla/Firefox/Releases +tags: + - Firefox + - NeedsTranslation + - TopicStub +translation_of: Mozilla/Firefox/Releases +--- +
{{FirefoxSidebar}}

本页提供每个Firefox的版本的“与Firefox开发者相关的发行说明”文章的链接。这些日志文章可以让你查看每个Firefox版本增加了哪些功能和修复的错误。

+ +
{{ListSubpages("",1,1,1)}}
diff --git a/files/zh-cn/mozilla/firefox/the_about_protocol/index.html b/files/zh-cn/mozilla/firefox/the_about_protocol/index.html new file mode 100644 index 0000000000..9b889c3338 --- /dev/null +++ b/files/zh-cn/mozilla/firefox/the_about_protocol/index.html @@ -0,0 +1,163 @@ +--- +title: Firefox 与 "about" 协议 +slug: Mozilla/Firefox/The_about_protocol +translation_of: Mozilla/Firefox/The_about_protocol +--- +
{{FirefoxSidebar}}

Firefox 在 about: URL 协议中藏有很多隐藏的功能和有用的信息。最常用的 URL 就是 about:config,它提供首选项的显示和修改功能。以下是 about: 伪协议的完整列表:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
about: 页面描述
about:显示版本和构建信息,以及查阅贡献者、许可信息和构建配置的链接。
about:about提供 about: 页面的完整列表
about:accounts同步 功能使用的页面
about:addons附加组件管理器
about:app-manager应用管理器
about:buildconfig显示构建此 Firefox 所用的配置和平台
about:cache显示有关内存、磁盘和应用缓存的信息
about:compartments显示有关 compartments 的信息。从 Firefox 26 开始,此信息可在 about:memory 的 "Other Measurements"  部分找到
about:config允许查看和更改 Firefox 内部的首选项(偏好和设置)
about:crashes列出所有崩溃报告
about:credits列出所有参与 Firefox 产品的贡献者姓名
about:customizing切换到“定制”模式,允许用户定制 Firefox 的用户界面
about:downloads显示用 Firefox 进行的下载
about:healthreport显示 Firefox 的性能信息(如果用户已启用“健康报告”功能)
about:homeFirefox 原生的开始页(新窗口的第一个页面)
about:license显示许可信息
about:logoFirefox 标志
about:memory提供一种方法探查内存使用情况,以及保存为报告,还有运行 GC 和 CC
about:mozilla一个特殊页面,显示“Mozilla 之书”摘录
about:networking显示网络相关的信息
about:newtab新建一个标签页时显示的页面
about:permissions提供一种方法来显示和管理网站权限。在 Firefox 45 中已去除({{bug(933917)}})
about:plugins显示已安装插件的信息
about:preferencesFirefox 设置(也可通过 Firefox > 选项 来打开)
about:privatebrowsing打开新的隐私浏览窗口时显示的页面
about:reader指示在一个页面上开启了阅读视图。 参见Firefox 排除干扰的阅读视图
about:rights显示权利信息
about:robots显示有关机器人的信息,一个特殊的页面
about:sessionrestore会话恢复(Firefox 从崩溃恢复时显示)
about:support故障排除信息(也称“疑难解答”信息)。也可通过 Firefox 菜单 > ? (问号) > 故障排除信息 打开
about:sync-log显示 同步 功能所用的同步协议的日志
about:sync-progress这是 同步 功能设置完成后显示的页面
about:sync-tabs列出 同步 功能同步的标签页
about:telemetry显示在 Firefox 运行时已收集和将发送到 Mozilla 的遥测数据(如果用户已启用“遥测”功能)
about:webrtc有关 WebRTC 的使用情况
about:welcomeback在 Firefox 被重置后显示的信息页面
+ +

这些 URL 在 {{source("docshell/base/nsAboutRedirector.cpp")}} 中的 kRedirMap 数组定义。该数组映射大部分 URL,比如 config 指向 chrome: 伪协议,例如 chrome://global/content/config.xul。about 的位置信息在 {{source("docshell/build/nsDocShellModule.cpp")}} 也存有副本。

diff --git a/files/zh-cn/mozilla/firefox_for_android/index.html b/files/zh-cn/mozilla/firefox_for_android/index.html new file mode 100644 index 0000000000..955aa200c0 --- /dev/null +++ b/files/zh-cn/mozilla/firefox_for_android/index.html @@ -0,0 +1,65 @@ +--- +title: Firefox for Android +slug: Mozilla/Firefox_for_Android +translation_of: Mozilla/Firefox_for_Android +--- +

对于越来越多的人来说,移动设备是他们上网的主要方式,甚至是唯一方式。Firefox Android版(代号 Fennec)是一个开放的,可定制的,基于标准的浏览器,就像桌面版的Firefox。

+ +

Firefox Android版从原生的Android小部件构建用户界面而不是XUL:这极大的提高了性能,特别是启动时间和内存消耗上。

+ +

有助于Firefox for Android

+ +

关于Firefox for Android项目主要出发点的一些信息参见 “Get Involved” 页

+ +

你可以帮助我们建立和改善 Firefox for Android:

+ + + +

为移动web开发

+ +

我们已经开始了一个移动设备设计网站的指南

+ +

With Firefox for Android, you've got access a number of APIs that expose the underlying capabilities of the device, closing the gap between the Web and native applications:

+ + + +

To test your web site on Firefox for Android, you can install it on an Android device or run it on your desktop using the Android Emulator.

+ +

构建Mobile附加组件

+ +

Firefox for Android supports add-ons using the exact same extension system used by all other Gecko-based applications. We did not invent a new add-on system. This means that building an add-on for Firefox on Android is the same process that would be used for desktop Firefox. Add-ons that work with desktop Firefox do not automatically work in Firefox on Android. The user interfaces are just too different.

+ +
Firefox on Android has a unique application identifier which must be used in install.rdf. The identifier is {aa3c5121-dab2-40e2-81ca-7ea25febc110}
+ +

Both classic restart-required and newer restartless add-on approaches are supported. Using the restartless approach is preferred whenever possible because the user experience is far superior to forcing an application restart when installing or removing an add-on.

+ +

快速概览

+ + + +

获取Firefox for Android的帮助

+ +

Documentation and tutorials for using and troubleshooting Firefox for Android are available on the Mozilla Support website.

+ +

 

diff --git a/files/zh-cn/mozilla/gecko/index.html b/files/zh-cn/mozilla/gecko/index.html new file mode 100644 index 0000000000..a5863d1b6d --- /dev/null +++ b/files/zh-cn/mozilla/gecko/index.html @@ -0,0 +1,74 @@ +--- +title: Gecko +slug: Mozilla/Gecko +tags: + - Gecko + - Mozilla +translation_of: Mozilla/Gecko +--- +
{{FirefoxSidebar}}
+ +
+

Gecko 是由 Mozilla 工程开发出的布局引擎的名字。它的原名是 NGLayout。Gecko 的功能就是读取 web 内容,如HTMLCSSXULJavaScript, 之后将其渲染到用户界面上。在基于 XUL 的应用中,Gecko 也同样用来渲染应用程序的用户界面。

+
+ +

Gecko 被使用在许多应用程序中,包括一些浏览器,如 Firefox,SeaMonkey等(要获取完整的列表,请参考 Wikipedia's article on Gecko)。使用相同 Gecko 版本的产品对标准则有同样的支持。

+ + + + + + + + +
+

文档

+ +
+
Gecko FAQ
+
关于 Gecko 常见的问题。
+
 Gecko DOM 参考文档
+
DOM参考文档。
+
Gecko event 参考文档
+
使用在 Gecko 和 Mozilla 应用中 event 的参考文档。要获取 web 标准的 DOM event, 请参考 DOM event reference.
+
Gecko 版本和应用程序版本
+
它们使用的Gecko和应用程序版本。
+
 Mozilla 中对布局的介绍
+
关于布局的技术性介绍。
+
嵌入 Mozilla
+
在您的应用中使用 Gecko。
+
由 Gecko 支持的字符集
+
Gecko所支持的字符集列表。
+
HTML 解析器线程
+
在 HTML 解析器中的多线程描述。
+
{{interwiki('wikimo', 'Gecko:Home_Page', 'Gecko Home Page on MozillaWiki')}}
+
活跃开发者之家。路线图以及最新的资源。
+
+ +

View All...

+
+

社区

+ +
    +
  • View Mozilla forums... {{DiscussionList("dev-tech-layout", "mozilla.dev.tech.layout")}}
  • +
+ + + + + +
+
 
+
+
+ +

 

+ +

 

diff --git a/files/zh-cn/mozilla/gecko/versions/index.html b/files/zh-cn/mozilla/gecko/versions/index.html new file mode 100644 index 0000000000..cd2989399c --- /dev/null +++ b/files/zh-cn/mozilla/gecko/versions/index.html @@ -0,0 +1,130 @@ +--- +title: Gecko版本和对应的应用程序版本 +slug: Mozilla/Gecko/Versions +tags: + - Gecko +translation_of: Mozilla/Gecko/Versions +--- +

下面的表格记录了 Gecko 的每个版本以及建立在该版本 Gecko 之上的应用程序的版本.

+

注意在 Gecko 2.0 之后(也就是 Gecko 5.0 开始), Firefox 和 Thunderbird 同 Gecko 采用同一个版本号.

+

另外从 Gecko 17开始, SpiderMoneky 也开始使用这个版本号, 比如 SpiderMonkey 17SpiderMonkey 24, 抛弃了之前使用的 1.8.x 小版本号方式, SpiderMoneky 最后一个小版本号是 1.8.8, 最后一个稳定版的小版本号是 1.8.5. 这些版本号也可以从 Mozilla 发布的 SpiderMonkey 源码包的文件名中看出 

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Gecko  版本基于它的应用程序版本
Gecko 24Firefox 24, Thunderbird 24, SeaMonkey 2.21
Gecko 23Firefox 23, SeaMonkey 2.20
Gecko 22Firefox 22, SeaMonkey 2.19
Gecko 21Firefox 21, {{ interwiki('wikimo', 'SeaMonkey/Features/2.18', 'SeaMonkey 2.18') }}
Gecko 20Firefox 20, {{ interwiki('wikimo', 'SeaMonkey/Features/2.17', 'SeaMonkey 2.17') }}
Gecko 19Firefox 19, {{ interwiki('wikimo', 'SeaMonkey/Features/2.16', 'SeaMonkey 2.16') }}
Gecko 18Firefox 18, Firefox OS 1.0, {{ interwiki('wikimo', 'SeaMonkey/Features/2.15', 'SeaMonkey 2.15') }}
Gecko 17Firefox 17, Thunderbird 17, {{ interwiki('wikimo', 'SeaMonkey/Features/2.14', 'SeaMonkey 2.14') }}
Gecko 16Firefox 16, Thunderbird 16, {{ interwiki('wikimo', 'SeaMonkey/Features/2.13', 'SeaMonkey 2.13') }}
Gecko 15Firefox 15, Thunderbird 15, {{ interwiki('wikimo', 'SeaMonkey/Features/2.12', 'SeaMonkey 2.12') }}
Gecko 14Firefox 14, Thunderbird 14, {{ interwiki('wikimo', 'SeaMonkey/Features/2.11', 'SeaMonkey 2.11') }}
Gecko 13Firefox 13, Thunderbird 13, {{ interwiki('wikimo', 'SeaMonkey/Features/2.10', 'SeaMonkey 2.10') }}
Gecko 12Firefox 12, Thunderbird 12, {{ interwiki('wikimo', 'SeaMonkey/Features/2.9', 'SeaMonkey 2.9') }}
Gecko 11Firefox 11, Thunderbird 11, {{ interwiki('wikimo', 'SeaMonkey/Features/2.8', 'SeaMonkey 2.8') }}
Gecko 10Firefox 10, Thunderbird 10, {{ interwiki('wikimo', 'SeaMonkey/Features/2.7', 'SeaMonkey 2.7') }}
Gecko 9Firefox 9, Thunderbird 9, {{ interwiki('wikimo', 'SeaMonkey/Features/2.6', 'SeaMonkey 2.6') }}
Gecko 8Firefox 8, Thunderbird 8, {{ interwiki('wikimo', 'SeaMonkey/Features/2.5', 'SeaMonkey 2.5') }}
Gecko 7Firefox 7, Thunderbird 7, {{ interwiki('wikimo', 'SeaMonkey/Features/2.4', 'SeaMonkey 2.4') }}
Gecko 6Firefox 6, Thunderbird 6, {{ interwiki('wikimo', 'SeaMonkey/Features/2.3', 'SeaMonkey 2.3') }}
Gecko 5Firefox 5, Thunderbird 5, {{ interwiki('wikimo', 'SeaMonkey/Features/2.2', 'SeaMonkey 2.2') }}
Gecko 2Firefox 4, Thunderbird 3.3, {{ interwiki('wikimo', 'SeaMonkey/Features/2.1', 'SeaMonkey 2.1') }}
Gecko 1.9.2Firefox 3.6, Thunderbird 3.1
Gecko 1.9.1Firefox 3.5, Thunderbird 3, {{ interwiki('wikimo', 'SeaMonkey:New_for_2.0', 'SeaMonkey 2.0') }}
Gecko 1.9Firefox 3
Gecko 1.8.1Firefox 2, Thunderbird 2, SeaMonkey 1.1
Gecko 1.8Firefox 1.5, Thunderbird 1.5, SeaMonkey 1.0
Gecko 1.7Firefox 1.0, Thunderbird 1.0, Nvu 1.0, Mozilla Suite 1.7
older versions of Gecko match the Mozilla Suite versions
+

 

diff --git "a/files/zh-cn/mozilla/gecko/\345\265\214\345\205\245mozilla/index.html" "b/files/zh-cn/mozilla/gecko/\345\265\214\345\205\245mozilla/index.html" new file mode 100644 index 0000000000..e2e5daa728 --- /dev/null +++ "b/files/zh-cn/mozilla/gecko/\345\265\214\345\205\245mozilla/index.html" @@ -0,0 +1,49 @@ +--- +title: 嵌入 Mozilla +slug: Mozilla/Gecko/嵌入Mozilla +tags: + - 㠌入Mozilla +translation_of: Mozilla/Gecko/Embedding_Mozilla +--- +
Gecko允许第三方开发人员使用与Mozilla相同的技术。这意味着您可以将Web浏览器嵌入到第三方应用程序中,通过网络后端打开通道和流,遍历DOM等等。甚至可以使用用最新版chrome构建的应用程序。
+ +
+ + + + + + + + +
+

大纲

+ +
+
Gecko 基础绑定
+
嵌入gecko渲染引擎的介绍.
+
嵌入提示
+
一些关于嵌入的常见问题。
+
Mozilla 㠌入 API 概述
+
Mozilla嵌入API简介.
+
嵌入编辑器
+
本文档描述了编辑器可嵌入性的当前状态、现有实现中的问题、我们需要处理的一些可能的嵌入场景,以及将满足这些情况的嵌入解决方案。
+
玩转你自己的浏览器-一个嵌入方法
+
关于嵌入Mozilla的简单介绍。
+
+ +

View All...

+
+

社区

+ +
    +
  • 查看Mozilla论坛.. {{ DiscussionList("dev-embedding", "mozilla.dev.embedding") }}
  • +
  • #绑定 IRC 信道
  • +
+ + + + +
diff --git a/files/zh-cn/mozilla/how_mozilla_determines_mime_types/index.html b/files/zh-cn/mozilla/how_mozilla_determines_mime_types/index.html new file mode 100644 index 0000000000..fbe9917902 --- /dev/null +++ b/files/zh-cn/mozilla/how_mozilla_determines_mime_types/index.html @@ -0,0 +1,94 @@ +--- +title: How Mozilla determines MIME Types +slug: Mozilla/How_Mozilla_determines_MIME_Types +translation_of: Mozilla/How_Mozilla_determines_MIME_Types +--- +

Introduction

+ +

All data handling in Mozilla is based on the MIME type of the content. This means that every time an URI is loaded, Mozilla must find out its MIME type. The several ways how this happens are described in this document.

+ +

Content-Type "hints"

+ +

Mozilla has a concept of "content-type hints". This means that, for example, if Mozilla encounters a <link type="text/css" rel="stylesheet" href="..."> element, a type of text/css will be assumed. This is, however, overridden by the actual MIME type the server sends (if any). (For this specific example, the server override only happens in standards-compliant mode. See Mozilla's Quirks Mode or Web Author FAQ).

+ +

Similar handling happens for <a href="..." type="foo/bar">, starting in Mozilla 1.6alpha.

+ +

HTTP

+ +

For HTTP URIs Mozilla usually gets a MIME type sent from the server, and uses it. Contrary to Internet Explorer's MIME type guessing, Mozilla will generally not sniff the type of the document. However, starting in Mozilla 1.7alpha, Mozilla does do content sniffing, like this:

+ +

When the Content-Type sent by the server is one of (case-sensitively)

+ + + +

and the server did not send a Content-Encoding header, Mozilla will sniff the first block of data it gets and check for non-text bytes. Text bytes are 9-13, 27, and 31-255. When encountering a non-text byte, the helper app dialog will be shown, showing the MIME type corresponding to the extension of the file.

+ +

Also, for images loaded via <img src>, Mozilla's image library will do content sniffing (never extension sniffing) to find out the real type of the image.

+ +

If the server did not send a Content-Type header, Mozilla uses the unknown decoder to find a MIME type.

+ +

File URIs

+ +

For file: URIs, Mozilla will ask the ExternalHelperAppService for a MIME type.

+ +

FTP

+ +

Like HTTP URIs without a MIME type, FTP URIs go through the unknown decoder.

+ +

Unknown Decoder

+ +

Located at {{ Source("netwerk/streamconv/converters/nsUnknownDecoder.cpp") }}, the interesting part starts at {{ Source("netwerk/streamconv/converters/nsUnknownDecoder.cpp#287", "line 287") }}, the sSnifferEntries array together with the DetermineContentType function. It does the following:

+ + + +

ExternalHelperAppService

+ +

(located at {{ Source("uriloader/exthandler/nsExternalHelperAppService.cpp") }})

+ +

The file->MIME type mapping works like this:

+ + + +

Helper Applications

+ +

A somewhat related issue are the helper applications. When loading an URI with a type that Mozilla can not handle, a helper app dialog shows up, and the displayed information comes from these sources:

+ + + + + +

Document Loading - From Load Start to Finding a Handler

+ +
+

Original Document Information

+ + +
diff --git a/files/zh-cn/mozilla/how_to_get_a_process_dump_with_windows_task_manager/index.html b/files/zh-cn/mozilla/how_to_get_a_process_dump_with_windows_task_manager/index.html new file mode 100644 index 0000000000..9833241199 --- /dev/null +++ b/files/zh-cn/mozilla/how_to_get_a_process_dump_with_windows_task_manager/index.html @@ -0,0 +1,48 @@ +--- +title: 怎样在任务管理器中获取进程的dump +slug: Mozilla/How_to_get_a_process_dump_with_Windows_Task_Manager +translation_of: Mozilla/How_to_get_a_process_dump_with_Windows_Task_Manager +--- +

介绍

+ +

当追踪进程为何挂起的时候,获取运行进程的dump是很有用的。这篇文章描述怎样从任务管理器中提取进程dump。 (为了获取thunderbird或者其他产品的dump,用一些指令替换火狐中的一些名称)

+ +

起因

+ +

一个内存dump被创建代表了创建者文件时的火狐状态的快照,它包含了,活动tab的URL,历史信息,可能甚至包含密码,依赖于你获取快照的时机,当重现问题的时候,适当创建一个新的说明文件,并且抓取dump。请帮忙做这些。

+ +

要求

+ +
+
+
Windows
+
为了获取进程度dump,你需要Wndows Vista及以上系统
+
+
一个火狐日构建版本或发布版
+
你需要火狐的符号表 Mozilla symbol server. 你可以用 官方日构建版本 或者发布版本. 你可以获取最新的日构建版本在 http://ftp.mozilla.org/pub/mozilla.o.../latest-trunk/.
+
+ +

创建dump文件

+ +

确保火狐没有在运行.

+ +

运行火狐,重现问题

+ +

打开火狐,重现引起问题的步骤.  一旦出现,继续以下步骤

+ +

挂起之后

+ +
    +
  1. 打开任务管理器 (CTRL+SHIFT+ESC).
  2. +
  3. 在进程列表中查找 Firefox.exe
  4. +
  5. 右键 Firefox.exe 选择 "创建dump文件". 任务管理器需要dump写的位置.
  6. +
+ +

其他

+ + + + diff --git a/files/zh-cn/mozilla/implementing_pontoon_in_a_mozilla_website/index.html b/files/zh-cn/mozilla/implementing_pontoon_in_a_mozilla_website/index.html new file mode 100644 index 0000000000..2964582ca0 --- /dev/null +++ b/files/zh-cn/mozilla/implementing_pontoon_in_a_mozilla_website/index.html @@ -0,0 +1,76 @@ +--- +title: 在 Mozilla 项目中使用 Pontoon +slug: Mozilla/Implementing_Pontoon_in_a_Mozilla_website +tags: + - 本地化 +translation_of: Mozilla/Implementing_Pontoon_in_a_Mozilla_website +--- +

Pontoon 是一个基于 web 的所见即所得(WYSIWYG)的本地化(l10n)工具。在 Mozilla ,我们都是使用 Pontoon 去本地化众多的 Mozilla 项目和被称为 Gaia 的 Firefox OS app 接口。Pontoon 是一个非常简单、直接的工具,本地化人员只需要很少甚至没有技术能力就可以使用它,这将减少项目本地化版本的发布时间。下面我们来谈谈怎么将 Pontoon 加入到你的 Mozilla 项目里。

+ +
+

你想帮忙改进 Pontoon 吗?了解如何在 GitHub 上参与。

+
+ +
+

只是开始你项目的 l10n? 查看 本地化你的项目 上的 wiki。

+
+ +

A. 本地化你的项目

+ +

我们意识到这些已经被认为是 Mozilla 本地化项目的标准最佳实践 ,但我们觉得还是应该在这里做个小小的提醒。

+ +
    +
  1. 确保你的项目支持下列任一种 l10n 框架(gettextXLIFFL20nlangproperties等等).
  2. +
  3. 将可本地化的字符串提取到资源文件中。
  4. +
  5. 推送源文件到存储库中(SVN、HG、Git)。 +
      +
    • 各个区域的本地化文件夹必须位于同一级目录下。区域的本地化需要起名为 templatesen-USen-us 或者 en。如果存储库中存在同名的多个本地化文件夹,并且文件夹内的文件都是受支持的格式,则只会使用第一个文件夹。这样的话,你可能需要把所有的本地化文件夹都放在一个专用的 locales 目录下。 文件名中请务必不要包含本地化代码。
    • +
    • 正确的模式: +
      /locales/{本地化代码}/path/to/file.extension
      +
    • +
    • 错误模式: +
      /locales/{本地化代码}/path/to/file.{本地化代码}.extension
      +
    • +
    +
  6. +
  7. 确保 Pontoon 有存储库的写入权限。 + +
  8. +
+ +

B. (optional) Enable in-page localization of your web project

+ +
    +
  1. Link a script from your HTML <body> element, so Pontoon can talk to your site, detect content and make it localizable in place. You only need to do this in the environment that will be used for in-page localization, e.g. staging server: + + +
  2. +
  3. If your site uses CSP,  please make sure that the following is permitted for domain pontoon.mozilla.org: +
      +
    1. loading inside iframe
    2. +
    3. loading remote CSS
    4. +
    5. loading remote images
    6. +
    +
  4. +
  5. If your site uses the X-Frame-Options header, please make sure loading inside iframe is permitted for domain pontoon.mozilla.org.
  6. +
  7. Make sure your site supports HTTPS. It's free, automated and open. Let's encrypt!
  8. +
+ +

C. Add your project to Pontoon

+ +

Your project is now ready to be set up in Pontoon. Please file a bug in Localization Infrastructure and Tools :: Administration / Setup and provide the following information:

+ + + +

For more details, please get in touch with the Project Management Team.

diff --git a/files/zh-cn/mozilla/index.html b/files/zh-cn/mozilla/index.html new file mode 100644 index 0000000000..efab963ead --- /dev/null +++ b/files/zh-cn/mozilla/index.html @@ -0,0 +1,8 @@ +--- +title: Mozilla 产品与私有技术 +slug: Mozilla +translation_of: Mozilla +--- +

以下文章内容,与如何下载并组建 Mozilla 程式的代码相关。此外,也会收录一些有助理解代码如何运作、如何组建 Mozilla 程式的附加元件之类的文章。

+ +

{{LandingPageListSubpages}}

diff --git a/files/zh-cn/mozilla/instantbird/index.html b/files/zh-cn/mozilla/instantbird/index.html new file mode 100644 index 0000000000..67c7285a5f --- /dev/null +++ b/files/zh-cn/mozilla/instantbird/index.html @@ -0,0 +1,62 @@ +--- +title: Instantbird +slug: Mozilla/Instantbird +translation_of: Mozilla/Instantbird +--- +

Instantbird(及时鸟) 是一个和Mozilla很有渊源的即时通讯软件.  当前文档指向的通讯内核文档同样被应用于Thunderbird(雷鸟)

+ +

及时鸟和火狐浏览器基于相同的技术平台。它源自于谷歌的一个 夏日炎炎爱编程 项目。目的是为了给libpurple(Pidgin 的后端)创建一个 XUL界面。当时及时鸟并没有被认可 。尽管如此,从2007年开始,它不断发展壮大,有了自己的协议,并且已经不再局限于libpurple的前端。

+ + + + + + + + + + +
+

文档

+ +
+
+
+
创建及时鸟
+
从comm-central仓库创建及时鸟。
+
通讯内核
+
后端代码,包含了通讯协议的大体文档({{ Interface("prplIProtocol") }} 和 friends)。
+
消息格式
+
展示了消息的主题相关信息。
+
键盘快捷键
+
键盘快捷键列表
+
+

链接

+
+
Latest nightly builds最新创建
+
These are generally stable, but expect some breakage from time to time and file bugs.大体稳定,但有可能会有bug
+
+ +

View All...

+
+

社区

+ +
    +
  • #instantbird on irc.mozilla.org (for users and developers)
  • +
  • Support is handled on the support-instantbird mailing list or on IRC: {{ DiscussionList("support-instantbird", "mozilla.support.instantbird") }}
  • +
  • Extension questions can be discussed on the dev-chat group or on IRC: {{ DiscussionList("dev-chat", "mozilla.dev.chat") }}
  • +
  • a list of all Instantbird communication channels
  • +
+ +

工具

+ +
    +
  • DOM 监视器
  • +
+ + + +
    +
  • 拓展
  • +
+
diff --git a/files/zh-cn/mozilla/introduction_to_layout_in_mozilla/index.html b/files/zh-cn/mozilla/introduction_to_layout_in_mozilla/index.html new file mode 100644 index 0000000000..3a2df97afb --- /dev/null +++ b/files/zh-cn/mozilla/introduction_to_layout_in_mozilla/index.html @@ -0,0 +1,360 @@ +--- +title: Mozilla 中对布局的介绍 +slug: Mozilla/Introduction_to_Layout_in_Mozilla +tags: + - cn +translation_of: Mozilla/Introduction_to_Layout_in_Mozilla +--- +

概要

+ + + +

基本数据流

+ + + +

+ +

关键数据结构

+ +

+ + + +

+ +

关键数据结构

+ + + +

详细执行步骤

+ + + +

设置

+ + + +

+ +

内容模型的构建

+ + + +

+ +

框架Frame 的构建

+ + + +

+ +

Style 選定

+ + + +

回流

+ + + +

回流

+ + + +

增量回流

+ +

+ + + +

增量回流

+ +

+ + + +

增量回流

+ +

+ + + +

增量回流

+ +

+ + + +

繪畫

+ + + +

漸進

+ + + +

+ +

未来(?)技术讲座

+ + + +

最后

+ + + +
+

原始文档信息

+ + +
diff --git a/files/zh-cn/mozilla/ipdl/creating_a_new_protocol/index.html b/files/zh-cn/mozilla/ipdl/creating_a_new_protocol/index.html new file mode 100644 index 0000000000..d256886913 --- /dev/null +++ b/files/zh-cn/mozilla/ipdl/creating_a_new_protocol/index.html @@ -0,0 +1,32 @@ +--- +title: 创建一个新的协议 +slug: Mozilla/IPDL/Creating_a_New_Protocol +translation_of: Mozilla/IPDL/Creating_a_New_Protocol +--- +

这是有关如何向构建中添加新IPDL协议的详细信息的快速入门。您应该首先了解IPDL的工作原理

+ +

创建协议文件

+ +

协议文件应与实现它的代码位于同一目录中。协议名称以P开头,并且协议文件必须命名为PProtocolName.ipdl。IPDL协议应位于mozilla命名空间或子命名空间中。

+ +

要将文件连接到构建,需要将IPDL文件添加到最近的moz.build文件中的IPDL_SOURCES。有关示例,请参见 dom/ipc/moz.build 

+ +

协议层次结构

+ +

除非您正在从事某些特殊项目,否则您的协议将适合多进程插件或选项卡的协议层次结构。插件的顶级协议是PPluginModule。选项卡的顶级协议是PContent。您应该知道哪种协议将管理新协议,以及会导致哪些生存期问题。如有疑问,请在#content频道中询问IRC。

+ +

建立新协议

+ +

要构建新的协议声明并生成标头,请在ipc/ipdl中创建:

+ +
make -C objdir/ipc/ipdl
+ +

如果存在协议级别的错误,则IPDL编译器将打印相关的错误消息并停止。要查看生成的标题,请在中查看objdir/ipc/ipdl/_ipdlheaders

+ +

创建实现

+ +

C ++实现从IPDL生成的抽象类PNewProtocolParent和PNewProtocolChild继承。它必须实现抽象方法以在每一侧接收适当的消息。可以从生成的PNewProtocolParent.h和PNewProtocolChild.h标头中读取方法签名。

+ +

编写测试

+ +

PBrowser管理的协议必须使用带有的mochitest-chrome测试框架进行测试<browser remote="true">出于测试目的,可以在JPW包装器上使用同步调用。使用xpcshell测试框架可以测试与特定窗口无关的协议,该框架在Electrolysis中具有其他原语,用于在内容过程中启动和运行JS命令。

diff --git a/files/zh-cn/mozilla/ipdl/index.html b/files/zh-cn/mozilla/ipdl/index.html new file mode 100644 index 0000000000..051c353f2c --- /dev/null +++ b/files/zh-cn/mozilla/ipdl/index.html @@ -0,0 +1,33 @@ +--- +title: IPC Protocol Definition Language (IPDL) +slug: Mozilla/IPDL +tags: + - IPC + - IPDL + - NeedsTranslation + - PBackground + - TopicStub +translation_of: Mozilla/IPDL +--- +

IPDL是“IPC(进程间通信)协议定义语言”的缩写,是一种特定于Mozilla的语言,允许C++代码以有组织和安全的方式在进程或线程之间传递消息。Firefox中多进程插件和选项卡的所有消息都是用IPDL语言声明的。

+ +

当前文档

+ + + +

Future planned docs

+ + diff --git "a/files/zh-cn/mozilla/ipdl/\345\205\245\351\227\250/index.html" "b/files/zh-cn/mozilla/ipdl/\345\205\245\351\227\250/index.html" new file mode 100644 index 0000000000..b710a91971 --- /dev/null +++ "b/files/zh-cn/mozilla/ipdl/\345\205\245\351\227\250/index.html" @@ -0,0 +1,670 @@ +--- +title: IPDL入门 +slug: Mozilla/IPDL/入门 +translation_of: Mozilla/IPDL/Tutorial +--- +

IPDL – IPC Inter-process communication Protocol Definition Language,全称的意思是进程间通信协议定义语言。这是Mozilla特有的一种使C++代码能以有组织地、安全地在进程或者线程间传递信息的语言。Firefox中有关多进程插件和选项卡的所有消息均以IPDL语言声明。

+ +
如果想尝试添加一个新的IPDL协议, 参考 创建一个新的协议.
+ +

所有的IPDL信息都是由 父端 和 子端 发送,二者也被称为 角色。 IPDL 协议 声明了 角色间该如何进行通信:它声明了角色间可能发送的消息,以及描述了何时允许发送消息的状态机。

+ +

父端角色通常是对话中更持久的一方:

+ + + + + + + + + + + + + + + + + + + + + + +
父端/子端角色
父端子端
IPC 选项卡Chrome 进程Content 进程
IPC 插件Content 进程Plugin 进程
+ +

每个协议都会在单独的文件中声明。IPDL 编译器会据每个IPDL 协议中生成一些 C++头文件。生成的代码帮忙解决了 底层通信层(套接字和管道)的一些细节、构造和发送消息,以及确保所有角色遵守其规范,并处理一些错误情况。以下 IPDL代码 定义了 浏览器角色 和 插件角色 的非常基本的交互:

+ +
async protocol PPlugin
+{
+child:async Init(nsCString pluginPath);
+  async Shutdown();
+
+parent:
+  async Ready();
+};
+
+ +

这段代码声明了 PPlugin 协议。 有两条消息从 父端发送到了子端, Init()Shutdown()。 另外还有一条消息从子端发送到了父端, Ready()

+ +
IPDL 协议要以字母 P开头. 声明了该协议的文件也必须是对应的名称,如 PPlugin.ipdl.
+ +

生成的 C++ 代码

+ +

PPlugin.ipdl 被编译后会在构建树目录 ipc/ipdl/_ipdlheaders/ 生成头文件PPluginParent.h,和  PPluginChild.h。PPluginParent 和 PPluginChild 都是待实现的抽象类. 每个传出消息都是可以调用的C++方法。每个传入的消息都是必须实现的纯虚拟C++^方法:

+ +
class PPluginParent
+{
+public:
+  bool SendInit(const nsCString& pluginPath) {
+    // generated code to send an Init() message
+  }
+
+  bool SendShutdown() {
+    // generated code to send a Shutdown() message
+  }
+
+protected:
+  /**
+   * A subclass of PPluginParent must implement this method to handle the Ready() message.
+   */
+  bool RecvReady() = 0;
+};
+
+class PPluginChild
+{
+protected:
+  bool RecvInit(const nsCString& pluginPath) = 0;
+  bool RecvShutdown() = 0;
+
+public:
+  bool SendReady() {
+    // generated code to send a Ready() message
+  }
+};
+
+ +

这些父级和子级抽象类负责所有的 “协议层” 问题, 如序列化数据,发送和接收消息,以及检查协议安全性。实现者需要做的是创建子类来执行每条消息中涉及的实际工作。下面是浏览器实现者 使用 PPluginParent 的一个非常简单的方法示例。

+ +
class PluginParent : public PPluginParent
+{
+public:
+  PluginParent(const nsCString& pluginPath) {
+    // launch child plugin process
+    SendInit(pluginPath);
+  }
+
+  ~PluginParent() {
+    SendShutdown();
+  }
+
+protected:
+  bool RecvReady() {
+    mObservers.Notify("ready for action");
+  }
+};
+
+ +

下面是C++实现者在增加插件过程中如何使用PPluginChild的代码:

+ +
class PluginChild : public PPluginChild
+{
+protected:
+  void RecvInit(const nsCString& pluginPath) {
+    mPluginLibrary = PR_LoadLibrary(pluginPath.get());
+    SendReady();
+  }
+  void RecvShutdown() {
+    PR_UnloadLibrary(mPluginLibrary);
+  }
+
+private:
+  PRLibrary* mPluginLibrary;
+};
+
+ +

调用子流程并将这些协议角色 关联到我们的IPC “传输层” 超出了本文档的范围。有关更多详细信息,请参见 IPDL进程和线程
+
+ 因为 协议消息 被表示为C++方法,所以很容易忘记它们实际上是异步消息:默认情况下,C++方法将在消息被分发之前立即返回。
+
+ Recv* 方法的参数(本例中的 const nsCString& pluginPath) 是对临时对象的引用,因此如果需要保留它们的数据,请复制它们。

+ +

方向

+ +

每种消息类型都包括一个“方向”。消息方向 是指 消息是可以从父端 发送到 子端,抑或是从子端发送到父端,或者两种方式都可以。有三个关键字充当了方向说明符。上面介绍的 child,第二个是 parent,这意味着在 parent 标签下声明的消息只能从 子端发送到父端。第三个是both,这意味着声明的消息可以进行双向发送。下面的简要示例 显示了如何使用这些 说明符,以及这些说明符如何 影响 生成的 抽象角色类。

+ +
// PDirection.ipdl
+async protocol PDirection
+{
+child:async Foo();  // can be sent from-parent-to-child
+parent:
+  async Bar();  // can be sent from-child-to-parent
+both:async Baz();  // can be sent both ways
+};
+
+ +
// PDirectionParent.h
+class PDirectionParent
+{
+protected:
+  virtual void RecvBar() = 0;
+  virtual void RecvBaz() = 0;
+
+public:
+  void SendFoo() { /* boilerplate */ }
+  void SendBaz() { /* boilerplate */ }
+};
+
+ +
// PDirectionChild.h
+class PDirectionChild
+{
+protected:
+  virtual void RecvFoo() = 0;
+  virtual void RecvBaz() = 0;
+
+public:
+  void SendBar() { /* boilerplate */ }
+  void SendBaz() { /* boilerplate */ }
+};
+
+ +

您可以在协议规范中多次使用  childparent, 和 both标签。它们的行为类似于C++中的publicprotected, 和 private 标签。

+ +

参数

+ +

消息声明允许任意数量的 参数。参数指定与消息一起发送的数据。它们的值由 发送方 序列化,由 接收方 反序列化。IPDL支持内置 和 自定义基元类型,以及 联合union 和数组。

+ +
+
+
+

内置的简单类型包括C++整型(bool,char,int,double) 和 XPCOM字符串类型(nsString,nsCString)。IPDL会自动导入这些类型,因为它们很常见,而且base IPC 库知道如何序列化和反序列化这些类型。有关自动导入类型的最新列表,请参见 ipc/ipdl/ipdl/builtin.py 。

+ +

角色 可以作为参数传递。C++签名将在一侧接受 PProtocolParent*,在另一侧将其转换为PProtocolChild*。

+ +

Maybe 类型

+ +

如果要传递可能未定义的参数,可以在类型名称后添加? 后缀。接下来你就可以传递 mozilla::Maybe 对象而不是具体的值。

+ +
protocol PMaybe
+{
+child:
+  async Maybe(nsCString? maybe);
+};
+
+ +

自定义基本类型

+ +

当需要发送 IPDL内置类型 之外的 类型数据 时,可以在IPDL规范中添加  using 声明。您的C++代码必须提供 自定义序列化程序和反序列化 程序。

+ +
using mozilla::plugins::NPRemoteEvent;
+
+sync protocol PPluginInstance
+{
+child:async HandleEvent(NPRemoteEvent);
+};
+
+ +

联合Union

+ +

IPDL 内置支持声明 联合Union 类型。

+ +
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
+
+union Variant
+{
+  void_t;
+  bool;
+  int;
+  double;
+  nsCString;
+  PPluginScriptableObject;
+};
+ +

此 联合Union 生成一个C++接口,其内容如下:

+ +
struct Variant
+{
+  enum Type {
+    Tvoid_t, Tbool, Tint, Tdouble, TnsCString, TPPlugionScriptableObject
+  };
+  Type type();
+  void_t& get_void_t();
+  bool& get_bool();
+  int& get_int();
+  double& get_double();
+  nsCString& get_nsCString();
+  PPluginScriptableObject* get_PPluginScriptableObject();
+};
+
+ +

Union.type() 可用于确定 IPDL 消息处理程序中接收到的联合Union 类型,其余函数 给予对其内容的访问权限。要初始化 联合Union ,只需为其分配一个有效值,如下所示:

+ +
aVariant = false;
+
+ +

结构 Struct

+ +

IPDL 具有对 可序列化数据类型 的 任意集合 的内置支持。

+ +
struct NameValuePair
+{
+  nsCString name;
+  nsCString value;
+};
+ +

在实现代码中,可以像这样创建和使用这些结构:

+ +
NameValuePair entry(aString, anotherString);
+foo(entry.name(), entry.value()); // Named accessor functions return references to the members
+
+ +

数组 Array

+ +

IPDL具有简单的数组语法:

+ +
InvokeMethod(nsCString[] args);
+ +

·在C++中,这被转换为 nsTArray 引用:

+ +
virtual bool RecvInvokeMethod(nsTArray<nsCString>& args);
+
+
+
+
+ +

如果在单独的  .ipdlh 文件中定义了  IPDL生成的数据结构,则可以在多个 协议 中使用它们。这些文件必须像常规 .ipdl 文件一样添加到ipdl.mk  makefile中,并且它们使用相同的语法(除了它们不能声明协议)。要使用  Foo.ipdlh 中定义的结构,请按如下方式包含它。

+ +
// in a .ipdl file
+include Foo;
+
+ +

同步和RPC消息传递

+ +

到目前为止,所有消息都是异步的。消息发送出去的同时,C++方法会立即返回。但是,如果我们希望等待消息被处理,或者从消息中获取返回值,该怎么办呢?

+ +

在 IPDL 中,有三种不同的语义:

+ +
    +
  1. 异步(asynchronous) 语义;发送方未被阻塞。
  2. +
  3. 等待,直到接收方确认它收到了消息。我们称之为 同步(synchronous 语义,因为发送方阻塞,直到接收方接收到消息并发回回复。消息可能具有返回值。
  4. +
  5.  rpc 语义是同步语义的变体,见下文。
  6. +
+ +

请注意,父端 可以向 子端 发送消息,反之亦然,因此上述三种情况下的“发送者”和“接收者”可以是父端  或 子端 。消息传递语义以 同样的方式 应用于两个方向。因此,例如在从 子端 到 父端的同步语义中, 子端 将阻塞,直到 父端 接收到消息 和 响应到达为止,而在从父端 到 子端 的异步语义中,父端 不会阻塞。

+ +

创建插件实例时,浏览器应该阻塞,直到实例创建完成,并且需要插件返回的一些信息:

+ +
sync protocol PPluginInstance
+{
+child:
+    sync Init() returns (bool windowless, bool ok);
+};
+
+ +

我们在插件协议中添加了两个新的关键字,sync returns 同步(sync)  将消息标记为正在同步发送。returns 关键字 标识了 在对消息的响应中 返回的值列表的开始。

+ +

异步消息的返回值

+ +

Bug 1313200 引入了 将 returns  与 async异步 消息一起使用的能力:

+ +
protocol PPluginInstance
+{
+child:
+    async AsyncInit() returns (bool windowless, bool ok);
+    async OtherFunction() returns (bool ok);
+};
+
+ +

对于调用方,每个带有 returns 块的 async 异步消息 MessageName 都将为 SendMessageName 生成两个重载。第一个重载将有一个 resolve回调 和 reject 回调 作为其最后两个参数;第二个重载将没有任何 额外 参数,但它将返回 PProtocol{Parent,Child}::MessageNamePromise ,这是一个 MozPromise类型。

+ +

第一个重载的 resolve 回调 以及 MozPromise Then() 方法的成功回调都只有一个参数。如果消息只返回returns 一个值 (例如上面的OtherFunction),则对于resolve 和success回调,参数都是returns返回值本身(作为const常量引用);如果消息returns 返回多个值(例如上面的InitAsync),则对于resolve 和success 回调,参数都是返回值的元组(例如,Tuple<bool, bool>)。另一方面, reject/failure  回调接受 mozilla::ipc::ResponseRejectReason&&,并在发生致命错误(如IPC错误)时调用。因此,除了 callback/promise 样式响应处理之外,这两个重载在功能上是等效的。

+ +

生成的C++代码如下:

+ +
class PPluginInstanceParent
+{
+ public:
+  typedef MozPromise<Tuple<bool, bool> ResponseRejectReason, true> AsyncInitPromise;
+  typedef MozPromise<bool, ResponseRejectReason, true> OtherFunctionPromise;
+
+  void
+  SendAsyncInit(mozilla::ipc::ResolveCallback<Tuple<bool, bool>>&& aResolve,
+                mozilla::ipc::RejectCallback&& aReject);
+
+  RefPtr<AsyncInitPromise>
+  SendAsyncInit();
+
+  void
+  SendOtherFunction(mozilla::ipc::ResolveCallback<bool>&& aResolve,
+                    mozilla::ipc::RejectCallback&& aReject);
+
+  RefPtr<OtherFunctionPromise>
+  SendOtherFunction();
+};
+
+ +

在被调用方,除了声明的消息参数外,RecvMessageName 将有一个 MessageNameResolver&& 函数作为其最终(附加)参数。调用此函数将 初始化 调用传递给SendMessageName的回调 或 SendMessageName返回的promise解析。
+
+ 生成的C++将产生如下所示的结果:

+ +
class PPluginInstanceChild
+{
+ public:
+  typedef std::function<void(Tuple<const bool&, const bool&>)> AsyncInitResolver;
+  typedef std::function<void(const bool&)> OtherFunctionResolver;
+
+  virtual mozilla::ipc::IPCResult
+  RecvAsyncInit(AsyncInitResolver&& aResolve) = 0;
+
+  virtual mozilla::ipc::IPCResult
+  RecvOtherFunction(OtherFunctionResolver&& aResolver) = 0
+};
+
+ +

为了使程序员更容易注意到阻塞的本质,Synchronous和RPC消息的C++方法名称是不同的:

+ + + + + + + + + + + + + + + + + + + + + +
发送方接收方
async/syncSendMessageNameRecvMessageName
rpcCallMessageNameAnswerMessageName
+ +

消息语义强度

+ +

IPDL协议 也像消息一样具有 “语义限定符”。这里的不同之处在于这里的语语义限定符是可选的; 默认语义是异步的。 必须指出的是 协议的语义至少与其 最强的消息语义 一样“强”,其中同步语义 “强于” 异步。这意味着异步协议无法在不违反 此类型规则 的情况下声明同步消息,而同步协议可以声明异步消息。下面显示了具有同步消息的恰当协议。

+ +
sync protocol PPluginInstance
+{
+child:
+    sync Init() returns (bool windowless, bool ok);
+};
+ +

该方法生成的C++代码将 外参指针 用于 返回值:

+ +
class PPluginInstanceParent
+{
+  ...
+  bool SendInit(bool* windowless, bool* ok) { ... };
+};
+
+class PPluginInstanceChild
+{
+  ...
+  virtual bool RecvInit(bool* windowless, bool* ok) = 0;
+}
+ +

RPC 语义

+ +

“RPC” 代表“远程过程调用”,该第三种语义对 过程调用语义 进行建模。RPC 和 sync 语义之间的差别, 快速总结一下就是,RPC 允许“重入”消息处理程序:虽然参与者在等待RPC“调用”的“应答”时被阻塞,但它可以被 解除阻塞 以处理新的传入RPC调用

+ +

在下面的示例协议中,子端角色 提供了一个 “CallMeCallYou()” RPC接口,父接口提供一个 “CallYou()” RPC接口。 rpc 限定符意味着,如果父对象对子参与者调用“CallMeCallYou()”,那么子参与者在服务这个调用时,可以回调到父参与者的 “CallYou()” 消息。

+ +
rpc protocol Example {
+child:
+    rpc CallMeCallYou() returns (int rv);
+
+parent:
+    rpc CallYou() returns (int rv);
+};
+
+ +

如果这是一个sync 同步协议,那么在为“CallMeCallYou()”消息提供服务时,将不允许 子端角色 调用 父端角色 的 “CallYou()” 方法。(子端角色 将被 极端“偏见” 终止。)

+ +

首选语义

+ +

尽可能使用异步async 语义。
+
+ 不鼓励对 消息回复 进行阻塞。如果您真的需要阻塞 回复,请 非常小心 地使用sync 同步语义。不小心使用同步消息可能会陷入麻烦;虽然 IPDL 可以检查 和/或 保证您的代码不会死锁,但很容易通过阻塞导致严重的性能问题。
+
+ 请不要使用RPC语义。RPC语义的存在主要是为了支持 远程插件(NPAPI),这我们别无选择。

+ +
Chrome 对 content调用(用于IPC选项卡) 必须仅使用异步语义。为了保持响应性,chrome 进程需要永不阻塞 可能处于繁忙或挂起的 content 进程。
+ +

消息分发顺序

+ +

传递是“按顺序”的,也就是说,消息按照发送的顺序传递给接收者,而不考虑消息的语义。如果角色A发送消息M1,接着是M2来发送给角色B,B将被唤醒以处理M1,然后是M2。

+ +

子协议和协议管理

+ +

到目前为止,我们已经看到了一个单一的协议,但现实世界中没有一个孤立的情况会有一个单一的协议。相反,协议被安排在子协议的受管层次结构中。子协议绑定到追踪其生命周期并充当工厂的“管理器”。协议层次结构从一个顶级协议开始,所有的 子协议角色 最终都是从该协议创建的。在Mozilla中有两个主要的顶层协议:用于远程插件的 PPluginModule和用于远程选项卡的 PContent

+ +

以下示例扩展了 顶级的 plugin协议来管理插件实例。

+ +
// ----- file PPlugin.ipdl
+
+include protocol PPluginInstance;
+
+rpc protocol PPlugin
+{
+    manages PPluginInstance;
+child:
+    rpc Init(nsCString pluginPath) returns (bool ok);
+    // This part creates constructor messages
+    rpc PPluginInstance(nsCString type, nsCString[] args) returns (int rv);
+};
+
+ +
// ----- file PPluginInstance.ipdl
+
+include protocol PPlugin;
+
+rpc protocol PPluginInstance
+{
+    manager PPlugin;
+child:
+    rpc __delete__();
+    SetSize(int width, int height);
+};
+
+ +

这个例子有几个新元素:`include protocol`将另一个协议声明导入到这个文件中。请注意,这不是预处理器指令,而是IPDL语言的一部分。生成的C++代码将为 导入的协议 提供适当的#include预处理器指令。
+
+ `manages`语句声明此协议管理PPluginInstance。PPlugin协议必须为PPluginInstance角色声明构造函数和析构函数消息。`manages`语句还意味着PPluginInstance角色与创建它们的插件角色的生命周期有关:如果此PPlugin实例被销毁,则与其关联的所有PPluginInstance都将失效或销毁。
+
+ 令人困惑的是,强制 构造函数和析构函数消息(分别为PPluginInstance 和 __delete__ )存在于不同的位置。 构造函数必须位于管理协议中,而析构函数属于 被管理的子协议。·这些消息具有与C++构造函数相似的语法,但行为不同。构造函数和析构函数像其他IPDL消息一样具有参数、方向、语义和返回值。必须为每个托管协议声明构造函数和析构函数消息。

+ +

每个子协议必须包含一个`manager`语句。
+
+ 在C++层,子类和父类中的子类都必须实现用于allocate和deallocate子协议角色的方法。构造函数和析构函数被转换为消息的标准C++方法。
+
+ 注意:__delete__是一个内置构造,并且是唯一不需要重写实现的IPDL消息(即Recv/Answer__delete__)。然而,当应该对协议的析构 进行某些操作而不是使用DeallocPProtocol功能时,鼓励被覆盖的实现。

+ +
class PPluginParent
+{
+  /* Allocate a PPluginInstanceParent when the first form of CallPluginInstanceConstructor is called */
+  virtual PPluginInstanceParent* AllocPPluginInstance(const nsCString& type, const nsTArray<nsCString>& args, int* rv) = 0;
+
+  /* Deallocate the PPluginInstanceParent after PPluginInstanceDestructor is done with it */
+  virtual bool DeallocPPluginInstance(PPluginInstanceParent* actor) = 0;
+
+  /* constructor message */
+  virtual CallPPluginInstanceConstructor(const nsCString& type, const nsTArray<nsCString>& args, int* rv) { /* generated code */ }
+
+  /* alternate form of constructor message: supply your own PPluginInstanceParent* to bypass AllocPPluginInstance */
+  virtual bool CallPPluginInstanceConstructor(PPluginInstanceParent* actor, const nsCString& type, const nsTArray<nsCString>& args, int* rv)
+  { /* generated code */ }
+
+  /* destructor message */
+  virtual bool Call__delete__(PPluginInstanceParent* actor) { /* generated code */ }
+
+  /* Notification that actor deallocation is imminent, IPDL mechanisms are now unusable */
+  virtual void ActorDestroy(ActorDestroyReason why);
+
+  ...
+};
+
+class PPluginChild
+{
+  /* Allocate a PPluginInstanceChild when we receive the PPluginInstance constructor */
+  virtual PPluginInstanceChild* AllocPPluginInstance(const nsCString& type, const nsTArray<nsCString>& args, int* rv) = 0;
+
+  /* Deallocate a PPluginInstanceChild after we handle the PPluginInstance destructor */
+  virtual bool DeallocPPluginInstance(PPluginInstanceChild* actor) = 0;
+
+  /* Answer the constructor message. Implementing this method is optional: it may be possible to answer the message directly in AllocPPluginInstance. */
+  virtual bool AnswerPPluginInstanceConstructor(PPluginInstanceChild* actor, const nsCString& type, const nsTArray<nsCString>& args, int* rv) { }
+
+  /* Answer the destructor message. */
+  virtual bool Answer__delete__(PPluginInstanceChild* actor) = 0;
+
+  /* Notification that actor deallocation is imminent, IPDL mechanisms are now unusable */
+  virtual void ActorDestroy(ActorDestroyReason why);
+
+  ...
+};
+ +

子协议角色的生命周期

+ +

AllocPProtocol 和 DeallocPProtocol 是一对匹配的函数。这些功能的典型实现是使用' new '和' delete ':

+ +
class PluginChild : PPluginChild
+{
+ virtual PPluginInstanceChild* AllocPPluginInstance(const nsCString& type, const nsTArray<nsCString>& args, int* rv)
+  {
+    return new PluginInstanceChild(type, args, rv);
+  }
+
+  virtual bool DeallocPPluginInstanceChild(PPluginInstanceChild* actor)
+  {
+    delete actor; // actor destructors are always virtual, so it's safe to call delete on them!
+    return true;
+  }
+
+  ...
+};
+ +

然而,在某些情况下,外部代码可能包含对需要引用计数或其他生命周期策略的角色实现的引用。在这种情况下,alloc/dealloc 可以执行不同的操作。以下是引用计数的示例:

+ +
class ExampleChild : public nsIObserver, public PExampleChild { ... };
+
+virtual PExampleChild* TopLevelChild::AllocPExample()
+{
+  RefPtr<ExampleChild*> actor = new ExampleChild();
+  return actor.forget();
+}
+
+virtual bool TopLevelChild::DeallocPExample(PExampleChild* actor)
+{
+  NS_RELEASE(static_cast<ExampleChild*>(actor));
+  return true;
+}
+
+ +

如果实现协议的对象不能在AllocPFoo内构造,先前已经构造,并且在其整个生命周期中不需要IPDL连接,或者实现引用计数的协议(第一种形式的构造函数不可用),则可以使用第二种形式的 SendPFooConstructor:

+ +
class ExampleChild
+{
+public:
+    void DoSomething() {
+        aManagerChild->SendPExampleConstructor(this, ...);
+    }
+};
+
+ +

在内部,第一个构造函数表单只需调用

+ +
PExample(Parent|Child)* actor = AllocPExample(...);
+SendPExampleConstructor(actor, ...);
+return actor;
+
+ +

效果一致。

+ +

子协议删除

+ +

值得了解协议删除过程。·考虑到简单的协议:

+ +
// --- PExample.ipdl
+include protocol PSubExample;
+
+async protocol PExample
+{
+    manages PSubExample;
+
+parent:
+    async PChild();
+};
+
+// --- PSubExample.ipdl
+include protocol PExample;
+
+async protocol PSubExample
+{
+    manager PExample;
+
+child:
+    async __delete__();
+};
+
+ +

我们假设存在 PSubExampleParent/Child,这样一些元素现在希望从父端触发协议的删除。

+ +
aPSubExampleParent->Send__delete__();
+ +

will trigger the following ordered function calls:

+ +
PSubExampleParent::ActorDestroy(Deletion)
+/* Deletion is an enumerated value indicating
+   that the destruction was intentional */
+PExampleParent::DeallocPSubExample()
+ +
PSubExampleChild::Recv__delete__()
+PSubExampleChild::ActorDestroy(Deletion)
+PExampleChild::DeallocPSubExample()
+ +

ActorDestroy是一个生成的函数,它允许代码在知道参与者释放即将到来的情况下运行。·这对于生命周期在IPDL之外的角色很有用 。例如,可以设置一个标志,表明与IPDL相关的功能不再安全使用。

+ +

从C++访问协议树

+ +

The IPDL compiler generates methods that allow actors to access their manager (if the actor isn't top-level) and their managees (if any) from C++.  For a protocol PFoo managed by PManager, that manages PManagee, the methods are

+ +

IPDL编译器生成允许参与者从C++访问其管理器(如果参与者不是顶级)和受管对象(如果有的话)的方法。对于协议PFoo,由 管理 PManagee的 PManager管理,这些方法是

+ +
PManager* PFoo::Manager()
+const InfallibleTArray<PManagee*> PFoo::ManagedPManagee();
+void PFoo::ManagedPManagee(InfallibleTArray<PManagee*>&);
+
+ +

关闭和错误处理

+ +

实现IPDL消息的C++方法返回bool:true表示成功,false表示灾难性失败。如果数据已损坏或格式错误,则消息实现应从消息实现返回false。只要消息实现返回false,IPDL就会立即开始灾难性的错误处理:子进程(tab或plugin)的通信通道将被断开,并且进程将终止。对于“正常”错误条件,如无法加载网络请求,不要从消息处理程序返回false!正常的错误应该用消息或返回值发出信号。

+ +

注意: 以下段落尚未实施. IPDL跟踪两个端点之间的所有活动协议。如果子侧崩溃或挂起::

+ + + +

销毁管理器协议时,将通知所有子协议:

+ + + +

当顶层协议被破坏时,这等同于关闭该连接的整个IPDL机制,因为不能再发送更多的消息,并且所有子协议都被销毁。

diff --git a/files/zh-cn/mozilla/javascript-dom_prototypes_in_mozilla/index.html b/files/zh-cn/mozilla/javascript-dom_prototypes_in_mozilla/index.html new file mode 100644 index 0000000000..5136550830 --- /dev/null +++ b/files/zh-cn/mozilla/javascript-dom_prototypes_in_mozilla/index.html @@ -0,0 +1,145 @@ +--- +title: JavaScript-DOM Prototypes in Mozilla +slug: Mozilla/JavaScript-DOM_Prototypes_in_Mozilla +translation_of: Mozilla/JavaScript-DOM_Prototypes_in_Mozilla +--- +
+

Prototype setup on an XPConnect wrapped DOM node in Mozilla

+
+ +

When a DOM node is accessed from JavaScript in Mozilla, the native C++ DOM node is wrapped using XPConnect and the wrapper is exposed to JavaScript as the JavaScript representation of the DOM node. When XPConnect wraps a C++ object it will create a JSObject that is unique to this C++ object. In the case where the C++ object has class info (nsIClassInfo), the JSObject is a more or less empty JSObject which is not really that special. All the methods that are supposed to show up on this JSObject are actually not properties of the object itself, but rather properties of the prototype of the JSObject for the wrapper (unless the C++ object's class info has the flag nsIXPCScriptable::DONT_SHARE_PROTOTYPE set, but lets assume that's not the case here).

+ +

As an example of this let's look at an HTML image element in a document.

+ +
var obj = document.images[0];
+
+ +

Here, obj will not really have any properties (except for the standard JSObject properties such as constructor, and the non-standard __parent__, __proto__, etc.), all the DOM functionality of obj comes from obj's prototype (obj.__proto__) that XPConnect sets up when exposing the first image in document to JavaScript. Here are a few of the properties of obj's prototype:

+ +
obj.__proto__
+  parentNode (getter Function)
+  src (getter and setter Functions)
+  getElementsByTagName (Function)
+  TEXT_NODE (Number property, constant)
+  ...
+
+ +

All those properties come from the interfaces that the C++ image object (nsHTMLImageElement) implements and chooses to expose to XPConnect through the object's class info. One of these interfaces is nsIDOMHTMLImageElement, others are nsIDOMNSHTMLImageElement (Netscape extensions to the standard interface), nsIDOMEventTarget, nsIDOMEventListener, nsIDOM3Node, and so on.

+ +

The prototype object that XPConnect creates for the classes that have class info are shared within a scope (window). Because of this, the following holds true (assuming img1 and img2 are two different image objects in the same document):

+ +
img1.__proto__ === img2.__proto__
+
+ +

If img1 would come from one document and img2 from another document, then the above would not be true. Both prototypes would look identical, but they would be two different JSObject's.

+ +

This sharing of prototypes lets users do cool things like modify how all instances of a given class works by modifying the prototype of one instance. As an example:

+ +
function bar() {
+  alert("Hello world!");
+}
+
+document.images[0].__proto__.foo = bar;
+
+ +

This would make every image in this document have a callable foo property (i.e. a foo() method).

+ +

Alternatively, one can access and modify the prototype of an HTMLImageElement through the prototype property of the constructor:

+ +
HTMLImageElement.prototype.foo = bar;
+
+ +

Modifying the prototype of a Host object is not guaranteed by ECMAScript specification. Moreover, no specification guarantees that there will be a globally available HTMLImageElement, or that such object will be the constructor for any arbitrary image's [[Prototype]].

+ +

A third way through which one can access the prototype of an object is through the constructor property of the object, which itself points (initially) to the constructor:

+ +
document.images[0].constructor.prototype.foo = bar;
+
+ +

Note though, the above may or may not work in Mozilla.

+ +

So far so good; we have shared prototypes, and XPConnect gives us most of this automatically. But this is not good enough, in addition to being able to share and represent each "class" with a constructor, we also want users to be able to extend interfaces, like Node. Node is a DOM interface, but there are no pure Node instances; there are lots of different classes that implement Node (HTMLImageElement, HTMLDocument, ProcessingInstruction, et c.).

+ +

But the fact that an instance of a Node will never exist in Mozilla does not mean that the Node interface is useless, in fact, Node can be extended just as we've been doing. If you think back to the HTMLImageElement examples above, those examples let you define new properties on all image elements. By modifying the Node top-level object, you can do similar things to all objects that implement Node. This means you can add a property to every node in a DOM tree by doing something like this:

+ +
Node.prototype.foo = bar;
+
+ +

Again, modifying host objects is an unsafe practice. It is not guaranteed to work or be error-free in any implementation. It is not standard and cannot be expected to have any result.

+ +

Here is an attempt to modify a host object:

+ +
   (function(){
+       try {
+           Image.prototype.src = 1;
+       }
+       catch(ex){ alert(ex); }
+   })();
+
+ +

This demonstrates that the Image constructor, a host object supported in nearly all browsers for Mac and Windows, has a prototype property, and that an attempt to modify the prototype's src - property results in an error.

+ +

Another example would be modifying the pageX property of a MouseEvent instance. The pageX property actually needs a patch because it doesn't get set correctly in initMouseEvent {{ Bug(411031) }}.

+ +

Here is a diagram that shows the prototype layout of a HTMLDivElement in Mozilla:

+ +
   HTMLDivElement.prototype
+             |
+             |.__proto__
+             |
+    HTMLElement.prototype
+             |
+             |.__proto__
+             |
+      Element.prototype
+             |
+             |.__proto__
+             |
+       Node.prototype
+             |
+             |.__proto__
+             |
+      Object.prototype
+             |
+             |.__proto__
+             |
+           null
+
+ +

If you have an instance of a HTMLDivElement in JavaScript, the following will hold true:

+ +
div.__proto__ === HTMLDivElement.prototype
+
+ +

which means that the following should also be true:

+ +
div.__proto__ === div.constructor.prototype
+
+ +

Non Standard

+ +

No browser is required to provide modifiable __proto__, nor a global Node, nor provide any way to get at host objects nor their associated prototypes. If such objects are provided, they are not guaranteed by any specification to have any effect on the environment. Results in other browsers is not guaranteed.

+ +

So how does all this work in the Mozilla DOM code?

+ +

It all happens in XPConnect and nsDOMClassInfo.{cpp,h} in the DOM code. During startup, the nsDOMClassInfo code registers two different types of "global names", these are names of properties of the global object with special meaning to the DOM code. The two types of "global names" are class constructor names and class prototype names. What's the difference? Class constructor names are names of real classes, and class prototype names are names of "classes" that are inherited by real classes, but are not real classes. A few examples of class constructor names would be HTMLImageElement, HTMLDocument, Element, NodeList, and two examples of class prototype names would be Node and CharacterData.

+ +

This registration is done with the nsScriptNameSpaceManager, which is in charge of keeping track of what names are registered in the global namespace, and what kinds of names those names are (i.e. class constructor name, class prototype name). When a class constructor name is registered (nsGlobalNameStruct::eTypeClassConstructor), the nsScriptNameSpaceManager is given a DOM class info ID (a 32 bit ID that identifies class info defined in nsDOMClassInfo). When a class prototype name is registered (nsGlobalNameStruct::eTypeClassProto), the nsScriptNameSpaceManager is given the nsIID of the interface that is inherited by the class which the registered name is a prototype of (e.g. NS_GET_IID(nsIDOMNode) for Node). nsScriptNameSpaceManager also deals with other types of names, but those are unrelated to the DOM object prototype setup, so we will ignore those here.

+ +

Once the registration is done, the nsDOMClassInfo code uses the registry every time a named property is resolved on a global object (because of this, the nsScriptNameSpaceManager needs to be pretty fast at looking things up in its registry; that's why it is a hash table). When a property is resolved on the global object, the nsDOMClassInfo code will ask the nsScriptNameSpaceManager if the name is a known name (in nsWindowSH::GlobalResolve()), and if the name is known, the code will look at the type of the name and act accordingly.

+ +

If a class constructor or class prototype name is resolved, the class info code will define the constructor for that class, and also define the prototype property of that constructor (i.e. HTMLImageElement.prototype). The prototype of a constructor will either be the prototype object that XPConnect creates for a class (if the name is the name of a real class) or simply an empty JSObject of a specific JSClass that is defined in nsDOMClassInfo.cpp (nsDOMClassInfo::sDOMConstructorProtoClass).

+ +

As the prototype property of the constructor is being defined, the code also sets up the prototype of the prototype property of the constructor (i.e. HTMLImageElement.prototype.__proto__). To do this, the code figures out what the name of the immediate prototype of the class is by looking at the parent of the primary interface in the class info (if the name is a class constructor, such as HTMLImageElement) or by looking at the parent of the interface that the IID stored in the nsScriptNameSpaceManager for this name represents (if the name is a class prototype, such as Node). Once the name of the parent interface is known (and the name is not nsISupports) the code will look up a property by that name on the global object. This will cause the code to recurse down along the parent chain of the interface of interest for the name we started out resolving (i.e. nsWindowSH::GlobalResolve() will be called for every name on the parent chain). The result of this recursion is that by resolving the name HTMLImageElement, we'll create the constructor HTMLImageElement, HTMLElement, Element, and Node, and the prototype properties on all those constructor will be correctly set up. This means that the next time the name of a class constructor is resolved in the same scope, say HTMLAnchorElement, the code will resolve the name HTMLAnchorElement, find the parent name, which is HTMLElement, and resolve that, but since we've already resolved HTMLElement as a result of resolving the name HTMLImageElement earlier, the recursion will stop right there.

+ +

Ok, so that's how class constructor and their prototype properties are set up, what about the actual prototype chain of a XPConnected DOM object? The beauty of this code is that the prototype property of a class constructor is the real XPConnect prototype for that class. When XPConnect wraps a DOM object (i.e. creates a XPConnect JavaScript wrapper for a DOM object), XPConnect will call the scriptable helper method nsDOMClassInfo::PostCreate() which will make sure the prototype chain of the wrapper JSObject is properly set up. In this call, the nsDOMClassInfo code just needs to resolve the name of the class on the global object, and the prototype will be set up by the resolving code (nsWindowSH::GlobalResolve()). This is also done only once per class, nsDOMClassInfo::PostCreate() checks if the prototype of the prototype of the wrapper JSObject (i.e. obj.__proto__.__proto__) has been set up already, if it has, then there's nothing left to do in nsDOMClassInfo::PostCreate().

+ +
+

Original Document Information

+ + +
diff --git a/files/zh-cn/mozilla/javascript_code_modules/assert.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/assert.jsm/index.html new file mode 100644 index 0000000000..a9cbfe6aeb --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/assert.jsm/index.html @@ -0,0 +1,448 @@ +--- +title: Assert.jsm +slug: Mozilla/JavaScript_code_modules/Assert.jsm +translation_of: Mozilla/JavaScript_code_modules/Assert.jsm +--- +

{{ gecko_minversion_header("31") }}

+ +

The Assert.jsm JavaScript code module implements the CommonJS Unit Testing specification version 1.1, which provides a basic, standardized interface for performing in-code logical assertions with optional, customizable error reporting. To use it, you first need to import the code module into your JavaScript scope:

+ +
Components.utils.import("resource://testing-common/Assert.jsm");
+
+ +

Assert 类提供了执行常见逻辑断言的方法。

+ +

Method overview

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
undefined ok(value, message);
undefined equal(actual, expected, message);
undefined notEqual(actual, expected, message);
undefined deepEqual(actual, expected, message);
undefined notDeepEqual(actual, expected, message);
undefined strictEqual(actual, expected, message);
undefined notStrictEqual(actual, expected, message);
undefined throws(block, expected, message);
Promise rejects(promise, expected, message);
undefined greater(lhs, rhs, message);
undefined greaterOrEqual(lhs, rhs, message);
undefined less(lhs, rhs, message);
undefined lessOrEqual(lhs, rhs, message);
undefined setReporter(reporterFunc);
undefined report(failed, actual, expected, message, operator);
+ +

Constructor

+ +

Creates a new Assert object.

+ +
let assert = new Assert(reporterFunc);
+
+ +

The new Assert instance, assert, uses reporterFunc to report assertion results or throws an AssertionError when an assertion fails, as default behavior.

+ +

ok, equal, notEqual, deepEqual, notDeepEqual, strictEqual, notStrictEqual, throws, setReporter, report

+ +

Methods

+ +

ok()

+ +

Pure assertion tests whether a value is truthy, as determined by !!guard.
+ This statement is equivalent to assert.equal(true, !!guard, message_opt);. To test strictly for the value true, use assert.strictEqual(true, guard, message_opt);.

+ +
undefined ok(
+  actual,
+  message
+);
+
+ +
Parameters
+ +
+
actual
+
Test subject to be evaluated as truthy
+
message
+
Short explanation of the expected result
+
+ +

equal()

+ +

The equality assertion tests shallow, coercive equality with ==.

+ +
undefined equal(
+  actual,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
actual
+
Test subject to be evaluated as equivalent to expected
+
expected
+
Test reference to evaluate against actual
+
message
+
Short explanation of the expected result
+
+ +

notEqual()

+ +

The non-equality assertion tests for whether two objects are not equal with !=.

+ +
undefined notEqual(
+  actual,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
actual
+
Test subject to be evaluated as not equivalent to expected
+
expected
+
Test reference to evaluate against actual
+
message
+
Short explanation of the expected result
+
+ +

deepEqual()

+ +

The equivalence assertion tests a deep equality relation.
+ We check using the most exact approximation of equality between two objects to keep the chance of false positives to a minimum.
+ JSON.stringify is not designed to be used for this purpose; objects may have ambiguous toJSON() implementations that would influence the test.

+ +
undefined deepEqual(
+  actual,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
actual
+
Test subject to be evaluated as equivalent to expected, including nested properties
+
expected
+
Test reference to evaluate against actual
+
message
+
Short explanation of the expected result
+
+ +

notDeepEqual()

+ +

The non-equivalence assertion tests for any deep inequality.

+ +
undefined notDeepEqual(
+  actual,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
actual
+
Test subject to be evaluated as not equivalent to expected, including nested properties
+
expected
+
Test reference to evaluate against actual
+
message
+
Short explanation of the expected result
+
+ +

strictEqual()

+ +

The strict equality assertion tests strict equality, as determined by ===.

+ +
undefined strictEqual(
+  actual,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
actual
+
Test subject to be evaluated as strictly equivalent to expected
+
expected
+
Test reference to evaluate against actual
+
message
+
Short explanation of the expected result
+
+ +

notStrictEqual()

+ +

The strict non-equality assertion tests for strict inequality, as determined by !==.

+ +
undefined notStrictEqual(
+  actual,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
actual
+
Test subject to be evaluated as not strictly equivalent to expected
+
expected
+
Test reference to evaluate against actual
+
message
+
Short explanation of the expected result
+
+ +

throws()

+ +

Expected to throw an error.

+ +
undefined throws(
+  block,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
block
+
Function block to evaluate and catch eventual thrown errors
+
expected
+
Test reference to evaluate against the thrown result from block
+
message
+
Short explanation of the expected result
+
+ +

rejects()

+ +

Expected to reject a promise. Returns a Promise that resolves when the promise either resolves or rejects.

+ +
Promise rejects(
+  promise,
+  expected,
+  message
+);
+
+ +
Parameters
+ +
+
promise
+
Promise promise to wait for rejection and catch eventual thrown errors
+
expected
+
Test reference to evaluate against the thrown result from block
+
message
+
Short explanation of the expected result
+
+ +

greater()

+ +

The greater than assertion tests two numbers with the > operator.

+ +
undefined greater(
+  lhs,
+  rhs,
+  message
+);
+
+ +
Parameters
+ +
+
lhs
+
The left hand side of the operator
+
rhs
+
The right hand side of the operator
+
message
+
Short explanation of the expected result
+
+ +

greaterOrEqual()

+ +

The greater or equal than assertion tests two numbers with the >= operator.

+ +
undefined greaterOrEqual(
+  lhs,
+  rhs,
+  message
+);
+
+ +
Parameters
+ +
+
lhs
+
The left hand side of the operator
+
rhs
+
The right hand side of the operator
+
message
+
Short explanation of the expected result
+
+ +

less()

+ +

The lesser than assertion tests two numbers with the < operator.

+ +
undefined less(
+  lhs,
+  rhs,
+  message
+);
+
+ +
Parameters
+ +
+
lhs
+
The left hand side of the operator
+
rhs
+
The right hand side of the operator
+
message
+
Short explanation of the expected result
+
+ +

lessOrEqual()

+ +

The lesser or equal than assertion tests two numbers with the <= operator.

+ +
undefined lessOrEqual(
+  lhs,
+  rhs,
+  message
+);
+
+ +
Parameters
+ +
+
lhs
+
The left hand side of the operator
+
rhs
+
The right hand side of the operator
+
message
+
Short explanation of the expected result
+
+ +

setReporter()

+ +

Set a custom assertion report handler function.

+ +
undefined setReporter(
+  reporterFunc
+);
+
+ +
Parameters
+ +
+
reporterFunc
+
Reporter handler function.
+ Arguments passed in to this function are: +
+
err
+
An error object when the assertion failed or null when it passed
+
message
+
Message describing the assertion
+
stack
+
Stack trace of the assertion function.
+
+
+
+ +

report()

+ +

All of the aforementioned functions must throw an AssertionError when a corresponding condition is not met, with a message that may be undefined if not provided.
+ All assertion methods provide both the actual and expected values to the assertion error for display purposes.
+
+ This report method only throws errors on assertion failures, as per spec, but consumers of this module (think: xpcshell-test, mochitest) may want to override this default implementation.

+ +
undefined report(
+  failed,
+  actual,
+  expected,
+  message,
+  operator
+);
+
+ +
Parameters
+ +
+
failed
+
Indicates if the assertion failed or not
+
actual
+
The result of evaluating the assertion
+
expected
+
Expected result from the test author
+
message
+
Short explanation of the expected result
+
operator
+
Operation qualifier used by the assertion method (ex: '==')
+
+ +

Examples

+ +

Custom reporter example

+ +
Components.utils.import("resource://testing-common/Assert.jsm");
+
+let assert = new Assert();
+
+assert.setReporter(function customReporter(err, message, stack) {
+  if (err) {
+    do_report_result(false, err.message, err.stack);
+  } else {
+    do_report_result(true, message, stack);
+  }
+});
+
+ +

See also

+ + diff --git a/files/zh-cn/mozilla/javascript_code_modules/dict.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/dict.jsm/index.html new file mode 100644 index 0000000000..b27d445241 --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/dict.jsm/index.html @@ -0,0 +1,344 @@ +--- +title: Dict.jsm +slug: Mozilla/JavaScript_code_modules/Dict.jsm +translation_of: Mozilla/JavaScript_code_modules/Dict.jsm +--- +

{{ gecko_minversion_header("5.0") }}

+ +

{{ warning("This is obsolete - new code should use Map().") }}

+ +

The Dict.jsm JavaScript code module offers routines for managing dictionaries of key/value pairs. To use it, you first need to import the code module into your JavaScript scope:

+ +
Components.utils.import("resource://gre/modules/Dict.jsm");
+
+ +

创建一个字典

+ +

You can create a new, empty dictionary by simply calling the Dict() constructor:

+ +
var newDict = new Dict();
+
+ +

If you wish, you may also pass in an object literal of key/value pairs with which to initialize the dictionary:

+ +
var someObj = {};
+var newDict = new Dict({key1: "foo", key2: someObj});
+
+ +

Note that values may be any JavaScript object type.

+ +
Note: You can actually specify non-strings as keys; these are converted to strings before being used, so they're documented here as if they were a string parameter.
+ +

从Firefox 19开始,你可以通过传入一个JSON字符串来初始化字典对象:

+ +
var someJSON = '{key1: "foo", key2: {}}';
+var newDict = new Dict(someJSON);
+
+ +
注: 传入的任意字符串都会被当成JSON字符串来对待.
+ +

方法概述

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Dict copy();
boolean del(String aKey);
Object get(String aKey, [optional] Object aDefault);
boolean has(String aKey);
Array listitems();
Array listkeys();
Array listvalues();
void set(String aKey, Object aValue);
{{ fx_minversion_inline("19") }} String toJSON();
String toString();
+ +

属性

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性名类型描述
countNumber字典中键值对的个数
itemsIterator +

Returns an iterator over all of the items in the dictionary; each item is returned as a pair (a two-element array) with the first element being the key and the second being the value.

+ +
Note: The order in which items are returned is arbitrary, and may change without notice. In addition, if the dictionary changes during iteration, no guarantees are made as to what will happen.
+
keysIterator +

Returns an iterator over all the keys in the dictionary.

+ +
Note: The order in which items are returned is arbitrary, and may change without notice. In addition, if the dictionary changes during iteration, no guarantees are made as to what will happen.
+
valuesIterator +

Returns an iterator over all the values in the dictionary.

+ +
Note: The order in which items are returned is arbitrary, and may change without notice. In addition, if the dictionary changes during iteration, no guarantees are made as to what will happen.
+
+ +

构造器

+ +

Dict()

+ +

创建并返回一个新的字典对象.

+ +
Dict Dict();
+
+Dict Dict(
+  Object initalKeysAndValues
+);
+
+ +
参数
+ +
+
initialKeysAndValues {{ optional_inline() }}
+
A object containing key/value pairs with which to initialize the dictionary.
+
+ +
返回值
+ +

一个新的字典对象,实现有下面这些方法.

+ +

方法

+ +

copy()

+ +

返回一个字典对象的浅拷贝; that is, a copy of the dictionary including the items immediately included within the dictionary; however, any objects referenced by those top-level objects are not copied.

+ +
Dict copy();
+
+ +
参数
+ +

+ +
返回值
+ +

A new dictionary object containing the same top-level items as the original dictionary on which the copy() method was called.

+ +

del()

+ +

根据指定的键,从该字典中删除一个键值对.

+ +
boolean del(
+  String aKey
+);
+
+ +
参数
+ +
+
aKey
+
从该字典中要删除的键.
+
+ +
返回值
+ +

如果成功删除指定的键值对,则返回true,如果指定的键不存在,则返回false.

+ +

get()

+ +

返回该字典对象中指定键所对应的值.

+ +
Object get(
+  String aKey,
+  [optional] Object aDefault
+);
+
+ +
参数
+ +
+
aKey
+
The key whose value should be returned.
+
aDefault {{ optional_inline() }}
+
The value to return if the specified key isn't found. If you don't specify a default value, undefined is returned for keys that aren't found.
+
+ +
返回值
+ +

The value of the specified key, or undefined if no matching key was found.

+ +

has()

+ +

判断指定的键是否存在与当前字典对象中.

+ +
boolean has(
+  String aKey
+);
+
+ +
参数
+ +
+
aKey
+
判断该键是否存在与当前字典对象中..
+
+ +
返回值
+ +

如果指定的键存在与当前字典中,则返回true,否则返回false.

+ +

listitems()

+ +

返回一个由当前字典中所有键值对组成的数组.

+ +
注: 数组中元素的排列顺序是任意的.
+ +
Array listitems();
+
+ +
参数
+ +

+ +
返回值
+ +

一个由当前字典中所有键值对组成的数组.

+ +

listkeys()

+ +

返回一个由当前字典中所有键组成的数组.

+ +
注: 数组中元素的排列顺序是任意的.
+ +
Array listkeys();
+
+ +
参数
+ +

+ +
返回值
+ +

一个由当前字典中所有键组成的数组.

+ +

listvalues()

+ +

返回一个由当前字典中所有值组成的数组.

+ +
注: 数组中元素的排列顺序是任意的.
+ +
Array listvalues();
+
+ +
参数
+ +

+ +
返回值
+ +

一个由当前字典中所有值组成的数组.

+ +

set()

+ +

设置指定键所对应的值,如果该键不存在,则添加上这个新键.

+ +
void set(
+  String aKey,
+  Object aValue
+);
+
+ +
参数
+ +
+
aKey
+
设置改建所对应的值.
+
aValue
+
为指定键所设置的新值.
+
+ +

toJSON()

+ +

返回一个代表当前字典的 JSON字符串.

+ +
String toJSON();
+
+ +
参数
+ +

+ +
返回值
+ +

返回一个代表了该字典对象中所有键值对的JSON字符串,空字典将返回"{}".

+ +

toString()

+ +

返回一个代表该字典对象的字符串.

+ +
String toString();
+
+ +
参数
+ +

+ +
返回值
+ +

返回一个代表了该字典对象中所有键值对的字符串,空字典将返回"{}".

+ +

示例

+ +

创建和填充字典

+ +

下面的例子首先创建一个新的空字典,然后添加进一些键值对.

+ +
var myDict = new Dict();
+myDict.set("name", "John Smith");
+myDict.set("email", "jsmith@example.com");
+myDict.set("phone", "650-555-1234");
+
+ +

判断字典中指定的键是否存在

+ +

接着上面的个例子,你可以检测某个键是否存在于myDict中:

+ +
if (myDict.has("email")) {
+  /* an "email" key exists on the object */
+}
+
diff --git a/files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/download/index.html b/files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/download/index.html new file mode 100644 index 0000000000..41230df3c4 --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/download/index.html @@ -0,0 +1,335 @@ +--- +title: Download +slug: Mozilla/JavaScript_code_modules/Downloads.jsm/Download +translation_of: Mozilla/JavaScript_code_modules/Downloads.jsm/Download +--- +

 Download 对象仅仅表示下载,同时包含相关的状态和行为。这个对象是短时存在的,但是它可被包含在DownloadList 对象,因此它能够通过用户接口调用和跨sessions.

+ +

调用Downloads.createDownload() 方法可以创建一个新的Download 对象。

+ +

方法概览

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Promise start();
Promise launch();
Promise showContainingDirectory();
Promise cancel();
Promise removePartialData();
Promise whenSucceeded();
Promise finalize([optional] boolean aRemovePartialData);
+ +

属性

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性类型描述
canceled {{ReadOnlyInline()}}boolean +

表示下载被取消。这个属性可设置为true,当被取消下载重新下载时被设置为false。

+ +

This property becomes true as soon as the cancel() method is called, though the stopped property might remain false until the cancellation request has been processed. Temporary files or part files may still exist even if they are expected to be deleted, until the stopped property becomes true.

+
contentTypestring +

The MIME type of the download, for example "text/plain", or null if the MIME type is not available.

+ +

This property may be populated or changed while the download is in progress, using the MIME type provided by the server.

+
currentBytes {{ReadOnlyInline()}}number +

Number of bytes currently transferred. This value starts at zero, and may be updated regardless of the value of hasProgress.

+ +
Note: You shouldn't rely on this property being equal to totalBytes to determine whether the download is completed.  You should use the individual state properties instead, since this value may not be updated after the last piece of data is transferred.
+
error {{ReadOnlyInline()}}DownloadErrorWhen the download fails, this is set to a DownloadError instance indicating the cause of the failure. If the download has been completed successfully or has been canceled, this property is null. This property is reset to null when a failed download is restarted.
hasPartialData {{ReadOnlyInline()}}boolean +

Indicates whether, at this time, there is any partially downloaded data that can be used when restarting a failed or canceled download.

+ +

This property is relevant while the download is in progress, and also if it failed or has been canceled. If the download has been completed successfully, this property is not relevant anymore.

+ +

Whether partial data can actually be retained depends on the saver and the download source, and may not be known before the download is started.

+
hasProgress {{ReadOnlyInline()}}booleanIndicates whether this download's progress property is able to report partial progress while the download proceeds, and whether the value in totalBytes is relevant. This depends on the saver and the download source.
launchWhenSucceededbooleanIf this property is true when the download finishes successfully, the target file will be opened or executed automatically.
launcherPathstringLocal file path of the application to be used to launch the target file, or null if the file should be launched with the default application associated with the contentType property or the extension of the target file.
onchangeFunction +

This can be set to a function that is called after other properties change.

+ +
+

Warning: This property cannot be used if the download is part of a DownloadList.

+
+
progress {{ReadOnlyInline()}}number +

Progress percent, from 0 to 100. Intermediate values are reported only if hasProgress is true.

+ +
Note: You shouldn't rely on this property being equal to 100 to determine whether the download is completed. You should use the individual state properties (for example, the succeeded property) instead.
+
saver {{ReadOnlyInline()}}DownloadSaverSaver object associated with this download.
source {{ReadOnlyInline()}}DownloadSourceSource of this download.
startTime {{ReadOnlyInline()}}DateIndicates the start time of the download. When the download starts, this property is set to a valid Date object. The default value is null before the download starts.
stopped {{ReadOnlyInline()}}booleanIndicates that the download never started, has been completed successfully, failed, or has been canceled. This property becomes false when a download is started for the first time, or when a failed or canceled download is restarted.
succeeded {{ReadOnlyInline()}}booleanThis propery is true if the download has been completed successfully.
target {{ReadOnlyInline()}}DownloadTargetTarget of this download.
totalBytes {{ReadOnlyInline()}}number +

When hasProgress is true, this indicates the total number of bytes to be transferred before the download finishes; this value can be zero if the file is empty.

+ +

Note: This property's value may not match the actual final size of the downloaded file if the download is encoded during the network transfer. You can use the DownloadTarget.size property to get the actual size of the completely-downloaded file once the download has succeeded.

+ +

When hasProgress is false, this property is always zero.

+
tryToKeepPartialDataboolean +

Indicates whether any partially downloaded data should be retained, to use when restarting a failed or canceled download. The default is false.

+ +

Whether partial data can actually be retained depends on the saver and the download source, and may not be known before the download is started.

+ +

To have any effect, this property must be set before starting the download. Resetting this property to false after the download has already started will not remove any partial data.

+ +
Note: If this property is set to true, care should be taken that partial data is removed before the reference to the download is discarded. This can be done using the removePartialData() or the finalize() methods.
+
+ +

方法

+ +

start()

+ +

Starts the download for the first time, or restarts a download that failed or has been canceled.

+ +

Calling this method when the download has been completed successfully has no effect, and the method returns a resolved promise. If the download is in progress, the method returns the same promise as the previous call.

+ +

If the cancel() method was called but the cancellation process has not finished yet, this method waits for the cancellation to finish, then restarts the download immediately.

+ +
Note: If you need to start a new download from the same source, rather than restarting a failed or canceled one, you should create a separate Download object with the same source as the current one.
+ +
Promise start();
+
+ +
Parameters
+ +

None.

+ +
Promise resolves to
+ +

undefined when the download has finished successfully and you can access the target file.

+ +
Promise can be rejected with
+ +

DownloadError if the download failed.

+ +

launch()

+ +

Opens or executes the target file after download has completed.

+ +

If the launcherPath property is null, the file will be opened with the default application for the MIME type specified in the contentType property. If the content type is not available, an attempt will be made to obtain it from the extension of the target file.

+ +

If the launcherPath property is set, the file will be opened with the specified custom application.

+ +
Promise launch();
+
+ +
Parameters
+ +

None.

+ +
Promise resolves to
+ +

undefined when the instruction to launch the file has been successfully given to the operating system. Note that the OS might still take a while until the file is actually launched.

+ +

showContainingDirectory()

+ +

Shows the folder containing the target file, or where the target file will be saved. This may be called at any time, even if the download failed or is currently in progress.

+ +
Promise showContainingDirectory();
+
+ +
Parameters
+ +

None.

+ +
Promise resolves to
+ +

undefined when the instruction to open the containing folder has been successfully given to the operating system. Note that the OS might still take a while until the folder is actually opened.

+ +

cancel()

+ +

Cancels the download.

+ +

The cancellation request is asynchronous. Until the cancellation process finishes, temporary files or part files may still exist even if they are expected to be deleted.

+ +

In case the download completes successfully before the cancellation request could be processed, this method has no effect, and it returns a resolved promise. You should check the properties of the download at the time the returned promise is resolved to determine if the download was canceled.

+ +

Calling this method when the download has been completed successfully, failed, or has been canceled has no effect, and the method returns a resolved promise. This behavior is designed for the case where the call to cancel happens asynchronously, and is consistent with the case where the cancellation request could not be processed in time.

+ +
Promise cancel();
+
+ +
Parameters
+ +

None.

+ +
Promise resolves to
+ +

undefined when the cancellation process has finished.

+ +
Promise can be rejected with
+ +

Never rejected.

+ +

removePartialData()

+ +

Removes any partial data kept as part of a canceled or failed download.

+ +

If the download is not canceled or failed, this method has no effect, and it returns a resolved promise. If the cancel() method was called but the cancellation process has not finished yet, this method waits for the cancellation to finish, then removes the partial data.

+ +

After this method has been called, if the tryToKeepPartialData property is still true when the download is restarted, partial data will be retained during the new download attempt.

+ +
Promise removePartialData();
+
+ +
Parameters
+ +

None.

+ +
Promise resolves to
+ +

undefined when the partial data has been successfully removed.

+ +

whenSucceeded()

+ +

Returns a promise that is resolved as soon as this download finishes successfully, even if the download was stopped and restarted meanwhile.

+ +

You can use this property for scheduling download completion actions in the current session, for downloads that are controlled interactively. If the download is not controlled interactively, you should use the promise returned by the start() method instead, to check for success or failure.

+ +
Promise whenSucceeded();
+
+ +
Parameters
+ +

None.

+ +
Promise resolves to
+ +

undefined when the download has finished successfully and you can access the target file.

+ +
Promise can be rejected with
+ +

Never rejected.

+ +

finalize()

+ +

Ensures that the download is stopped, and optionally removes any partial data kept as part of a canceled or failed download. After this method has been called, the download cannot be started again.

+ +
Note: This method should be used in place of the cancel() and removePartialData() methods while shutting down or disposing of the download object, to prevent other callers from interfering with the operation. This is required because cancellation and other operations are asynchronous.
+ +
Promise finalize(
+  boolean aRemovePartialData
+);
+
+ +
Parameters
+ +
+
aRemovePartialData {{optional_inline()}}
+
Whether any partially downloaded data should be removed after the download has been stopped. The default is false.
+
+ +
Promise resolves to
+ +

undefined when the operation has finished successfully.

+ +

查看其他

+ + diff --git a/files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/index.html new file mode 100644 index 0000000000..1df73bfd16 --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/downloads.jsm/index.html @@ -0,0 +1,306 @@ +--- +title: Downloads.jsm +slug: Mozilla/JavaScript_code_modules/Downloads.jsm +tags: + - Add-ons + - Download Manager + - Extensions + - Files + - JavaScript + - Modules + - NeedsTranslation + - TopicStub +translation_of: Mozilla/JavaScript_code_modules/Downloads.jsm +--- +

{{ gecko_minversion_header("26") }}

+ +

The Downloads.jsm JavaScript code module provides a single entry point to interact with the downloading capabilities of the platform, including starting new downloads, controlling ongoing downloads, and retrieving download-related configuration. To use it, you first need to import the code module into your JavaScript scope:

+ +
Components.utils.import("resource://gre/modules/Downloads.jsm");
+
+ +

Method overview

+ + + + + + + + + + + + + + + + +
Promise<Download> createDownload(Object aProperties);
Promise<void> fetch(aSource, aTarget, [optional] Object aOptions);
Promise<DownloadList> getList(aType);
Promise<DownloadSummary> getSummary(aType);
+ +

Constants

+ + + + + + + + + + + + + + + + + + + + +
ConstantDescription
PUBLICWork on downloads that were not started from a private browsing window.
PRIVATEWork on downloads that were started from a private browsing window.
ALLWork on both Downloads.PRIVATE and Downloads.PUBLIC downloads.
+ +

Properties

+ + + + + + + + + + + + + + +
AttributeTypeDescription
Error Read only ConstructorConstructor for a DownloadError object. When you catch an exception during a download, you can use this to verify if ex instanceof Downloads.Error, before reading the exception properties with the error details. Example (using Task.jsm): +
+try {
+  yield Downloads.fetch(sourceUri, targetFile);
+} catch (ex if ex instanceof Downloads.Error && ex.becauseTargetFailed) {
+  console.log("Unable to write to the target file, ignoring the error.");
+}
+
+ +

Methods

+ +

createDownload()

+ +

Creates a new Download object.

+ +
Promise<Download> createDownload(
+  Object aProperties
+);
+
+ +
Parameters
+ +
+
aProperties
+
Provides the initial properties for the newly created download. This matches the serializable representation of a Download object. Some of the most common properties in this object include: +
    +
  • source: String containing the URI for the download source. Alternatively, may be an {{Interface("nsIURI")}}, a DownloadSource object, or an object with the following properties: +
      +
    • url: String containing the URI for the download source.
    • +
    • isPrivate: {{optional_inline()}} Indicates whether the download originated from a private window. If omitted, the download is public.
    • +
    • referrer: {{optional_inline()}} String containing the referrer URI of the download source. Can be omitted or null if no referrer should be sent or the download source is not HTTP.
    • +
    +
  • +
  • target: String containing the path of the target file. Alternatively, may be an {{Interface("nsIFile")}}, a DownloadTarget object, or an object with the following properties: +
      +
    • path: String containing the path of the target file.
    • +
    +
  • +
  • saver: {{optional_inline()}} String representing the class of the download operation. If omitted, defaults to "copy". Alternatively, may be the serializable representation of a DownloadSaver object.
  • +
+
+
+ +
Promise resolves to
+ +

The newly created Download object.

+ +

fetch()

+ +

Downloads data from a remote network location to a local file.

+ +

This download method does not provide user interface or the ability to cancel or restart the download programmatically. For that, you should obtain a reference to a Download object using the createDownload() function.

+ +

Since the download cannot be restarted, any partially downloaded data will not be kept in case the download fails.

+ +
Promise fetch(
+  aSource,
+  aTarget,
+  Object aOptions
+);
+
+ +
Parameters
+ +
+
aSource
+
String containing the URI for the download source. Alternatively, may be an {{Interface("nsIURI")}} or a DownloadSource object.
+
aTarget
+
String containing the path of the target file. Alternatively, may be an {{Interface("nsIFile")}} or a DownloadTarget object.
+
aOptions {{optional_inline()}}
+
An optional object used to control the behavior of this function. You may pass an object with a subset of the following fields: +
    +
  • isPrivate: {{optional_inline()}} Indicates whether the download originated from a private window. If omitted, the download is public.
  • +
+
+
+ +
Promise resolves to
+ +

undefined when the download has finished successfully and you can access the target file.

+ +
Promise can be rejected with
+ +

DownloadError if the download failed.

+ +

getList()

+ +

Retrieves the specified type of DownloadList object. There is one download list for each type, and this method always retrieves a reference to the same download list when called with the same argument.

+ +

Calling this function may cause the download list to be reloaded from the previous session, if it wasn't loaded already.

+ +
Promise<DownloadList> getList(aType);
+
+ +
Parameters
+ +
+
aType
+
This can be Downloads.PUBLIC, Downloads.PRIVATE, or Downloads.ALL. Downloads added to the Downloads.PUBLIC and Downloads.PRIVATE lists are reflected in the Downloads.ALL list, and downloads added to the Downloads.ALL list are also added to either the Downloads.PUBLIC or the Downloads.PRIVATE list based on their properties.
+
+ +
Promise resolves to
+ +

The requested DownloadList object.

+ +

getSummary()

+ +

Retrieves the specified type of DownloadSummary object. There is one download summary for each type, and this method always retrieves a reference to the same download summary when called with the same argument.

+ +

Calling this function does not cause the list of public downloads to be reloaded from the previous session. The summary will behave as if no downloads are present until the getList() method is called.

+ +
Promise<DownloadSummary> getSummary(aType);
+
+ +
Parameters
+ +
+
aType
+
This can be Downloads.PUBLIC, Downloads.PRIVATE, or Downloads.ALL.
+
+ +
Promise resolves to
+ +

The requested DownloadSummary object.

+ +

Examples

+ +

Downloading to a local file

+ +

This example downloads an HTML file without showing progress, handling errors programmatically.

+ +
Components.utils.import("resource://gre/modules/Downloads.jsm");
+Components.utils.import("resource://gre/modules/osfile.jsm")
+Components.utils.import("resource://gre/modules/Task.jsm");
+
+Task.spawn(function () {
+
+  yield Downloads.fetch("http://www.mozilla.org/",
+                        OS.Path.join(OS.Constants.Path.tmpDir,
+                                     "example-download.html"));
+
+  console.log("example-download.html has been downloaded.");
+
+}).then(null, Components.utils.reportError);
+
+ +

Observing downloads

+ +

This example logs a message every time a change occurs in one of the global download lists.

+ +

To demonstrate the logging, a new download is started while a message box is being shown. The download is stopped and removed from the list when the message box is closed, regardless of whether it has been completed or not.

+ +
Components.utils.import("resource://gre/modules/Downloads.jsm");
+Components.utils.import("resource://gre/modules/osfile.jsm")
+Components.utils.import("resource://gre/modules/Task.jsm");
+
+Task.spawn(function () {
+
+  let list = yield Downloads.getList(Downloads.ALL);
+
+  let view = {
+    onDownloadAdded: download => console.log("Added", download),
+    onDownloadChanged: download => console.log("Changed", download),
+    onDownloadRemoved: download => console.log("Removed", download)
+  };
+
+  yield list.addView(view);
+  try {
+    let download = yield Downloads.createDownload({
+      source: "http://www.mozilla.org/",
+      target: OS.Path.join(OS.Constants.Path.tmpDir, "example-download.html"),
+    });
+    list.add(download);
+    try {
+      download.start();
+      alert("Now monitoring all downloads. Close the message to stop.");
+    } finally {
+      yield list.remove(download);
+      yield download.finalize(true);
+    }
+  } finally {
+    yield list.removeView(view);
+  }
+
+}).then(null, Components.utils.reportError);
+
+ +

Conversion from nsIDownloadManager

+ +

Starting in Firefox for Desktop version 26, the {{interface("nsIDownloadManager")}} and {{interface("nsIDownload")}} interfaces are not available anymore.

+ +

The new module works differently from the old component. In general, you should be aware of the following highlights:

+ + + +

While some of the legacy methods and properties have an equivalent in Downloads.jsm, there might be subtle differences in behavior. For example, the properties that handle progress are now more detailed and don't use the special value -1 anymore. You may see the documentation of the new methods and properties for details.

+ +

Using it in a XUL app

+ +

In a XUL standalone application (running with XULRunner or firefox --app), you have to do additionnal things in order to use the new download manager. By default it is not enabled. It will be enabled when the bug 851471 will be closed. If you don't activate it, you could use Downloads.jsm, but your view will not be called by the external helper app service (when a user click on a file to download, in a web page). To enable the new download manager :

+ + + +
 Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar)
+                   .registerFactory(Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}"), "", "@mozilla.org/transfer;1", null);
+
+
+ +

 

+ +

See also

+ + + +
 
diff --git a/files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/index.html new file mode 100644 index 0000000000..bc18819d7a --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/index.html @@ -0,0 +1,19 @@ +--- +title: Geometry.jsm +slug: Mozilla/JavaScript_code_modules/Geometry.jsm +translation_of: Mozilla/JavaScript_code_modules/Geometry.jsm +--- +

{{ gecko_minversion_header("2.0") }}

+

The Geometry.jsm JavaScript code module provides routines for performing common geometry operations on points and rectangles. It exports two classes: Point and Rect.

+

To use these routines, you first need to import the code module into your JavaScript scope:

+
Components.utils.import("resource://gre/modules/Geometry.jsm");
+
+

Once you've imported the module, you can then use the Point and Rect classes.

+
+ Note: Although this module is usable from mobile, and is present in Firefox 4, it's currently not used in Firefox 4 and attempting to use it may produce unreliable results there.
+

See also

+ diff --git a/files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/services.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/services.jsm/index.html new file mode 100644 index 0000000000..1acdc77cdf --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/geometry.jsm/services.jsm/index.html @@ -0,0 +1,25 @@ +--- +title: Services.jsm +slug: Mozilla/JavaScript_code_modules/Geometry.jsm/Services.jsm +translation_of: Mozilla/JavaScript_code_modules/Services.jsm +--- +

{{ gecko_minversion_header("2") }}

+

The Services.jsm  模块提供了一系列的javascript模块,用来简化各种常用的操作.

+

在使用它们之前,你必须首先将Services模块导入到自己的作用域内:

+
Components.utils.import("resource://gre/modules/Services.jsm");
+
+

然后你可以通过服务访问器来轻松的从Services对象导出所需要的模块. 例如,要想获取一个preferences服务,你可以用下面的语句:

+
var prefsService = Services.prefs;
+
+

服务访问器

+ + +
服务访问器 服务接口 服务名
appinfo {{ interface("nsIXULAppInfo") }}
{{ interface("nsIXULRuntime") }}
Application information service
console {{ interface("nsIConsoleService") }} Error console service
contentPrefs {{ interface("nsIContentPrefService") }}

Content Preferences service

cookies {{ interface("nsICookieManager2") }}

Cookie Manager 2 service

dirsvc {{ interface("nsIDirectoryService") }}
{{ interface("nsIProperties") }}
Directory service
droppedLinkHandler {{ interface("nsIDroppedLinkHandler") }} Dropped link handler service
eTLD {{ interface("nsIEffectiveTLDService") }}

EffectiveTLD service

io {{ interface("nsIIOService") }}
{{ interface("nsIIOService2") }}
I/O Service
locale {{ interface("nsILocaleService") }} Locale service
logins {{ interface("nsILoginManager") }}

Password Manager service

obs {{ interface("nsIObserverService") }} Observer service
perms {{ interface("nsIPermissionManager") }} Permission manager service
prefs {{ interface("nsIPrefBranch") }}
{{ interface("nsIPrefBranch2") }}
{{ interface("nsIPrefService") }}
Preferences service
prompt {{ interface("nsIPromptService") }} Prompt service
scriptloader {{ interface("mozIJSSubScriptLoader") }} JavaScript subscript loader service
search {{ interface("nsIBrowserSearchService") }} Browser search service1
startup {{ interface("nsIAppStartup") }} Application startup service
storage {{ interface("mozIStorageService") }} Storage API service
strings {{ interface("nsIStringBundleService") }} String bundle service
sysinfo {{ interface("nsIPropertyBag2") }} System info service
telemetry {{ interface("nsITelemetry") }} Telemetry service
tm {{ interface("nsIThreadManager") }} Thread Manager service
urlFormatter {{ interface("nsIURLFormatter") }}

URL Formatter service

vc {{ interface("nsIVersionComparator") }} Version comparator service
wm {{ interface("nsIWindowMediator") }} Window mediator service
ww {{ interface("nsIWindowWatcher") }} Window watcher service
DOMRequest {{ interface("nsIDOMRequestService") }} DOMRequest service
cpmm {{ interface("nsIFrameMessageManager") }} Child Process Message Manager
ppmm {{ interface("nsIFrameMessageManager") }} Parent Process Message Manager
+

Thunderbird 和 SeaMonkey中该特性不可用.

+

相关链接

+ +

{{ languages( { "en": "en/JavaScript_code_modules/Services.jsm" } ) }}

diff --git a/files/zh-cn/mozilla/javascript_code_modules/http.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/http.jsm/index.html new file mode 100644 index 0000000000..1e77c4e852 --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/http.jsm/index.html @@ -0,0 +1,74 @@ +--- +title: Http.jsm +slug: Mozilla/JavaScript_code_modules/Http.jsm +tags: + - API + - HTTP +translation_of: Mozilla/JavaScript_code_modules/Http.jsm +--- +

HTTP.jsm

+ +

Http.jsm 提供了 httpRequest-XMLHttpRequest的包装器,它为处理HTTP请求提供了方便和简化的API。

+ +

httpRequest 支持以下参数:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namemeaning
headersheader 的数组
postData +

取值范围:

+ +
    +
  • string: 按原样发送
  • +
  • 数组: 编码为表单值
  • +
  • null/undefined: 没有POST数据.
  • +
+
+

method

+
GET, POST , PUT (如果postData存在,将自动设置).
onLoad +

加载完成时调用的方法,它接受两个参数:responseText和XHR对象。

+
onError +

当错误发生时调用的方法,它接受三个参数:error、responseText和XHR对象。

+
logger +

实现调试和日志方法的对象(例如log.jsm)。

+
+ +

header 或 postData 是作为二维数组给出的,对于每个内部数组,第一个值是键,第二个值是值。例如: [["key1", "value1"], ["key2", "value2"]].

+ +

提交 post 数据

+ +

httpRequest允许向post请求附加数据。可以通过postData选项指定数据。postData可以有两种类型:字符串或数组。当给出null/undefined时,将不发送任何数据。如果给定一个字符串,数据将按原样追加到请求中。如果给定一个参数数组,它将被视为一个键值对数组。数组的元素将采用url编码,并会强制设置content type为“application/x-www-form-urlencoded;charset=utf-8"。Http.jsm只在post数据是数组时强行设置content type,并自动序列化它。如果提供的postdata是一个字符串,则不设置内容类型。在这种情况下,可以通过header参数设置content type。

+ +

可选的XHR 配置

+ +

在调用httpRequest之后,可以手动修改XHR对象上的内容。httpRequest返回一个XHR对象,该对象可用于设置请求的附加参数。例如,可以将XHR配置为在处理响应时使用任何自定义mime类型,而不管服务器返回什么。为此,可以通过调用httpRequest获得XHR对象,然后调用它的overrideMimeType()方法去设置MIME-Type。另一个例子可以在这里找到。

diff --git a/files/zh-cn/mozilla/javascript_code_modules/index.html b/files/zh-cn/mozilla/javascript_code_modules/index.html new file mode 100644 index 0000000000..415663945b --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/index.html @@ -0,0 +1,84 @@ +--- +title: JavaScript 代码模块 +slug: Mozilla/JavaScript_code_modules +tags: + - Add-ons(加载项) + - JavaScript + - TopicStub + - XPCOM + - mo + - 扩展 + - 模块 +translation_of: Mozilla/JavaScript_code_modules +--- +

{{Non-standard_Header}}

+ +
+

注意: JavaScript代码模块和JavaScript 标准中的模块(module)不是一回事。 要学习如何使用标准中的模块,请点击 {{JSxRef("Statements/export", "export")}} 和 {{JSxRef("Statements/import", "import")}} 查看。

+
+ +

JavaScript 代码模块用于具备不同权限的作用域之间的代码共享。例如,Firefox 可以使用模块,也可以通过扩展来使用模块,以避免重复代码。

+ + + + + + + + +
+

话题总览

+ +
+
使用JavaScript代码模块
+
介绍如何使用JavaScript代码模块
+
Component.utils.import
+
如何导入一个JavaScript的代码模块。
+
Component.utils.unload {{gecko_minversion_inline("7.0")}}
+
如何上传一个JavaScript的代码模块
+
代码片段: Module
+
如何使用模块代码的实例。
+
Mozilla实验室的 JS Modules
+
本页面列出了JS模块的列表,以及下载链接和文档,扩展开发人员可以在代码中使用它们。
+
+ +
+
+
+

标准代码模块

+ +
+
ctypes.jsm {{fx_minversion_inline("3.6")}}
+
提供一个允许JS代码在不需要开发一个XPCOM元素的前提下调用本地库的接口。
+
FileUtils.jsm {{gecko_minversion_inline("1.9.2")}}
+
提供处理文件的有用的方法
+
Geometry.jsm {{gecko_minversion_inline("2.0")}}
+
提供用于对点和矩形执行基本几何操作的方法。
+
ISO8601DateUtils.jsm
+
提供在JavaScript Date 对象和ISO 8601 data字符串之间转换的方法。
+
Dict.jsm {{gecko_minversion_inline("5.0")}}
+
提供一个可以访问键值对词典的API。
+
NetUtil.jsm
+
提供一些有用的网络实用函数,使您能够轻松地将输入流中的数据异步复制到输出流的。
+
PopupNotifications.jsm {{gecko_minversion_inline("2.0")}}
+
提供一种给用户弹出非模态(non-modal)通知的简便方法
+
openLocationLastURL.jsm {{gecko_minversion_inline("1.9.1.4")}}
+
提供读取使用文件菜单中的“打开定位(Open Location)” 时打开的最后一个URL的能力。
+
DownloadLastDir.jsm {{gecko_minversion_inline("2.0")}}
+
提供最后一次下载时的目录路径。
+
PluralForm.jsm
+
提供获取当前区域使用的正确的复数形式的一种简便方法,当然也可以使用一种指定的复数规则来将一个词语复数化。
+
Services.jsm {{gecko_minversion_inline("2.0")}}
+
提供getter来方便地获取对一些常用服务的访问。
+
source-editor.jsm {{fx_minversion_inline("11.0")}}
+
源编辑器(Souce Editor)是指那些you开发者工具所提供的编辑器,如样式编辑器;此接口实现了源编辑器,并且允许你与之交互。
+
XPCOMUtils.jsm
+
包含一些为JS组件加载器所加载的JavaScript组件的实用程序。
+
PerfMeasurement.jsm {{fx_minversion_inline("4.0")}}
+
提供对底层硬件和操作系统性能测量工具的访问。
+
AddonManager.jsm {{gecko_minversion_inline("2.0")}}
+
安装、管理和卸载加载项(add-ons)的接口。
+
AddonRepository.jsm {{gecko_minversion_inline("2.0")}}
+
允许搜索加载项(add-ons)列表。
+
+
diff --git a/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/deferred/index.html b/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/deferred/index.html new file mode 100644 index 0000000000..aa0d921e0c --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/deferred/index.html @@ -0,0 +1,190 @@ +--- +title: Deferred +slug: Mozilla/JavaScript_code_modules/Promise.jsm/Deferred +translation_of: Mozilla/JavaScript_code_modules/Promise.jsm/Deferred +--- +

 Deferred 对象返回了一个已经被废弃的方法Promise.defer() 并提供给新的promise用来改变promise的状态。

+ +

从Gecko 30开始,该对象就已经被废弃,并建议不再使用。可以通过 new Promise() 构造新的promise取代,(或者使用向后/向前兼容的Deferred方法实现,如下:)。等价方法如下: 

+ +
var deferred = Promise.defer();
+doSomething(function cb(good) {
+    if (good)
+        deferred.resolve();
+    else
+        deferred.reject();
+});
+return deferred.promise;
+ +

应写成:

+ +
return new Promise(function(resolve, reject) {
+    doSomething(function cb(good) {
+        if (good)
+            resolve();
+        else
+            reject();
+    });
+});
+ +

方法概览

+ + + + + + + + + + +
void resolve([optional] aValue);
void reject([optional] aReason);
+ +

属性

+ + + + + + + + + + + + + + +
AttributeTypeDescription
promise {{ReadOnlyInline()}}Promise新创建的promise,在pending阶段被初始化
+ +

方法

+ +

resolve()

+ +

将指定的值赋给新建的promise,或者改变已存在的 promise 状态。如果关联的 promise 已经调用过 resolve 方法,无论是传入值、rejection,或另一个 promise,此方法都不会起效果。

+ +
Note: This function is bound to its associated promise when Promise.defer() is called, and can be called with any value of this.
+ +
Note: Calling this method with a pending promise as the aValue argument, and then calling it again with another value before the promise is resolved or rejected, will have no effect the second time, as the associated promise is already resolved to the pending promise value as its resolution.
+ +
void resolve(
+  aValue
+);
+
+ +
Parameters
+ +
+
aValue Optional
+
If this value is not a promise, including undefined, it becomes the fulfillment value of the associated promise. If this value is a promise, then the associated promise will be resolved to the passed promise, and follow the state as the provided promise (including any future transitions).
+
+ +

reject()

+ +

Rejects the associated promise with the specified reason. If the promise has already been resolved, either to a value, a rejection, or another promise, this method does nothing.

+ +
Note: This function is bound to its associated promise when Promise.defer() is called, and can be called with any value of this.
+ +
void reject(
+  aReason
+);
+
+ +
Parameters
+ +
+
aReason Optional
+
+

The rejection reason for the associated promise. Although the reason can be undefined, it is generally an Error object, like in exception handling.

+ +
Note: This argument should not be a promise. Specifying a rejected promise would make the rejection reason equal to the rejected promise itself, and not its rejection reason.
+
+
+ +

Backwards and forwards compatible helper

+ +

This Deferred function can be used for backwards and forwards compatibility, due to a change that took place in Firefox 30.

+ +
function Deferred() {
+	// update 062115 for typeof
+	if (typeof(Promise) != 'undefined' && Promise.defer) {
+		//need import of Promise.jsm for example: Cu.import('resource:/gree/modules/Promise.jsm');
+		return Promise.defer();
+	} else if (typeof(PromiseUtils) != 'undefined'  && PromiseUtils.defer) {
+		//need import of PromiseUtils.jsm for example: Cu.import('resource:/gree/modules/PromiseUtils.jsm');
+		return PromiseUtils.defer();
+	} else {
+		/* A method to resolve the associated Promise with the value passed.
+		 * If the promise is already settled it does nothing.
+		 *
+		 * @param {anything} value : This value is used to resolve the promise
+		 * If the value is a Promise then the associated promise assumes the state
+		 * of Promise passed as value.
+		 */
+		this.resolve = null;
+
+		/* A method to reject the assocaited Promise with the value passed.
+		 * If the promise is already settled it does nothing.
+		 *
+		 * @param {anything} reason: The reason for the rejection of the Promise.
+		 * Generally its an Error object. If however a Promise is passed, then the Promise
+		 * itself will be the reason for rejection no matter the state of the Promise.
+		 */
+		this.reject = null;
+
+		/* A newly created Promise object.
+		 * Initially in pending state.
+		 */
+		this.promise = new Promise(function(resolve, reject) {
+			this.resolve = resolve;
+			this.reject = reject;
+		}.bind(this));
+		Object.freeze(this);
+	}
+}
+ +

and use this function as would Promise.defer:

+ +
function funcWithDefer() {
+  var deferred = new Deferred();
+  var promise = deferred.promise;
+  promise.then(
+    function(aVal) {
+      console.log('Fullfilled - ', aVal);
+    },
+    function(aReason) {
+      console.error('Rejected - aReason:', aReason)
+    }
+  );
+
+  //deferred.resolve('aVal of resolved');
+  deferred.reject('reject val');
+
+  return promise;
+}
+
+var promise_funcWithDefer = funcWithDefer();
+promise_funcWithDefer.then(
+  function(aVal) {
+    console.log('Fullfilled - promise_funcWithDefer - ', aVal);
+  },
+  function(aReason) {
+    var refObj = {name:'promise_funcWithDefer', aReason:aReason};
+    console.error('Rejected - promise_funcWithDefer - ', refObj);
+  }
+).catch(
+  function(aCatch) {
+    console.error('Caught - promise_funcWithDefer - ', aCatch);
+    throw aCatch;
+  }
+);
+ +

See also

+ + + +

+ +

diff --git a/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/index.html new file mode 100644 index 0000000000..a02f5f0385 --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/index.html @@ -0,0 +1,172 @@ +--- +title: Promise.jsm +slug: Mozilla/JavaScript_code_modules/Promise.jsm +tags: + - NeedsTranslation + - TopicStub +translation_of: Mozilla/JavaScript_code_modules/Promise.jsm +--- +

{{ gecko_minversion_header("25") }}

+

The Promise.jsm JavaScript code module implements the Promises/A+ proposal as known in April 2013. To use it, you first need to import the code module into your JavaScript scope:

+
Components.utils.import("resource://gre/modules/Promise.jsm");
+
+
+

Note: A preliminary promise module is also available starting from Gecko 17, though it didn't conform to the Promises/A+ proposal until Gecko 25:

+
Components.utils.import("resource://gre/modules/commonjs/promise/core.js");     // Gecko 17 to 20
+Components.utils.import("resource://gre/modules/commonjs/sdk/core/promise.js"); // Gecko 21 to 24
+
+

This implementation also includes helper functions that are specific to the Add-on SDK. While you may still import this module from the above paths, the recommended way for loading it is through the Add-on SDK loader.

+
+

Introduction

+

For an introduction to promises, you may start from the Add-on SDK documentation, keeping in mind that only the core subset is implemented in this module.

+

A promise is an object representing a value that may not be available yet. Internally, a promise can be in one of three states:

+ +

A reference to an existing promise may be received by different means, for example as the return value of a call into an asynchronous API. In this case, the state of the promise can be observed but not directly controlled.

+

To observe the state of a promise, its then method must be used. This method registers callback functions that are called as soon as the promise is either fulfilled or rejected. The method returns a new promise, that in turn is fulfilled or rejected depending on the state of the original promise and on the behavior of the callbacks. For example, unhandled exceptions in the callbacks cause the new promise to be rejected, even if the original promise is fulfilled. See the documentation of the then method for details.

+

Promises may also be created using the Promise.defer() function, the main entry point of this module. The function, along with the new promise, returns separate methods to resolve or reject the promise. See the documentation of the Deferred object for details.

+

Method overview

+ + + + + + + + + + + + +
Deferred defer();
Promise resolve([optional] aValue);
Promise reject([optional] aReason);
+

Methods

+

defer()

+

Creates a new pending promise and provides methods to resolve or reject it.

+
Deferred defer();
+
+
Parameters
+

None.

+
Return value
+

A new object, containing the new promise in the promise property, and the methods to change its state in the resolve and reject properties. See the Deferred documentation for details.

+

resolve()

+

Creates a new promise fulfilled with the specified value, or propagates the state of an existing promise.

+
Promise resolve(
+  aValue
+);
+
+
Parameters
+
+
+ aValue {{ optional_inline() }}
+
+ If this value is not a promise, including undefined, it becomes the fulfillment value of the returned promise. If this value is a promise, then the returned promise will be resolved with the value, i.e. it will eventually assume the same state as the provided promise.
+
+
Return value
+

A promise that can be pending, fulfilled, or rejected.

+

reject()

+

Creates a new promise rejected with the specified reason.

+
Promise reject(
+  aReason
+);
+
+
Parameters
+
+
+ aReason {{ optional_inline() }}
+
+

The rejection reason for the returned promise. Although the reason can be undefined, it is generally an Error object, like in exception handling.

+
+ Note: This argument should not be a promise. Specifying a rejected promise would make the rejection reason equal to the rejected promise itself, and not its rejection reason.
+
+
+
Return value
+

A rejected promise.

+

Examples

+
Components.utils.import("resource://gre/modules/Promise.jsm");
+
+// This function creates and returns a new promise.
+function promiseValueAfterTimeout(aValue, aTimeout)
+{
+  let deferred = Promise.defer();
+
+  try {
+    // An asynchronous operation will trigger the resolution of the promise.
+    // In this example, we don't have a callback that triggers a rejection.
+    setTimeout(function () {
+      deferred.resolve(aValue);
+    }, aTimeout);
+  } catch (ex) {
+    // Generally, functions returning promises propagate exceptions through
+    // the returned promise, though they may also choose to fail early.
+    deferred.reject(ex);
+  }
+
+  // We don't return the deferred to the caller, but only the contained
+  // promise, so that the caller cannot accidentally change its state.
+  return deferred.promise;
+}
+
+// This code uses the promise returned be the function above.
+let promise = promiseValueAfterTimeout("Value", 1000);
+
+let newPromise = promise.then(function onFulfill(aValue) {
+  console.log("Fulfilled with this value: " + aValue);
+}, function onReject(aReason) {
+  console.log("Rejected with this reason: " + aReason);
+});
+
+// Unexpected errors should always be reported at the end of a promise chain.
+newPromise.then(null, Components.utils.reportError);
+
+ Note: More examples for consuming promises are available in the Promise object documentation.
+

The case of unhandled rejections

+

One of the difficult problems with promises is locating uncaught rejections.

+
+

Warning: When consuming promises, you should always handle or report errors (rejection reasons). See handling errors and common pitfalls.

+
+

Rejection handlers provide information about the exact error time and location, but the handlers may sometimes be forgotten. Consider the following cases:

+
function f() {
+  return Promise.reject(new Error("BOOM!")); // If nobody catches the error, how will it be reported?
+}
+
+
+function g() {
+  return Promise.resolve().then(function() {
+    throw new Error("BOOM!"); // If nobody catches the error, how will it be reported?
+  });
+}
+
+function h() {
+  Promise.reject(new Error("BOOM!"); // Oops, we forgot to return the promise, nobody can catch it!
+}
+
+

We adopt the following strategy: if a promise is rejected at the time of its garbage-collection and if the promise is at the end of a promise chain (i.e. thatPromise.then has never been called), then we print a warning.

+
+ Note: This warning is generated some time after the error occurred, and may provide less information about the error location. It generally indicates the need to insert a proper error handler. When a proper rejection handler is used, it effectively replaces this delayed reporting.
+
let deferred = Promise.defer();
+let p = deferred.promise.then();
+deferred.reject(new Error("I am an uncaught error"));
+deferred = null;
+p = null;
+


+ In this snippet, since deferred.promise is not the last in the chain, no error will be reported for that promise. However, since p is the last promise in the chain, the error will be reported for p.
+
+ Note that this may, in some cases, cause an error to be reported more than once. For instance, consider:

+
let deferred = Promise.defer();
+let p1 = deferred.promise.then();
+let p2 = deferred.promise.then();
+deferred.reject(new Error("I am an uncaught error"));
+p1 = p2 = deferred = null;
+


+ In this snippet, the error is reported both at p1 and at p2.

+

See also

+ diff --git a/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/promise/index.html b/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/promise/index.html new file mode 100644 index 0000000000..947fd3acdc --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/promise.jsm/promise/index.html @@ -0,0 +1,226 @@ +--- +title: Promise +slug: Mozilla/JavaScript_code_modules/Promise.jsm/Promise +translation_of: Mozilla/JavaScript_code_modules/Promise.jsm/Promise +--- +

Promise对象代表暂时不可用的值。

+ +

一个已存在的promise引用可以通过不同的方式被接收,如作为异步API的返回值。一旦得到一个promise对象,就可以调用其 then() 方法,以在其值可用时或者出现异常时执行一个动作。

+ +

可以通过 new Promise() 方法创建Promise对象,当使用一个已存在的Promise对象时,不需要引入 Promise.jsm 模块。

+ +

promise内部状态可为以下三种之一:

+ + + +
+

备注: 使用promise时,应该始终对异常(拒绝理由)进行处理或报告。如果你看见了"A promise chain failed to handle a rejection"的错误信息,你可能就需要检查你的代码。参见下面的 异常处理和常见误区

+
+ +

文档约定

+ +

文档规定,完成值的类型通过尖括号内的内容指定。如 OS.File.exists 方法返回一个完成值类型为boolean的promise:

+ +
Promise<boolean> exists(string path);
+
+ +

拒绝理由可能在function文档中单独规定,除非特别指定,一般使用 Error 对象作为拒绝理由。

+ +

方法概览

+ + + + + + + + + + +
Promise then([optional] Function onFulfill, [optional] Function onReject);
Promise catch([optional] Function onReject);
+ +

构造函数

+ +

创建一个新的promise,初始化为等待状态,并提供解决函数的引用,用于改变其状态。

+ +
new Promise(executor);
+ +

参数

+ +
+
executor
+
+

该函数会马上被调用,它带有两个参数的函数对象:

+ +

 

+
+
+
executor(resolve, reject);
+ +

构造函数直到执行完成才会返回。解决函数可以在任何时间被调用,在执行过程完成前后都可以,其目标是控制promise的最终状态。如果执行过程抛出异常,异常值会被传递到reject解决函数中。

+
+
+ +

解决函数

+ +

resolve()

+ +

用特定值满足绑定的promise,或者把状态传递到一个已存在的promise。如果绑定的promise已经被解决(可能是一个值,也可能是一个rejection,或者是另一个promise),该方法不会做任何事。

+ +
+

备注: 调用该方法时,如果用一个pending状态的promise作为aValue参数,然后在该promise状态改变为fullfilled或者rejected前用另一个值再次调用,第二次调用将不会生效,因为这个绑定的promise已经被pending promise所解决了。

+
+ +
void resolve(
+  aValue
+);
+ +
参数
+ +
+
aValue  可选
+
如果这个值不是一个promise,包括  undefined, 它会变成绑定promise的实现值。如果这个值是promise,绑定promise会被传递的promise解决,并跟随所提供的promise的状态(包括任何未来的转变)。
+
+ +

reject()

+ +

用特定原因拒绝绑定的promise。如果promise已经被解决了,不管是值,拒绝,还是另一个promise,这个方法都不会做任何事。

+ +
void reject(
+  aReason
+);
+ +
参数
+ +
+
aReason 可选
+
绑定promise的拒绝原因。通常是一个 Error 对象,就像在异常处理那样,尽管理由也可以是 undefined。
+
+ +
+

备注: 该参数不应该是promise。要说明一个被拒绝的promise,应该让拒绝原因等于被拒绝promise自身,而非其拒绝原因。

+
+ +

方法

+ +

then()

+ +

一旦promise完成或被拒绝,就立即执行一个回调函数,并返回一个新的promise对象,新promise的状态取决于promise和传入的回调函数

+ +
回调函数始终会在then返回值后被调用,即使promise早已完成或已被拒绝。也可对多次调用同一个promise的then方法。所有的回调函数会按照其注册的顺序被调用。
+ +

 

+ +
+

警告: 如果 onFulfill 抛出异常,不会调用 onReject ,异常也不会被捕获和输出到控制台(你会看到一个promise chain失败错误),可以在返回的promise上注册一个错误处理函数,以处理在任一回调中出现的异常(使用 catch() 或者 then() ),来处理发生在任何一个注册回调函数的异常。

+
+ +

 

+ +
+

注意:当多次调用同一个promise的then方法,所有注册的回调函数独立执行。如,当在一个回调函数中出现异常时,不会影响后面回调函数的执行。回调函数的结果只会对其注册所使用的then方法返回的promise产生影响,每一次调用then方法返回的都是不同的promise对象。

+
+ +
Promise then(
+  Function onFulfill,
+  Function onReject
+);
+
+ +
参数
+ +
+
onFulfill {{optional_inline()}}
+
当promise完成时,会调用该函数,并将完成值作为其唯一参数传入,该函数的输出会决定新的promise的状态。如果该参数不是函数(通常为null),则由then返回的新的promise的状态为已完成,且完成值与原promise相同
+
onReject {{optional_inline()}}
+
+

当promise被拒绝时,会调用该函数,并将拒绝理由作为其唯一参数传入,且该函数的输出会决定新的promise的状态。如果该参数不是函数(通常为undefined),则由then返回的新的promise的状态为拒绝,且拒绝理由与原promise相同。

+
+
+ +
返回值
+ +

新的promise对象,初始状态为未完成,最终状态取决于回调函数的输出:

+ + + +
+

catch()

+ +

等价于调用onFulfill参数为undefined的 then() 方法。如果你链式调用then( onFulfill ).catch( onReject ),onFulfill中抛出的异常会被捕捉并传递到onReject。

+ +
Promise catch(
+  Function onReject
+);
+ +

等价于以下调用:

+ +
p.then(undefined, logError);
+p.catch(logError);
+
+ +
 
+ +

调试

+ +

按照设计,在不调用 then()的情况下,promise的即时状态和值不能通过代码同步检测到。

+ +

为了有助于调试,只有当手动检查promise时,才能看到那些不能通过代码访问的特殊属性的信息(目前由于缺少复杂的语言或调试器的支持,属性名是随机生成的)。

+ +

这些代码可访问和可审查的属性有:

+ + + +

Promise properties are visible in the debugger.Promise handlers can be watched from the Console.

+ +

示例

+ +

请看 示例 页面.

+ +

异常处理和常见误区

+ +

promise应该报告未处理的错误,除非交给其他程序处理该错误。

+ +
// ###### WRONG: Silently drops any rejection notified by "OS.File.Exists".
+OS.File.exists(path).then(exists => { if (exists) myRead(path); });
+
+// ###### WRONG: Silently drops any exception raised by "myRead".
+OS.File.exists(path).then(exists => { if (exists) myRead(path); }, Components.utils.reportError);
+
+// CORRECT (for example, might report the exception "myRead is not defined")
+OS.File.exists(path).then(exists => { if (exists) myRead(path); })
+                    .catch(null, Components.utils.reportError);
+
+// CORRECT (the function returns a promise, and the caller will handle the rejection)
+function myReadIfExists(path)
+{
+  return OS.File.exists(path).then(exists => { if (exists) myRead(path); });
+}
+ +

参见

+ + diff --git a/files/zh-cn/mozilla/javascript_code_modules/timer.jsm/index.html b/files/zh-cn/mozilla/javascript_code_modules/timer.jsm/index.html new file mode 100644 index 0000000000..83ae26b154 --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/timer.jsm/index.html @@ -0,0 +1,33 @@ +--- +title: Timer.jsm +slug: Mozilla/JavaScript_code_modules/Timer.jsm +tags: + - JavaScript + - JavaScript计时器 + - 插件 + - 模块 +translation_of: Mozilla/JavaScript_code_modules/Timer.jsm +--- +

{{ gecko_minversion_header("22") }}

+ +

Timer.jsm JavaScript模块包含纯JavaScript对setTimeoutclearTimeoutsetIntervalclearInterval功能的实现且适用于DOM窗口函数,但它还可以被那些无法访问DOM窗口的代码(如JavaScript模块框架里的脚本)使用。

+ +

 

+ +

要使用Timer.jsm,首先导入它:

+ +
Components.utils.import("resource://gre/modules/Timer.jsm");
+
+ +

然后如同在DOM窗口中一样使用setTimeout和clearTimeout,例如:

+ +
let timeoutID = setTimeout(function() { console.log("Hello!"); }, 500);
+
+clearTimeout(timeoutID);
+
+ +

类似地,你可以使用setInterval和clearInterval,比如:

+ +
let intervalID = setInterval(function() { console.log("Happening every 500ms!"); }, 500);
+
+clearInterval(intervalID);
diff --git a/files/zh-cn/mozilla/javascript_code_modules/using/index.html b/files/zh-cn/mozilla/javascript_code_modules/using/index.html new file mode 100644 index 0000000000..41fdf9970e --- /dev/null +++ b/files/zh-cn/mozilla/javascript_code_modules/using/index.html @@ -0,0 +1,194 @@ +--- +title: 使用 JavaScript 代码 modules 模式 +slug: Mozilla/JavaScript_code_modules/Using +tags: + - Add-ons + - Extensions + - Guide + - JavaScript + - XPCOM +translation_of: Mozilla/JavaScript_code_modules/Using +--- +

{{ gecko_minversion_header("1.9") }}

+ +

JavaScript code modules 在Gecko1.9中引入并被用于具备不同权限的作用域之间的代码共享。 Modules 也可以用于创建全局js单例,这在之前是通过使用XPCOM(跨平台组件模型)实现的。一个 JavaScript code module 是仅仅是位于注册位置的一些 JavaScript 代码。Module 被载入特定的js域,比如 XUL script or JavaScript XPCOM script, 通过Components.utils.import() or Components.utils["import"]().

+ +

创建 JavaScript code module

+ +

一个简单的例子my_module.jsm:

+ +
var EXPORTED_SYMBOLS = ["foo", "bar"];
+
+function foo() {
+  return "foo";
+}
+
+var bar = {
+  name : "bar",
+  size : 3
+};
+
+var dummy = "dummy";
+
+ +

可以看到 module 使用规范的js语言来创建函数,对象,常量以及其他的数据类型。 Module 还定义了一个名为 EXPORTED_SYMBOLS 的特殊数组,这个数组中的每一项都会被输出到声明中并且被注入到引入的作用域中。例如:

+ +
Components.utils.import("resource://app/my_module.jsm");
+
+alert(foo());         // displays "foo"
+alert(bar.size + 3);  // displays "6"
+alert(dummy);         // displays "dummy is not defined" because 'dummy' was not exported from the module
+
+ +
Note: When you're testing changes to a code module, be sure to change the application's build ID (e.g. the version) before your next test run; otherwise, you may find yourself running the previous version of your code module's code still.
+ +

The URL for a code module

+ +

正如你在上例中看到的, 你需要一个 URL 来导入一个代码块 (code module)。 (就像例子中的 "resource://app/my_module.jsm".)

+ +

有三种模式的URL可供选择: chrome:……({{ gecko_minversion_inline("2") }}), resource:……, 或者 file:…….

+ + + +

通过code modules共享对象

+ +

Components.utils.import() 的一个非常重要行为就是 module 加载后会被缓存起来, 并且随后的的导入不会重新加载一个新版的module, 而是使用之前缓存的版本。这就意味着当导入 module 多次时, 一个给定的 module 会被共享多次。只要引入某个module,任何对数据,对象和函数的变化都会体现在不同的引入该module的域中。比如,一个简单的module被引入到两个不同的域中,在其中一个域中做改变,另一个域也共享这种改变。如下例 :

+ +

Scope 1:

+ +
Components.utils.import("resource://app/my_module.jsm");
+
+alert(bar.size + 3);  // displays "6"
+
+bar.size = 10;
+
+ +

Scope 2:

+ +
Components.utils.import("resource://app/my_module.jsm");
+
+alert(foo());         // displays "foo"
+alert(bar.size + 3);  // displays "13"
+
+ +

这种共享行为可以被用来创建单例对象(singleton objects)并且可以被 跨windows 和 XUL script 和 XPCOM 组件所共享。

+ +

注意:引入某个module的域获得了一组该module中定义的输出符号的按值复制的副本( by-value copy )。 对这些输出符号的改变或者重新定义不会传播到其他的域中。 (虽然对象的属性会通过引用来改变。)。例子如下:

+ +

Scope 1:

+ +
Components.utils.import("resource://app/my_module.jsm");
+
+bar = "foo";
+alert(bar);         // displays "foo"
+
+ +

Scope 2:

+ +
Components.utils.import("resource://app/my_module.jsm");
+
+alert(bar);         // displays "[object Object]"
+
+ +

按值复制的主要效果就是简单类型的全局变量不会在不同的域之间共享。所以我们经常将变量放在大括号中,然后以对象的形式输出 (就像上例中的bar)。

+ +

{{ h2_gecko_minversion("Unloading code modules", "7.0") }}

+ +

Components.utils.unload() 允许你卸载之前引入的module。该方法被调用后, 指向该module的引用可以继续工作,但是后续对该module的引入,就会重新加载并重新分配指向该module的引用值。

+ +

Extending resource: URLs

+ +

{{ Gecko("2.0") }}之前,加载code module最常用的方式是—— resource: URLs. Resource URL 的基本语法如下:

+ +
resource://<alias>/<relative-path>/<file.js|jsm>
+
+ +

<alias> 是某个位置的别称,通常是一个相对于应用程序或者 XUL runtime的物理位置。这是一些由XUL runtime设置的预定义的别称:

+ + + +

<relative-path> 可以是多层的,经常是相对于alias的位置。最常见的相对路径是 "modules" 并常常被XUL Runner and Firefox使用. Code modules 是简单的js文件以 .js or .jsm 作为后缀。

+ +

<alias> 对于你的插件必须是唯一的,因为应用和其他的扩展共享同样的命名空间对所有的别称。

+ +

使用chrome.manifest

+ +

The easiest way for extensions and XUL applications to add custom aliases is by registering an alias in the chrome manifest using a line like this:

+ +
resource aliasname uri/to/files/
+
+ +

For example, if the XPI for your foo extension includes a top-level modules/ directory containing the bar.js module (that is, the modules/ directory is a sibling to chrome.manifest and install.rdf), you could create an alias to that directory via the instruction:

+ +
resource foo modules/
+
+ +

(Don't forget the trailing slash!) You could then import the module into your JavaScript code via the statement:

+ +
Components.utils.import("resource://foo/bar.js");
+
+ +

Programmatically adding aliases

+ +

Custom aliases to paths that can be represented as an {{ interface("nsILocalFile") }} can be programmatically added as well. For example:

+ +
// Import Services.jsm unless in a scope where it's already been imported
+Components.utils.import("resource://gre/Services.jsm");
+
+var resProt = Services.io.getProtocolHandler("resource")
+                      .QueryInterface(Components.interfaces.nsIResProtocolHandler);
+
+var aliasFile = Components.classes["@mozilla.org/file/local;1"]
+                          .createInstance(Components.interfaces.nsILocalFile);
+aliasFile.initWithPath("/some/absolute/path");
+
+var aliasURI = Services.io.newFileURI(aliasFile);
+resProt.setSubstitution("myalias", aliasURI);
+
+// assuming the code modules are in the alias folder itself
+
+ +

Notes

+ +

自定义 modules 和 XPCOM components

+ +

Note that prior to {{ Gecko("2.0") }} JavaScript XPCOM components are loaded before chrome registration. This means you can't use Components.utils.import() with your own resource URL at the top level in a component source. A possible solution is moving the call to Components.utils.import() into the XPCOM component constructor (discussion).

+ +

Packaging notes

+ +

It's important to note that you should not typically put your JavaScript code modules in a JAR file in your add-on. Firefox 3.6 doesn't support them at all, and there's only one case in which it's remotely useful: a Firefox 4-only add-on which must be installed unpacked. Otherwise placing code modules in a JAR file breaks compatibility unnecessarily.

+ +

Importing CommonJS modules

+ +

The JavaScript code modules described here are not the same thing as CommonJS modules, but you can import CommonJS modules into any scope where you can use Components.utils.import. Just call the following:

+ +
const { require } = Cu.import("resource://gre/modules/commonjs/toolkit/require.js", {})
+ +

This will import require() into your scope.

+ +

You can then use that to import CommonJS modules. You can import Add-on SDK modules in just the same way you could from an SDK add-on:

+ +
// import the SDK's base64 module
+
+var base64 = require("sdk/base64");
+base64.encode("hello"); // "aGVsbG8="
+ +

You can import other CommonJS modules, too, as long as you know the path to them:

+ +
// import my module
+
+var myModule = require("resource://path/to/my/module.js");
+ +

In this case, though, you might be better off creating your own loader, so you can specify the paths property yourself.

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/javascript_tips/index.html b/files/zh-cn/mozilla/javascript_tips/index.html new file mode 100644 index 0000000000..2de76fff08 --- /dev/null +++ b/files/zh-cn/mozilla/javascript_tips/index.html @@ -0,0 +1,112 @@ +--- +title: JavaScript 编程技巧 +slug: Mozilla/JavaScript_Tips +translation_of: Mozilla/JavaScript_Tips +--- +

XUL 技巧

+ + + +
var UniqueName = {
+  _privateMember: 3,
+  publicMember: "A string",
+
+  init: function UN_init() {
+    this.doSomething(this.anotherMember);
+  },
+
+  doSomething: function UN_doSomething(aParam) {
+    alert(aParam);
+  }
+};
+
+ +

XPConnect

+ + + +
if (target instanceof Components.interfaces.nsIRDFResource)
+  return target.Value;
+if (target instanceof Components.interfaces.nsIRDFLiteral)
+  return target.Value;
+return null;
+
+ + + +
var weakObserver = {
+  QueryInterface: function QueryInterface(aIID) {
+    if (aIID.equals(Components.interfaces.nsIObserver) ||
+        aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
+        aIID.equals(Components.interfaces.nsISupports))
+       return this;
+    throw Components.results.NS_NOINTERFACE;
+  },
+  observe: function observe(aSubject, aTopic, aState) {
+  }
+}
+
+ + + +

DOM 元素

+ + + +

References

+ + + +

{{ languages( { "ja": "ja/JavaScript_style_guide" } ) }}

diff --git a/files/zh-cn/mozilla/js-ctypes/index.html b/files/zh-cn/mozilla/js-ctypes/index.html new file mode 100644 index 0000000000..fc3eb24564 --- /dev/null +++ b/files/zh-cn/mozilla/js-ctypes/index.html @@ -0,0 +1,53 @@ +--- +title: js-ctypes +slug: Mozilla/js-ctypes +translation_of: Mozilla/js-ctypes +--- +

js-ctype可以让应用程序和浏览器扩展代码调用用C/C++语言编写的本地代码.C++的支持程度有限,查看{{bug("505907")}}了解更多详情.和二进制的XPCOM组件不同的是,用户编写的二进制文件可以用在多个版本的Firefox中.

+
+ 注: js-ctype只能在chrome代码中使用,也就是说,普通网页不能使用js-ctype,只有在扩展程序中可用.
+ + + + + + + +
+

文档

+
+
+ 介绍:使用js-ctype
+
+ 开始使用js-ctype.
+
+ JS-ctype参考
+
+ 关于js-ctype API的参考指南.
+
+ OS标准库
+
+ 不同操作系统的标准库文档(比如:在Windows上哪个函数存在于哪个dll文件上的文档)
+
+ 相关问题
+
+ 关于js-ctype的常见问题解答
+
+

View All...

+

代码示例

+ 添加到iPhoto +
+
+ 一个Firefox扩展,使用js-ctype调用了Mac OS X中的核心基础框架,从而在Firefox中实现了一个"添加到iPhoto"的功能.
+
+
+

社区

+
    +
  • 查看Mozilla论坛...{{DiscussionList("dev-extensions", "mozilla.dev.extensions")}}
  • +
+ + +
+

 

diff --git a/files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/ctypes/index.html b/files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/ctypes/index.html new file mode 100644 index 0000000000..e375c3df54 --- /dev/null +++ b/files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/ctypes/index.html @@ -0,0 +1,534 @@ +--- +title: ctypes +slug: Mozilla/js-ctypes/js-ctypes_reference/ctypes +translation_of: Mozilla/js-ctypes/js-ctypes_reference/ctypes +--- + + + + +
+

草案
+ 本页尚未完工.

+ +
+ +

The ctypes object contains methods and predefined data types used to create and manage a library.

+ +

方法概览

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CType ArrayType(type[, length]);
CData cast(data, type);
CType FunctionType(abi, returnType[, argType1, ...]);
CData Int64(n);
String libraryName(name);
Library open(libSpec);
CType PointerType(typeSpec);
CType StructType(name[, fields]);
CData UInt64(n);
+ +

属性

+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
errnoNumber最后一次的系统错误。与库中的errno一样,所有平台都一样,不能被设置。.
winLastErrorNumber|undefined最后一次发生的Windows 的错误。与Windows下的 GetLastError类似,只在Window下有效,不能被设置。
+ +

常量

+ +

ABI constants

+ +

这些常量是用于调用库的方法时使用。

+ + + + + + + + + + + + + + + + + + + + +
ConstantDescription
default_abiCorresponds to cdecl; standard libraries use this ABI. You also use this for all system calls on Mac OS X and Linux.
stdcall_abiUsed for calling functions declared with stdcall on Windows. These functions' names are automatically mangled for you by js-ctypes.
winapi_abi用于调用Windows 系统函数。与楼上的不同之处在于不能自己指定函数名字.
+ +

预定义的数据类型

+ +

原始类型

+ +

这些类型在所有平台的表现方式都一样

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescription
int8_tSigned 8-bit integer.
uint8_tUnsigned 8-bit integer.
int16_tSigned 16-bit integer.
uint16_tUnsigned 16-bit integer.
int32_tSigned 32-bit integer.
uint32_tUnsigned 32-bit integer.
int64_tSigned 64-bit integer.
uint64_tUnsigned 64-bit integer.
float32_t32-bit floating-point value.
float64_t64-bit floating-point value.
+ +
Note: Some 64-bit values are outside the range of numeric values supported by JavaScript. Because of this, ctypes.int64 and ctypes.uint64 do not automatically convert to JavaScript numbers. Instead, they convert to objects of the wrapper types ctypes.Int64 and ctypes.UInt64, which are JavaScript objects rather than CData objects. See 64-bit integers for details.
+ +

C语言特定类型

+ +

These types are designed to work exactly like the corresponding type on the native platform.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescription
boolA Boolean type that behaves like the corresponding C type on the platform.
shortA short integer type that behaves like the corresponding C type on the platform.
unsigned_shortAn unsigned short integer type that behaves like the corresponding C type on the platform.
intAn integer type that behaves like the int C type on the platform.
unsigned_intAn unsigned integer type that behaves like the unsigned int C type on the platform.
long +

A long integer type that behaves like the corresponding C type on the platform.

+ +
+

NOTE This automatically converts to an Int64 JavaScript object on all platforms, since it's unknown whether this is a 32-bit or 64-bit value. This is done for compatibility's sake.

+
+
unsigned_long +

An unsigned long integer type that behaves like the corresponding C type on the platform.

+ +
+

NOTE This automatically converts to a UInt64 JavaScript object on all platforms, since it's unknown whether this is a 32-bit or 64-bit value. This is done for compatibility's sake.

+
+
long_longA integer type at least 64 bits wide.
unsigned_long_longAn unsigned integer type at least 64 bits wide.
floatA floating point value that behaves like the float type on the platform.
doubleA double-precision floating point value that behaves like the double type on the platform.
+ +

字符类型

+ +

Character types are 8-bit values that behave like their C counterparts. They're similar to the int8_t and uint8_t types, except conversion is handled differently.

+ +

For example, ctypes.char.array(30)(str) converts the string str to UTF-8 and returns a new CData object of array type.

+ + + + + + + + + + + + + + + + + + + + +
TypeDescription
char +

A character type that behaves like the char C type on the platform.

+
signed_charA signed character that behaves like the char type on the platform.
unsigned_charAn unsigned character that behaves like the unsigned char type on the platform.
+ +
大小与处理器位数有关的类型
+ +

Because it's unknown whether these values will be 32-bit or 64-bit, they are not automatically converted into JavaScript numbers. Instead, these convert into ctypes.Int64 or ctypes.UInt64 JavaScript objects; see 64-bit integers for details.

+ + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescription
size_tA platform-dependent size type.
ssize_tA platform-dependent size type.
intptr_tA platform-dependent integer representation of a pointer.
uintptr_tA platform-dependent unsigned integer representation of a pointer.
+ +

JavaScript characters

+ +

16-bit C Unicode characters are handled by js-ctypes using the jschar type.

+ + + + + + + + + + + + +
TypeDescription
jscharA 16-bit unsigned character. This is different from uint16_t in that C jschar values are automatically converted into 1-character JavaScript strings. These are Unicode characters.
+ +

Special C types

+ +

These types represent C types that have special meanings.

+ + + + + + + + + + + + + + + + +
TypeDescription
void_t +

The special C type void. This can only be used as a return value type.

+ +
Note: You must use void_t, not void, since void is a keyword in JavaScript.
+
voidptr_tThe C type void *. This is a pointer to an indeterminate type of data.
+ +

Large integer types

+ +

Because JavaScript doesn't support large (64-bit) integers, js-ctypes provides two data types allowing access to 64-bit integer data.

+ + + + + + + + + + + + + + + + +
TypeDescription
Int64A JavaScript object representing a 64-bit signed integer.
UInt64A JavaScript object representing a 64-bit unsigned integer.
+ +

Methods

+ +

cast()

+ +

把某个对象转换成新的类型,返回值是拥有这些值的新类型的对象。更多了解可以查看Type casting

+ +
CData cast(
+  data,
+  type
+);
+ +
Parameters
+ +
+
data
+
要转换的数据对象。
+
type
+
转换后的数据类型,可以是 Predefined data types, 也可以是任何自定义类型。
+
+ +
Return value
+ +

拥有相同数据的,不过类型是type的一个新对象。

+ +

libraryName()

+ +

Returns the correct platform-specific filename for a given library name (e.g. libnss3.dylib for nss3 on OS X.)

+ +
String libraryName(
+  name
+);
+
+ +
Parameters
+ +
+
name
+
The name of the library.
+
+ +
Return value
+ +

String containing the platform-specific filename of the library.

+ +

open()

+ +

Opens a library, specified by a pathname. The library is loaded from the specified full path, or, if a partial path is specified, from the appropriate library directory based on the platform on which the application is running. See Library search paths for more details.

+ +
Library open(
+  libSpec
+);
+
+ +
Parameters
+ +
+
libSpec
+
The native library to open, specified as a pathname string.
+
+ +
Return value
+ +

A Library object representing the opened library.

+ +

举些栗子

+ +

Windows下使用StructType()的例子

+ +

好了,上帝说要有按钮TB_BUTTON,所以我们到MSDN上找TB_BUTTON 的结构体 (MSDN :: TB_BUTTON Structure) ,然后找到了:

+ +
typedef struct {
+  int       iBitmap;
+  int       idCommand;
+  BYTE      fsState;
+  BYTE      fsStyle;
+#ifdef _WIN64
+  BYTE      bReserved[6];
+#else
+#if defined(_WIN32)
+  BYTE      bReserved[2];
+#endif
+#endif
+  DWORD_PTR dwData;
+  INT_PTR   iString;
+} TBBUTTON, *PTBBUTTON, *LPTBBUTTON;
+ +

所以我们现在注意到64位和32位是不同的。所以我们将会指出这个不同之处,然后创造结构体。代码看起来会是这样的:

+ +
var struct_TBButton;
+if (ctypes.voidptr_t.size == 4 /* 32-bit */) {
+  struct_TBButton = ctypes.StructType('TBButton', [
+    {'iBitmap': ctypes.int},
+    {'idCommand': ctypes.int},
+    {'fbState': ctypes.unsigned_char},
+    {'fsStyle': ctypes.unsigned_char},
+    {'bReserved': ctypes.unsigned_char},
+    {'bReserved2': ctypes.unsigned_char},
+    {'dwData': ctypes.uintptr_t},
+    {'iString': ctypes.intptr_t}
+  ]);
+}
+else if (ctypes.voidptr_t.size == 8 /* 64-bit */) {
+  struct_TBButton = ctypes.StructType('TBButton', [
+    {'iBitmap': ctypes.int},
+    {'idCommand': ctypes.int},
+    {'fbState': ctypes.unsigned_char},
+    {'fsStyle': ctypes.unsigned_char},
+    {'bReserved': ctypes.unsigned_char},
+    {'bReserved2': ctypes.unsigned_char},
+    {'bReserved3': ctypes.unsigned_char},
+    {'bReserved4': ctypes.unsigned_char},
+    {'bReserved5': ctypes.unsigned_char},
+    {'bReserved6': ctypes.unsigned_char},
+    {'dwData': ctypes.uintptr_t},
+    {'iString': ctypes.intptr_t}
+  ]);
+}
+else {
+  throw new Error("wut?!");
+}
+
+console.log(struct_TBButton.size);
+// 20 on 32-bit, 32 on 64-bit if I'm not mistaken
+ +

There is another way to do this, we can use ArrayType, but example for this I don't know at this time.

+ +

Credit for this example is to nmaier (StackOverflow :: Getting TB_BUTTON is crashing and not working)

+ +

Example of cast and FunctionType on Windows

+ +
Components.utils.import("resource://gre/modules/ctypes.jsm");
+
+var kernel = ctypes.open("kernel32.dll");
+var HMODULE = ctypes.uint32_t;
+var HWND = ctypes.uint32_t;
+var LPCTSTR = ctypes.jschar.ptr;
+var LPCSTR = ctypes.char.ptr;
+var LoadLibrary = kernel.declare("LoadLibraryW", ctypes.winapi_abi, HMODULE, LPCTSTR);
+var GetProcAddress = kernel.declare("GetProcAddress", ctypes.winapi_abi, ctypes.void_t.ptr, HMODULE, LPCSTR);
+
+var hUser = LoadLibrary("user32");
+var funcPtr = GetProcAddress(hUser, "MessageBoxW");
+
+// Now we have a pointer to a function, let's cast it to the right type
+var MessageBoxType = ctypes.FunctionType(ctypes.winapi_abi, ctypes.int32_t, [HWND, LPCTSTR, LPCTSTR, ctypes.uint32_t]);
+funcPtr = ctypes.cast(funcPtr, MessageBoxType.ptr);
+funcPtr(0, "Test1", "Test2", 0);
+
+ +

Credit for this example is to Wladimir Palant (StackOverflow :: How to call a function using pointer in js-ctypes)

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/index.html b/files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/index.html new file mode 100644 index 0000000000..d451510edb --- /dev/null +++ b/files/zh-cn/mozilla/js-ctypes/js-ctypes_reference/index.html @@ -0,0 +1,96 @@ +--- +title: js-ctypes reference +slug: Mozilla/js-ctypes/js-ctypes_reference +tags: + - JavaScript + - NeedsTranslation + - TopicStub + - js-ctypes +translation_of: Mozilla/js-ctypes/js-ctypes_reference +--- + + +

This doc is a work in progress.

+ +

ctypes Reference

+ +

The ctypes object is the base of the ctypes API. It is obtained by by loading the ctypes module:

+ +

Components.utils.import("resource://gre/modules/ctypes.jsm");

+ +

You can use the ctypes object to load libraries, construct types, and perform miscellaneous tasks such as type casting. The ctypes object also provides numerous predefined types that correspond to primitives and common typedefs in C.

+ +

Working with libraries

+ +

To load a Library, use ctypes.open().

+ +

The Library object is used mostly to declare native functions provided by the library so that js-ctypes knows how to call them. See Library.declare() for instructions on how to declare these functions.

+ +

Once you have finished working with a Library, call Library.close().

+ +

Calling conventions

+ +

See ABI.

+ +

Types and data

+ +

To use js-ctypes effectively, it is important to understand the different kinds of objects that the module provides. There are three major categories:

+ +

Types

+ +

These represent a type in C, and are thus represented by CType objects. These objects have two main purposes. First, they provide a concrete representation of different data types, allowing the programmer to describe the arguments and return type of a native function (see Library.declare()).  Second, they serve as constructors to create concrete instances of the given type, i.e. CData objects.

+ +

Out of the box, js-ctypes supports a number of predefined types.

+ +

Type constructors

+ +

These are functions that define new types, and thus return a CType object. These include

+ + + +

Data

+ +

These are instances of types, represented by CData objects and instantiated by calling CType objects as functions.

+ +

These distinctions are crucial, and understanding them will alleviate much of the confusion surrounding js-ctypes. Calling a Type Constructor will return a CType. Calling a CType will return a CData. You declare the arguments and return value of a native function with CType objects. You call a native function with CData objects.

+ +

Other Features

+ +

Error-handling

+ +

js-ctypes supports both errno (on all platforms) and GetLastError (on Windows platforms).

+ +

Callbacks

+ +

You can pass regular JavaScript functions as callbacks to native functions. See the Callbacks page for details.

+ +

64-Bit integer handling

+ +

Because JavaScript Number objects can't directly represent every possible 64-bit integer value, js-ctypes provides new types for these. See Int64 and UInt64.

diff --git a/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/declaring_and_using_callbacks/index.html b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/declaring_and_using_callbacks/index.html new file mode 100644 index 0000000000..ae8223ec83 --- /dev/null +++ b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/declaring_and_using_callbacks/index.html @@ -0,0 +1,100 @@ +--- +title: Declaring and Using Callbacks +slug: Mozilla/js-ctypes/Using_js-ctypes/Declaring_and_Using_Callbacks +tags: + - 回调 + - 声明和使用回调 + - 立即调用函数表达式 +translation_of: Mozilla/js-ctypes/Using_js-ctypes/Declaring_and_Using_Callbacks +--- +

{{jsctypesSidebar("Introduction")}}

+ +

C函数偶尔将函数指针作为参数,它们通常用作回调。.在这些情况下,js-ctypes允许您传递常规JavaScript函数作为回调。这是非常强大的,因为它允许本地代码透明地调用JavaScript。

+ +
警告: 回调必须在它们注册的同一线程上调用。js-ctypes中没有并发逻辑,因此在其他线程上调用回调会导致事情崩溃。
+ +

先决条件

+ + + +

声明回调

+ +

A callback is declared by using ctypes.FunctionType. The first argument is the calling convention, the second argument is the return type, and the third is an array of arguments the callback expects.

+ +

The return type of the javascript callback must match the return type declared, otherwise js-ctypes will throw an error saying "unexpected return type".

+ +

范例

+ +

例子 1

+ +

这个回调返回bool并有两个参数。

+ +
var myFuncTypeDeclaration = ctypes.FunctionType(ctypes.default_abi, ctypes.bool, [ctypes.int, ctypes.voidptr_t]);
+
+function myJSCallback(cInt, cPtr) {
+    return true; // as the return of the FunctionType was ctypes.bool we must make our javascript callback return bool otherwise js-ctypes will throw error saying unexpected type return
+}
+
+var myCCallback = myFuncTypeDeclaration.ptr(myJSCallback);
+
+ +

例子 2

+ +

这个回调返回void,没有参数。当void是返回类型时,javascript回调一定不能返回,或者它应该返回未定义。

+ +
var myFuncTypeDeclaration = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, []);
+
+function myJSCallback() {
+    return undefined; // as the return of the FunctionType was ctypes.void_t we must return undefined OR dont return at all otherwise js-ctypes will throw an error saying unexpected type
+}
+
+var myCCallback = myFuncTypeDeclaration.ptr(myJSCallback);
+
+ +

使用回调

+ +

Since callbacks are function pointers in C, js-ctypes has special handling for function pointer types. Consider the following code:

+ +
function myJSCallback(foo, bar) { .... };
+var funcType = ctypes.FunctionType(...);
+var funcPtrType = funcType.ptr;
+var regularFuncPtr = funcPtrType();
+var callback = funcPtrType(myJSCallback);
+
+ +

js-ctypes detects that funcPtrType is a type of function pointer, and adds a special case to its constructor. In the ordinary case, invoking the type object creates a regular CData object containing a pointer to the data. However, if the first argument is a function, js-ctypes creates a special object (known internally as a CClosure) that wraps the JavaScript function within an ordinary C function. This can all be done in a single line of code, like so:

+ +
var callback = ctypes.FunctionType(...).ptr(function(...) {...});
+
+ +
Note: The use of .ptr() here isn't a method call; we're accessing a property that dynamically creates a callable object, and then invoking the result.
+ +

If two arguments are passed to the callback constructor, the second is used as the this parameter:

+ +
function myJSCallback() {
+  alert(this.message);
+};
+
+var receiver = { message: 'hi there!' };
+var callback = funcPtrType(myJSCallback, receiver); // alerts with 'hi there' when the callback is invoked
+
+ +

If three arguments are passed to the callback constructor, the third argument is used as a sentinel value which the callback returns if an exception is thrown. The sentinel value must be convertible to the return type of the callback:

+ +
function myJSCallback() {
+  throw "uh oh";
+};
+
+var callback1 = funcPtrType(myJSCallback, null, -1); // Returns -1 to the native caller when the exception is thrown.
+
+ +
Warning: You must store a reference to the callback object as long as the native code might call it. If you don't, the GC might collect the relevant data structures, and the browser will crash when native code attempts to invoke your callback.
+ +

参数和返回值

+ +

js-ctypes automatically handles the conversion between JavaScript and C value representations. Before the JavaScript callback function is invoked, js-ctypes converts the arguments passed by the caller to JavaScript values. Where possible, js-ctypes will convert arguments to primitive types. For arguments of complex types, temporary CData objects will be created.

+ +

The return value is converted in a similar manner.

diff --git a/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/index.html b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/index.html new file mode 100644 index 0000000000..6a91cfb28f --- /dev/null +++ b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/index.html @@ -0,0 +1,210 @@ +--- +title: 使用 js-ctypes +slug: Mozilla/js-ctypes/Using_js-ctypes +translation_of: Mozilla/js-ctypes/Using_js-ctypes +--- +

{{ gecko_minversion_header("2.0") }}

+ +

{{ draft() }}

+ +

在使用 js-ctypes 前,你需要导入 ctypes.jsm 代码模块(Javascript Code Module)。这非常简单,只需要在所需的 Javascript scope 内包含下面这行代码 :

+ +
Components.utils.import("resource://gre/modules/ctypes.jsm")
+ +

加载本地库

+ +

在引入上述的代码模块后,你可以调用 ctypes.open() 来加载你想使用的本地库。例如:在Windows下,你可以这样引入系统的user32库:

+ +
var lib = ctypes.open("user32.dll");
+ +

On Mac OS X, you can load the Core Foundation library from the Core Foundation framework like this:

+ +
var coreFoundation = ctypes.open("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation");
+ +

返回值是一个库对象,你可以用这个库对象去声明方法和数据类型,以供使用。

+ +
Note: js-ctypes only works with C libraries; you can't use C++ methods directly. Instead, you'll need to create a shim library that uses C functions that then call into the C++ library for you.
+ +

库搜索路径

+ +

如果你指定了库的完整路径,那么就可以直接加载该库. 否则,系统会以一套标准的流程来搜索该库。

+ +

Windows

+ +

在Window下,搜索库的顺序如下:

+ +
    +
  1. The application's directory.
  2. +
  3. The system directory.
  4. +
  5. The 16-bit system directory.
  6. +
  7. The Windows directory.
  8. +
  9. The current working directory
  10. +
  11. The directories listed in the PATH environment variable.
  12. +
+ +
Note: 该内容来至于 this article on MSDN.
+ +

用完了

+ +

当你使用完库之后,你应该通过调用库对象的close()方法来关闭它。

+ +
lib.close();
+ +

如果关闭库失败,库会在垃圾回收时,自动关闭。

+ +

使用库

+ +

你可能需要声明一些新类型。这些类型可能是简单的,也可能是像结构体这样较复杂的类型,欲知详情请查看 Declaring types。大多数情况下,你会需要 声明一个或多个函数(declare one or more functions),以供调用。 

+ +

只要你声明了类型和方法,你就可以使用他们。 实例化C 类型的数据对象和引用他们可以参考 Working with data

+ +

内存管理

+ +

If JS code creates a structure or array, that memory will be valid as long as the JS object stays alive. Pointers to that memory must be carefully managed to make sure the underlying memory is still referenced.

+ +

When binary code hands back a pointer/handle to allocated memory, the JS code must make sure to free that memory with the correct allocator. It is usually best to expose a freeing function from the binary.

+ +

保持活着的对象

+ +

The following js-ctypes objects will hold references to objects, keeping them alive. This is not an exhaustive list, but will help you understand memory management and how it affects your use of js-ctypes:

+ + + +

究竟会不会保持活着的对象

+ +

It's important to note that getting direct access to the contents of a CData object using address(), addressOfElement(), or contents, will result in a CData object that does not hold its referent alive. Be sure to hold an explicit reference to be sure the referent object doesn't get garbage collected before you're done using it.

+ +

闭包

+ +

You also need to be sure to retain references to any JavaScript code that native code may call back into. This should be obvious, but is important enough to be worth stating explicitly.

+ +

当有疑问时, malloc()

+ +

When you absolutely, positively need to keep data around, you can use malloc() to allocate it directly. This bypasses JavaScript's memory management and lets you handle memory management yourself.

+ +

示例

+ +

这些例子提供对js-ctypes使用的快速浏览。 要看更复杂的例子,请翻阅js-ctypes examples

+ +

调用 Windows 例程

+ +

这个例子演示了怎么使用ctypes来调用Win32 API。

+ +
Components.utils.import("resource://gre/modules/ctypes.jsm");
+
+var lib = ctypes.open("C:\\WINDOWS\\system32\\user32.dll");
+
+/* Declare the signature of the function we are going to call */
+var msgBox = lib.declare("MessageBoxW"/* 函数名称*/,
+                         ctypes.winapi_abi,/*ABI类型,有3种,这里指调用系统的接口*/
+                         ctypes.int32_t,/*返回值*/
+                         ctypes.int32_t,/*告警类型*/
+                         ctypes.jschar.ptr,/*告警内容*/
+                         ctypes.jschar.ptr,/*标题*/
+                         ctypes.int32_t);/*按钮类型*/
+var MB_OK = 0;
+
+var ret = msgBox(0, "Hello world", "title", MB_OK);
+
+lib.close();
+ +

第三行, 就是 user32.dll 系统库被加载的地方。第六行声明了 msgBox() 函数是一个调用系统函数MessageBoxW的方法. 第十五行调用了msgBox() ,会显示出一个告警框哦~。

+ +

最后当我们完成使用之后,千万记得用close来关闭它。

+ +

相较于给定完整的路径,通常只是给一个文件名。

+ +

关于声明函数

+ +

我们已经知道可以通过MSDN来获取MessageBox (MessageBoxW is just a unicode version of same function) 的相关信息,用以声明函数。也学习了关于lib.declare怎么使用:lib.declare. 学习了数据类型的使用: Data Types. 我们知道了它可以这样来声明:

+ +
int WINAPI MessageBox(
+  _In_opt_  HWND hWnd,
+  _In_opt_  LPCTSTR lpText,
+  _In_opt_  LPCTSTR lpCaption,
+  _In_      UINT uType
+);
+ +

所以我们阅读这个文章关于类型定义和使用: Declaring Types

+ +
var lib = ctypes.open("user32.dll");
+
+ +

甚至不用后缀:

+ +
var lib = ctypes.open("user32");
+
+ +

在 Mac OS X 上调用 Carbon 例程

+ +

This example demonstrates how to use ctypes to call a Carbon function on Mac OS X.

+ +
Note:This example will not work on 64bit OS X, you will likely need to change to the Cocoa API.
+ +
/* build a Str255 ("Pascal style") string from the passed-in string */
+
+function makeStr(str) {
+  return String.fromCharCode(str.length) + str;
+}
+
+Components.utils.import("resource://gre/modules/ctypes.jsm");
+
+var carbon = ctypes.open("/System/Library/Frameworks/Carbon.framework/Carbon");
+
+stdAlert = carbon.declare("StandardAlert",       /* function name */
+                          ctypes.default_abi,    /* ABI type */
+                          ctypes.int16_t,        /* return type */
+                          ctypes.int16_t,        /* alert type */
+                          ctypes.char.ptr,       /* primary text */
+                          ctypes.char.ptr,       /* secondary text */
+                          ctypes.uint32_t,       /* alert param */
+                          ctypes.int16_t);       /* item hit */
+
+var hit = 0;
+var msgErr = makeStr("Carbon Says...");
+var msgExp = makeStr("We just called the StandardAlert Carbon function from JavaScript!");
+
+var err = stdAlert(1, msgErr, msgExp, 0, hit);
+
+carbon.close();
+ +

The makeStr() function is a utility routine that takes as input a standard JavaScript string and returns a Carbon-style "Pascal" string, which is a length byte followed by the characters of the string itself. Note that this only works correctly if the string is in fact under 256 characters; if it's longer, this will fail spectacularly.

+ +

In line 9, the Carbon library is loaded from the system's Carbon framework.

+ +

Line 11 declares the stdAlert() function, which will call the Carbon StandardAlert routine. It uses the default ABI, returns a 16-bit integer (which is a Carbon OSErr value), and accepts an integer (the alert type), two strings, a pointer to a parameter block, which we aren't using, and another integer, which is used to return the hit item. See Apple's documentation for StandardAlert for details.

+ +

After that, we simply set up our parameters by using makeStr() to generate the two Str255 strings we need, then call stdAlert(), which produces the following alert window:

+ +

ctype-mac-dialog.png

+ +

The last thing we do is call carbon.close() to close the library when we're done using it.

+ +

在 Linux/POSIX 上调用 LibC 例程

+ +

This example demonstrates how to use ctypes to call a libc function on Linux.

+ +
/* import js-ctypes */
+Components.utils.import("resource://gre/modules/ctypes.jsm");
+
+/* Open the library */
+try {
+    /* Linux */
+    var libc = ctypes.open("libc.so.6");
+} catch (e) {
+    /* Most other Unixes */
+    libc = ctypes.open("libc.so");
+}
+
+/* Import a function */
+var puts = libc.declare("puts",             /* function name */
+                        ctypes.default_abi, /* call ABI */
+                        ctypes.int,       /* return type */
+                        ctypes.char.ptr);   /* argument type */
+
+var ret = puts("Hello World from js-ctypes!");
+wge
diff --git a/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/memory_management/index.html b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/memory_management/index.html new file mode 100644 index 0000000000..291ef8205d --- /dev/null +++ b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/memory_management/index.html @@ -0,0 +1,88 @@ +--- +title: 内存管理 +slug: Mozilla/js-ctypes/Using_js-ctypes/Memory_Management +tags: + - GC + - js-ctypes + - 内存管理 +translation_of: Mozilla/js-ctypes/Using_js-ctypes/Memory_Management +--- + + +

内存管理

+ +

If JS code creates a structure or an array, that memory will be valid as long as the JS object stays alive. Pointers to that memory must be carefully managed to make sure the underlying memory is still referenced.

+ +

When binary code hands back a pointer/handle to allocated memory, the JS code must make sure to free that memory with the correct allocator. It is usually best to expose a freeing function from the binary.

+ +

保持 objects 活着

+ +

The following js-ctypes objects will hold references to objects, keeping them alive. This is not an exhaustive list, but will help you to  understand memory management and how it affects your use of js-ctypes:

+ + + +

什么不保持 objects 活着

+ +

It's important to note that getting direct access to the contents of a CData object using address()addressOfElement(), or contents, will result in a CData object that does not hold its referent alive. Be sure to hold an explicit reference so that the referent object doesn't get into garbage collection, before you're done using it.

+ +

闭包

+ +

You also need to be sure to retain references to any JavaScript code that native code may call back into. This should be obvious, but is important enough to be worth stating explicitly.

+ +

有疑问时, malloc()

+ +

When you need to keep data around, you can use malloc() to allocate it directly. This bypasses JavaScript's memory management and lets you handle memory management yourself.

+ + diff --git a/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/working_with_arraybuffers/index.html b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/working_with_arraybuffers/index.html new file mode 100644 index 0000000000..521fa9030f --- /dev/null +++ b/files/zh-cn/mozilla/js-ctypes/using_js-ctypes/working_with_arraybuffers/index.html @@ -0,0 +1,212 @@ +--- +title: Working with ArrayBuffers +slug: Mozilla/js-ctypes/Using_js-ctypes/Working_with_ArrayBuffers +translation_of: Mozilla/js-ctypes/Using_js-ctypes/Working_with_ArrayBuffers +--- + + +

导读

+ +

类型转换页的指针类型部分解释了此操作的基本原理。第二个代码示例提供了操作的具体说明。

+ +

ArrayBuffer 是简单的字节数组 ,这种js 类型 等同于 ctypes.uint8_t.array(###) (ctypes.unsigned_char are also ctypes.uint8_t).

+ +

bug 732936 包括使用ArrayBuffer的讨论.

+ +

This feature is based on the following work:

+ +

https://dxr.mozilla.org/mozilla-central/source/js/src/ctypes/CTypes.cpp#3080

+ +

https://dxr.mozilla.org/mozilla-central/source/js/src/vm/ArrayBufferObject.cpp#1301

+ +

Example 1 - Image Data

+ +

The following example illustrates how to transfer a byte array pointed by ctypes.uint8_t.ptr to ImageData of canvas. This example is based on the fact that the ImageData returned from CanvasRenderingContext2D.getImageData is a Uint8ClampedArray view for an ArrayBuffer.

+ +

The following codeblock provides a basic example of getting and setting Uint8ClampedArray and ArrayBuffer of ImageData:

+ +
// context is a CanvasRenderingContext2D of some canvas
+var imageData = context.getImageData(x, y, w, h);
+var array = imageData.data; // array is a Uint8ClampedArray
+var buffer = imageData.data.buffer; // buffer is a ArrayBuffer
+
+// incomingBuffer is a TypedArray
+var imageData2 = context.createImageData(w, h);
+imageData2.data.set(incomingBuffer);
+
+ +

Further, if you have a byte array pixelBuffer, and you need to create ImageData from it. The data property holds an array of bytes.

+ +

We start with the following:

+ +
// pixelBuffer is a pointer to a RGBA pixel buffer of 400x400 image.
+pixelBuffer.toString(); // "ctypes.uint8_t.ptr(ctypes.UInt64("0x352e0000"))"
+
+var imgWidth = 400;
+var imgHeight = 400;
+var myImgDat = new ImageData(imgWidth, imgHeight);
+
+ +

Method 1: Passing ArrayType CData to Uint8ClampedArray.prototype.set

+ +

One method is to get into a js-ctypes array, and then set it into the ImageData, as illustrated by the following code example.

+ +
// Cast pointer to array, to pass to Uint8ClampedArray.prototype.set.
+var casted = ctypes.cast(pixelBuffer.address(), ctypes.uint8_t.array(myImgData.data.length).ptr).contents; // myImgDat.data.length is imgWidth * imgHeight * 4 because per pixel there is r, g, b, a numbers
+casted.toString(); // "ctypes.uint8_t.array(640000)([45, 66, 135, 255, 99, 86, 55, 255, .......... ])"
+myImgDat.data.set(casted);
+
+ +

The ctypes.cast takes a couple of milliseconds, however, the myImgDat.data.set takes up to 800ms for a size of 52,428,800 (which is image size of 1280 x 1024 pixels). So, for the size of 640,000 it takes about 98ms.

+ +

Method 2: Manually Handled

+ +

Another strategy is to handle it manually, as illustrated by the following code example:

+ +
var casted = ctypes.cast(pixelBuffer.address(), ctypes.uint8_t.array(myImgData.data.length).ptr).contents; // myImgDat.data.length is imgWidth * imgHeight *4 because per pixel there is r, g, b, a numbers
+
+/** METHOD A **/
+for (var nIndex = 0; nIndex < casted.length; nIndex = nIndex + 4) { // casted.length is same as myImgDat.data.length
+    var r = casted[nIndex];
+    var g = casted[nIndex + 1];
+    var b = casted[nIndex + 2];
+    var a = casted[nIndex + 3];
+
+    myImgDat.data[nIndex] = r;
+    myImgDat.data[nIndex + 1] = g;
+    myImgDat.data[nIndex + 2] = b;
+    myImgDat.data[nIndex + 3] = a;
+}
+
+
+/***** OR DO THE BELOW WHICH USES THE .set METHOD *****/
+
+/** METHOD B **/
+var normalArr = [];
+for (var nIndex = 0; nIndex < cast.length; nIndex = nIndex + 4) { // casted.length is same as myImgDat.data.length
+    var r = casted[nIndex];
+    var g = casted[nIndex + 1];
+    var b = casted[nIndex + 2];
+    var a = casted[nIndex + 3];
+
+    normalArr.push(r);
+    normalArr.push(g);
+    normalArr.push(b);
+    normalArr.push(a);
+}
+myImgDat.data.set(normalArr);
+
+ +

The preceding example, however, does not take advantage of Method 1, but instead manually goes through the array and sets the ImageData array. The cast takes a couple of milliseconds, roughly the same as Method 1. However, the manual Method A, in the preceding example, takes ~1300 ms. Method B takes ~1400 ms, for an array length of 52,428,800 (which is image size of 1280 x 1024 pixels).

+ +

Method 3: Transfer byte array by calling memcpy

+ +

This is the recommended method, as it only takes a couple of milliseconds, even for large arrays. Notice that the following example does not cast the pixelBuffer. Passing an ArrayBuffer object to pointer type will pass the pointer to buffer (Based on https://dxr.mozilla.org/mozilla-central/source/js/src/ctypes/CTypes.cpp#3080). Further, it returns dataPointer, and there is no extra allocation (Based on https://dxr.mozilla.org/mozilla-central/source/js/src/vm/ArrayBufferObject.cpp#1301).

+ +
var lib;
+switch (OS.Constants.Sys.Name.toLowerCase()) {
+    case 'winnt':
+    case 'winmo':
+    case 'winnt': //windows
+        lib = ctypes.open('msvcrt');
+        break;
+    case 'darwin': // mac
+        lib = ctypes.open('libc.dylib');
+        break;
+    case 'freebsd':
+        lib = ctypes.open('libc.so.7');
+        break;
+    case 'openbsd':
+        lib = ctypes.open('libc.so.61.0');
+        break;
+    case 'android':
+    case 'sunos':
+    case 'netbsd':
+    case 'dragonfly':
+        lib = ctypes.open('libc.so');
+        break;
+    case 'linux':
+        lib = ctypes.open('libc.so.6');
+        break;
+    case 'gnu/kfreebsd':
+        lib = ctypes.open('libc.so.0.1');
+        break;
+    default:
+        //assume unix
+        try {
+            lib = ctypes.open(ctypes.libraryName('c'));
+        } catch (ex) {
+            throw new Error('I dont know where to memcpy is defined on your operating system, "' + OS.Constants.Sys.Name + '"');
+            lib.close();
+        }
+}
+
+try {
+    var memcpy = lib.declare('memcpy', OS.Constants.Sys.Name.toLowerCase().indexOf('win') == 0 ? ctypes.winapi_abi : ctypes.default_abi,
+        ctypes.void_t, // return
+        ctypes.void_t.ptr, // *dest
+        ctypes.void_t.ptr, // *src
+        ctypes.size_t // count
+    );
+} catch (ex) {
+    throw new Error('I dont know where to memcpy is defined on your operating system, "' + OS.Constants.Sys.Name + '"');
+    lib.close()
+}
+
+memcpy(myImgDat.data, pixelBuffer, myImgDat.data.length); // myImgDat.data.length is imgWidth * imgHeight *4 because per pixel there is r, g, b, a numbers
+
+lib.close();
+
+ +

See Also

+ + diff --git a/files/zh-cn/mozilla/localization/faq/index.html b/files/zh-cn/mozilla/localization/faq/index.html new file mode 100644 index 0000000000..33cecd28f0 --- /dev/null +++ b/files/zh-cn/mozilla/localization/faq/index.html @@ -0,0 +1,17 @@ +--- +title: 本地化 FAQ +slug: Mozilla/Localization/FAQ +tags: + - 本地化 +translation_of: Mozilla/Localization/FAQ +--- +

 

+ +

本页列出了可能不需要完整页面的调整和提示。 有关通用本地化的更多详细文档,请参阅我们的 本地化 页面。
+
+ 我如何在实体中保留空白?
+         如果你真的想保留空格,或者你正在寻找一个不间断的空间,你可以通过&ua0; 或 \ua0 到DTD和属性文件,
+ 如何在 .properties 条目中不显示变量?
+         您可以简单地将该值设置为零宽度,即使用%1$0.S

+ +

 

diff --git a/files/zh-cn/mozilla/localization/index.html b/files/zh-cn/mozilla/localization/index.html new file mode 100644 index 0000000000..b74757ccc1 --- /dev/null +++ b/files/zh-cn/mozilla/localization/index.html @@ -0,0 +1,20 @@ +--- +title: 参与 Mozilla 本地化工作 +slug: Mozilla/Localization +tags: + - Landing + - Localization + - Mozilla + - NeedsTranslation + - TopicStub + - Translation + - l10n +translation_of: Mozilla/Localization +--- +

Localization (L10n) is the process of translating software user interfaces from one language to another and adapting it to suit a foreign culture. These resources are for anyone with an interest in the technical aspects involved in localization. They are for developers and all contributors

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/localization/l10n_style_guide/index.html b/files/zh-cn/mozilla/localization/l10n_style_guide/index.html new file mode 100644 index 0000000000..86e242c5ca --- /dev/null +++ b/files/zh-cn/mozilla/localization/l10n_style_guide/index.html @@ -0,0 +1,482 @@ +--- +title: Mozilla 本地化风格指南 +slug: Mozilla/Localization/L10n_Style_Guide +translation_of: Mozilla/Localization/L10n_Style_Guide +--- +

前言

+ +
      风格指南定义风格指南用于定义我们用来评价翻译质量的标准 Mozilla 和 Mozilla 的本地化社区定义的规则组成,主要针对如何以最佳的方式翻译 Mozilla 的产品网站和其他项目。风格指南可以用来同时翻译和评估翻译质量。通过遵循这些规则,翻译人员会更容易得到高质量的翻译,便于更好的展示 Mozilla 的价值观和文化。这里我们列出国际上其他组织制定的一些风格指南的例子:
+ + + +
本风格指南分为两个主要部分:第一部分特定语言相关,必须由每个 Mozilla 的本地化社区(包括特定的语言风格,术语和单位)来定义的规则;第二个是由 Mozilla 为所有语言定义的一般规则,可以帮助你较好的翻译(包括准确度和流畅性原则
+ +

 

+ +

简体中文相关 Mozilla 风格

+ +
    +
+ +
+

基本要求

+ +
    +
  1. +

    准确表述原文的意思、情感、立场、价值观;

    +
  2. +
  3. +

    既要避免翻译后反而模糊,也要避免翻译无须翻译的词语,力求浅显易懂;

    + +
      +
    • +

      若有译法尚有争议的单词,应采用最常使用的译法,并在词语后以全角括号标注英文

      +
    • +
    +
  4. +
  5. +

    中文应该意思清晰且符合中文表达习惯,同一句里不要重复出现相同主语(如“if you forget your password”应译为“如果您忘记了密码”),且应适当减少数词与量词

    +
  6. +
  7. +

    明显是美国文化的,或在中国大陆当代文化下难以理解的,可用相近的中国大陆文化代替,但不能与第 1 点抵触;

    +
  8. +
  9. +

    不必字对字、句对句翻译,原文如果表达不清晰,中文应该意译,并且应根据上下文和注释进行推断并填补或删减相应的信息,但不能与第 1 点抵触;

    +
  10. +
  11. +

    情况 5 不能太多;

    +
  12. +
  13. +

    对同样短语的翻译,前后必须一致,可利用 Pontoon 的 Translation Memory 查看以往译法,也可参考其他工具

    +
  14. +
  15. +

    对用户和开发者称“您”,对职员和志愿者称“你”,若需轻松的语气则一律用“你”;

    +
  16. +
  17. +

    不要使用机器翻译的成果来提交,也就是说您可以使用 Google Translate 来帮助您理解内容,但是不能不经考虑就把其自动翻译的结果放在翻译里;

    +
  18. +
  19. +

    若产品内显示的中文换行不理想,应适当增删文字,在网页上也可使用 \n 强制换行。

    +
  20. +
  21. +

    不太有把握的,请大胆地通过这些方式进行讨论。

    +
  22. +
+
+ +
 
+ +
+

术语表

+ +
这里我们列出一些可参考的 软件/互联网 相关的术语和定义的列表:
+ + + +
使用对应术语翻译的时候,请注意要保持一致性。而且要注意避免以下几点:
+ + + +
 
+ +

词语形式

+ +
复数 
+ +
Pontoon 上 zh-CN 区分单复数。汉语由于没有区分单复数形式,所以一般单数和复数翻译成一样即可。但有时区分单复数会带来更好效果。
+ +
 
+ +
特殊符号
+ +
 
+ +
+

常用的有以下几个:

+ +
    +
  • +

    \n   换行

    +
  • +
  • +

    \t   水平制表符

    +
  • +
  • +

    \v  竖直制表符

    +
  • +
+ +

您不需要将同样数量的格式标记放在翻译中,但是如果它们之一有在原文开始或者结束位置的时候,您必须在翻译中使之包含在对应的开始或者结束之处。

+ + +

如果要显示非转义字符,则需要使用 \ 来表明取消转义,如 " (半角双引号)表示字符串的开始或者结束,如果要在内容中使用该符号,则需输入 \",还可以参考以下例子:

+ +

----------------------------------------------------------------

+ +

\"\\t\"

+ +

----------------------------------------------------------------

+ +

在运行时显示的结果是 "t"

+ + +

(2)XML 中的角括号和“&”号

+ +

有一些模块中 XML 被频繁地使用,XML 将“<”“>”和“&”视为保留字符,您不能将其直接添加到翻译中。必须将其实体以下面的形式表示:

+ +

&lt 代表 <; &gt 代表 >; &amp 代表 &。

+ + +

(3) TRUE 和 FALSE

+“TRUE”和“FALSE”多不要翻译它们。如果程序读不到正确的值,可能会出现问题。
+ +
 
+ +
标点的使用
+ +

一般的原则是:除了小括号、省略号和破折号保留不变以外,都应该使用中文(全角)标点符号。英文标点符号后方常常跟随有一个半角空格,请在翻译成中文标点符号时将其去除。

+ + +
    +
  1. +

    英文中的 , 在中文中可能是 ,或者 、

    +
  2. +
  3. +

    英文中的 . 在中文中应该是 ,或者 。,视上下文而定,多数是 。

    +
  4. +
  5. +

    英文中的 \"%s\" 在 GUI 程序中应该翻译为 “%s”, 而不是 \"%s\" 或者 \“%s\”,而且后者是不符合换码序列要求的。即在 GUI 程序中`something' 和 'something' 以及 \"something\" 都应该翻译为 “某事”

    +
  6. +
  7. +

    英文中的 : 应该翻译为:(全角)而不是 :(半角), 而作为分隔符时(例如时间),: 保留为英文(半角)的, 因为这个时候不是标点符号

    +
  8. +
  9. +

    英文中的 ( ) 应该一般都翻译成全角小括号( )。

    +
  10. +
  11. +

    英文中的“…”或“...”,应该保持不变,前者等价于半个全角中文省略号

    +
  12. +
  13. +

    英文中的 -- 应该保持不变。由于全角破折号 —— 兼容性不好,有时显示为两个方格,所以不再使用。

    +
  14. +
  15. +

    其他标点符号的使用参见中华人民共和国 GB/T 15834-2011

    +
  16. +
+ +
 
+ +
空格
+ +
+

为了美观,通常建议在中文与英文、中文与阿拉伯数字、英文与阿拉伯数字之间加入一个半角空格。例如:

+ +

----------------------------------------------------------------

+ +

原文 "Installing driver for %1"

+ +

翻译 "正在安装 %1 的驱动程序"

+ + +

原文 ""

+ +

"Parameter start_num specifies the character at which to start the search. "

+ +

"The first character is character number 1. If start_num is omitted, it is "

+ +

"assumed to be 1."

+ +

翻译 ""

+ +

"参数 start_num 指定开始搜索的字符位置。第一个字符序号为 1。如果省略 "

+ +

"start_num,默认它为 1。"

+ +

----------------------------------------------------------------

+ + +

对于小括号和全角双引号,其两侧不加空格:

+ +

----------------------------------------------------------------

+ +

原文 "Original idea and author (KDE1)"

+ +

翻译 "原始创意和作者(KDE1)"

+ + +

原文 ""

+ +

"The APM Management subsystem seems to be disabled.\n"

+ +

"Try executing \"apm -e 1\" (FreeBSD) and see if \n"

+ +

"that helps.\n"

+ +

翻译 ""

+ +

"APM 管理子系统似乎被禁用了。\n"

+ +

"试试执行“apm -e 1”(FreeBSD)并看看\n"

+ +

"是否有用。\n"

+ +

----------------------------------------------------------------

+ + +

包含 XML/HTML 标签的条目,如要在标签中的内容两侧添加空格,请把空格置于标签外侧,否则空格可能显示不出来。

+ +

----------------------------------------------------------------

+ +

这是 &lt;b&gt;HTML&lt;/b&gt; 的语法手册

+ +

----------------------------------------------------------------

+
+ +
 
+ +
单项中的快捷字符
+ +

  与 Gnome 或者 KDE 菜单不同,Firefox 中的菜单快捷键无需添加到翻译的字符串中。

+ +

例如:

+ +

KDE 菜单:

+ +

----------------------------------------------------------------

+ +

msgid "C&lear"

+ +

msgstr "清除(&L)"

+ +

----------------------------------------------------------------

+ +

而 Firefox 中,直接翻译为 "清除"即可,不可添加 "(&L)"。

+ +
翻译中参数的位置
+ +

有时候原来的参数顺序不符合中文的语法,一方面, 翻译可以通过调整副词、语序等手法来符合中文习惯,另外一方面,在必要的情况下,需要改变参数的位置,例如:

+ +

----------------------------------------------------------------

+ +

原文 "%1$S articles match rule %2$S"

+ +

翻译 "匹配规则 %2$S 的文章有 %1$S 个"

+ +

----------------------------------------------------------------

+ + +

即用 %1$S、%2$S、%3$S 等符号标明参数在原文里出现的位置。同时,任何一个参数的顺序进行了调整,则在这一句译文中所有参数都必须注明原文位置,否则无法通过格式检查。

+ +
关于换行
+ +

对于很长的译文,就涉及到了换行问题。多数情况下没有限制,因为不影响最终的显示效果,只要阅读起来方便就行。下面几种格式都是正确的:

+ +

----------------------------------------------------------------

+ +

原文 ""

+ +

"Preview failed: neither the internal KDE PostScript viewer (KGhostView) nor "

+ +

"any other external PostScript viewer could be found."

+ +

翻译 ""

+ +

"预览失败:找不到 KDE 内建的 PostScript 查看器(KGhostView)或其它外部"

+ +

"的 PostScript 查看器。"

+ + +

原文 ""

+ +

"Preview failed: neither the internal KDE PostScript viewer (KGhostView) nor "

+ +

"any other external PostScript viewer could be found."

+ +

翻译 "预览失败:找不到 KDE 内建的 PostScript 查看器(KGhostView)或其它外部"

+ +

"的 PostScript 查看器。"

+ + +

原文 ""

+ +

"Preview failed: neither the internal KDE PostScript viewer (KGhostView) nor "

+ +

"any other external PostScript viewer could be found."

+ +

翻译 ""

+ +

"预览失败:找不到 KDE 内建的 PostScript 查"

+ +

"看器(KGhostView)或其它外部"

+ +

"的 PostScript 查看器。"

+ +

----------------------------------------------------------------

+ +
 
+ +
关于时间的翻译
+ +

鉴于关于日期和时间的译法十分复杂,现在将国家标准中有关规定简要介绍一下,并给出推荐译法。

+ +

国标 GB/T 7408-94《数据元和交换格式 信息交换 日期和时间表示法》

+ +

1994-12-06 发布,1995-08-01 实施   国家技术监督局发布

+ +

本标准等效采用国际标准 ISO 8601-1988《数据元和交换格式  信息交换 日期和时间表示法》

+ + +

以下是最需要注意的几个要点:

+ +

(1) 在日期格式中不能出现空格,即“2003 年”这样的格式是不符合国标的。

+ +

(2) 表示日期时,必须按照年月日的顺序;年份一般用四位数字,而月、日必须使用带前导零的两位数字;必须使用“-”作为分隔符,或完全不使用分隔符。 即“2004-01-03”或“20040103”来表示 2004年1月3日。

+ +

(3) 表示时间时,时、分、秒都必须使用两位数字,中间用“:”(半角括号)分隔,或完全不使用分隔符。小时计法采用 24 小时制,不区分上下午。

+ +

(4) 日期和时间写在一起的时候,应先写日期再写时间。在日期和时间都不使用分隔符的情况下,在中间添加字母“T”进行分隔,即“19850412T101530”。

+ + +

时间的表示方法同 date 命令的表示方法,现将常见的几个对应其含义列表如下:

+ +
    +
  1. +

    %%     一个 % 字符

    +
  2. +
  3. +

    %A      星期几(如“星期一”)

    +
  4. +
  5. +

    %B      月份(如“八月”)

    +
  6. +
  7. +

    %d      日期(00-31)

    +
  8. +
  9. +

    %D      日期,格式等于 %m/%d/%y (例如:08/25/09)

    +
  10. +
  11. +

    %F      日期,格式等于 %Y-%m-%d (例如:2009-08-25)

    +
  12. +
  13. +

    %g      ISO-8601 格式年份的最后两位(例如:09)

    +
  14. +
  15. +

    %G      ISO-8601 格式年份(例如:2009)

    +
  16. +
  17. +

    %H      小时(00-23)

    +
  18. +
  19. +

    %i       小时(00-12)

    +
  20. +
  21. +

    %m     月份(01-12)

    +
  22. +
  23. +

    %M     分钟(00-59)

    +
  24. +
  25. +

    %n      换行

    +
  26. +
  27. +

    %p      显示“上午”或者“下午”两个字

    +
  28. +
  29. +

    %S      秒(00-60)

    +
  30. +
  31. +

    %t       制表符

    +
  32. +
  33. +

    %T      时间,等于 %H:%M:%S

    +
  34. +
  35. +

    %x      日期(例如:12/31/99)

    +
  36. +
  37. +

    %X      时间(例如:23:13:48)

    +
  38. +
  39. +

    %y      年份的最后两位(例如:09)

    +
  40. +
  41. +

    %Y      年份(例如:2009)

    +
  42. +
+ +

 

+ +

参考文档: 开源软件简体中文翻译指南

+ +

 

+
+ +

Mozilla l10n 通用翻译风格

+ +

准确度

+ +

意译

+ +
翻译的重中之重是达意。译者需要首先本身理解文字的确切意思,然后尽量寻找自己语言中最贴切的文字,尽量不增加或删减任何多余的意义。 有时,要找到完全一致的翻译可能会很困难,当发生这样的情况时,多问问自己如下这些问题:
+ + + +

有些时候,旧的翻译记录以及机器翻译工具可能会提供错误的建议。如果您的翻译流程中使用了其中任何一种,请确保在提交翻译之前检查并修正。要完全避免文字直译,特别是对那些看起来在中英文之间相似,但是实际上意思可能不同的词。

+ +

不应翻译的内容

+ +
快捷键以及访问键
+ +

在 Firefox 或其他软件中,均可以使用键盘快捷键来调用特定的命令。例如,可以使用组合键 CTRL+O (Mac 为 Cmd+O  ) 打开一个文件。加速键则因操作系统而异,但是对应的字符一般也是可本地化的。这通常被称为快捷键或者命令键。例如,打开文件… 菜单通常对应:

+ +
<!ENTITY openFileCmd.label "Open File…">
+<!ENTITY openFileCmd.accesskey "O">
+<!ENTITY openFileCmd.commandkey "o">
+ +

命令键保存在键 openFileCmd.commandkey 中。一般情况下不应修改这个字符,因为通常即使不同的操作系统也使用一样的快捷键(例如 CTRL+S 保存)或者类似的软件中同样的功能都会使用同样的快捷键(例如 CTRL+T 打开新的标签页)。除非该字符在对应的键盘布局中没有,我们才需对其进行修改。例如,意大利语中字母 [ 需要使用 ALT+è 组合键,因此这样的命令键就无法正常工作。

+ +

在如上的代码片段中也为 打开文件定义了一个访问键,访问键用于使用键盘访问图形界面中的项目,例如:如果 文件 菜单定义了访问键 F,同时  打开文件… 菜单定义了访问键 O,那么你可以按 ALT+F 来访问文件菜单,然后按 O 键来打开一个文件。

+ +

访问键以及命令键,在 .dtd 和 .properties 文件中通常使用单独的行进行定义,而且在键 ID 中通常会包含 .accesskey 字符串。

+ +
变量
+ +

变量不应该被翻译。变量通常以特殊字符开始(例如 $,#,% 等),并后面无空格紧跟着词。例如:$BrandShortName 和 %S。如有需要,你可以移动变量在字符串中的位置。

+ +
品牌,版权以及商标
+ +

品牌名称,以及版权声明和商标不应被翻译,或者使用非拉丁语字符替换。详情请查看 Mozilla 品牌指南

+ +

翻译特定文化相关的引用

+ +

有时候,Mozilla 产品或网站项目(例如 市场宣传)中可能会引用美国文化相关的一些概念。翻译这些内容的时候,最好是找到自己文化中等同的一些文化概念。例如,一个美国人可能会说“干的漂亮,本垒打!”,本垒打指的是垒球中的成功范例。对应较贴切的翻译就是要使用类似等同的比喻,以足球为例,就可以翻译为“干的漂亮,好球!”。

+ +

法律相关内容

+ +

Mozilla 项目也常包含一些法律内容,如最终用户许可,隐私政策等等。在进行这些内容的翻译时,要特别注意按 Mozilla 的文化以及价值观,确保翻译的精确,流畅,谨慎的进行审核。

+ +

流畅

+ +
 
+ +
要做到流畅的翻译,翻译者不应仅根据语言对应的标准语法,标点和拼写规则,还需尽量避免出现二义性,不一致性,难以理解等问题。
+ +
 
diff --git a/files/zh-cn/mozilla/localization/localizing_extension_descriptions/index.html b/files/zh-cn/mozilla/localization/localizing_extension_descriptions/index.html new file mode 100644 index 0000000000..9b9bfcac8f --- /dev/null +++ b/files/zh-cn/mozilla/localization/localizing_extension_descriptions/index.html @@ -0,0 +1,60 @@ +--- +title: 本地化 +slug: Mozilla/Localization/Localizing_extension_descriptions +tags: + - Localization +translation_of: Mozilla/Localization/Localizing_extension_descriptions +--- +

     

+
+

本地化 是指将软件的用户界面从一种语言翻译成另一种语言并且适应相应文化习惯的过程。 下面这些是关于基于 Mozilla 的 程序/扩展 本地化的资源。

+
+ + + + + + + +
+

文摘

+
+
+ 创建一个新的本地化
+
+ 创建新的本地化的志愿者必读.
+
+
+
+ XUL 教程:本地化
+
+ 本地化 XUL 应用程序的XUL 教程部分.
+
+
+
+ 编写本地化代码
+
+ 给予编程者玩好本地化的最好的文章和指南.
+
+
+
+ 本地化扩展描述
+
+ 要本地化一个扩展的描述(在【扩展】窗口中显示在扩展名称下面的字符串),你需要使用特殊的首选项键去忽略在你的 install.rdf 文件中指定的描述. 这篇文章包含如何修改这个首选项键的说明.
+
+

查看全部...

+
+

其他页面

+ +

相关文章

+
+
+ Extensions, XUL
+
+

查看全部...

+
+

 

diff --git a/files/zh-cn/mozilla/mercurial/basics/index.html b/files/zh-cn/mozilla/mercurial/basics/index.html new file mode 100644 index 0000000000..26c4d7cb03 --- /dev/null +++ b/files/zh-cn/mozilla/mercurial/basics/index.html @@ -0,0 +1,56 @@ +--- +title: Mercurial basics +slug: Mozilla/Mercurial/Basics +translation_of: Mozilla/Mercurial/Basics +--- +

我要跟你啰嗦一些关于Mercurial的东西,它可以帮助您少入坑。本页言辞较喷且是以生存型为导向(什么是生存型请自行渡娘)。但我依然坚信Mercurial要比CVS强。——Jorendorff于2008年5月12日16:06(PDT)

+ +

期望什么

+ +

Mercurial is not CVS. The commands aren't the same. The concepts aren't the same. How is Mercurial different from CVS?

+ +

This gun is loaded. You can shoot yourself in the foot. You can lose work. The tool tries to protect you, but it can happen anyway. The two common failure modes are: (a) you run a command without knowing what it's going to do; (b) you hg commit or hg qrefresh with a mistaken understanding of the state of your working directory. So you accidentally commit changes that you didn't want to commit; or you accidentally commit a broken merge; etc. Often it's not immediately obvious that anything is wrong.

+ +

Forewarned is forearmed. Don't do these things. Don't run commands without knowing what they're going to do—hg help is your friend. Don't commit without diffing and thinking. And don't let yourself get into "play mode" and stop paying attention to the fact that what you're playing with is your own uncommitted work.

+ +

Mercurial is not magic dust. Mercurial is flexible, powerful, and fun. It lets you attempt stuff you never would have tried in CVS. But of course not everything turns out to have been a good idea. (For example, we tried sharing patch queues. It sort of sucked.)

+ +

避免入坑

+ +

Use the latest stable release of Mercurial.

+ +

Learn how to get your bearings. Use read-only commands (like hg status, hg head, hg parents, hg log, hg diff, hg outgoing) to check the status of your repository. This is a key skill.

+ +

Configure a merge program and make sure you know how to use it. DO IT NOW. Otherwise you will likely screw up your repository at some point.

+ +

Mercurial doesn't leave conflict markers in your files; instead, it wants you to fix the conflicts immediately, using a merge program (like kdiff3) which it can launch for you.

+ +

This can be error-prone. By default, Mercurial uses the first merge program it finds on your system, and merge programs can have a learning curve. Mercurial does not do a good job of detecting busted merges and refusing to proceed, so just by closing a window you can unwittingly put yourself in a bad state. Bad merges may lead to seemingly inexplicable Mercurial behavior in the future.

+ +

If a merge fails, make sure Mercurial knows that it has failed. When you're first learning the ropes, merges often go wrong. You might see this message:

+ +
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+There are unresolved merges, you can redo the full merge using:
+  hg update -C 2
+  hg merge 1
+
+ +

This means some conflicts weren't resolved during the merge. If you don't know exactly what they are and how to fix them, use that hg update -C command to tell Mercurial that you've given up on that merge.

+ +

If you don't, Mercurial won't know, and the next time you commit, it'll make a merge changeset. This is bad. The result can look a lot like accidentally destroying a bunch of work, actually, but the damage can be undone.

+ +

If hg parents shows two parents, you're merging.

+ +

If you use Mercurial Queues, back up your work. hg qrefresh destructively replaces the old patch with the new one! Use hg qinit -c to create a separate backup repository for your patches and hg commit --mq -m backup regularly.

+ +

Don't use Mercurial Queues in a repository that someone might pull from since applied (non-public) patches would also be pulled.

+ +

Recovering

+ +

握了个草! Mercurial 这么宝——Mercurial剁你手!

+ +

千万别轻易试玩(亵玩)Mercurial哦. 想想你的手,想想你的臂膀,别呀,你还可有个完整.

+ +

寻求帮助IRC频道. 在 Mozilla IRC 或 #mercurial on freenode 中输入 #hg 或者 #developers .

+ +

 

diff --git a/files/zh-cn/mozilla/mercurial/index.html b/files/zh-cn/mozilla/mercurial/index.html new file mode 100644 index 0000000000..64029a1d1e --- /dev/null +++ b/files/zh-cn/mozilla/mercurial/index.html @@ -0,0 +1,43 @@ +--- +title: Mercurial +slug: Mozilla/Mercurial +tags: + - Developing Mozilla + - Mercurial + - NeedsTranslation + - TopicStub +translation_of: Mozilla/Mercurial +--- +

 

+ +
+

Please refer to Mercurial For Mozillians at ReadTheDocs for current best-practices around Mercurial, including many helpful extra tools and guidelines that make using Mercurial fast and easy.

+
+ +

Mercurial (also known as "hg"), is the distributed version control software used for the development of Firefox, Thunderbird, and the shared Gecko core. It replaced CVS after Mozilla 1.9 was branched.

+ +

hg is the Mercurial command-line tool, Hg being the chemical symbol for the element mercury.

+ +

Installation, configuration, and getting the source

+ +

See Installing Mercurial for installation and configuration tips.

+ +

See Getting Mozilla Source Code Using Mercurial for getting a tree to build.

+ +

Learning to use Mercurial

+ +

If you are new to Mercurial, you should start with the official guide.

+ +

Then, move on to Mercurial basics and Mercurial FAQ and the version control tool docs for Mozilla-centric Mercurial information.

+ +

Further reading

+ +

The Mercurial tag lists the Mercurial-related articles on MDN.

+ +

And on wiki.mozilla.org, these helpful pages:

+ + diff --git a/files/zh-cn/mozilla/mercurial/installing_mercurial/index.html b/files/zh-cn/mozilla/mercurial/installing_mercurial/index.html new file mode 100644 index 0000000000..1ea2cc22e3 --- /dev/null +++ b/files/zh-cn/mozilla/mercurial/installing_mercurial/index.html @@ -0,0 +1,145 @@ +--- +title: Installing Mercurial +slug: Mozilla/Mercurial/Installing_Mercurial +translation_of: Mozilla/Mercurial/Installing_Mercurial +--- +

{{ Note('If you have not yet read the Mercurial basics do so now, or see Mercurial for other resources.') }}

+ +
+

Please refer to Mercurial For Mozillians at ReadTheDocs for current best-practices around Mercurial, including many helpful extra tools and guidelines that make using Mercurial fast and easy.

+
+ +

安装

+ +

See Installing Mercurial from the Mozilla Version Control Guide.

+ +

基本设置

+ +

You should configure Mercurial before submitting patches to Mozilla.

+ +

If you will be pulling the Firefox source code or one of the derived repositories, the easiest way to configure Mercurial is to run the mercurial-setup mach command:

+ +
./mach mercurial-setup
+ +

This command starts an interactive wizard that will help ensure your Mercurial is configured with the latest recommended settings. This command will not change any files on your machine without your consent.

+ +

If you don't have the Firefox source code available, you should edit your Mercurial configuration file to look like the following:

+ +
[ui]
+username = Your Real Name <user@example.com>
+merge = your-merge-program (or internal:merge)
+
+[diff]
+git = 1
+showfunc = 1
+unified = 8
+
+[defaults]
+commit = -v
+
+ +

On Windows, these settings can be added to $HOME\.hgrc or $HOME\Mercurial.ini, or, if you'd like global settings, C:\mozilla-build\hg\Mercurial.ini or C:\Program Files\Mercurial\Mercurial.ini. On UNIX-like systems, they should be in your $HOME/.hgrc file.

+ +

You can configure the editor to use for commit messages using the editor option in the [ui] section or by setting the EDITOR environment variable.

+ +

If you are trying to access the repository through a proxy server, see these instructions.

+ +

其他设置

+ +

Merge 合并程序

+ +

After installing, choose a merge program. Seriously. Do it now. If you don't, Mercurial will choose one for you and spring it on you when you least expect it.

+ +

A reasonable thing to do is to set ui.merge=internal:merge in the Mercurial configuration file (see below), which makes Mercurial try to merge changes and add the conflict markers (a la CVS) to the files that couldn't be merged.

+ +

Under Ubuntu, you can install meld package, then in in the Mercurial configuration file (see below) set ui.merge=meld

+ +

You can see the list of merge conflicts by looking for "merging ... failed!" in the update output.

+ +

配置 kdiff3 作为合并工具

+ +

If you're on Linux and you have kdiff3 installed, you probably want to configure kdiff3 as a merge tool.  (It's better than meld because it will actually resolve a bunch of the conflicts without prompting you, generally quite accurately.)  You can do this by adding the following lines (which come from contrib/mergetools.hgrc in the Mercurial distribution):

+ +
[merge-tools]
+kdiff3.args=--auto -L1 base --L2 local --L3 other $base $local $other -o $output
+kdiff3.regkey=Software\KDiff3
+kdiff3.regappend=\kdiff3.exe
+kdiff3.fixeol=True
+kdiff3.gui=True
+
+
+ +

Extensions

+ +

There's a number of extensions you can enable. See http://mercurial.selenic.com/wiki/UsingExtensions. Almost everyone should probably enable the following:

+ + + +

These can all be turned on by just adding this to your .hgrc file:

+ +
[extensions]
+color =
+rebase =
+histedit =
+progress =
+transplant =
+pager =
+
+ +

In addition, there are some 3rd party extensions that are incredibly useful for basic development:

+ +
+
mozext
+
Mozilla-specific functionality to aid in developing Firefox/Gecko.
+
trychooser
+
Automatically creates a try commit message and then pushes changes to Mozilla's Try infrastructure. Just run: +
hg trychooser
+
+
qimportbz
+
Import patches from Bugzilla. Creates a filename and commit message for you based on the bug's metadata. +
hg qimport bz://1234567
+  
+
+
bzexport
+
Export patches to Bugzilla. There are quite a few optional arguments here to create new or update existing bugs with the attment, as well as auto matically request reviews. Type hg help bzexport for a full list but the basic syntax is: +
hg bzexport -i 1234567
+
+
+ +

Installing these is fairly easy. You'll just need to find a place on your system to store the extensions, and clone the extension repos into it:

+ +
hg clone https://bitbucket.org/edgimar/crecord
+hg clone https://bitbucket.org/sfink/mqext
+hg clone https://hg.mozilla.org/users/robarnold_cmu.edu/qimportbz
+git clone https://github.com/pbiggar/trychooser
+
+ +

And then add then to your .hgrc file

+ +
[extensions]
+qcrecord =  /path/to/crecord/crecord
+mqext =  path/to/mqext
+qimportbz =  path/to/qimportbz
+trychooser = path/to/trychooser/trychooser
+
+ +

Configuring the try repository

+ +

If you have access to the try server you may want to configure Mercurial so you can refer to it simply as "try", since it can be useful from all your trees.  This can be done by adding this to your ~/.hgrc (or Mercurial.ini):

+ +

 

+ +
[paths]
+try = ssh://hg.mozilla.org/try/
+
+ +

You can also configure short names like this that are specific to a particular repository by adding a [paths] section to the .hg/hgrc file within a repository.  There are two magic names, "default" and "default-push", which are used as the default push/pull targets.  (If "default" is specified and "default-push" is not, "default" is used for both.)

+ +

Alternatively, you can install the trychooser extension (older version).

diff --git a/files/zh-cn/mozilla/mfbt/index.html b/files/zh-cn/mozilla/mfbt/index.html new file mode 100644 index 0000000000..a8b644e23f --- /dev/null +++ b/files/zh-cn/mozilla/mfbt/index.html @@ -0,0 +1,48 @@ +--- +title: Mozilla Framework Based on Templates (MFBT) +slug: Mozilla/MFBT +translation_of: Mozilla/MFBT +--- +

The Mozilla Framework Based on Templates ("mfbt") is the central repository for macros, functions, and data structures used throughout Mozilla code, including in the JavaScript engine. Its code resides in the {{ Source("mfbt/") }} source directory, but headers within it should be included using paths like "mozilla/StandardInteger.h". It is fairly new, so its functionality is currently sparse. Feel free to file bugs to add new functionality to it, or to move existing functionality into it, as needed. 

+ +

mfbt code goes to some length to document all its interfaces in comments, including examples when possible. It also attempts to define its functionality in well-named files, such that simply skimming the contents of {{ Source("mfbt/") }} will quickly suggest the relevant header to examine. Therefore this document primarily attempts to direct readers to the correct file to read those comments. Feel free to file a documentation bug if you think this approach could be improved, and feel free to make improvements to this document if you see them.

+ +

Functionality

+ +

Types and type manipulation

+ +

{{ Source("mfbt/StandardInteger.h", "StandardInteger.h") }} implements the <stdint.h> interface. (The <stdint.h> standard header is not available on all platforms and so cannot be used directly. This header also provides a useful "hook" for embeddings that must customize the types underlying the fixed-size integer types.)

+ +

{{ Source("mfbt/Types.h", "Types.h") }} includes StandardInteger.h and further provides size_t.

+ +

{{ Source("mfbt/CheckedInt.h", "CheckedInt.h") }} implements checked integers. They behave like integers, but safely check for integer overflow and divide-by-zero. Useful for input validation.

+ +

{{ Source("mfbt/FloatingPoint.h", "FloatingPoint.h") }} provides various operations for examining and working upon double-precision floating point values, and for producing various special floating point values.

+ +

Core

+ +

{{ Source("mfbt/Types.h", "Types.h") }} further provides macros to define imported and exported C symbols.

+ +

{{ Source("mfbt/Attributes.h", "Attributes.h") }} implements various function and class attribute macros. The function macros control inlining, note whether a function returns, and enforce various C++-related restrictions on inheritance and use. The class macros permit controlling the inheritability of a class.

+ +

{{ Source("mfbt/Likely.h", "Likely.h") }} provides MOZ_LIKELY and MOZ_UNLIKELY macros to annotate conditions with their expected truthiness.

+ +

{{ Source("mfbt/Util.h", "Util.h") }} implements various other bits of useful functionality. (This header will likely be further split up so that its functionality is less grab-bag.)

+ +

Debugging

+ +

{{ Source("mfbt/Assertions.h", "Assertions.h") }} provides assertion macros in implementing runtime assertions and compile-time assertions.

+ +

{{ Source("mfbt/GuardObjects.h", "GuardObjects.h") }} provides macros which can be used to annotate an RAII-style guard class, so that any attempt to create an unnamed temporary for it will assert. (An unnamed temporary lives for a shorter period of time than the scope where it's found, so it usually isn't what was desired.)

+ +

Data structures

+ +

{{ Source("mfbt/LinkedList.h", "LinkedList.h") }} implements a type-safe doubly-linked list class. Most new code should use this rather than {{ Source("nsprpub/pr/include/prclist.h", "PRCList") }}.

+ +

{{ Source("mfbt/RangedPtr.h", "RangedPtr.h") }} implements RangedPtr, a smart pointer template whose value may be manipulated only within a range specified at construction time, and which may be dereferenced only at valid locations in that range.  This pointer is a useful way to expose access to values within an array.

+ +

{{ Source("mfbt/RefPtr.h", "RefPtr.h") }} implements various smart pointer templates to simplify reference counting of values of particular classes.

+ +

{{ Source("mfbt/Scoped.h", "Scoped.h") }} implements scope-based resource management, to simplify the task of cleaning up resources when leaving a scope.

+ +

{{ Source("mfbt/ThreadLocal.h", "ThreadLocal.h") }} implements thread-local storage, aka "TLS", also called thread-specific storage. It should be used only for static-storage-duration variables, such as global variables or static class members.

diff --git a/files/zh-cn/mozilla/mozilla_on_github/index.html b/files/zh-cn/mozilla/mozilla_on_github/index.html new file mode 100644 index 0000000000..a215aef188 --- /dev/null +++ b/files/zh-cn/mozilla/mozilla_on_github/index.html @@ -0,0 +1,121 @@ +--- +title: GitHub上的Mozilla项目 +slug: Mozilla/Mozilla_on_GitHub +translation_of: Mozilla/Mozilla_on_GitHub +--- +

Although Mozilla's major, core projects are located on the Mozilla Mercurial server, such as mozilla-central, there are a number of tools, services, and so forth whose code is hosted on GitHub. This article offers a quick guide to getting started with Mozilla code on GitHub as well as a list of many of the most interesting GitHub repositories containing Mozilla project code.

+ +

起步

+ +

You can look at code on GitHub without an account; that's the first thing you should know. To do more—that is, to contribute to the code or to fork it and start your own project based on Mozilla-related code—you'll need a GitHub account. You can learn more about setting up an account on the GitHub site.

+ +

Most Mozilla project code is located in repositories owned by the user Mozilla. That's a great place to start looking for any projects not listed below.

+ +

项目

+ +

This list covers the larger-scale and more important projects we have hosted on GitHub. It's not an authoritative, complete list, since it's hard to keep track of all the smaller projects that crop up (and even, at times, the large ones!). You can see a complete list of Mozilla projects on GitHub.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Project nameDescription
PDF.jsA Portable Document Format (PDF) reader written entirely in JavaScript.
ShumwayShumway is a Flash VM and runtime written in JavaScript.
addon-sdkThe Mozilla Add-on SDK.
asknotThe What Can I Do For Mozilla web site, which helps you figure out how you can contribute to Mozilla.
bugsahoyA Web page to help new Mozilla contributors find bugs to work on.
bugzilla-dashboardA convenient dashboard to help you get an overview of your bugs.
codefirefoxThe CodeFirefox site, with videos and tutorials about how to contribute to the Firefox project and Mozilla code in general.
dxrAn intelligent tool for browsing source code.
emscriptenThe Emscripten LLVM-to-JavaScript compiler.
fxdt-adaptersThe Firefox Developer Tools Adapter lets you debug various remote targets from the Firefox Developer Tools.
gecko-devA read-only mirror of the Mercurial repositories used for Mozilla private code.
kitsuneKitsune is the platform that drives the Mozilla support web site, SUMO.
kumaThe Django project that powers this site (MDN).
mdnCode samples for the MDN Web site.
mozbrickThe Mozilla Brick project.
mozilla-B2GThe Firefox OS project.
mozilla-appmakerThe Appmaker project -- a Web tool to let non-programmers create apps.
mozilla-l10nScripts and tools used by the localization drivers.
mozilla-metricsTools used to collect metrics about Mozilla code.
mozilla-servicesMozilla cloud services projects.
opennewsThe Knight-Mozilla Open News project, helping the journalism/technology community do great work through shared knowledge and code.
rust-langRust编程语言, 为安全地进行高并发编码而设计!
servoThe next-generation rendering engine.
+ +

 

diff --git a/files/zh-cn/mozilla/mozilla_persona/index.html b/files/zh-cn/mozilla/mozilla_persona/index.html new file mode 100644 index 0000000000..583cb6cb5a --- /dev/null +++ b/files/zh-cn/mozilla/mozilla_persona/index.html @@ -0,0 +1,155 @@ +--- +title: Mozilla Persona +slug: Mozilla/Mozilla_Persona +tags: + - Mozilla + - Persona +--- +
+

保持联系或获取帮助!

+

关注 我们的 blog,加入 我们的邮件列表,或在 IRC 中的 #identity 找到我们。

+
+

Mozilla Persona 是一个用于 web 的完全去中心化且安全的验证系统,基于开放 BrowserID 协议。Mozilla 当前管理一个 Persona 相关的一个可选的、中心化服务的一小组套件。

+

为什么你和你的站点应该使用 Persona?

+
    +
  1. Persona 完全消除了站点特定的密码, 把用户和网站从创建、管理和安全存放密码的责任中解放出来。
  2. +
  3. Persona 易于使用。只需点击两次,一个 Persona 用户可以登入到一个诸如 VoostThe Times Crossword 的新站点,绕开了账户创建相关的摩擦。
  4. +
  5. Persona 易于实现。开发人员在一个下午就可以把 Persona 添加到站点上。
  6. +
  7. 最好的是,不会被锁定。 开发人员获取所有他们用户的验证过的邮件地址,而用户可以在 Persona 上使用任何邮件地址。
  8. +
  9. Persona 基于 BrowserID 协议构建。一旦流行的浏览器供应商实现了 BrowserID,它们不再需要依赖于 Mozilla 来登入。
  10. +
+

继续阅读来开始!

+
+ 注意:Persona 在活跃开发中。关注我们的 blog 来了解新特性,或加入我们的邮件列表来提供反馈!
+

在你的站点上使用 Persona

+ + + + + + + + + + + +
+

准备开始

+
+
+ 为什么使用 Persona?
+
+ 了解在你的站点上支持 Persona 的原因和它与其它身份验证系统的区别。
+
+ 快速安装
+
+ 一份快捷的攻略,展示了如何向你的网站中添加 Persona。
+
+
+

Persona API 参考

+
+
+ navigator.id API 参考
+
+ navigator.id 对象的参考,web 开发者可以用此来把 Persona 继承到站点中。
+
+ 验证 API 参考
+
+ 建立在 https://verifier.login.persona.org/verify 上的远程验证 API 的参考。
+
+
+

指导

+
+
+ 安全考虑
+
+ 确保 Persona 部署安全的实践和技术。
+
+ 浏览器兼容性
+
+ 准确获知哪些浏览器支持 Persona。
+
+ 国际化
+
+ 了解 Persona 如何处理不同的语言。
+
+
+

资源

+
+
+ 库和插件
+
+ 寻找你偏好的编程语言、web 框架、博客或是内容管理系统(CMS)的即插库。
+
+ Persona cookbook
+
+ Persona 站点的示例源代码。包括 PHP、Node.JS 等等的片段。
+
+ 品牌资源
+
+ 登入按钮和其它向用户表现 Persona 的图形。
+
+
+

 

+ + + + + + + +
+

给身份提供者的信息

+

如果你是一个电子邮件提供商或另一个身份提供服务,翻阅下面的链接来获知如何成为一个 Persona 身份提供者。

+
+
+ IdP 概述
+
+ Persona 身份提供者的高层视角。
+
+ 实现一个 IdP
+
+ 成为一个 IdP 的详细技术细节指导。
+
+ 开发提示
+
+ 开发一个新的身份提供者的一系列开发提示和技巧。
+
+ .well-known/browserid
+
+ .well-known/browserid 文件的结构和用途概述,这个文件被 IdPs 用于通知它们支持这个协议。
+
+
+

Persona 项目

+
+
+ 术语表
+
+ BrowserID 和 Persona 定义的术语。
+
+ FAQ
+
+ 常见问题的回答。
+
+ 协议概述
+
+ 底层 BrowserID 协议的中等技术概述。
+
+ 加密
+
+ 一瞥 Persona 和 BrowserID 背后的密码学概念。
+
+ 协议规范
+
+ 这里是深层技术细节。
+
+ Persona 网站
+
+ 要让 Persona 运作, 我们在https://login.persona.org 建立了三个服务:一个备用身份提供者、一个可迁移的 {{ domxref("navigator.id") }} API 实现以及一个身份断言验证服务。
+
+ Persona 源码
+
+ Persona 网站背后的源码托管在 GitHub 的一个仓库上。欢迎提交补丁!
+
+
+

 

diff --git a/files/zh-cn/mozilla/participating_in_the_mozilla_project/index.html b/files/zh-cn/mozilla/participating_in_the_mozilla_project/index.html new file mode 100644 index 0000000000..1de9ed81ad --- /dev/null +++ b/files/zh-cn/mozilla/participating_in_the_mozilla_project/index.html @@ -0,0 +1,94 @@ +--- +title: 加入Mozilla项目 +slug: Mozilla/Participating_in_the_Mozilla_project +translation_of: Mozilla/Participating_in_the_Mozilla_project +--- +

如果你有兴趣帮助解决bug或者参与Mozilla平台的代码工作,这里是找到为你指出正确方向的文档的地方。

+ + + + + + + +
+

通用话题

+
+
+ Mozilla开发者手册
+
+ 为Mozilla代码库做贡献的开发向导和提示。
+
+ Mozilla源代码
+
+ 通过下载或者版本控制来获取Mozilla代码的方法,以及怎样将你的代码加入到代码树中。
+
+ 编译
+
+ 编译Mozilla项目(包括Firefox和Thunderbird)。
+
+ Mozilla平台
+
+ 关于Mozilla平台的信息,包括所有的API接口和所包含的技术,以及如何在你的自己的项目中使用它们。
+
+ Mozilla文档
+
+ 帮助我们创建和改进Mozilla及开放互联网的文档。
+
+ 调试
+
+ 调试Mozilla代码时有用的提示和参考。
+
+ 质量保证
+
+ 关于测试及bug跟踪的相关信息。
+
+ 本地化
+
+ 关于翻译Mozilla项目及其文档等到各种语言。
+
+

项目主页

+
+
+ Thunderbird
+
+ Mozilla的邮件客户端。
+
+ Sunbird
+
+ Mozilla的日历项目。
+
+
+

工具

+
+
+ Bugzilla
+
+ Bugzilla数据库用来跟踪Mozilla项目的相关事件。
+
+ MXR
+
+ 基于Web浏览及搜索Mozilla源代码库。
+
+ Bonsai
+
+ Bonsai工具帮助你找到谁在何时对代码库进行了什么修改。
+
+ Tinderbox
+
+ Tinderbox显示树的状态(无论当前是否编译成功)。 在check-in和check-out之前都要进行检查以确认你正工作在一个working tree上。
+
+ 崩溃跟踪
+
+ SocorroTalkback提供崩溃跟踪服务。
+
+ 性能跟踪
+
+ Mozilla项目的性能跟踪。
+
+ 开发者论坛
+
+ 一个有针对性主题的论坛。在这里你可以讨论开发的各种事件。
+
+
+

  {{ languages( { "en": "en/Participating_in_the_Mozilla_project", "ja": "ja/Participating_in_the_Mozilla_project"} ) }}

diff --git a/files/zh-cn/mozilla/performance/about_colon_memory/index.html b/files/zh-cn/mozilla/performance/about_colon_memory/index.html new file mode 100644 index 0000000000..6710a2441b --- /dev/null +++ b/files/zh-cn/mozilla/performance/about_colon_memory/index.html @@ -0,0 +1,144 @@ +--- +title: 'about:memory' +slug: 'Mozilla/Performance/about:memory' +translation_of: 'Mozilla/Performance/about:memory' +--- +

about:memory 是一个 Firefox 内置的特殊页面,你可以在此查看、保存、载入和比较 Firefox 内存使用的详细测量数据。你还可以执行其他与内存有关的操作,例如执行 GC 和 CC、转储 GC 和 CC 日志记录,以及转储 DMD 报告。这个页面在所有版本当中都可以找到,并且无需任何准备工作就可以使用。

+

如何生成内存报告

+

假设你要测量 Firefox 的内存使用情况(也许你是想自己研究,或者是他人要你用 about:memory 生成“内存报告”以便帮你分析问题),你都可以按照下列步骤进行操作。

+ +

请注意,上述方式生成的数据会包含一些与隐私有关的内容,例如你此时所打开网页的完整清单。如果你不想分享这些信息,可以在点击 "Measure and save..." 或 "Measure..." 按钮之前先勾上 “anonymize” 复选框。这样就会去除所有隐私相关的数据,虽然这有可能不太便于他人帮你分析内存占用情况。

+

从文件载入内存报告

+

从文件载入内存报告最简单的方式是点击 "Load..." 按钮,你也可以点击 "Load and diff..." 按钮来找出两个内存报告文件间的不同之处。

+

单个内存报告文件也可以直接被自动载入,只需在 about:memory 后面加上一个文件查询字符串,例如:

+
about:memory?file=/home/username/reports.json.gz
+
+

这种方式在载入 Firefox OS 设备上已转储的内存报告文件时尤为实用。

+

内存报告所保存的文件使用的是用 gzip 压缩的 JSON 格式。这些文件既可以直接载入,也可以解压后再载入。

+

分析内存报告

+

你在 about:memory 页面中看到的几乎所有事物都有着相应的工具提示来解释。将鼠标悬停在任意按钮上就可以看到关于其作用的描述。将鼠标悬停在任意测量数据上就可以查看对它所指内容的描述。

+

测量数据基础介绍

+

大多数测量数据的单位都是字节,少部分使用的是计数值或百分比。

+

测量数据大多以树形结构呈现,例如:

+
 585 (100.0%) -- preference-service
+ └──585 (100.0%) -- referent
+    ├──493 (84.27%) ── strong
+    └───92 (15.73%) -- weak
+        ├──92 (15.73%) ── alive
+        └───0 (00.00%) ── dead
+
+

叶节点代表实际的测量数据值,每个内部节点的值都是它子节点值的总和。

+

使用树形结构是为了让测量数据可以根据需要进一步分成类、子类、子类的子类……,直至任意深度。单个树形下的所有测量数据都不会有任何重叠。

+

树的路径可以使用 '/' 来分隔,例如,preference/referent/weak/dead 表示上述例子中直到最终叶节点的整个路径。

+

单击每个子树都可以收起或展开它们。如果你发现某些树所占空间特别大,可以试试先收起所有隶属于它的子树,然后根据需要逐步展开。

+

区段

+

内存报告是在每个进程的基础上显示,每个区段为一个进程。每个进程中的测量数据都包含以下一些子区段。

+

Explicit Allocations

+

这个区段包含单个叫做 "explicit" 的树,它测量的是通过显式调用堆积分配(heap allocations)函数和非堆积分配函数方式分配的所有内存,堆积分配函数像是 malloc 和 new,而非堆积分配函数可以是 mmap 和 VirtualAlloc。

+

下面的例子是一个打开了 cnn.com、techcrunch.com 和 arstechnica.com 这几个标签页的浏览器会话。为了更好地呈现,我们将部分子树展开,其他部分全部收起。

+
191.89 MB (100.0%) -- explicit
+├───63.15 MB (32.91%) -- window-objects
+│   ├──24.57 MB (12.80%) -- top(http://edition.cnn.com/, id=8)
+│   │  ├──20.18 MB (10.52%) -- active
+│   │  │  ├──10.57 MB (05.51%) -- window(http://edition.cnn.com/)
+│   │  │  │  ├───4.55 MB (02.37%) ++ js-compartment(http://edition.cnn.com/)
+│   │  │  │  ├───2.60 MB (01.36%) ++ layout
+│   │  │  │  ├───1.94 MB (01.01%) ── style-sheets
+│   │  │  │  └───1.48 MB (00.77%) -- (2 tiny)
+│   │  │  │      ├──1.43 MB (00.75%) ++ dom
+│   │  │  │      └──0.05 MB (00.02%) ── property-tables
+│   │  │  └───9.61 MB (05.01%) ++ (18 tiny)
+│   │  └───4.39 MB (02.29%) -- js-zone(0x7f69425b5800)
+│   ├──15.75 MB (08.21%) ++ top(http://techcrunch.com/, id=20)
+│   ├──12.85 MB (06.69%) ++ top(http://arstechnica.com/, id=14)
+│   ├───6.40 MB (03.33%) ++ top(chrome://browser/content/browser.xul, id=3)
+│   └───3.59 MB (01.87%) ++ (4 tiny)
+├───45.74 MB (23.84%) ++ js-non-window
+├───33.73 MB (17.58%) ── heap-unclassified
+├───22.51 MB (11.73%) ++ heap-overhead
+├────6.62 MB (03.45%) ++ images
+├────5.82 MB (03.03%) ++ workers/workers(chrome)
+├────5.36 MB (02.80%) ++ (16 tiny)
+├────4.07 MB (02.12%) ++ storage
+├────2.74 MB (01.43%) ++ startup-cache
+└────2.16 MB (01.12%) ++ xpconnect
+

要弄懂这里的所有细节需要一些专业知识才行,不过还是有几点内容需要指出。

+ +

部分附加组件的内存占用也会被识别出来,如下例所示。

+
├───40,214,384 B (04.17%) -- add-ons
+│   ├──21,184,320 B (02.20%) ++ {d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}/js-non-window/zones/zone(0x100496800)/compartment([System Principal], jar:file:///Users/njn/Library/Application%20Support/Firefox/Profiles/puna0zr8.new/extensions/%7Bd10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d%7D.xpi!/bootstrap.js (from: resource://gre/modules/addons/XPIProvider.jsm:4307))
+│   ├──11,583,312 B (01.20%) ++ jid1-xUfzOsOFlzSOXg@jetpack/js-non-window/zones/zone(0x100496800)
+│   ├───5,574,608 B (00.58%) -- {59c81df5-4b7a-477b-912d-4e0fdf64e5f2}
+│   │   ├──5,529,280 B (00.57%) -- window-objects
+│   │   │  ├──4,175,584 B (00.43%) ++ top(chrome://chatzilla/content/chatzilla.xul, id=4293)
+│   │   │  └──1,353,696 B (00.14%) ++ top(chrome://chatzilla/content/output-window.html, id=4298)
+│   │   └─────45,328 B (00.00%) ++ js-non-window/zones/zone(0x100496800)/compartment([System Principal], file:///Users/njn/Library/Application%20Support/Firefox/Profiles/puna0zr8.new/extensions/%7B59c81df5-4b7a-477b-912d-4e0fdf64e5f2%7D/components/chatzilla-service.js)
+│   └───1,872,144 B (00.19%) ++ treestyletab@piro.sakura.ne.jp/js-non-window/zones/zone(0x100496800)
+

此外还有一些内容需要指出:

+ +

Other Measurements

+

这个区段包含多个树,包括与 "explicit" 树中测量数据相交叉(cross-cut)的树。比如说,在 "explicit" 这个树中所有 DOM 和 layout 测量数据会被分解到每个窗口当中,而在 "Other Measurements" 区段中,这些测量数据又会被汇总成整个浏览器,如下例所示。

+
26.77 MB (100.0%) -- window-objects
+├──14.59 MB (54.52%) -- layout
+│  ├───6.22 MB (23.24%) ── style-sets
+│  ├───4.00 MB (14.95%) ── pres-shell
+│  ├───1.79 MB (06.68%) ── frames
+│  ├───0.89 MB (03.33%) ── style-contexts
+│  ├───0.62 MB (02.33%) ── rule-nodes
+│  ├───0.56 MB (02.10%) ── pres-contexts
+│  ├───0.47 MB (01.75%) ── line-boxes
+│  └───0.04 MB (00.14%) ── text-runs
+├───6.53 MB (24.39%) ── style-sheets
+├───5.59 MB (20.89%) -- dom
+│   ├──3.39 MB (12.66%) ── element-nodes
+│   ├──1.56 MB (05.84%) ── text-nodes
+│   ├──0.54 MB (02.03%) ── other
+│   └──0.10 MB (00.36%) ++ (4 tiny)
+└───0.06 MB (00.21%) ── property-tables
+

但是这个区段部分树的测量数据又不会与 "explicit" 树的相交叉,比如上面提到的 "preference-service" 这个例子当中的树。

+

最后,在这个区段结尾处是其他单独的测量数据,如下例所示。

+
    0.00 MB ── canvas-2d-pixels
+    5.38 MB ── gfx-surface-xlib
+    0.00 MB ── gfx-textures
+    0.00 MB ── gfx-tiles-waste
+          0 ── ghost-windows
+  109.22 MB ── heap-allocated
+        164 ── heap-chunks
+    1.00 MB ── heap-chunksize
+  114.51 MB ── heap-committed
+  164.00 MB ── heap-mapped
+      4.84% ── heap-overhead-ratio
+          1 ── host-object-urls
+    0.00 MB ── imagelib-surface-cache
+    5.27 MB ── js-main-runtime-temporary-peak
+          0 ── page-faults-hard
+    203,349 ── page-faults-soft
+  274.99 MB ── resident
+  251.47 MB ── resident-unique
+1,103.64 MB ── vsize
+

这里有一些值得注意的测量数据:

+ +

System

+

这个区段只会在 Firefox OS 当中出现,它包含取自操作系统的对整个设备测量的数据。除此以外,该区段还有助于详细了解整个设备的内存是如何被使用的。

diff --git a/files/zh-cn/mozilla/performance/index.html b/files/zh-cn/mozilla/performance/index.html new file mode 100644 index 0000000000..dac76d9a75 --- /dev/null +++ b/files/zh-cn/mozilla/performance/index.html @@ -0,0 +1,138 @@ +--- +title: Performance +slug: Mozilla/Performance +tags: + - NeedsTranslation + - Performance + - TopicStub +translation_of: Mozilla/Performance +--- +

The articles linked to from here will help you improve performance, whether you're developing core Mozilla code or an add-on.

+ + + + + + + +
+

Documentation

+
+
+ Reporting a Performance Problem
+
+ A user friendly guide to reporting a performance problem. A development environment is not required.
+
+ Performance best practices in extensions
+
+ A performance "best practices" guide for extension developers.
+
+ Measuring Add-on Startup Performance
+
+ A guide for add-on developers on how to set up a performance testing environment.
+
+ XUL School: Add-on Performance
+
+ Tips for add-on developers to help them avoid impairing application performance.
+
+ GPU performance
+
+ Tips for profiling and improving performance when using a GPU.
+
+

View all pages tagged with "Performance"...

+

Memory profiling and leak detection tools

+
+
+ about:memory
+
+ about:memory is the easiest-to-use tool for measuring memory usage in Mozilla code, and is the best place to start. It also lets you do other memory-related operations like trigger GC and CC, dump GC & CC logs, and dump DMD reports. about:memory is built on top of Firefox's memory reporting infrastructure.
+
+ DMD
+
+ DMD is a tool that identifies shortcomings in about:memory's measurements, and can also do multiple kinds of general heap profiling.
+
+ areweslimyet.com
+
+ areweslimyet.com (a.k.a. AWSY) is a memory usage and regression tracker.
+
+ BloatView
+
+ BloatView prints per-class statistics on allocations and refcounts, and provides gross numbers on the amount of memory being leaked broken down by class. It is used as part of Mozilla's continuous integration testing.
+
+ Refcount tracing and balancing
+
+ Refcount tracing and balancing are ways to track down leaks caused by incorrect uses of reference counting. They are slow and not particular easy to use, and thus most suitable for use by expert developers.
+
+ GC and CC logs
+
+ GC and CC logs can be generated and analyzed to in various ways. In particular, they can help you understand why a particular object is being kept alive.
+
+ Valgrind
+
+ Valgrind is a tool that detects various memory-related problems at runtime, including leaks. Valgrind is used as part of Mozilla's continuous integration testing, though the coverage is limited because Valgrind is slow.
+
+ LeakSanitizer
+
+ LeakSanitizer (a.k.a. LSAN) is similar to Valgrind, but it runs faster because it uses static source code instrumentation. LSAN is part of Mozilla's continuous integration testing, with most tests running through it as part of the AddressSanitizer (a.k.a. ASAN) test jobs.
+
+ Apple tools
+
+ Apple provides some tools for Mac OS X that report similar problems to those reported by LSAN and Valgrind. The "leaks" tool is not recommended for use with SpiderMonkey or Firefox, because it gets confused by tagged pointers and thinks objects have leaked when they have not (see bug 390944).
+
+ TraceMalloc
+
+ TraceMalloc is a tool that does various kinds of heap profiling.
+
+ Leak Gauge
+
+ Leak Gauge is a tool that can be used to detect certain kinds of leaks in Gecko, including those involving documents, window objects, and docshells.
+
+ LogAlloc
+
+ LogAlloc is a tool that dumps a log of memory allocations in Gecko. That log can then be replayed against Firefox's default memory allocator independently or through another replace-malloc library, allowing the testing of other allocators under the exact same workload.
+
+

See also the documentation on Leak-hunting strategies and tips.

+
+

Profiling and performance tools

+
+
+ Profiling with the Built-in Profiler {{ gecko_minversion_inline("16.0") }}
+
+ The built-in profiler is a good tool to start with.
+
+ Profiling with Instruments
+
+ How to use Apple's Instruments tool to profile Mozilla code.
+
+ Profiling with Xperf
+
+ How to use Microsoft's Xperf tool to profile Mozilla code.
+
+ Profiling with Zoom
+
+ Zoom is a profiler for Linux done by the people who made Shark
+
+ Measuring performance using the PerfMeasurement.jsm code module {{ gecko_minversion_inline("2.0") }}
+
+ Using PerfMeasurement.jsm to measure performance data in your JavaScript code.
+
+ Adding a new Telemetry probe
+
+ Information on how to add a new measurement to the Telemetry performance-reporting system
+
+ Profiling JavaScript with Shark {{ gecko_minversion_inline("1.9") }}
+
+ How to use the Mac OS X Shark profiler to profile JavaScript code in Firefox 3.5 or later.
+
+ Profiling with Shark
+
+ How to use Apple's Shark tool to profile Mozilla code.
+
+
+ +
+
+ JavaScript, XPCOM, Developing Mozilla, Extensions, Addons
+
+
+

 

diff --git a/files/zh-cn/mozilla/performance/scroll-linked_effects/index.html b/files/zh-cn/mozilla/performance/scroll-linked_effects/index.html new file mode 100644 index 0000000000..5d3c1a7bf0 --- /dev/null +++ b/files/zh-cn/mozilla/performance/scroll-linked_effects/index.html @@ -0,0 +1,121 @@ +--- +title: Scroll-linked effects +slug: Mozilla/Performance/Scroll-linked_effects +tags: + - CSS + - JavaScript + - Web动画 + - 性能 + - 滚动 +translation_of: Mozilla/Performance/Scroll-linked_effects +--- +

scroll-linked 效果指的是某种因滚动条位置变化的而产生的效果,例如,为了产生视差滚动效果而更新 position 属性。 本文讨论 scroll-linked 效果、这些效果对性能的影响、相关工具以及可以缓解问题的技术。

+ +

滚动效果解释

+ +

滚动效果一般是指通过监听 {{event("scroll")}} 事件,并以某种方式修改页面上的元素(通常是 CSS 的 {{cssxref("position")}} 或 {{cssxref("transform")}} 属性)你可以在 CSS Scroll API: Use Cases 找到这样的效果。

+ +

当滚动在浏览器主线程上完成时,这些效果运行良好。但是,大多数浏览器现在支持一种异步滚动,以便为用户提供恒定每秒60帧的体验。在异步滚动模型中,视觉滚动位置(译者注:即用户看到的滚动位置)在合成器线程中更新,并在 DOM 更新 {{event("scroll")}} 事件、主线程触发 {{event("scroll")}} 事件之前对用户可见。这意味着实际显示的效果将会落后于用户看到的滚动位置一点点。 这可能会导致效果变得迟缓,总之,我们想要避免这种情况。

+ +

下面是一些在异步滚动中不能良好运行的例子,以及可以很好地运行的等效版本:

+ +
+ +
+ +

示例1:粘性定位

+ +

这是一个粘性定位效果的实现,其中“toolbar”的 div 将在您向下滚动时“粘”在屏幕顶部

+ +
+ +
<body style="height: 5000px" onscroll="document.getElementById('toolbar').style.top = Math.max(100, window.scrollY) + 'px'">
+ <div id="toolbar" style="position: absolute; top: 100px; width: 100px; height: 20px; background-color: green"></div>
+</body>
+ +

这种粘性定位的实现依赖于监听滚动事件,来重新定位toolbar”的 div。由于滚动事件监听器运行于浏览器主线程的 JavaScript 中,它与用户可见的滚动是异步的。所以,因为有异步滚动,事件处理程序将相对于用户可见的滚动来说是有延迟的,这个 div 不会像预期那样保持视觉上的固定。相反,它将随用户的滚动移动,然后在滚动事件处理器运行时突然回到应有的位置。这种恒定的移动和捕捉将会导致视觉效果的抖动。其中一种解决方法是使用为此设计的 CSS 属性,而不是用滚动事件监听器:

+ +
+ +
<body style="height: 5000px">
+ <div id="toolbar" style="position: sticky; top: 0px; margin-top: 100px; width: 100px; height: 20px; background-color: green"></div>
+</body>
+ +

此版本适用于异步滚动,当用户滚动时,浏览器会更新“toolbar”的 div 的位置。

+ +

示例2:滚动捕捉

+ +

此特性已从 Web 标准中删除。 虽然一些浏览器可能仍然支持它,但它正在被放弃。尽量不要使用它,并尽可能更新现有代码。https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-coordinate#Browser_compatibility

+ +
+ +

以下是滚动捕捉的实现,当用户的滚动停止在 snaptarget 附近时,滚动位置捕捉到特定目的地(snaptarget)。

+ +
+ +
<body style="height: 5000px">
+ <script>
+    function snap(destination) {
+        if (Math.abs(destination - window.scrollY) < 3) {
+            scrollTo(window.scrollX, destination);
+        } else if (Math.abs(destination - window.scrollY) < 200) {
+            scrollTo(window.scrollX, window.scrollY + ((destination - window.scrollY) / 2));
+            setTimeout(snap, 20, destination);
+        }
+    }
+    var timeoutId = null;
+    addEventListener("scroll", function() {
+        if (timeoutId) clearTimeout(timeoutId);
+        timeoutId = setTimeout(snap, 200, parseInt(document.getElementById('snaptarget').style.top));
+    }, true);
+ </script>
+ <div id="snaptarget" style="position: relative; top: 200px; width: 100%; height: 200px; background-color: green"></div>
+</body>
+ +

在该示例中,有滚动事件监听器,其检测滚动位置是否在“snaptarget”的 div 顶部的 200 像素内。 如果是,则触发动画,将 div 的顶部“卡”到滚动位置。 由于此动画由浏览器主线程上的 JavaScript 驱动,所以可以被其他选项卡或其他窗口中运行的 JavaScript 中断。 因此,动画可能最终看起来很漂亮,但并不像预期那样平滑。 相反,使用 CSS 的 snap-points 属性将允许浏览器异步运行动画,为用户提供平滑的视觉效果。

+ +
+ +
<body style="height: 5000px">
+ <style>
+    body {
+        scroll-snap-type: proximity;
+        scroll-snap-destination: 0 0;
+    }
+    #snaptarget {
+        scroll-snap-coordinate: 0 -8px;
+    }
+ </style>
+ <div id="snaptarget" style="position: relative; top: 200px; width: 100%; height: 200px; background-color: green"></div>
+</body>
+ +

即使浏览器的主线程中运行的 JavaScript 速度较慢,该版本也能在浏览器中顺利运行。

+ +

其他效果

+ +

在不少情况下,scroll-linked 效果能够通过 CSS 和在排序线程运行来重新实现。 然而, 有时浏览器提供的 API 不允许这么做。但是不管怎样, 如果 Firefox(从版本 46 之后)检测到页面上的 scroll-linked 效果, 将在控制台向开发人员显示警告 。 需要说明的是,使用滚动效果的页面如果在 JavaScript 中不监听滚动事件将无法获得此警告。你可以参考此博客文章( Asynchronous scrolling in Firefox )来了解更多通过 CSS 来实现避免页面延迟的例子。

+ +

未来改进

+ +

未来我们将在 compositor 中支持更多的效果。为了完成这个目标,我们需要你(没错,就是你!)来告诉我们更多的你努力实现的 scroll-linked 效果,以便我们可以找到好的方式来支持它们。目前有几个对于 API 的提案可以实现这种效果,它们也都有各自的优缺点。目前正在审议的提案是:

+ + + +

Call to action

+ +

如果你对下列内容有想法或意见:

+ + + +

请与我们联系,您可以通过 public-houdini 邮件列表来加入讨论。

diff --git a/files/zh-cn/mozilla/persona/bootstrapping_persona/index.html b/files/zh-cn/mozilla/persona/bootstrapping_persona/index.html new file mode 100644 index 0000000000..4f1c519c0a --- /dev/null +++ b/files/zh-cn/mozilla/persona/bootstrapping_persona/index.html @@ -0,0 +1,29 @@ +--- +title: Persona引导 +slug: Mozilla/Persona/Bootstrapping_Persona +translation_of: Archive/Mozilla/Persona/Bootstrapping_Persona +--- +

为了真正成功实现分权,Persona需要得到三方面的支持:

+ +

This creates a chicken-and-egg problem: none of these groups would significantly benefit unless there was a critical mass of users, but a distributed system can't get a critical mass of users without support from the above groups.

+

To solve this problem, https://login.persona.org hosts three resources:

+
    +
  1. A fallback Identity Provider, which vouches for users whose email providers don't support Persona.
  2. +
  3. A cross-browser, JavaScript implementation of the navigator.id APIs for browsers without native support.
  4. +
  5. A hosted verification API to make it easy for sites to verify user credentials.
  6. +
+

Together, this allows web sites to offer Persona to users regardless of browser and without email providers needing to get involved.

+

These services are temporary, and the Persona system is designed such that they transparently and automatically drop away as native support gets added to browsers and email providers. Thus, they will become less relevant as Persona matures, and may eventually be removed all together. At that point, https://login.persona.org won't feature at all in the Persona system.

+

Fallback Identity Provider

+

Any domain can become an Identity Provider as long as relying parties are willing to trust the certificates issued by that domain. We expect email providers to act as an IdPs for the addresses they administer, making the user experience of Persona seamless for those users.  It allows the user to leverage their existing relationship with the email provider when authenticating at other sites.

+

However, email providers won't become IdPs until there is significant demand from their users. In the meantime, Mozilla operates a fallback IdP at https://login.persona.org. This fallback allows users to sign into sites with their existing email address, regardless of whether or not the email provider supports Persona. The fallback IdP will certify email addresses from any domain using its own authentication flow and its own password, so long as the user is able to prove control of an address by clicking a link in a verification email.

+

Once an email provider supports Persona natively, its users will transparently begin use it instead of the fallback IdP.

+

Cross-browser API Library

+

For Persona to work, the user's browser must support the navigator.id API. Eventually, browsers will add native support for these APIs, but until then a cross-browser implementation is available at https://login.persona.org/include.js. By including this file, web sites can already begin using Persona. Once native implementations of the API are available, the library will automatically defer to those.

+

Remote verification service

+

At https://login.persona.org Mozilla hosts a remote verification service that web sites can use to verify identity assertions sent from users. This makes it simpler for web sites to support Persona as it takes care of parsing the assertion and cryptographically verifying user identities.

+

Once the Persona data formats stabilize, verification will most likely be done locally on each site's server. This transition is especially important for user privacy, since it will make it impossible for the fallback IdP to track its users. Even with remote verification, users of native IdPs can't be tracked by that IdP.

diff --git a/files/zh-cn/mozilla/persona/branding/index.html b/files/zh-cn/mozilla/persona/branding/index.html new file mode 100644 index 0000000000..3120f9a4c8 --- /dev/null +++ b/files/zh-cn/mozilla/persona/branding/index.html @@ -0,0 +1,79 @@ +--- +title: 品牌资源 +slug: Mozilla/Persona/branding +tags: + - 图片 + - 按钮 +translation_of: Archive/Mozilla/Persona/User_interface_guidelines +--- +

使用 Persona 样式的按钮登陆

+

图片样式

+

Persona样式的登录按钮有三个版本,三种颜色:

+

英文按钮

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Sign in with your EmailSign in with PersonaSign in
Black
Blue
Red
+

中文按钮

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 使用Email登录使用Persona登录登录
黑色
蓝色
红色
+

中文按钮打包下载

+

地址:persona_sign_in_zh_cn.20130513.001.by.will.chen.7z

+

CSS-Based

+

Sawyer Hollenshead 制作了一些非常优秀的 CSS-based 的按钮. Download (.zip)

+

更多信息

+

你可以在 Sean Martell's style primer找到更多关于Persona视觉效果设计的信息.

diff --git a/files/zh-cn/mozilla/persona/browser_compatibility/index.html b/files/zh-cn/mozilla/persona/browser_compatibility/index.html new file mode 100644 index 0000000000..e362b74b3a --- /dev/null +++ b/files/zh-cn/mozilla/persona/browser_compatibility/index.html @@ -0,0 +1,89 @@ +--- +title: 浏览器兼容性 +slug: Mozilla/Persona/Browser_compatibility +tags: + - Files +translation_of: Archive/Mozilla/Persona/Browser_compatibility +--- +

支持的浏览器

+

Persona 支持下列浏览器。 Persona 包含一个跨平台的 JavaScript 库,因此用户使用时不需要安装任何插件。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
桌面浏览器
Internet Explorer8.0*, 9.0, 10.0** (详见下方的 兼容模式 说明)
Firefox现有稳定版本, 测试版本, Aurora, 夜间发布版本 和 扩展支持版本
+ 以往稳定版本
Chrome最新稳定版本
Safari最新稳定版本
Opera最新稳定版本
iOS 浏览器
SafariiOS 5.x — 6.x
Android 浏览器
默认浏览器2.2 — 4.x
Firefox现有稳定版本, 测试版本, Aurora 和 夜间发布版本
+ 以往稳定版本
ChromeLatest Stable Release
+

*: Windows XP. : Windows Vista 和 Windows 7. **Windows 8.  : 如果时间允许.

+

不支持的浏览器

+ +

Internet Explorer 的“兼容模式”

+

从 8.0 版开始, Internet Explorer 提供了一项名为“兼容模式”的功能, 其在渲染页面时会模拟 8.0 以前版本的行为。 这个特性可以通过三种方法控制:

+
    +
  1. 浏览器中的本地设置
  2. +
  3. 页面中的 DOCTYPE 声明
  4. +
  5. 网站在 HTTP 头或页面 <meta> 标签中使用 "X-UA-Compatible"。 此方法会覆盖前两种
  6. +
+

由于 Persona 不支持 Internet Explorer 8.0 以前版本, 任何 Internet Explorer 如果模拟了8.0 以前版本也将不能支持 Persona 。 这通常是由于:

+ +

详情请见 "Understanding Compatibility Modes in Internet Explorer 8" 和 "IE8 and IE9 Complications".

+

其他浏览器

+

除非明显不被支持, 任何同时支持 {{ domxref("window.postMessage()") }} 和 {{ domxref("Storage", "localStorage") }} 的浏览器都应该能使 Persona 正常运行。 2010年3月后所有主流浏览器都支持这些 API 。

+

已知问题

+ diff --git a/files/zh-cn/mozilla/persona/glossary/index.html b/files/zh-cn/mozilla/persona/glossary/index.html new file mode 100644 index 0000000000..430bacbabe --- /dev/null +++ b/files/zh-cn/mozilla/persona/glossary/index.html @@ -0,0 +1,61 @@ +--- +title: 术语表 +slug: Mozilla/Persona/Glossary +translation_of: Archive/Mozilla/Persona/Glossary +--- +

"Persona" 和 "BrowserID"

+

Persona 是 Mozilla 的全新分布式登录系统的完整实现。

+

BrowserID 是 Persona 基于的开放协议。

+

常用 Persona 术语

+
+
+ BrowserID
+
+ 一种基于电子邮件地址的,开放、去中心化的用户认证协议。
+
+ 身份凭证提供者 ("IdP")
+
+ 为其用户签发身份凭证的服务。
+
+ 邮件服务提供商可以通过在其服务中增加 BrowserID 支持成为身份凭证提供者。 Mozilla 为不支持 Persona 的邮件服务提供商提供了身份凭证服务, 其位于 login.persona.org.
+
+ login.persona.org
+
+ 由 Mozilla Identity 团队运行的备用身份凭证服务。
+
+ Persona
+
+ Mozilla 对用户公布的整套认证服务的名称,这套服务包括由 Mozilla Identity 团队运行的备用身份凭证服务。 最终用户应该不需要知道 "BrowserID" 这个术语。
+
+ Persona 可能逐渐包含 BrowserID 协议之外的功能,如 Firefox Sync 的部分功能,或者 Open Web Apps 的控制面板。
+
+ Relying Party ("RP")
+
+ 允许用户通过 Persona 登录的任何网站,应用或服务。
+
+

项目代号

+
+
+ BigTent
+
+ 三个身份凭证服务的集合,分别针对 Hotmail,Gmail 和 Yahoo Mail 的用户。 BigTent 通过OpenID 或 OAuth 等方式连接各个邮件服务提供商。 源码位于 https://github.com/mozilla/browserid-bigtent 。
+
+ Vinz Clortho
+
+ 电子邮件后缀为 @mozilla.com@mozilla.org 的身份凭证服务。 通过 LDAP 运行。 源码位于 https://github.com/mozilla/vinz-clortho 。 项目名称向1984年的电影《捉鬼敢死队》致敬。
+
+

不常用 Persona 术语

+
+
+ 一级认证机构 ("Primary")
+
+ 弃用术语, 指能同时作为身份认证提供者的邮件服务提供商。
+
+ 二级认证机构 ("Secondary)
+
+ 弃用术语,指为其邮件服务提供商不支持 Persona 的用户提供备用身份认证服务的身份认证提供者。Mozilla 在 login.persona.org 运行了一个备用身份认证服务。
+
+ Verified Email Protocol
+
+ BrowserID 协议的旧称。
+
diff --git a/files/zh-cn/mozilla/persona/index.html b/files/zh-cn/mozilla/persona/index.html new file mode 100644 index 0000000000..5c19bec83a --- /dev/null +++ b/files/zh-cn/mozilla/persona/index.html @@ -0,0 +1,138 @@ +--- +title: Mozilla Persona +slug: Mozilla/Persona +tags: + - Mozilla + - Persona + - zh-CN +translation_of: Archive/Mozilla/Persona +--- +
+

保持联系或获取帮助!

+ +

关注 我们的 blog,加入 我们的邮件列表,或在 IRC 中的 #identity 找到我们。

+
+ +
+

提示:Mozilla将在2016年11月关闭Persona.org

+ +

邮件列表:https://mail.mozilla.org/pipermail/persona-notices/2016/000005.html

+
+ +

Mozilla Persona 是一个用于 web 的完全去中心化且安全的验证系统,基于开放 BrowserID 协议。Mozilla 当前管理一个 Persona 相关的一个可选的、中心化服务的一小组套件。

+ +

为什么你和你的站点应该使用 Persona?

+ +
    +
  1. Persona 完全消除了站点特定的密码, 把用户和网站从创建、管理和安全存放密码的责任中解放出来。
  2. +
  3. Persona 易于使用。只需点击两次,一个 Persona 用户可以登入到一个诸如 VoostThe Times Crossword 的新站点,绕开了账户创建相关的摩擦。
  4. +
  5. Persona 易于实现。开发人员在一个下午就可以把 Persona 添加到站点上。
  6. +
  7. 最好的是,不会被锁定。 开发人员获取所有他们用户的验证过的邮件地址,而用户可以在 Persona 上使用任何邮件地址。
  8. +
  9. Persona 基于 BrowserID 协议构建。一旦流行的浏览器供应商实现了 BrowserID,它们不再需要依赖于 Mozilla 来登入。
  10. +
+ +

继续阅读来开始!

+ +
注意:Persona 在活跃开发中。关注我们的 blog 来了解新特性,或加入我们的邮件列表来提供反馈!
+ +

在你的站点上使用 Persona

+ + + + + + + + + + + + +
+

准备开始

+ +
+
为什么使用 Persona?
+
了解在你的站点上支持 Persona 的原因和它与其它身份验证系统的区别。
+
快速安装
+
一份快捷的攻略,展示了如何向你的网站中添加 Persona。
+
+
+

Persona API 参考

+ +
+
navigator.id API 参考
+
navigator.id 对象的参考,web 开发者可以用此来把 Persona 继承到站点中。
+
验证 API 参考
+
建立在 https://verifier.login.persona.org/verify 上的远程验证 API 的参考。
+
+
+

指导

+ +
+
安全考虑
+
确保 Persona 部署安全的实践和技术。
+
浏览器兼容性
+
准确获知哪些浏览器支持 Persona。
+
国际化
+
了解 Persona 如何处理不同的语言。
+
+
+

资源

+ +
+
库和插件
+
寻找你偏好的编程语言、web 框架、博客或是内容管理系统(CMS)的即插库。
+
Persona cookbook
+
Persona 站点的示例源代码。包括 PHP、Node.JS 等等的片段。
+
品牌资源
+
登入按钮和其它向用户表现 Persona 的图形。
+
+
+ +

 

+ + + + + + + + +
+

给身份提供者的信息

+ +

如果你是一个电子邮件提供商或另一个身份提供服务,翻阅下面的链接来获知如何成为一个 Persona 身份提供者。

+ +
+
IdP 概述
+
Persona 身份提供者的高层视角。
+
实现一个 IdP
+
成为一个 IdP 的详细技术细节指导。
+
开发提示
+
开发一个新的身份提供者的一系列开发提示和技巧。
+
.well-known/browserid
+
.well-known/browserid 文件的结构和用途概述,这个文件被 IdPs 用于通知它们支持这个协议。
+
+
+

Persona 项目

+ +
+
术语表
+
BrowserID 和 Persona 定义的术语。
+
FAQ
+
常见问题的回答。
+
协议概述
+
底层 BrowserID 协议的中等技术概述。
+
加密
+
一瞥 Persona 和 BrowserID 背后的密码学概念。
+
协议规范
+
这里是深层技术细节。
+
Persona 网站
+
要让 Persona 运作, 我们在https://login.persona.org 建立了三个服务:一个备用身份提供者、一个可迁移的 {{ domxref("navigator.id") }} API 实现以及一个身份断言验证服务。
+
Persona 源码
+
Persona 网站背后的源码托管在 GitHub 的一个仓库上。欢迎提交补丁!
+
+
+ +

 

diff --git a/files/zh-cn/mozilla/persona/protocol_overview/index.html b/files/zh-cn/mozilla/persona/protocol_overview/index.html new file mode 100644 index 0000000000..9e61fb2b95 --- /dev/null +++ b/files/zh-cn/mozilla/persona/protocol_overview/index.html @@ -0,0 +1,96 @@ +--- +title: 协议概述 +slug: Mozilla/Persona/Protocol_Overview +tags: + - Persona +translation_of: Archive/Mozilla/Persona/Protocol_Overview +--- +

Persona is built on the BrowserID protocol. This page describes the BrowserID protocol at a high level.

+ +

角色

+ +

The protocol involves three actors:

+ + + +

Persona and the BrowserID protocol use email addresses as identities, so it's natural for email providers to become IdPs.

+ +

Mozilla operates a fallback IdP so that users can use any email address with Persona, even one with a specific domain that isn't an IdP itself.

+ +

协议步骤

+ +

There are three distinct steps in the protocol:

+ +
    +
  1. User Certificate Provisioning
  2. +
  3. Assertion Generation
  4. +
  5. Assertion Verification
  6. +
+ +

As a prerequisite, the user should have an active identity (email address) that they wish to use when logging in to websites. The protocol does not require that IdP-backed identities are SMTP-routable, but it does require that identities follow the user@domain format.

+ +

用户认证过程

+ +

In order to sign into an RP, a user must be able to prove ownership of their preferred email address. The foundation of this proof is a cryptographically signed certificate from an IdP certifying the connection between a browser's user and a given identity within the IdP's domain.

+ +

Because Persona uses standard public key cryptography techniques, the user certificate is signed by the IdP's private key and contains:

+ + + +

The user's browser generates a different keypair for each of the user's email addresses, and these keypairs are not shared across browsers. Thus, a user must obtain a fresh certificate whenever one expires, or whenever using a new browser or computer. Certificates must expire within 24 hours of being issued.

+ +

When a user selects an identity to use when signing into an RP, the browser checks to see if it has a fresh user certificate for that address. If it does, this step is complete and the browser continues with the assertion generation step below. If the browser does not have a fresh certificate, it attempts to obtain one from the domain associated with the chosen identity.

+ +
    +
  1. The browser fetches the /.well-known/browserid support document over SSL from the identity's domain.
  2. +
  3. Using information from the support document, the browser passes the user's email address and associated public key to the IdP and requests a signed certificate.
  4. +
  5. If necessary, the user is asked to sign into the IdP before provisioning proceeds.
  6. +
  7. The IdP creates, signs, and gives a user certificate to the user's browser.
  8. +
+ +

With the certificate in hand, the browser can continue with generating an identity assertion and signing into an RP.

+ +

user-certificate-provisioning.png

+ +

生成断言

+ +

The user certificate establishes a verifiable link between an email address and a public key. However, this is alone not enough to log into a website: the user still has to show their connection to the certificate by proving ownership of the private key.

+ +

In order to prove ownership of a private key, the user's browser creates and signs a new document called an "identity assertion." It contains:

+ + + +

The browser then presents both the user certificate and the identity assertion to the RP for verification.

+ +

验证断言

+ +

The combination of user certificate and identity assertion is sufficient to confirm a user's identity.

+ +

First, the RP checks the domain and expiration time in the assertion. If the assertion is expired or intended for a different domain, it's rejected. This prevents malicious re-use of assertions.

+ +

Second, the RP validates the signature on the assertion with the public key inside the user certificate. If the key and signature match, the RP is assured that the current user really does possess the key associated with the certificate.

+ +

Last, the RP fetches the IdP's public key from its /.well-known/browserid document and verifies that it matches the signature on the user certificate. If it does, then the RP can be certain that the certificate really was issued by the domain in question.

+ +

Once verifying that this is a current login attempt for the proper RP, that the user certificate matches the current user, and that the user certificate is legitimate, the RP is done and can authenticate the user as the identity contained in the certificate.

+ +

assertion-generation-and-verify.png

+ +

The Persona Fallback IdP

+ +

What if a user's email provider doesn't support Persona? In that case, the provisioning step would fail. By convention, the user's browser handles this by asking a trusted third party, https://login.persona.org/, to certify the user's identity on behalf of the unsupported domain. After demonstrating ownership of the address, the user would then receive a certificate issued by the fallback IdP, login.persona.org, rather than the identity's domain.

+ +

RPs follow a similar process when validating the assertion: the RP would ultimately request the fallback IdP's public key in order to verify the certificate.

diff --git a/files/zh-cn/mozilla/persona/quick_setup/index.html b/files/zh-cn/mozilla/persona/quick_setup/index.html new file mode 100644 index 0000000000..e39958eb98 --- /dev/null +++ b/files/zh-cn/mozilla/persona/quick_setup/index.html @@ -0,0 +1,140 @@ +--- +title: 快速安装 +slug: Mozilla/Persona/Quick_Setup +tags: + - Mozilla + - Persona +translation_of: Archive/Mozilla/Persona/Quick_Setup +--- +

要把 Persona 登录系统添加到你的站点只需要 5 步:

+
    +
  1. 在你的页面中包含 Persona 的 JavaScript 库。
  2. +
  3. 添加“登入”和“登出”按钮。
  4. +
  5. 监视登入和登出行为。
  6. +
  7. 验证用户证书。
  8. +
  9. 回顾最佳实现。
  10. +
+

你应该能在一个下午就建立好并运行,但重要的是:如果你要在你的站点上使用 Persona,请花一点时间订阅 Persona 通知 邮件列表。它流量非常低,只用于通知那些对你站点有负面影响的变更或安全问题。

+

步骤1:包含 Persona 库

+

Persona 被设计为跨浏览器且可在全部主要桌面和移动浏览器中工作。

+

在未来我们期望浏览器提供 Persona 的原生支持,但我们同时提供了一个 JavaScript 库完整地实现了用户界面和客户端部分的协议。通过包含这个库,你的用户会可以用 Persona 登入,无论他们的浏览器是否有原生支持。

+

一 旦页面中的这个库加载完毕,你需要的 Persona 函数({{ domxref("navigator.id.watch()", "watch()") }}、{{ domxref("navigator.id.request()", "request()") }} 和 {{ domxref("navigator.id.logout()", "logout()") }})会在全局对象 navigator.id 中可用。

+

要包含 Persona JavaScript 库,你可以把这个 script 标签放进你页面的首部:

+
<script src="https://login.persona.org/include.js"></script>
+
+

必须在每个使用 {{ domxref("navigator.id") }} 中函数的页面里包含这个标签。因为 Persona 始终在开发中,你不应该自行托管 include.js 文件。

+

步骤2:添加登入/登出按钮

+

因 为 Persona 被设计为一个 DOM API,你必须在用户点击你站点上的登入或登出按钮时调用函数。要打开 Persona 对话框并提示用户登入,你应该调用 {{ domxref("navigator.id.request()") }} 。而登出要调用 {{ domxref("navigator.id.logout()") }} 。

+

例如:

+
var signinLink = document.getElementById('signin');
+if (signinLink) {
+  signinLink.onclick = function() { navigator.id.request(); };
+};
+
+var signoutLink = document.getElementById('signout');
+if (signoutLink) {
+  signoutLink.onclick = function() { navigator.id.logout(); };
+};
+
+

那些按钮的是什么样子的?查看我们的品牌资源页面中的预制图片和基于 CSS 的按钮!

+

步骤3:监视登入/登出行为

+

要把 Persona 封装成函数,你需要告诉它当用户登入/登出时做什么。调用 {{ domxref("navigator.id.watch()") }} 函数就可以实现,它支持三个参数:

+
    +
  1. +

    你站点当前用户的 loggedInEmail ,如果没有则为 null 。你应该在渲染页面的时候动态生成它。

    +
  2. +
  3. +

    当触发 onlogin 行为的时候调用的函数。这个函数会被传递一个必须认证的“身份断言”参数。

    +
  4. +
  5. +

    当触发 onlogout 行为的时候调用的函数。这个函数不会被传递任何参数。

    +
  6. +
+
+

注意:你必须总是在调用 {{ domxref("navigator.id.watch()") }} 时同时包含 onloginonlogout

+
+

例如,如果你现在认为鲍勃已经登入到你的站点,你会这样做:

+
var currentUser = 'bob@example.com';
+
+navigator.id.watch({
+  loggedInUser: currentUser,
+  onlogin: function(assertion) {
+    // 一个用户已经登入!这是你需要做的:
+    // 1. 把断言发送到后端验证并创建一个会话。
+    // 2. 更新你的 UI。
+    $.ajax({ /* <-- 本例使用了 jQuery,但你也可以用你想用的 */
+      type: 'POST',
+      url: '/auth/login', // 这是你网站上的一个 URL
+      data: {assertion: assertion},
+      success: function(res, status, xhr) { window.location.reload(); },
+      error: function(res, status, xhr) { alert("登入失败" + res); }
+    });
+  },
+  onlogout: function() {
+    // 一个用户已经登出!这是你需要做的:
+    // 销毁用户的会话并重定向用户或做后端的调用。
+    // 同样,让 loggedInUser 在下个页面加载时变为 null。
+    // (这是一个字面的 JavaScript null。不是 false、 0 或 undefined。null。)
+    $.ajax({
+      type: 'POST',
+      url: '/auth/logout', // 这是你网站上的一个 URL
+      success: function(res, status, xhr) { window.location.reload(); },
+      error: function(res, status, xhr) { alert("登出失败" + res); }
+    });
+  }
+});
+
+

在本例中,onloginonlogout 都通过向你站点的后端发送异步 POST 请求来实现。后端随后通常用设定或删除会话 cookie 中的信息来登入或登出用户。之后,如果一切都核对无误,页面重加载来考虑账户的新登录状态。

+

你当然可以用 AJAX 来不用重加载或重定向来实现,但这超出了本教程的范畴。

+

必须在每个有登入/登出按钮的页面上调用这个函数。要为用户支持 Persona 加强功能,诸如自动登录和全局登出,你应该在网站上的每个页面都调用这个函数。

+

步骤4:验证用户证书

+

Persona 用“身份断言”来代替密码,那是一种类似一次性、单站点的、用户邮件地址捆绑的密码。当用户想要登入时,你的 onlogin 回调会传入一个该用户的断言来调用。在你登入他们前,你必须验证断言的有效性。

+

在你的服务器上而不是用户浏览器上运行的 JavaScript 中验证断言是极度重要的,因为那很容易伪造。上面的例子用 jQuery 的 $.ajax() 辅助函数来把断言通过 POST/auth/login 来呈递给后端。

+

一旦你的服务器获得了断言,你如何验证它?最简单的方法是用 Mozilla 提供的辅助服务。简单地把断言以两个参数 POSThttps://verifier.login.persona.org/verify

+
    +
  1. assertion: 用户提供的身份断言。
  2. +
  3. audience: 你网站的主机名和端口。你必须在后端硬编码这个值;不要从用户提供的任何数据中派生这个值。
  4. +
+

例如,如果你是 example.com,你可以用下面的命令行来测试断言:

+
$ curl -d "assertion=<ASSERTION>&audience=https://example.com:443" "https://verifier.login.persona.org/verify"
+
+

如果它是有效的,你会得到像这样的一个 JSON 响应:

+
{
+  "status": "okay",
+  "email": "bob@eyedee.me",
+  "audience": "https://example.com:443",
+  "expires": 1308859352261,
+  "issuer": "eyedee.me"
+}
+
+

你可以阅读验证服务 API来获知更多关于验证服务的内容。一个 /api/login 实现的使用了 PythonFlask web 框架和 Requests HTTP 库的例子看起来是这样:

+
@app.route('/auth/login', methods=['POST'])
+def login():
+    # 请求必须包含我们要验证的断言
+    if 'assertion' not in request.form:
+        abort(400)
+
+    # 把断言发送给 Mozilla 的验证服务
+    data = {'assertion': request.form['assertion'], 'audience': 'https://example.com:443'}
+    resp = requests.post('https://verifier.login.persona.org/verify', data=data, verify=True)
+
+    # 验证器响应了吗?
+    if resp.ok:
+        # 处理响应
+        verification_data = json.loads(resp.content)
+
+        # 检查断言是否有效
+        if verification_data['status'] == 'okay':
+            # 设置一个安全会话 cookie 来登入用户
+            session.update({'email': verification_data['email']})
+            return resp.content
+
+    # 哎哟,有什么东西不对,放弃
+    abort(500)
+
+

会话管理可能很像你现有的登录系统。首先的大区别是在验证用户身份采用了检查断言而不是检查密码。另一个不同是确保用户的邮件地址有效来用于 {{ domxref("navigator.id.watch()") }} 的 loggedInEmail 参数

+

登出很简单:你只需要移除用户的会话 cookie。

+

步骤5:回顾最佳实践

+

一旦所有的东西都工作正常并且你已经成功登入和登出你的站点,你应该花一会时间来回顾安全可靠地使用 Persona 的最佳实践

+

如果你在做一个要作为生产环境的站点,你会想要编写集成的测试来模拟用 Persona 登入或登出用户。要改善 Selenium 中的这个行为,请考虑使用 bidpom 库。mockmyid.compersonatestuser.org 这两个网站也可能会有用。

+

最后,不要忘记登记加入 Persona 通知 邮件列表,这样会通知你任何安全问题或 Persona API 的向后兼容变更。这个列表的流量非常低:它只用于通知会对你的站点造成负面影响的变更。

diff --git a/files/zh-cn/mozilla/persona/remote_verification_api/index.html b/files/zh-cn/mozilla/persona/remote_verification_api/index.html new file mode 100644 index 0000000000..55f37e793e --- /dev/null +++ b/files/zh-cn/mozilla/persona/remote_verification_api/index.html @@ -0,0 +1,120 @@ +--- +title: 远程验证 API +slug: Mozilla/Persona/Remote_Verification_API +translation_of: Archive/Mozilla/Persona/Remote_Verification_API +--- +

概述

+

当用户试图登入一个网站,他们的浏览器会生成一个名为断言的数据结构,这实质上是一个加密签名的邮件地址。浏览器把这个断言发送给网站,网站必须在登入用户前检验断言是否有效。

+

断言可以本地验证,或使用托管在 https://verifier.login.persona.org/verify 的 API。本页面描述如何使用这个 API。

+

方法

+

把 HTTP POST 请求发送至 https://verifier.login.persona.org/verify

+

参数

+

assertion: 断言由用户提供。作为传给  {{ domxref("navigator.id.watch()") }} 中 onlogin  函数的第一个参数。
+ audience: 你的站点的协议、域名和端口。 例如, "https://example.com:443"。

+

返回值

+

调用会返回一个包含 status 元素的 JSON 结构,这个元素值会是 "okay" 或是" failure" 。取决于 status 的值,这个结构包含下面列出的额外元素。

+

"okay"

+

断言是有效的。

+

在这种情况下 JSON 结构包含下面的额外元素:

+ + + + + + + + + + + + + + + + + + + +
"email"断言中包含欲登录人的邮件地址。
"audience"断言中包含 audience 值。 期望值为你的网站 URL。
"expires"断言过期的日期,表示为Date 对象的原始值: 即从 UTC 1970 年 1 月 1 日午夜至今的毫秒数。
"issuer"发出断言的身份提供者的主机名。
+

"failure"

+

断言是无效的。这种情况下,JSON 结构包含一个额外元素:

+ + + + + + + +
"reason"一个解释验证失败原因的字符串。
+

示例

+

node.js

+

例中使用了一个采用 express.js 的 node.js 服务器

+
var express = require("express"),
+    app = express.createServer(),
+    https = require("https"),
+    querystring = require("querystring");
+/* ... */
+
+// audience 值必须匹配你浏览器地址栏显示的值,
+// 包括协议、主机名、端口
+var audience = "http://localhost:8888";
+
+app.post("/authenticate", function(req, res) {
+  var vreq = https.request({
+    host: "verifier.login.persona.org",
+    path: "/verify",
+    method: "POST"
+  }, function(vres) {
+    var body = "";
+    vres.on('data', function(chunk) { body+=chunk; } )
+        .on('end', function() {
+          try {
+            var verifierResp = JSON.parse(body);
+            var valid = verifierResp && verifierResp.status === "okay";
+            var email = valid ? verifierResp.email : null;
+            req.session.email = email;
+            if (valid) {
+              console.log("assertion verified successfully for email:", email);
+            } else {
+              console.log("failed to verify assertion:", verifierResp.reason);
+            }
+            res.json(email);
+          } catch(e) {
+            console.log("non-JSON response from verifier");
+            // bogus response from verifier! return null
+            res.json(null);
+          }
+        });
+  });
+  vreq.setHeader('Content-Type', 'application/x-www-form-urlencoded');
+
+  var data = querystring.stringify({
+    assertion: req.body.assertion,
+    audience: audience
+  });
+  vreq.setHeader('Content-Length', data.length);
+  vreq.write(data);
+  vreq.end();
+  console.log("verifying assertion!");
+});
+
+
+

via Lloyd Hilaiel

+

PHP

+
$url = 'https://verifier.login.persona.org/verify';
+$assert = $_POST['assert'];
+$params = 'assertion='.$assert.'&audience=' .
+           urlencode('http://example.com:80');
+$ch = curl_init();
+$options = array(
+    CURLOPT_URL => $url,
+    CURLOPT_RETURNTRANSFER => TRUE,
+    CURLOPT_POST => 2,
+    CURLOPT_POSTFIELDS => $params
+);
+curl_setopt_array($ch, $options);
+$result = curl_exec($ch);
+curl_close($ch);
+echo $result;
+
+

Via Christian Heilmann

diff --git a/files/zh-cn/mozilla/persona/security_considerations/index.html b/files/zh-cn/mozilla/persona/security_considerations/index.html new file mode 100644 index 0000000000..d955e82d13 --- /dev/null +++ b/files/zh-cn/mozilla/persona/security_considerations/index.html @@ -0,0 +1,55 @@ +--- +title: 安全考虑 +slug: Mozilla/Persona/Security_Considerations +translation_of: Archive/Mozilla/Persona/Security_Considerations +--- +

When you add Persona support to your website, Persona takes on as much of the security burden as it can. However, some aspects of security can only be handled by your website. They're listed below.

+

Essential practices

+

Verify assertions on your server

+

When using Persona, identity assertions are passed into the onlogin function passed to {{ domxref("navigator.id.watch()") }}. You should always pass the assertion to your server for verification, and only your server should decide to grant the user additional permissions based on the verification result:

+
// Inside navigator.id.watch({ ...
+onlogin: function(assertion) {
+  // A user wants to log in! Here you need to:
+  // 1. Send the assertion to your backend for verification and to create a session.
+  // 2. Update your UI.
+},
+
+

If you try to verify the assertion using the JavaScript executing in the user's browser, then a malicious user will be able to impersonate a legitimate user of your site by locally injecting code and subverting your JavaScript. This is possible because you're not fully in control of the user's browser, where the code executes.

+

Again, you should always pass the assertion to your server for verification. Even if you're using the remote verification API.

+

Explicitly specify the audience parameter

+

To verify an assertion, you may issue a POST request to https://verifier.login.persona.org/verify. The request includes a parameter called audience:

+
assertion=<ASSERTION>&audience=https://mysite.com:443"
+

The audience parameter is required. You should always specify the audience explicitly in your code, or in your code's configuration. Specifically:

+ +

If you trust the user's browser to tell you the audience, then it becomes possible for a malicious web site to reuse assertions for its web site to log into your web site.

+

Verify SSL certificates

+

To verify an assertion, you may issue a POST request to https://verifier.login.persona.org/verify. You must ensure that your HTTPS request verifies the certificate sent from the server against a trusted root certificate. If you don't, then an attacker could pose as verifier.login.persona.org and issue false verifications.

+

Check that the library you are using to make the request verifies certificates correctly, and that you are initializing it with the appropriate root certificate(s).

+

For example, Python 2.7's standard urllib2 module does not validate server certificates. Instead, we recommend using the "requests" or "urllib3" modules in Python 2.x, or the standard http.client.HTTPSConnection class in Python 3.x. For Perl, ensure that you are using at least version 6.0 of libwww-perl. Depending on the language, library, and operating system that you're using, you may need to supply either a list of trusted CA roots or the single CA used by verifier.login.persona.org.

+

Implement CSRF protection

+

In a CSRF (Cross-Site Request Forgery) login attack, an attacker uses a cross-site request forgery to log the user into a web site using the attacker's credentials.

+

For example: a user visits a malicious web site containing a form element. The form's action attribute is set to an HTTP POST request to http://www.google.com/login, supplying the attacker's username and password. When the user submits the form, the request is sent to Google, the login succeeds and the Google server sets a cookie in the user's browser. Now the user's unknowingly logged into the attacker's Google account.

+

The attack can be used to gather sensitive information about the user. For example, Google's Web History feature logs all the user's Google search terms. If a user is logged into the attacker's Google account and the attacker has Web History enabled, then the user is giving the attacker all this information.

+

CSRF login attacks, and potential defenses against them, are documented more fully in Robust Defenses for Cross-Site Request Forgery (PDF). They're not specific to Persona: most login mechanisms are potentially vulnerable to them.

+

There are a variety of techniques which can be used to protect a site from CSRF login attacks, which are documented more fully in the study above.

+

One approach is to create a secret identifier in the server, shared with the browser, and require the browser to supply it when making login requests. For example:

+
    +
  1. As soon as the user lands on your site, before they try to log in, create a session for them on the server. Store the session ID in a browser cookie.
  2. +
  3. On the server, generate a random string of at least 10 alphanumeric characters. A randomly generated UUID is a good option. This is the CSRF token. Store it in the session.
  4. +
  5. Deliver the CSRF token to the browser by either embedding it in JavaScript or HTML as a hidden form variable.
  6. +
  7. Ensure that the AJAX submission or form POST includes the CSRF token.
  8. +
  9. On the server side, before accepting an assertion, check that the submitted CSRF token matches the session-stored CSRF token.
  10. +
+

Enhancements

+

Content Security Policy (CSP)

+

Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware.

+

If you use CSP on your site, you may need to tweak your policy to enable Persona. Depending on your policy, you may need to:

+ +

An example Apache configuration might include:

+
Header set X-Content-Security-Policy: "default-src 'self'; frame-src 'self' https://login.persona.org ; script-src 'self' https://login.persona.org"
diff --git a/files/zh-cn/mozilla/persona/why_persona/index.html b/files/zh-cn/mozilla/persona/why_persona/index.html new file mode 100644 index 0000000000..d7d96a46fc --- /dev/null +++ b/files/zh-cn/mozilla/persona/why_persona/index.html @@ -0,0 +1,30 @@ +--- +title: 为什么使用 Persona? +slug: Mozilla/Persona/Why_Persona +translation_of: Archive/Mozilla/Persona/Why_Persona +--- +

流行的用户名和密码系统并非长久之计:用户需要为每个他们使用的站点和服务创建并记住一个新的、复杂的密码,并且每个站点都要安全地存储密码。尽管如此,最近的事故证明了即使是巨头级的大公司也在密码安全上失误,这让他们的用户信息暴露在风险中。

+

Persona 是一个开放的、分布式、web 规模的身份识别系统,它取代了每个网站一个密码的局面。它解决了像 OpenID 这样系统的可用性和隐私相关的缺点而不诉诸于 Facebook Connect 这样的中心化基础架构。

+

Persona 摆脱了每站一密码

+

Persona 让用户在完成一个用于身份识别的简单一次性过程后只需点击两次即可登入网站,而不是每站一密码。这是在公钥密码学上构建的,安全可靠。用户的浏览器生成一个加密的“身份断言”来代替密码,它在几分钟后会过期并只在单个站点上有效。因为没有站点特定的密码,使用 Persona 的网站不需要关心密码数据库如何妥善存储或是丢失隐患。

+

这个快捷的登入过程也减少了用户访问新站点的摩擦。

+

Persona 身份是电子邮件地址

+

Persona 使用邮件地址作为身份,而不是任意形式的用户名。这让用户和开发者有所裨益:

+

用户使用邮件地址的优势

+ +

开发者使用邮件地址的优势

+ +

更不必说电子邮件已经是一个横跨无数服务提供者的有数以亿计账户的分布式系统。

+

Persona 与其它单点登录服务提供商有何区别?

+

Persona 安全、可靠,并且简单。它用其它提供商保护不用或不能的方法来用户隐私、用户控制和用户选择:

+

许多社交网络,诸如 Facebook 和 Google+,需要用户使用真名,并限制用户到单个账户。通过构建在邮件地址上,Persona 允许用户区分它们的工作、家庭、学校以及其它身份。

+

Persona 是开放的,也是分布式的:任何有电子邮件地址的人都可以登入使用 Persona 的站点。除此之外,任何人可以建立他们自己的身份提供者或委托给其它的权威机构,就像用电子邮件。这与需要一个单一中心化服务账号的社交登录服务相反。

+

Persona 也通过把用户浏览器放进认证过程中来提供保护用户隐私的新颖手段:浏览器从用户的邮件提供商获取证书,然后转向并把那些证书呈递给网站。电子邮件供应商不可能追踪用户,但网站仍然可以通过密码学验证证书来继续信任用户。大多数其它系统,即使是如 OpenID 这样的分布式系统,需要站点“背景连接通信(phone home)”才允许用户登入。

diff --git a/files/zh-cn/mozilla/preferences/index.html b/files/zh-cn/mozilla/preferences/index.html new file mode 100644 index 0000000000..442d12a5db --- /dev/null +++ b/files/zh-cn/mozilla/preferences/index.html @@ -0,0 +1,6 @@ +--- +title: Preferences +slug: Mozilla/Preferences +translation_of: Mozilla/Preferences +--- +This page was auto-generated because a user created a sub-page to this page. diff --git a/files/zh-cn/mozilla/preferences/mozilla_networking_preferences/index.html b/files/zh-cn/mozilla/preferences/mozilla_networking_preferences/index.html new file mode 100644 index 0000000000..117fa5d6af --- /dev/null +++ b/files/zh-cn/mozilla/preferences/mozilla_networking_preferences/index.html @@ -0,0 +1,536 @@ +--- +title: Mozilla 网络相关首选项 +slug: Mozilla/Preferences/Mozilla_networking_preferences +translation_of: Mozilla/Preferences/Mozilla_networking_preferences +--- +

摘要

+

本文列出了影响网络行为的首选项,并描述了可接受的值和行为。

+

受众

+

质量保证测试员、开发者以及熟知网络内部原理的骨灰级用户。
+ 要想获取关于首选项(包括如何编辑)的通用技术文档,请参阅“有关 Mozilla 首选项的简要指南”一文。

+

本文的目标是准确地记录有关 Core-Necko 的行为及是否在 Firefox 中默认存在的信息。

+

概观

+

The sections are in roughly alphabetical + functional order. The preferences are in order of usage by the UI (which is not often alphabetical order). Relevant bugs are provided only when absolutely necessary.

+
+

Note: Do not change any of these via about:config unless you know what you are doing. If you are uncertain what that phrase means, you probably do not.

+
+

If you qualify, you are probably one or more of the following:

+ +

首选项

+

HTTP(本部分仍在建设中)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
首选项名称可接受的值首选项是否默认存在及其他说明
general.useragent.contentlocalestring 
general.useragent.misc(major version number) string 
general.useragent.securitystring 
network.http.accept-encodinggzip,deflate (default string)no UI
network.http.accept.defaulttext/xml,application/xml,
+ application/xhtml+xml,text/html;

+ q=0.9,text/plain;
+ q=0.8,video/x-mng,image/png,
+ image/jpeg,image/gif;

+ q=0.2,*/*;q=0.1
 
network.http.default-socket-type(empty) default?
network.http.keep-alivetrue (default) 
network.http.keep-alive.timeout30no UI
network.http.max-connections96 
network.http.max-connections-per-server32 
network.http.max-persistent-connections-per-proxy4 
network.http.max-persistent-connections-per-server8 
network.http.pipeliningTrue? (on in mozilla, greyed)
network.http.pipelining.firstrequestTrue 
network.http.pipelining.maxrequests8 Hard-coded to 8 max so 30 will have no greater affect
network.http.proxy.keep-alivetrue (default) 
network.http.proxy.pipeliningTrue? (on in mozilla, greyed)
network.http.proxy.version1.1 (default)
+ 1.0
 
network.http.redirection-limit20 
network.http.request.max-start-delay10 
network.http.sendRefererHeader2 
network.http.sendSecureXSiteReferrertrue 
network.http.use-cachetrue 
network.http.version1.1 (default)
+ 1.0
 
+

文件

+ + + + + + + + + + + + + +
首选项名称Acceptable ValuesPreferences UI and comments
security.checkloaduritrue (default)
+ false
No UI
+ checkloaduri will disable file:// URLs on pages from a network (http: https: ftp:) source, for security reasons.
+ Errors are sent to the javascript console, not to the user via dialog box. This preference only works in Gecko versions before 1.8 (so Firefox 1.0 and Mozilla Suite builds). In Firefox 1.5 and Seamonkey 1.0 this preference no longer has an effect.
+

FTP(另请参见“代理”部分)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
首选项名称Acceptable ValuesPreferences UI (in bold) and comments
advanced.mailftpfalse (default)
+ true
Preferences | Advanced |
+ "{{ mediawiki.external('x') }} Set this email address as anonymous FTP password:"
+
+ If false, FTP uses "mozilla@example.com" as anonymous FTP password ({{ Bug("101027") }})
+ If true, FTP uses contents of network.ftp.anonymous_password for anonymous FTP password ({{ Bug("57763") }} comment 28)
network.ftp.anonymous_passwordempty (default)
+ any text string
Preferences | Advanced |
+ (under "{{ mediawiki.external(' ') }} Set this email address as anonymous FTP password:")
+ {{ mediawiki.external('text field') }}
+
+ If empty, FTP uses "mozilla@example.com" as anonymous FTP password.
network.ftp.idleConnectionTimeout300 (default)
+ any integer
No UI
+ Measured in seconds
+ The open connection can prevent other FTP clients on your system from connecting to sites that allow only one control connection ({{ Bug("117875") }})
network.dir.format0 = HTML view
+ 1 = raw view
+ 2 = HTML view
+ 3 = XUL view
Preferences | Debug | Networking
+ Networking
+ Directory Listing Format
+ ( ) HTML
+ ( ) XUL (tree-based)
+

缓存

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
首选项名称Acceptable ValuesPreferences UI (in bold) and comments
browser.cache.disk.capacity +

256000 (default)

+

any integer (in KB)

+
+

Preferences | Advanced | Cache
+ Cache: {{ mediawiki.external('MB') }} MB

+
+ Note: The default was 51200 prior to Gecko 9.0 {{ geckoRelease("9.0") }}.
+
browser.cache.disk.parent_directorypath to Cache folder in profile (default) +

Cache Folder: {{ mediawiki.external('text box') }}

+
+ Note: The contents of the disk and memory caches are different (a very large memory cache is not the same as pointing disk cache to memory mapped disk space (RAM disk).
+
browser.cache.disk.max_entry_size +

51200 (default)

+

-1 = no limit

+
+

The maximum size of an entry in the disk cache.

+
+ Note: Items larger than 1/8 of browser.cache.disk.capacity are never cached.
+
browser.cache.check_doc_frequency1 = Every time I view the page
+ 0 = Once per session
+ 3 = When the page is out of date (default)
+ 2 = Never
Compare the page in cache to the page on the network:
browser.cache.disk.enabletrue (default)Preferences | Debug | Cache
+ {{ mediawiki.external('x') }} Enable Disk Cache
+ {{ mediawiki.external('x') }} Enable Memory Cache
+
+ Disabling disk cache has the effect of setting it to zero.
browser.cache.memory.enabletrue (default)
browser.cache.memory.capacityany integer (in KB)Replaced by automatic sizing in Mozilla 1.4b ({{ Bug("105344") }}).
+ This value overrides the application.
+ 0 disables feature
+ (before, 4096 = default)
browser.cache.memory.max_entry_size +

5120 (default)

+

-1 = no limit

+
+

The maximum size of an entry in the memory cache (in KB).

+
+ Note: Items larger than 90% of browser.cache.memory.capacity are never cached.
+
network.http.use-cachetrue (default)no UI
browser.cache.disk_cache_sslfalse (default)no UI, added in 1.6a (see {{ Bug("205921") }})
network.prefetch-nextFalsePreferences | Advanced | Cache: Link Prefetching
+ {{ mediawiki.external('x') }} Prefetch web pages when idle, so that links in web page designed for prefetching can load faster.
browser.cache.disk.smart_size.first_runtrue (default)Indicates whether or not this is the first time smart sizing has been used.
browser.cache.disk.smart_size.enabledtrue (default)Indicates whether or not smart sizing of the disk cache is enabled.
+

DNS

+ + + + + + + + + + + + + + + + + +
首选项名称Acceptable ValuesPreferences UI (in bold) and comments
network.dnsCacheExpiration60 (seconds)default pref-less, not visible in about:config.
+ Create and set both values to "0" to disable.
network.dnsCacheEntries20 (entries)
+

Cookie

+

The old section in this document was removed because of dwitte's cookies re-write. Please see: Cookies Preferences in Mozilla

+

代理

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
首选项名称Acceptable ValuesPreferences UI (in bold) and comments
network.proxy.type0 = direct
+ 1 = manual
+ 2 = PAC
+ 3 = mapped to 0
+ 4 = WPAD
Preferences | Advanced | Proxies
+ Configure Proxies to Access the Internet
+ ( ) Direct connection to the internet
+ ( ) Auto-detect proxy settings (new in 1.8)
+ ( ) Manual proxy configuration
+ ( ) Automatic proxy configuration URL
+
+ 3 was old Communicator value for DIRECT.
network.proxy.http<Protocol> Proxy: hostname or IPv4 is acceptable. IPv6 needs to be tested.
+
+ Port: 0 will cause server:port preference for that manual proxy type to be ignored. 1-65xxx is valid range
Affects http: URLs
network.proxy.http_port
network.proxy.sslAffects https: URLs
+ Possibly affects SIMAP and SNEWS
network.proxy.ssl_port
network.proxy.ftpAffects ftp: URLs
network.proxy.ftp_port
network.proxy.gopher {{ obsolete_inline("2.0") }}Affects gopher: URLs
network.proxy.gopher_port {{ obsolete_inline("2.0") }}
network.proxy.socksUsed when application-specific proxy is not configured. Possibly affects other protocols
network.proxy.socks_port
network.proxy.socks_version5 (default)
+ 4
Communicator supported only SOCKS V4.
network.proxy.no_proxies_onlocalhost, 127.0.0.1 (default)
+ string of comma delimited fqdn's, hostnames, IPv4 addresses and CDIR blocks. See No Proxy For configuration.
Localhost is not proxied by default, {{ Bug("31510") }}.
network.proxy.autoconfig_urlempty (default)
+ URL string
must be absolute URl, no hostname
+

在线

+ + + + + + + + + + + + + + + + + + +
Preference NameAcceptable ValuesPreferences UI (in bold) and comments
network.onlinetrue = Mozilla is online (default)
+ false = Mozilla is offline
Necko updates the offline|online status to this value.
+ Changing this value does not change the actual networking status.
+ Value is not updated if "Ask me for online state at startup" was selected
+ for the current profile ({{ Bug("229677") }}).
offline.startup_state0 = use network.online (default)
+ 1 = prompt user
Preferences: Mail & Newsgroups | Offline | When starting up:
+ (Pref affects all modules, but was moved from Pref root, {{ Bug("202529") }})
+ {{ mediawiki.external('x') }} Remember previous online state
+ (Uses network.online to set online|offline status at startup)
+ {{ mediawiki.external(' ') }} Ask me for online state at startup
+ (Unlike Communicator, prompt always appears, {{ Bug("239564") }})
+

Gopher(另请参见“代理”部分)

+ + + + + + + + + + + + +
Preference NameAcceptable ValuesComments (bold for areas that user configures)
network.dir.formatsee FTP {{ obsolete_inline("2.0") }}
+

不推荐修改(Unsupported)

+ + + + + + + + + + + + + + + + + + +
Preference NameAcceptable ValuesComments (bold for areas that user configures)
browser.xul.error.pages.enabledfalse (default)
+ true
Does not appear in about.config unless added explicitly. See {{ Bug("28586") }})
network.protocol-handler.external.SCHEMEfalse (default)
+ true
Mac+Windows: sends URLs of <SCHEME> to the default OS handler
+ Linux/UNIX: sends URLs to application
+ For example: network.protocol-handler.external.mailto==true is used by Phoenix/Firebird/Firefox to access default mailers.
+ Handlers loaded before prefs are read cannot be redirected (e.g. file:)
+

 

+

已过时/已移除(此列表不全)

+ +

Under Investigation

+ +
+

原始文档信息

+ +
+

{{ languages( { "ja": "ja/Mozilla_Networking_Preferences" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/browser.altclicksave/index.html b/files/zh-cn/mozilla/preferences/preference_reference/browser.altclicksave/index.html new file mode 100644 index 0000000000..e00172c42c --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/browser.altclicksave/index.html @@ -0,0 +1,12 @@ +--- +title: browser.altClickSave +slug: Mozilla/Preferences/Preference_reference/browser.altClickSave +translation_of: Mozilla/Preferences/Preference_reference/browser.altClickSave +--- +

 browser.altClickSave 控制是否在按住alt键的同时点击链接执行下载动作.

+ +

+
true
在按住alt键的同时点击链接执行下载该链接的动作.
false (默认)
无下载动作 (查看{{ bug("736985") }}).
+
+

{{ languages( { "en": "en/Mozilla/Preferences/Preference_reference/browser.altClickSave" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/browser.download.lastdir.savepersite/index.html b/files/zh-cn/mozilla/preferences/preference_reference/browser.download.lastdir.savepersite/index.html new file mode 100644 index 0000000000..e758aedb86 --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/browser.download.lastdir.savepersite/index.html @@ -0,0 +1,31 @@ +--- +title: browser.download.lastDir.savePerSite +slug: Mozilla/Preferences/Preference_reference/browser.download.lastDir.savePerSite +translation_of: Mozilla/Preferences/Preference_reference/browser.download.lastDir.savePerSite +--- +

browser.download.lastDir.savePerSite 控制是否为每个网站记忆上次下载文件时所选的保存目录. 如果设置为 true, 则数据将保存在 content preference.

+ +

+
+
+ true (默认)
+
+ 该网站上次下载文件时用户所选的目录会被默认选择,如果是第一次在该网站下载文件,则会使用通用的 browser.download.lastDir 目录.
+
+ false
+
+ 下载文件时默认选择的目录会是通用的上次下载目录 ( browser.download.lastDir)
+
+

相关链接

+ +

{{ languages( { "en": "en/Mozilla/Preferences/Preferences_reference/browser.download.lastDir.savePerSite" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/browser.search.context.loadinbackground/index.html b/files/zh-cn/mozilla/preferences/preference_reference/browser.search.context.loadinbackground/index.html new file mode 100644 index 0000000000..c80e03a840 --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/browser.search.context.loadinbackground/index.html @@ -0,0 +1,14 @@ +--- +title: browser.search.context.loadInBackground +slug: >- + Mozilla/Preferences/Preference_reference/browser.search.context.loadInBackground +translation_of: >- + Mozilla/Preferences/Preference_reference/browser.search.context.loadInBackground +--- +

browser.search.context.loadInBackground 控制右键菜单中的"通过<搜索引擎>搜索<选中文字>"打开新标签页后,立即激活该标签页,还是保持当前标签页状态不变.

+ +

+
true
搜索页面在后台打开,保持当前标签页不变
false (默认)
搜索页面在前台打开(打开并激活).
+
+

{{ languages( { "en": "en/Mozilla/Preferences/Preference_reference/browser.search.context.loadInBackground" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/browser.urlbar.trimurls/index.html b/files/zh-cn/mozilla/preferences/preference_reference/browser.urlbar.trimurls/index.html new file mode 100644 index 0000000000..2f57e03212 --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/browser.urlbar.trimurls/index.html @@ -0,0 +1,12 @@ +--- +title: browser.urlbar.trimURLs +slug: Mozilla/Preferences/Preference_reference/browser.urlbar.trimURLs +translation_of: Mozilla/Preferences/Preference_reference/browser.urlbar.trimURLs +--- +

browser.urlbar.trimURLs 控制是否隐藏地址栏中域名前面的http协议字段和域名后面紧跟的斜杠 (前提是地址栏中的域名必须是当前网页的域名) .

+ +

+
true (默认值)
如果地址栏中的域名确实是当前网页的域名,那么顶级域名后面紧跟的斜杠会被隐藏.如果地址栏中的网址是以 http:// 协议开头且域名不以ftp. subdomain开头,也不包含@ (通常是ftp登陆信息)符号, 则这个http:// 前缀会被隐藏.

例如: https://www.example.org/ 会显示为 https://www.example.org, http://www.example.org/foobar 会显示为 www.example.org/foobar  http://ftp.example.org/foobar 保持不变.
false
显示完整的URL.
+
+

{{ languages( { "en": "en/Mozilla/Preferences/Preference_reference/browser.urlbar.trimURLs" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/dom.event.clipboardevents.enabled/index.html b/files/zh-cn/mozilla/preferences/preference_reference/dom.event.clipboardevents.enabled/index.html new file mode 100644 index 0000000000..cdff9ccd1a --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/dom.event.clipboardevents.enabled/index.html @@ -0,0 +1,12 @@ +--- +title: dom.event.clipboardevents.enabled +slug: Mozilla/Preferences/Preference_reference/dom.event.clipboardevents.enabled +translation_of: Mozilla/Preferences/Preference_reference/dom.event.clipboardevents.enabled +--- +

dom.event.clipboardevents.enabled 控制,当用户在网页上执行复制,粘贴或者剪切动作时,是否触发 oncopy, oncutonpaste 事件.

+ +

+
true (默认)
可以触发 oncopy, oncutonpaste 事件
false
不会触发 oncopy, oncutonpaste 事件
+
+

{{ languages( { "en": "en/Mozilla/Preferences/Preference_reference/dom.event.clipboardevents.enabled" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/index.html b/files/zh-cn/mozilla/preferences/preference_reference/index.html new file mode 100644 index 0000000000..f87f26f3cb --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/index.html @@ -0,0 +1,8 @@ +--- +title: Preference reference +slug: Mozilla/Preferences/Preference_reference +translation_of: Mozilla/Preferences/Preference_reference +--- +

{{ draft() }}

+

This is an automatically-generated list of subpages.

+

{{ListSubpages()}}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/javascript.options.strict/index.html b/files/zh-cn/mozilla/preferences/preference_reference/javascript.options.strict/index.html new file mode 100644 index 0000000000..0719935e05 --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/javascript.options.strict/index.html @@ -0,0 +1,13 @@ +--- +title: javascript.options.strict +slug: Mozilla/Preferences/Preference_reference/javascript.options.strict +translation_of: Mozilla/Preferences/Preference_reference/javascript.options.strict +--- +

当代码执行时,如果这条语句没有发生运行时错误,但却是用了非标准的特性,写法有问题,可能导致隐含的逻辑错误,则会生成JavaScript警告信息.该选项就控制着这些警告信息是否要打印到JavaScript控制台上.

+

 

+

可用的值和对应的效果

+

True: 在错误控制台上显示JavaScript错误和警告.
+
+ False: 在错误控制台上只显示JavaScript错误.(默认值)

+

 

+

相关链接: http://kb.mozillazine.org/Javascript.options.strict

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/ui.alertnotificationorigin/index.html b/files/zh-cn/mozilla/preferences/preference_reference/ui.alertnotificationorigin/index.html new file mode 100644 index 0000000000..7221433f99 --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/ui.alertnotificationorigin/index.html @@ -0,0 +1,12 @@ +--- +title: ui.alertNotificationOrigin +slug: Mozilla/Preferences/Preference_reference/ui.alertNotificationOrigin +translation_of: Mozilla/Preferences/Preference_reference/ui.alertNotificationOrigin +--- +

ui.alertNotificationOrigin 控制由 nsIAlertsService 生成的弹出提示窗口向外滚动时的位置和方向.

+ +

+
0
右下角,由下向上滑出
1
右下角, 由右向左滑出
2
左下角, 由下向上滑出
3
左下角, 由左向右滑出
4
右上角, 由上向下滑出
5
右上角, 由右向左滑出
6
左上角, 由上向下滑出
7
左上角, 由左向右滑出
+
+

{{ languages( { "en": "en/Mozilla/Preferences/Preference_reference/ui.alertNotificationOrigin" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderline/index.html b/files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderline/index.html new file mode 100644 index 0000000000..cbbb0e3961 --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderline/index.html @@ -0,0 +1,12 @@ +--- +title: ui.SpellCheckerUnderline +slug: Mozilla/Preferences/Preference_reference/ui.SpellCheckerUnderline +translation_of: Mozilla/Preferences/Preference_reference/ui.SpellCheckerUnderline +--- +

ui.SpellCheckerUnderline 控制拼写检查器给不认识的单词所加的下划线的颜色.

+ +

+
 颜色RGB值 例如 #ff0000 是红色.
+
+

{{ languages( { "en": "en/Mozilla/Preferences/Preference_reference/ui.SpellCheckerUnderline" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderlinestyle/index.html b/files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderlinestyle/index.html new file mode 100644 index 0000000000..573e8ec36f --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/ui.spellcheckerunderlinestyle/index.html @@ -0,0 +1,13 @@ +--- +title: ui.SpellCheckerUnderlineStyle +slug: Mozilla/Preferences/Preference_reference/ui.SpellCheckerUnderlineStyle +translation_of: Mozilla/Preferences/Preference_reference/ui.SpellCheckerUnderlineStyle +--- +

ui.SpellCheckerUnderlineStyle 控制拼写检查器给不认识的单词所加的下划线的样式.

+ +

+

下面的值被定义在源代码 nsStyleConsts.h 中.

+
0
无下划线
1
点状线
2
虚线
3
单实线
4
双实线
5 (默认值)
波浪线
+
+

{{ languages( { "en": "en/Mozilla/Preferences/Preference_reference/ui.SpellCheckerUnderlineStyle" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/ui.tooltipdelay/index.html b/files/zh-cn/mozilla/preferences/preference_reference/ui.tooltipdelay/index.html new file mode 100644 index 0000000000..c92dd03248 --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/ui.tooltipdelay/index.html @@ -0,0 +1,13 @@ +--- +title: ui.tooltipDelay +slug: Mozilla/Preferences/Preference_reference/ui.tooltipDelay +translation_of: Mozilla/Preferences/Preference_reference/ui.tooltipDelay +--- +

{{ gecko_minversion_header("11.0") }}

+

ui.tooltipDelay 存储着一个单位为毫秒的时间数值,该数值表示鼠标停留在某个元素上多长时间后显示出提示信息.

+ +

+
整数(单位为毫秒, 默认值: 500)
该数值表示鼠标停留在某个元素上多长时间后显示出提示信息,单位为毫秒,默认值为500ms.
+
+

{{ languages( { "zh-cn": "zh-cn/Mozilla/Preferences/Preference_reference/ui.tooltipDelay" } ) }}

diff --git a/files/zh-cn/mozilla/preferences/preference_reference/view_source.syntax_highlight/index.html b/files/zh-cn/mozilla/preferences/preference_reference/view_source.syntax_highlight/index.html new file mode 100644 index 0000000000..c09889f0be --- /dev/null +++ b/files/zh-cn/mozilla/preferences/preference_reference/view_source.syntax_highlight/index.html @@ -0,0 +1,6 @@ +--- +title: view_source.syntax_highlight +slug: Mozilla/Preferences/Preference_reference/view_source.syntax_highlight +translation_of: Mozilla/Preferences/Preference_reference/view_source.syntax_highlight +--- +

This page was auto-generated because a user created a sub-page to this page.

diff --git a/files/zh-cn/mozilla/projects/crash_reporting/index.html b/files/zh-cn/mozilla/projects/crash_reporting/index.html new file mode 100644 index 0000000000..bb8fd91519 --- /dev/null +++ b/files/zh-cn/mozilla/projects/crash_reporting/index.html @@ -0,0 +1,47 @@ +--- +title: Crash reporting +slug: Mozilla/Projects/Crash_reporting +tags: + - Crashes + - Developer Guide + - Developing Mozilla + - Firefox + - Mozilla + - NeedsTranslation + - QA + - TopicStub + - crash reports +translation_of: Mozilla/Projects/Crash_reporting +--- +

Firefox ships with an open-source crash reporting system. This system is combination of projects:

+ + + +

Where did my crash get submitted?

+ +

Crash data submitted using the Mozilla Crash Reporter is located on crash-stats. If you want to find a specific crash that you submitted, you first need to find the Crash ID that the server has assigned your crash. Type about:crashes into your location bar to get a page listing both submitted and unsubmitted crash reports. For more information, see How to get a stacktrace for a bug report.

+ +

Reports and queries

+ +

crash-stats has built-in reports of "topcrashes" for each release grouped by signature. There is also a custom query tool which allows users to limit searches on more precise information.

+ +

For more automated usage, a summary of each day's crash reports is published as a CSV file, as well as batch analysis jobs. These can be found at https://crash-analysis.mozilla.com/crash_analysis/

+ +

Finally, a set of Mozilla employees have access to directly query the underlying data in either SQL summary or using mapreduce on the storage cluster. If you are interested in obtaining this advanced access, contact Benjamin Smedberg.

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/projects/emscripten/index.html b/files/zh-cn/mozilla/projects/emscripten/index.html new file mode 100644 index 0000000000..9d488c2d8e --- /dev/null +++ b/files/zh-cn/mozilla/projects/emscripten/index.html @@ -0,0 +1,37 @@ +--- +title: Emscripten +slug: Mozilla/Projects/Emscripten +translation_of: Mozilla/Projects/Emscripten +--- +

Emscripten 是一个 LLVM (底层虚拟机)生成 JavaScript 的编译器. 它采用 LLVM 的字节码 (例如,使用 Clang 从 C/C++ 或者从其他语言生成的字节码) 并将其编译成可在 Web 上面运行的 JavaScript

+ +
+

重要提示:本页简要介绍了 Emscripten 是什么。要开始使用 Emscripten请访问官方的Emscripten Wiki

+
+ +

使用 Emscripten,你可以

+ + + +

Emscripten 使原生代码可立即使用在 Web 上:是一个具有众多独立兼容的实现,可在从 PC 到 iPad 的任何地方运行的标准平台。

+ +

借助 Emscripten,C / C ++ 开发人员无需手动将代码移植到 JavaScript 上,也无需学习 JavaScript。Web 开发人员也可以从中受益,因为他们可以在自己的站点中使用成千上万的已存在的原生实用程序和库。

+ +

实际上,任何可移植的 C 或 C++ 代码库都可以通过 Emscripten 编译成 JavaScript,从需要渲染图形,播放声音,加载和处理文件的高性能游戏到诸如 Qt 的应用程序框架。

+ +

Emscripten 生成的代码(其默认输出格式为 asm.js ,这是 JavaScript 的高度优化子集)在许多情况下可以以接近原生的速度执行。

+ +
+

注意:听起来有趣吗? 阅读有关 Emscripten 的更多信息并尝试一些 demo,然后开始使用它

+
+ +

MDN上其他有趣的文章

+ + diff --git a/files/zh-cn/mozilla/projects/index.html b/files/zh-cn/mozilla/projects/index.html new file mode 100644 index 0000000000..c1e43934a2 --- /dev/null +++ b/files/zh-cn/mozilla/projects/index.html @@ -0,0 +1,14 @@ +--- +title: Projects +slug: Mozilla/Projects +tags: + - Mozilla + - NeedsContent + - NeedsTranslation + - Projects + - TopicStub +translation_of: Mozilla/Projects +--- +

{{ draft() }}

+

Below you'll find links to documentation about various Mozilla projects; these are often parts of Firefox or other products, but may also be used in other projects as well.

+

{{ LandingPageListSubpages() }}

diff --git a/files/zh-cn/mozilla/projects/l20n/index.html b/files/zh-cn/mozilla/projects/l20n/index.html new file mode 100644 index 0000000000..ce256b741f --- /dev/null +++ b/files/zh-cn/mozilla/projects/l20n/index.html @@ -0,0 +1,127 @@ +--- +title: L20n +slug: Mozilla/Projects/L20n +translation_of: Mozilla/Projects/L20n +--- +

当这个文档还是草案的时候, 请上 GitHub.

+
+ 一个JavaScript本地化框架, 释放你的本地语言的魅力, 仅使用简单的代码.
+
+
+

Introducing L20n

+

L20n reinvents software localization. Users should be able to benefit from the entire expressive power of the natural language. L20n keeps simple things simple, and at the same time makes complex things possible.

+

Through L20n, Mozilla is creating a new generation of technology that places more power in localizers' hands. L20n lets localizers reach higher levels of free linguistic expression by sharpening the divide between localization and application logic. It allows to adapt your web application not only to languages and cultures, but also contextual data, user gender and screen dimensions.

+
+
+

What L20n looks like

+

Here is a simple, straightforward example showing an English string being provided:

+
<brandName "Firefox">
+<about "About \{{ brandName }}">
+

Here is the same string being provided in Slovenian:

+
<brandName {
+  nominative: "Firefox",
+  genitive: "Firefoxa",
+  dative: "Firefoxu",
+  accusative: "Firefox",
+  locative: "Firefoxu",
+  instrumental: "Firefoxom"
+}>
+<about "O \{{ brandName.locative }}">
+
+
+

 

+
+
+

For Developers

+

Documentation for developers wanting to implement localization functionality on their web apps using L20n.

+
+
+ Internationalization for your web app
+
+ First read for developers looking to use the L20n infrastructure.
+
+ L20n's HTML bindings
+
+ Tutorial on implementing L20n in your HTML code.
+
+ L20n JavaScript API
+
+ An API for l20n.js.
+
+ L20n syntax cheatsheet for developers
+
+ A simple cheatsheet to help developers as they add L20n to their localization infrastructure.
+
+
+
+

For Localizers

+

Documentation for Localizers creating localized content for a project that uses L20n.

+
+
+ Learn the L20n syntax
+
+ How to naturally localize applications using L20n. Complete with use cases and examples of L20n in action.
+
+ Localization use-cases
+
+ How to naturally localize applications using L20n. Complete with use cases and examples of L20n in action.
+
+ L20n and Translation Memory eXchange (TMX)
+
+ How L20n impacts the Translation Memory eXchange standard for translation memory data.
+
+ L20n syntax cheatsheet for localizers
+
+ A simple cheatsheet to help localizers as they localize projects with L20n.
+
+
+
+ +

Some additional resources for developers and localizers involved with L20n.

+
+
+ L20n.org
+
+ You can try L20n live in your browser on the project page.
+
+ L20n Tinker
+
+ Test out your own L20n code in L20n Tinker.
+
+ GitHub
+
+ Where the main code for the L20n infrastructure and design spec lives.
+
+ Wiki page
+
+ Info about the project to develop L20n.
+
+
+
+ +
    +
  1. For Developers +
      +
    1. Internationalization for your web app
    2. +
    3. L20n's HTML bindings
    4. +
    5. .lol file format
    6. +
    7. L20n syntax cheatsheet for developers
    8. +
    +
  2. +
  3. For Localizers +
      +
    1. Learn the L20n syntax
    2. +
    3. Localization use cases
    4. +
    5. L20n and Translation Memory eXchange (TMX)
    6. +
    7. L20n syntax cheatsheet for localizers
    8. +
    +
  4. +
  5. Additional resources +
      +
    1. L20n.org
    2. +
    3. L20n Tinker
    4. +
    5. L20n GitHub repo
    6. +
    7. Mozilla Wiki
    8. +
    +
  6. +
diff --git a/files/zh-cn/mozilla/projects/nspr/index.html b/files/zh-cn/mozilla/projects/nspr/index.html new file mode 100644 index 0000000000..2ae2b7b9d5 --- /dev/null +++ b/files/zh-cn/mozilla/projects/nspr/index.html @@ -0,0 +1,60 @@ +--- +title: NSPR +slug: Mozilla/Projects/NSPR +translation_of: Mozilla/Projects/NSPR +--- +

Netscape Portable Runtime (NSPR)  提供一套面向系统级的与平台无关的 API  和类似于libc的函数. 这些API被用在Mozilla客户端, Red Hat公司、Sun公司的服务应用程序以及其他公司的一些软件中。

+ + + + + + + +
+

文档

+
+
+ NSPR工程页面
+
+ Contains some older technical notes and training materials. (at mozilla.org)
+
+
+
+ 关于 NSPR
+
+ This topic describes, in general terms, the goals of NSPR and a bit about how it does it.
+
+
+
+ NSPR API Reference
+
+ The reference describes each API public macro, structure and function in the NSPR API.
+
+
+
+ NSPR build instructions
+
+ How to checkout and build from source.
+
+
+
+ NSPR release process
+
+ How to prepare an NSPR release.
+
+

View All...

+
+

Community

+
    +
  • View Mozilla forums...
  • +
+

{{ DiscussionList("dev-tech-nspr", "mozilla.dev.tech.nspr") }}

+ +
+
+ Necko, NSS
+
+
+

 

+

{{ languages( { "ja": "ja/NSPR", "it": "it/NSPR" } ) }}

diff --git a/files/zh-cn/mozilla/projects/nspr/reference/index.html b/files/zh-cn/mozilla/projects/nspr/reference/index.html new file mode 100644 index 0000000000..fe690af267 --- /dev/null +++ b/files/zh-cn/mozilla/projects/nspr/reference/index.html @@ -0,0 +1,770 @@ +--- +title: NSPR API Reference +slug: Mozilla/Projects/NSPR/Reference +tags: + - NSPR + - NSPR_API_Reference + - NeedsTranslation + - TopicStub +translation_of: Mozilla/Projects/NSPR/Reference +--- + + +

Introduction to NSPR

+ + + +

NSPR Types

+ + + +

Threads

+ + + +

Process Initialization

+ + + +

Locks

+ + + +

Condition Variables

+ + + +

Monitors

+ + + +

Cached Monitors

+ + + +

I/O Types

+ + + +

I/O Functions

+ + + +

Network Addresses

+ + + +

Atomic Operations

+ + + +

Interval Timing

+ + + +

Date and Time

+ + + +

Memory Management Operations

+ + + +

String Operations

+ + + +

Floating Point Number to String Conversion

+ + + +

Long Long (64-bit) Integers

+ +

BitMaps

+ +

Formatted Printing

+ +

Linked Lists

+ + + +

Dynamic Library Linking

+ + + +

Process Management and Interprocess Communication

+ + + +

Multiwait Receive

+ +

System Information and Environment Variables

+ +

Logging

+ + + +

Instrumentation Counters

+ +

Named Shared Memory

+ + + +

Anonymous Shared Memory

+ + + +

IPC Semaphores

+ + + +

Thread Pools

+ + + +

Random Number Generator

+ + + +

Hash Tables

+ + + +

NSPR Error Handling

+ + diff --git a/files/zh-cn/mozilla/projects/nspr/reference/memory_management_operations/index.html b/files/zh-cn/mozilla/projects/nspr/reference/memory_management_operations/index.html new file mode 100644 index 0000000000..9fbb05ae70 --- /dev/null +++ b/files/zh-cn/mozilla/projects/nspr/reference/memory_management_operations/index.html @@ -0,0 +1,424 @@ +--- +title: 内存管理操作 +slug: Mozilla/Projects/NSPR/Reference/Memory_Management_Operations +tags: + - GC + - NSPR +translation_of: Mozilla/Projects/NSPR/Reference/Memory_Management_Operations +--- + + +

本章介绍用于执行内存管理的全局函数和宏。NSPR 提供基于堆内存管理的函数,映射到熟悉的malloc(), calloc(), realloc(), 和 free().

+ + + +

内存分配函数

+ +

NSPR has its own heap, and these functions act on that heap. Libraries built on top of NSPR, such as the Netscape security libraries, use these functions to allocate and free memory. If you are allocating memory for use by such libraries or freeing memory that was allocated by such libraries, you must use these NSPR functions rather than the libc equivalents.

+ +

Memory allocation functions are:

+ + + +

PR_Malloc(), PR_Calloc(), PR_Realloc(), and PR_Free() have the same signatures as their libc equivalents malloc(), calloc(), realloc(), and free(), and have the same semantics. (Note that the argument type size_t is replaced by PRUint32.) Memory allocated by PR_Malloc(), PR_Calloc(), or PR_Realloc() must be freed by PR_Free().

+ +

内存分配 Macros

+ +

Macro versions of the memory allocation functions are available, as well as additional macros that provide programming convenience:

+ + diff --git a/files/zh-cn/mozilla/projects/psm/index.html b/files/zh-cn/mozilla/projects/psm/index.html new file mode 100644 index 0000000000..69fcd93234 --- /dev/null +++ b/files/zh-cn/mozilla/projects/psm/index.html @@ -0,0 +1,15 @@ +--- +title: Personal Security Manager (PSM) +slug: Mozilla/Projects/PSM +translation_of: Mozilla/Projects/PSM +--- +

PSM全称为Personal Security Manager,包含了一套在客户应用程序上执行密码操作的代码库。这些操作包括设置SSL连接,对象签名和签名认证,证书管理(包括发行和废弃),和其它通用PKI函数。

+ +

注意:

+ + + +

 

diff --git a/files/zh-cn/mozilla/projects/rhino/bsf/index.html b/files/zh-cn/mozilla/projects/rhino/bsf/index.html new file mode 100644 index 0000000000..8cf8b6c13e --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/bsf/index.html @@ -0,0 +1,10 @@ +--- +title: BSF +slug: Mozilla/Projects/Rhino/BSF +translation_of: Mozilla/Projects/Rhino/BSF +--- +

BSF是什么?

+

Bean Scripting Framework (BSF)起初被IBM开发,后来作为Apache Software Foundation开源代码的一部分.它为Java上的大量的脚本语言提供了一个框架,Rhino是被支持的语言之一.

+

这个框架已被大量的开源项目嵌入代码中, 包括 XSL 处理器 Xalan 和  XML/Java 构建工具 Ant. 查看 Xalan-Java Extensions 可以获取更多关于把JavaScript添加至XSL、在Apache Ant Manual中使用脚本构建项目时脚本任务的命令项的描述等信息.

+

Using BSF with Rhino

+

Now that the Apache Jakarta Bean Scripting Framework (BSF), version 2.4.0, has been officially released, you can use Rhino easily with BSF. See http://jakarta.apache.org/bsf/index.html.

diff --git a/files/zh-cn/mozilla/projects/rhino/community/index.html b/files/zh-cn/mozilla/projects/rhino/community/index.html new file mode 100644 index 0000000000..8d5c3a446c --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/community/index.html @@ -0,0 +1,24 @@ +--- +title: Rhino社区 +slug: Mozilla/Projects/Rhino/Community +translation_of: Mozilla/Projects/Rhino/Community +--- +

是否有在Rhino文档中找不到解答的问题?下面这些资源可以给你一些帮助:

+ +

邮件列表

+ +

在Google讨论组中有一个叫mozilla-rhino的讨论组,可以讨论Rhino相关的话题.

+ +

还有一个比较老的讨论组叫mozilla.dev.tech.js-engine.rhino,已经很久没有维护了,请使用新的讨论组,但是这个老的组可能也包含一些比较有历史意义的讨论,可以去参考浏览一下.

+ +

mozilla.dev.tech.js-engine这个讨论组讨论的是关于使用C语言实现的Javascript,也有在2007年9月27日之前关于Rhino的讨论.要看在2007年9月27日之前的讨论,请移步一个叫Google group for the earlier newsgroup的Google讨论组.

+ +

Bug 系统

+ +

最好的提交Rhino bug的方式是在Rhino的Github中提交.

+ +

如果你愿意解决一些提交的Bug,我们非常欢迎您解决她,并提交一个pull请求.

+ +

许多老的Rhino的问题都被记录在Bugzilla中.也许有一些比较有历史意义的bug. 最后注意Rhino有自己的产品类目.

+ +

{{ languages( { "ja": "ja/Rhino_help" } ) }}

diff --git a/files/zh-cn/mozilla/projects/rhino/debugger/index.html b/files/zh-cn/mozilla/projects/rhino/debugger/index.html new file mode 100644 index 0000000000..8b5ab147ca --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/debugger/index.html @@ -0,0 +1,220 @@ +--- +title: Rhino Debugger +slug: Mozilla/Projects/Rhino/Debugger +translation_of: Mozilla/Projects/Rhino/Debugger +--- +

The Rhino JavaScript debugger is a GUI that allows debugging of interpreted JavaScript scripts run in Rhino. Note that this debugger will not work with JavaScript scripts run in the mozilla browser since Rhino is not the engine used in such environments.

+

+

Current limitations:

+ +

Using the Rhino JavaScript Debugger

+

The Mozilla Rhino JavaScript engine includes a source-level debugger for debugging JavaScript scripts. The debugger is itself a Java program which you may run as

+
java org.mozilla.javascript.tools.debugger.Main [options] [filename.js] [script-arguments]
+
+
+

where the options are the same as the shell.

+

The Rhino JavaScript Debugger can debug scripts running in multiple threads and provides facilities to set and clear breakpoints, control execution, view variables, and evaluate arbitrary JavaScript code in the current scope of an executing script.

+
+
+ Console Window
+
+ The debugger redirects the System.out, System.in, and System.err streams to an internal JavaScript console window which provides an editable command line for you to enter JavaScript code and view system output. The console window maintains a history of the commands you have entered. You may move backward and forward through the history list by pressing the Up/Down arrow keys on the keyboard.
+
+ Opening Scripts
+
+ You may select the + + File->Open + menu item on the menu bar to load JavaScript scripts contained in files. This action will display a file-selection dialog box prompting you for the location of a script to load. The selected file will be compiled and displayed in a new window.
+
+ Running Scripts
+
+ You may select the + + File->Run + menu item on the menu bar to execute JavaScript scripts contained in files. This action will display a file-selection dialog box prompting you for the location of a script to execute. The loaded script will be run in a new thread and control will be given to the debugger on its first instruction.
+
+

Controlling Execution

+

The debugger provides the following facilities for you to control the execution of scripts you are debugging:

+
+
+ Step Into
+
+ To single step entering any function calls, you may do any of the following: +
    +
  • Select the + + Debug->Step Into + menu item on the menu bar
  • +
  • Press the + + Step Into + button on the toolbar
  • +
  • Press the F11 key on the keyboard
  • +
+

Execution will resume. If the current line in the script contains a function call control will return to the debugger upon entry into the function. Otherwise control will return to the debugger at the next line in the current function.

+
+
+ Step Over
+
+ To single step to the next line in the current function, you may do any of the following: +
    +
  • Select the + + Debug->Step Over + menu item on the menu bar
  • +
  • Press the + + Step Over + button on the toolbar
  • +
  • Press the F7 key on the keyboard
  • +
+

Execution will resume but control will return to the debugger at the next line in the current function or top-level script.

+
+
+ Step Out
+
+ To continue execution until the current function returns you may do any of the following: +
    +
  • Select the + + Debug->Step Out + menu item on the menu bar
  • +
  • Press the + + Step Out + button on the toolbar
  • +
  • Press the F8 key on the keyboard
  • +
+

Execution will resume until the current function returns or a breakpoint is hit.

+
+
+ Go
+
+ To resume execution of a script you may do any of the following: +
    +
  • Select the + + Debug->Go + menu item on the menu bar
  • +
  • Press the + + Go + button on the toolbar
  • +
  • Press the F5 key on the keyboard
  • +
+

Execution will resume until a breakpoint is hit or the script completes.

+
+
+ Break
+
+ To stop all running scripts and give control to the debugger you may do any of the following: +
    +
  • Select the + + Debug->Break + menu item on the menu bar
  • +
  • Press the + + Break + button on the toolbar
  • +
  • Press the Pause/Break key on the keyboard
  • +
+
+
+ Break on Exceptions
+
+ To give control to the debugger whenever a JavaScript is exception is thrown select the + + Debug->Break on Exceptions + checkbox from the menu bar. Whenever a JavaScript exception is thrown by a script a message dialog will be displayed and control will be given to the debugger at the location the exception is raised.
+
+ Break on Function Enter
+
+ Selecting + + Debug->Break on Function Enter + will give control to the debugger whenever the execution is entered into a function or script.
+
+ Break on Function Exit
+
+ Selecting + + Debug->Break on Function Return + will give control to the debugger whenever the execution is about to return from a function or script.
+
+ Moving Up and Down the Stack
+
+ The lower-left (dockable) pane in the debugger main window contains a combo-box labeled "Context:" which displays the current stack of the executing script. You may move up and down the stack by selecting an entry in the combo-box. When you select a stack frame the variables and watch windows are updated to reflect the names and values of the variables visible at that scope.
+
+ Setting and Clearing Breakpoints
+
+ The main desktop of the debugger contains file windows which display the contents of each script you are debugging. You may set a breakpoint in a script by doing one of the following: +
    +
  • Place the cursor on the line at which you want to set a breakpoint and right-click with the mouse. This action will display a pop-up menu. Select the + + Set Breakpoint + menu item.
  • +
  • Simply single-click on the line number of the line at which you want to set a breakpoint.
  • +
+

If the selected line contains executable code a red dot will appear next to the line number and a breakpoint will be set at that location.

+

You may clear breakpoint in a script by doing one of the following:

+
    +
  • Place the cursor on the line at which you want to clear a breakpoint and right-click with the mouse. This action will display a pop-up menu. Select the + + Clear Breakpoint + menu item.
  • +
  • Simply single-click on the red dot or the line number of the line at which you want to clear a breakpoint.
  • +
+

The red dot will disappear and the breakpoint at that location will be cleared.

+
+
+

Viewing Variables

+

The lower-left (dockable) pane in the debugger main window contains a tab-pane with two tabs, labeled "this" and "Locals". Each pane contains a tree-table which displays the properties of the current object and currently visible local variables, respectively.

+
+
+ This
+
+ The properties of the current object are displayed in the + + this + table. If a property is itself a JavaScript object the property may be expanded to show its sub-properties. The + + this + table is updated each time control returns to the debugger or when you change the stack location in the + + Context: + window.
+
+ Locals
+
+ The local variables of the current function are displayed in the + + Locals + table. If a variable is itself a JavaScript object the variable may be expanded to show its sub-properties. The + + Locals + table is updated each time control returns to the debugger or when you change the stack location in the + + Context: + window
+
+ Watch Window
+
+ You may enter arbitrary JavaScript expressions in the + + Watch: + table located in the lower-right (dockable) pane in the debugger main window. The expressions you enter are re-evaluated in the current scope and their current values displayed each time control returns to the debugger or when you change the stack location in the + + Context: + window.
+
+ Evaluation Window
+
+ The + + Evaluate + pane located in the lower-right (dockable) pane in the debugger main window contains an editable command line where you may enter arbitrary JavaScript code. The code is evaluated in the context of the current stack frame. The window maintains a history of the commands you have entered. You may move backward or forward through the history by pressing the Up/Down arrow keys on the keyboard.
+
diff --git a/files/zh-cn/mozilla/projects/rhino/documentation/index.html b/files/zh-cn/mozilla/projects/rhino/documentation/index.html new file mode 100644 index 0000000000..74ae49d94e --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/documentation/index.html @@ -0,0 +1,81 @@ +--- +title: Rhino 文档 +slug: Mozilla/Projects/Rhino/Documentation +translation_of: Mozilla/Projects/Rhino/Documentation +--- +

以下是面向 Rhino 脚本创作者和集成者的信息.

+ +

概述

+ +
+
简介
+
Rhino 和 JavaScript 的简介.
+
许可
+
Rhino 的许可信息.
+
依赖和局限
+
运行 Rhino 所需要的要件; 以及 Rhino 不能做什么.
+
发布存档
+
Rhino 的历史版本以及发行说明.
+
优化
+
优化级别的详细说明.
+
FAQ
+
针对 Rhino 的 FAQ.
+
Rhino 的历史
+
关于这只野兽(Rhino)的历史.
+
+ +

撰写脚本

+ +
+
在 Java 中撰写脚本
+
使用 Rhino 编写 Java 类的方法.
+
在 Java 中撰写脚本
+
使用 Rhino 编写 Java 类的方法. (旧版).
+
性能
+
撰写更高效的 JavaScript 的窍门.
+
+ +

JavaScript 工具

+ +
+
Rhino Shell
+
交互式或批处理式执行脚本.
+
JavaScript 调试器
+
调试执行于 Rhino 中的脚本.
+
JavaScript 编译器
+
将脚本编译成类文件.
+
运行Rhino测试
+
使用Rhino运行javascript单元测试.
+
+ +

嵌入 Rhino

+ +
+
嵌入教程
+
一个介绍如何将Rhino嵌入到你的应用程序的简短教程.
+
API Javadoc Reference (无法访问?  Try this at Jarvana.)
+
一个带有解释的Rhino编程api大纲(只有一些小提示).
+
Scopes and Contexts
+
描述如何在多线程环境中高效、灵活的使用scopes和contexts.
+
序列化
+
如何在Rhino中序列化javascript对象和函数.
+
运行时
+
一个对于javascrit运行时的简短介绍.
+
Small Footprint
+
对于那些热衷于小面积脚本嵌入(small-footprint embeddings)的人的提示.
+
例子
+
一些展示如何控制javascript引擎以及创建javascript宿主对象的例子.
+
Using Rhino with Bean Scripting Framework (BSF)
+
如何在支持BSF(Bean 脚本框架)的app中通过Apache Jakarta project使用Rhino.
+
+ +

外部链接

+ +
+
在java中使用的脚本语言
+
一篇将Rhino和Jython进行对比的文章.
+
+ +

Rhino 贡献者

+ +

有志于为 Rhino 贡献力量? 来看看 Rhino Wish List 吧.

diff --git a/files/zh-cn/mozilla/projects/rhino/download_rhino/index.html b/files/zh-cn/mozilla/projects/rhino/download_rhino/index.html new file mode 100644 index 0000000000..54bf9966b8 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/download_rhino/index.html @@ -0,0 +1,106 @@ +--- +title: 下载 Rhino +slug: Mozilla/Projects/Rhino/Download_Rhino +translation_of: Mozilla/Projects/Rhino/Download_Rhino +--- +

Rhino 同时提供源代码和已编译形式的下载.

+ +

字节码文件

+ +

Rhino 1.7R5 是最新的稳定发行版.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
发行版本发行时间变更日志下载链接
Rhino 1.7R42012-06-18New in Rhino 1.7R4rhino1_7R4.zip
Rhino 1.7R52015-01-29变更日志rhino1_7R5.zip
Rhino 1.7.62015-04-15变更日志rhino1.7.6.zip
Rhino 1.7.72015-06-17变更日志rhino1.7.7.zip
Rhino 1.7.7.12016-02-01变更日志rhino1.7.7.1.zip
Rhino 1.7.7.22017-08-24变更日志rhino1.7.7.2.zip
Rhino 1.7.82018-01-22变更日志rhino1.7.8.zip
Rhino 1.7.92018-03-15变更日志rhino1.7.9.zip
Rhino 1.7.102018-04-09变更日志rhino1.7.10.zip
Rhino 1.7.112019-05-30变更日志rhino1.7.11.zip
Rhino 1.7.122020-01-13变更日志rhino1.7.12.zip
+ +

下载较旧版本的Rhino,可以参考 Rhino 下载存档.

+ +

许可

+ +

Rhino 是开源的, 从 1.7R4 开始以 MPL 2.0 许可.

+ +

在此之前的版本遵循 MPL 1.1/GPL 2.0 许可.

+ +

参考更详细的 Rhino 许可证 信息.

+ +

源代码

+ +

除了从上面zip文件获取源外,Rhino 的源代码可以在GitHub上的https://github.com/mozilla/rhino找到。 要获取源,使用命令

+ +
$ git clone https://github.com/mozilla/rhino.git
+
+ +

Rhino 使用 Ant 作为它的构建系统.。在Rhino分配的顶级目录运行 ant 命令将打印打印可构建目标的清单。

diff --git a/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html b/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html new file mode 100644 index 0000000000..b7cf0168f5 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html @@ -0,0 +1,221 @@ +--- +title: 'Tutorial: Embedding Rhino' +slug: Mozilla/Projects/Rhino/Embedding_tutorial +translation_of: Mozilla/Projects/Rhino/Embedding_tutorial +--- +

Embedding Rhino can be done simply with good results. With more effort on the part of the embedder, the objects exposed to scripts can be customized further.

+

This tutorial leads you through the steps from a simple embedding to more customized, complex embeddings. Fully compilable examples are provided along the way.

+

The examples live in the rhino/examples directory in the distribution and in mozilla/js/rhino/examples in cvs. This document will link to them using lxr.

+

In this document, JavaScript code will be in green, Java code will be in green, and shell logs will be in purple.

+

In this document:

+ +

RunScript: A simple embedding

+

About the simplest embedding of Rhino possible is the RunScript example. All it does it read a script from the command line, execute it, and print a result.

+

Here's an example use of RunScript from a shell command line:

+
$ java RunScript "Math.cos(Math.PI)"
+-1
+$ java RunScript "function f(x){return x+1} f(7)"
+8
+
+

Note that you'll have to have both the Rhino classes and the RunScript example class file in the classpath. Let's step through the body of main one line at time.

+

Entering a Context

+

The code

+
Context cx = Context.enter();
+
+

Creates and enters a Context. A Context stores information about the execution environment of a script.

+

Initializing standard objects

+

The code

+
Scriptable scope = cx.initStandardObjects();
+
+

Initializes the standard objects (Object, Function, etc.) This must be done before scripts can be executed. The null parameter tells initStandardObjects to create and return a scope object that we use in later calls.

+

Collecting the arguments

+

This code is standard Java and not specific to Rhino. It just collects all the arguments and concatenates them together.

+
String s = "";
+for (int i=0; i < args.length; i++) {
+    s += args[i];
+}
+
+

Evaluating a script

+

The code

+
Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);
+
+

uses the Context cx to evaluate a string. Evaluation of the script looks up variables in scope, and errors will be reported with the filename <cmd> and line number 1.

+

Printing the result

+

The code

+
System.out.println(cx.toString(result));
+
+

prints the result of evaluating the script (contained in the variable result). result could be a string, JavaScript object, or other values. The toString method converts any JavaScript value to a string.

+

Exiting the Context

+

The code

+
} finally {
+    Context.exit();
+}
+
+

exits the Context. This removes the association between the Context and the current thread and is an essential cleanup action. There should be a call to exit for every call to enter. To make sure that it is called even if an exception is thrown, it is put into the finally block corresponding to the try block starting after Context.enter().

+

Expose Java APIs

+

Using Java APIs

+

No additional code in the embedding needed! The JavaScript feature called + + LiveConnect + allows JavaScript programs to interact with Java objects:

+
$ java RunScript "java.lang.System.out.println(3)"
+3.0
+undefined
+
+

Implementing interfaces

+

Using Rhino, JavaScript objects can implement arbitrary Java interfaces. There's no Java code to write -- it's part of Rhino's LiveConnect implementation. For example, we can see how to implement java.lang.Runnable in a Rhino shell session:

+
js> obj = { run: function() { print("hi"); } }
+[object Object]
+js> obj.run()
+hi
+js> r = new java.lang.Runnable(obj);
+[object Object]
+js> t = new java.lang.Thread(r)
+Thread[Thread-0,5,main]
+js> t.start()
+hi
+
+

Adding Java objects

+

The next example is RunScript2. This is the same as RunScript, but with the addition of two extra lines of code:

+
Object wrappedOut = Context.javaToJS(System.out, scope);
+ScriptableObject.putProperty(scope, "out", wrappedOut);
+
+

These lines add a global variable out that is a JavaScript reflection of the System.out variable:

+
$ java RunScript2 "out.println(42)"
+42.0
+undefined
+
+

Using JavaScript objects from Java

+

After evaluating a script it's possible to query the scope for variables and functions, extracting values and calling JavaScript functions. This is illustrated in the RunScript3 example. This example adds the ability to print the value of variable x and the result of calling function f. Both x and f are expected to be defined by the evaluated script. For example,

+
$ java RunScript3 "x = 7"
+x = 7
+f is undefined or not a function.
+$ java RunScript3 "function f(a) { return a; }"
+x is not defined.
+f("my args") = my arg
+
+

Using JavaScript variables

+

To print out the value of x, we add the following code:

+
Object x = scope.get("x", scope);
+if (x == Scriptable.NOT_FOUND) {
+    System.out.println("x is not defined.");
+} else {
+    System.out.println("x = " + Context.toString(x));
+}
+
+

Calling JavaScript functions

+

To get the function f, call it, and print the result, we add this code:

+
Object fObj = scope.get("f", scope);
+if (!(fObj instanceof Function)) {
+    System.out.println("f is undefined or not a function.");
+} else {
+    Object functionArgs[] = { "my arg" };
+    Function f = (Function)fObj;
+    Object result = f.call(cx, scope, scope, functionArgs);
+    String report = "f('my args') = " + Context.toString(result);
+    System.out.println(report);
+}
+
+

JavaScript host objects

+

Defining Host Objects

+

Custom host objects can implement special JavaScript features like dynamic properties.

+

Counter example

+

The Counter example is a simple host object. We'll go through it method by method below.

+

It's easy to try out new host object classes in the shell using its built-in defineClass function. We'll see how to add it to RunScript later. (Note that because the java -jar option preempts the rest of the classpath, we can't use that and access the Counter class.)

+
$ java -cp "js.jar;examples" org.mozilla.javascript.tools.shell.Main
+js> defineClass("Counter")
+js> c = new Counter(7)
+[object Counter]
+js> c.count
+7
+js> c.count
+8
+js> c.count
+9
+js> c.resetCount()
+js> c.count
+0
+
+

Counter's constructors

+

The zero-argument constructor is used by Rhino runtime to create instances. For the counter example, no initialization work is needed, so the implementation is empty.

+
public Counter () { }
+
+

The method jsConstructor defines the JavaScript constructor that was called with the expression new Counter(7) in the JavaScript code above.

+
public void jsConstructor(int a) { count
+= a; }
+
+

Class name

+

The class name is defined by the getClassName method. This is used to determine the name of the constructor.

+
public String getClassName() { return "Counter";
+}
+
+

Dynamic properties

+

Dynamic properties are defined by methods beginning with jsGet_ or jsSet_. The method jsGet_count defines the + + count + property.

+
public int jsGet_count() { return count++;
+}
+
+

The expression c.count in the JavaScript code above results in a call to this method.

+

Defining JavaScript "methods"

+

Methods can be defined using the jsFunction_ prefix. Here we define resetCount for JavaScript.

+
public void jsFunction_resetCount() { count
+= 0; }
+
+

The call c.resetCount() above calls this method.

+

Adding Counter to RunScript

+

Now take a look at the RunScript4 example. It's the same as RunScript except for two additions. The method ScriptableObject.defineClass uses a Java class to define the Counter "class" in the top-level scope:

+
ScriptableObject.defineClass(scope, Counter.class);
+
+

Now we can reference the Counter object from our script:

+
$ java RunScript4 "c = new Counter(3); c.count;
+c.count;"
+
+

It also creates a new instance of the Counter object from within our Java code, constructing it with the value 7, and assigning it to the top-level variable myCounter:

+
Object[] arg = { new Integer(7) };
+Scriptable myCounter = cx.newObject(scope, "Counter", arg);
+scope.put("myCounter", scope, myCounter);
+
+

Now we can reference the myCounter object from our script:

+
$ java RunScript3 'RunScript4 'myCounter.count; myCounter.count'
+8
+
diff --git a/files/zh-cn/mozilla/projects/rhino/examples/index.html b/files/zh-cn/mozilla/projects/rhino/examples/index.html new file mode 100644 index 0000000000..087697b94a --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/examples/index.html @@ -0,0 +1,35 @@ +--- +title: Rhino Examples +slug: Mozilla/Projects/Rhino/Examples +translation_of: Mozilla/Projects/Rhino/Examples +--- +
+  
+

+

Examples have been provided that show how to control the JavaScript engine and how  to implement scriptable host objects. All the examples are in the git tree at mozilla/js/rhino/examples.

+

Sample Scripts

+

The unique.js script allows printing unique lines from a file.

+

The liveConnect.js script shows a sample usage of LiveConnect (Java-to-JavaScript connectivity).

+

The jsdoc.js script is a JavaScript analog to Java's javadoc. It makes heavy use of regular expressions.

+

The checkParam.js script is a useful tool to check that @param tags in Java documentation comments match the parameters in the corresponding Java method.

+

The enum.js script is a good example of using a JavaAdapter to implement a Java interface using a JavaScript object.

+

The NervousText.js script is a JavaScript implementation of the famous NervousText applet using JavaScript compiled to Java classes using jsc. It can be run in the HTML page NervousText.html.

+

Controlling the JavaScript Engine

+

The RunScript class

+

RunScript.java is a simple program that executes a script from the command line.

+

The Control class

+

Control.java is a program that executes a simple script and then manipulates the result.

+

JavaScript Shell

+

Shell.java is a program that executes JavaScript programs; it is a simplified version of the shell in the tools package. The programs may be specified as files on the command line or by typing interactively while the shell is running.

+

PrimitiveWrapFactory

+

PrimitiveWrapFactory.java is an example of a WrapFactory that can be used to control the wrapping behavior of the Rhino engine on calls to Java methods.

+

Multithreaded Script Execution

+

DynamicScopes.java is a program that creates a single global scope object and then shares it across multiple threads. Sharing the global scope allows both information to be shared across threads, and amortizes the cost of Context.initStandardObjects by only performing that expensive operation once.

+

Implementing Host Objects

+

First check out the tutorial if you haven't already.

+

The Foo class - Extending ScriptableObject

+

Foo.java is a simple JavaScript host object that includes a property with an associated action and a variable argument method.

+

The Matrix class - Implementing Scriptable

+

Matrix.java provides a simple multidimensional array by implementing the Scriptable interface.

+

The File class - An advanced example

+

File.java extends ScriptableObject to provide a means of reading and writing files from JavaScript. A more involved example of host object definition.

diff --git a/files/zh-cn/mozilla/projects/rhino/index.html b/files/zh-cn/mozilla/projects/rhino/index.html new file mode 100644 index 0000000000..86818aa172 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/index.html @@ -0,0 +1,22 @@ +--- +title: Rhino +slug: Mozilla/Projects/Rhino +translation_of: Mozilla/Projects/Rhino +--- +

Image:rhino.jpg

+ +

Rhino 是一个完全使用Java语言编写的开源JavaScript实现。Rhino通常用于在Java程序中,为最终用户提供脚本化能力。它被作为J2SE 6上的默认Java脚本化引擎。

+ +

Rhino 下载

+ +

如何 获取源码和二进制文件

+ +

Rhino 文档

+ +

为脚本编写者和嵌入者提供的 一些Rhino信息.

+ +

Rhino 帮助

+ +

如果你被卡住了,可以参考 这里的一些资源.

+ +

{{ languages( { "zh-cn": "zh-cn/Rhino" } ) }}

diff --git a/files/zh-cn/mozilla/projects/rhino/license/index.html b/files/zh-cn/mozilla/projects/rhino/license/index.html new file mode 100644 index 0000000000..035688ed65 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/license/index.html @@ -0,0 +1,47 @@ +--- +title: Rhino license +slug: Mozilla/Projects/Rhino/License +translation_of: Mozilla/Projects/Rhino/License +--- +

Rhino is available under open source licenses.

+ +

MPL/GPL License

+ +

The majority of the source code for Rhino is available under a MPL 1.1/GPL 2.0 license.

+ +

License for portions of the Rhino debugger

+ +

Additionally, some files (currently the contents of toolsrc/org/mozilla/javascript/tools/debugger/treetable/) are available under the following license:

+ +
 * Copyright 1997, 1998 Sun Microsystems, Inc.  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 Sun Microsystems 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.
+
+ +
+

Norrisboyd 06:16, 14 April 2008 (PDT)

diff --git a/files/zh-cn/mozilla/projects/rhino/overview/index.html b/files/zh-cn/mozilla/projects/rhino/overview/index.html new file mode 100644 index 0000000000..ba6a9aaa18 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/overview/index.html @@ -0,0 +1,78 @@ +--- +title: Rhino overview +slug: Mozilla/Projects/Rhino/Overview +translation_of: Mozilla/Projects/Rhino/Overview +--- +

简介

+ +

大多数用过 JavaScript 的人都是将js脚本放入HTML页面中使用。然而, Rhino 仅仅是对javascript核心部分的实现,并没有包含操作HTML的对象或方法。

+ +

Rhino 包括

+ + + +

语言

+ +

JavaScript 的标准是 Standard ECMA-262 ECMAScript: A general purpose, cross-platform programming language. Rhino 1.3 及以上版本遵照上述标准的第3版。

+ +

Rhino 1.6 及以上版本实现了 ECMA-357 ECMAScript for XML (E4X) 标准. 查看详细的规格说明可以获得更多的信息,查看 Rhino version 1.6R1 release notes 可以看到Rhino对标准实现的具体情况。

+ +

此外,Rhino实现了JavaAdapters,这样我们可以用一个JavaScript对象来实现任何java的接口或者继承任何java的类。查看下载文件中example文件夹中的enum.js获取更多的信息。.

+ +

有很多JavaScript的书和教程。 我们推荐JavaScript: The Definitive Guide 这本书,里面有一章是说Rhino的。

+ +

废弃的语言特性

+ +

很多在JavaScript 1.2中定义的特性已经被废弃了. 这些特性允许“计算反射”:可以决定和影响它被评价方法等方面的能力。 这些特性没有被广泛使用,他们对阻碍和防止优化的行为强加了重要的约束。 这些被废弃的特性是 __proto__ 和 __parent__ 属性, 还有构造函数 With,、ClosureCall。在JavaScript 1.4中使用这些特性会产生错误。在其他的版本中使用这些特性,会产生警告。

+ +

国际化

+ +

The messages reported by the JavaScript engine are by default retrieved from the property file org/mozilla/javascript/resources/Messages.properties. If other properties files with extensions corresponding to the current locale exist, they will be used instead.

+ +

JavaScript语言版本

+ +

JavaScript引擎的很多行为与语言的版本有关。在浏览器调用中,JavaScript版本的选择是通过script标签中的LANGUAGE属性定义的,比如"JavaScript1.2"。

+ +

1.3 和更高版本是ECMA一致的。

+ +

操作符 ==  和 !=

+ +

1.2版本用 == 和 != 来处理绝对相等的问题。 在1.3或更高的版本里, == 和 != 和ECMA中所描述的一样。 操作符 === and !== 在所有版本中都表示绝对相等。

+ +

布尔转换

+ +

1.3之前的所有版本Boolean(new Boolean(false)) 值为false 。在1.3及1.3之后,它的值为true。

+ +

Array.prototype.toString 和 Object.prototype.toString

+ +

1.2版本只是返回数组或对象的文字符号 (比如"{{ mediawiki.external(1,2,3) }}" or "{a:1, b:2}" )。 在1.3或更高版本中这些函数与ECMA标准一致。

+ +

Array 构造函数

+ +

只有在1.2版本中,Array(i) 用一个参数i构造一个只有一个元素且元素的值为i的数组。 在其他版本中,使用和ECMA一致的标准 (一个没有元素的数组被构造,长度为i)。

+ +

String.prototype.substring

+ +

只有在1.2版本中, 如果第一个参数小于第二个参数,两个参数不会互换。其他的版本都符合ECMA标准。

+ +

String.prototype.split

+ +

只有对1.2版本,split按照Perl4的特例当用一个单独的空格字符作参数时, (跳过最先的空白,用空白分割). 其他的版本完全按照ECMA的标准分割。

+ +

安全

+ +

Rhino的安全特性提供了找到代码片段的来源的功能 (还有任何会轮流产生的代码片段)。这些特性考虑到了传统的基于URL的安全策略(在网景领航员中的JavaScript)的实现。执行信任的JavaScript代码时可以不考虑安全性特征。

+ +

运行不被信任的JavaScript代码时,需要做两件事来保证安全性。第一,每一个被创建的Context必须被提供一个实现SecuritySupport接口的实例。 这样在功能上给Rhino提供了让它执行安全相关任务的支持。

+ +

第二, security.requireSecurityDomain属性的值应该被改为true在资源束bundle org.mozilla.javascript.resources.Security中. 这个属性的值可以在运行时通过调用ContextisSecurityDomainRequired方法来决定。将这个属性设置为ture,要求任何编译或评估JavaScript的调用必须提供一个安全区域对象(任意类型),用来标识JavaScript代码。在一个典型的客户端嵌入中,这个对象可能是提供javascript的服务器的URL,或者是一个包含代码片段的签发人的代表(用于基于证书的安全策略)。

+ +

当JavaScript代码想要执行一个受限制的行为时,安全区域会被后面的方法检索。类上下文会从安全管理(java.lang.SecurityManager.getClassContext())中得到。执行限制行为的代码对应的类 可以通过寻找一个在类上下文中合适的位置得到。如果调用者是JavaScript,得到的类可能是一种或两种类型。首先,它可能是解释器(如果解释器模式有效)。第二,它有可能是一个生成的类,如果类文件生成支持。一个植入可以区分两种情况,通过调用在Context Class中调用isInterpreterClass()。 如果是解释器类,调用Context的getInterpreterSecurityDomain() 方法来获取当前正在执行的被解释的脚本或方法的安全区域。否则,就是一个生成的类,一个嵌入可以调用在实现SecuritySupport的类中调用getSecurityDomain()。当类被定义而且被打开,恰当的安全区域和它建立关联,而且可以通过调用这个方法找回。一旦安全区域被决定,一个植入可以执行任何检查者适合去决定是否允许去做的操作。

+ +

{{ languages( { "ja": "ja/Rhino_Overview" } ) }}

diff --git a/files/zh-cn/mozilla/projects/rhino/requirements_and_limitations/index.html b/files/zh-cn/mozilla/projects/rhino/requirements_and_limitations/index.html new file mode 100644 index 0000000000..8a159ae843 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/requirements_and_limitations/index.html @@ -0,0 +1,24 @@ +--- +title: Rhino requirements and limitations +slug: Mozilla/Projects/Rhino/Requirements_and_Limitations +translation_of: Mozilla/Projects/Rhino/Requirements_and_Limitations +--- +

Requirements

+

Recent versions of Rhino have only been tested with JDK 1.4 and greater. Older versions support JDKs as early as 1.1.

+

To use the JavaAdapter feature or an optimization level of 0 or greater, Rhino must be running under a security manager that allows the definition of class loaders.

+

Limitations

+

LiveConnect

+

If a JavaObject's field's name collides with that of a method, the value of that field is retrieved lazily, and can be counter-intuitively affected by later assignments:

+
javaObj.fieldAndMethod = 5;
+var field = javaObj.fieldAndMethod;
+javaObj.fieldAndMethod = 7;
+// now, field == 7
+
+

You can work around this by forcing the field value to be converted to a JavaScript type when you take its value:

+
javaObj.fieldAndMethod = 5;
+var field = javaObj.fieldAndMethod + 0; // force conversion now
+javaObj.fieldAndMethod = 7;
+// now, field == 5
+
+

JSObject

+

Rhino does NOT support the netscape.javascript.JSObject class.

diff --git a/files/zh-cn/mozilla/projects/rhino/scripting_java/index.html b/files/zh-cn/mozilla/projects/rhino/scripting_java/index.html new file mode 100644 index 0000000000..013ad3aa89 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/scripting_java/index.html @@ -0,0 +1,397 @@ +--- +title: Scripting Java +slug: Mozilla/Projects/Rhino/Scripting_Java +translation_of: Mozilla/Projects/Rhino/Scripting_Java +--- +

这篇文章描述了如何在rhino中使用java。使用脚本调用Java有很多用途,它使得我们可以利用Java中现有的库,来帮助我们构建强大的脚本。我们可以通过编写脚本,来对Java程序进行测试。可以通过脚本来进行探索式编程,辅助Java的开发,所谓探索式编程,就是通过快速地编程调用库或API来探索这些库或API可以做什么,显而易见,脚本语言很适合探索式编程。

+ +

这里注意,ECMA标准并没有包含和Java(或者其他任何对象系统)交互的标准。本文所描述的所有内容,应该被认为是一个扩展。

+ + + +

访问 Java Packages 和 Classes

+ +

Java的每段代码都是类的一部分,每一个JAVA类都是包的一部分。在Javascript中,脚本不属于任何package。我们可以访问Java包中的类么?

+ +

Rhino定义了一个顶层的变量Packages。Packages的所有属性都是Java中顶层的包,比如java和com。比如我们可以访问java包:

+ +
js> Packages.java
+[JavaPackage java]
+ +

还有一种更方便的方式,Rhino定义了一个顶层的变量java,等价于Packages.java。所以上面的例子可以更简介地写成:

+ +
js> java
+[JavaPackage java]
+
+ +

我们可以通过访问包的下层,来直接访问java类:

+ +
js> java.io.File
+[JavaClass java.io.File]
+
+ +

如果你的脚本需要访问很多的Java类,每次都附带完整的包名会使得编程很麻烦。Rhino提供了一个顶层的方法importPackage,它的功能和Java的import一样。比如,我们可以导入java.io包中的所有类,然后直接通过类名File来访问java.io.File:

+ +
js> importPackage(java.io)
+js> File
+[JavaClass java.io.File]
+
+ +

这里importPackage(java.io)使得java.io包中的所有类(例如File)可以在顶层被访问。这和Java中的java.io.*;等价。

+ +

要注意Java会暗中导入java.lang.*,但是Rhino不会。因为JavaScript的顶层对象Boolean、Math、Number、Object和String和java.lang包中同名的类并不相同。因为这种冲突,建议不要用importPackage来导入java.lang包。

+ +

有一点要注意的,就是Rhino对于指定包名或类名时是如何处理错误的。如果java.Myclass是可访问的,Rhino会试图加载名为java.MyClass的类,如果加载失败,它会假设java.MyClass是一个包名,不会报错:

+ +
js> java.MyClass
+[JavaPackage java.MyClass]
+
+ +

只有在你试图将这个对象当作类使用时,才会报错。

+ +

额外的包和类

+ +

额外的包和类也可以在Rhino中使用。确认你的.jar或.class文件在你的classpath里,你就可以在你的JavaScript应用中导入它们。这些包基本不会在java包中,所以你在使用时,需要在包前加上前缀"Packages"。 比如你想导入 org.mozilla.javascript 包,你应该像下面这样去使用importPackage():

+ +
$ java org.mozilla.javascript.tools.shell.Main
+js> importPackage(Packages.org.mozilla.javascript);
+js> Context.currentContext;
+org.mozilla.javascript.Context@bb6ab6
+
+ +

偶尔,我们也会见到在一些例子中使用包的完整名称,而没有使用importPackage()。这也是可以的,只是会让你多打一些字。如果使用完整的名称,上面的例子就会变成下面这样:

+ +
$ java org.mozilla.javascript.tools.shell.Main
+js> jsPackage = Packages.org.mozilla.javascript;
+[JavaPackage org.mozilla.javascript]
+js> jsPackage.Context.currentContext;
+org.mozilla.javascript.Context@bb6ab6
+
+ +

同样,你可以通过importClass()来导入一个类,上面的例子也可以像这样写:

+ +
$ java org.mozilla.javascript.tools.shell.Main
+js> importClass(Packages.org.mozilla.javascript.Context);
+js>  Context.currentContext;
+org.mozilla.javascript.Context@bb6ab6
+ +

和Java一起工作

+ +

现在我们可以访问Java类,下一步就是要创建一个对象。方法就和在Java中一样, 用new来创建对象:

+ +
js> new java.util.Date()
+Thu Jan 24 16:18:17 EST 2002
+
+ +

如果我们将创建的对象存放在JavaScript变量中,我们可以调用它的方法:

+ +
js> f = new java.io.File("test.txt")
+test.txt
+js> f.exists()
+true
+js> f.getName()
+test.txt
+
+ +

静态方法和属性可以直接通过类对象来访问:

+ +
js> java.lang.Math.PI
+3.141592653589793
+js> java.lang.Math.cos(0)
+1
+
+ +

不像Java,在JavaScript里,方法就是一个对象。它可以被评估,也可以被调用。如果我们去查看这个方法,我们可以看到这个方法所有重载的形式:

+ +
js> f.listFiles
+function listFiles() {/*
+java.io.File[] listFiles()
+java.io.File[] listFiles(java.io.FilenameFilter)
+java.io.File[] listFiles(java.io.FileFilter)
+*/}
+
+ +

输出告诉我们,File类有listFiles方法的三种重载:一种不包含参数的,另一种包含一个FilenameFilter类型的参数,第三个包含一个FileFilter类型的参数。所有的方法都返回一个File对象数组。可以观察到Java方法的参数和返回类型在探索式编程中是非常有用的,尤其是在对一个方法的参数和返回对象不确定的时候。

+ +

另一个有助于探索式编程的特性,是可以看到对象中定义的所有方法和属性。用JavaScript的for..in , 我们可以打印这些值:

+ +
js> for (i in f) { print(i) }
+exists
+parentFile
+mkdir
+toString
+wait
+[44 others]
+
+ +

注意这里不仅列出了File类中的所有方法,也列出了从基类java.lang.Object中继承的方法,例如wait。这使得我们可以更好地处理那些有复杂继承关系的对象,因为我们可以看到对象中所有可用的方法。

+ +

Rhino可以通过属性名来方便地访问JavaBean的属性。一个JavaBean的属性foo被方法getFoo和setFoo定义,另外,一个也叫foo的boolean类型的属性,可以被isFoo来定义。比如, 下面的代码实际上调用了File对象的getName和isDirectory方法。

+ +
js> f.name
+test.txt
+js> f.directory
+false
+
+ +

调用重载方法

+ +

 根据参数类型选择调用方法的过程称为重载决议。在 Java 中, 重载决议在编译时执行, 而在rhino中则在运行时发生。这种差异是不可避免的, 因为 JavaScript 使用动态类型, 在2章中: 由于变量的类型直到运行时才知道, 才会发生重载决议。

+ +
+
例如, 请查看下面的 Java 类, 它定义了许多重载方法并调用它们。 
+
+ + + +
public class Overload {
+
+    public String f(Object o) { return "f(Object)"; }
+    public String f(String s) { return "f(String)"; }
+    public String f(int i)    { return "f(int)"; }
+
+    public String g(String s, int i) { return "g(String,int)"; }
+    public String g(int i, String s) { return "g(int,String)"; }
+
+    public static void main(String[] args) {
+        Overload o = new Overload();
+        Object[] a = new Object[] { new Integer(3), "hi", Overload.class };
+        for (int i = 0; i != a.length; ++i)
+            System.out.println(o.f(a[i]));
+    }
+}
+
+ +

当我们编译和执行程序, 它产生输出

+ +
f(Object)
+f(Object)
+f(Object)
+
+ +

但是, 如果我们编写一个类似的脚本

+ +
var o = new Packages.Overload();
+var a = [ 3, "hi", Packages.Overload ];
+for (var i = 0; i != a.length; ++i)
+    print(o.f(a[i]));
+
+ +

并且运行它,将会输出

+ +
f(int)
+f(String)
+f(Object)
+
+ +

因为Rhino在运行时选择重载方法, 所以它会调用与该参数匹配的更具体的类型。 同时, 在编译时, Java 只在参数的类型上选择重载方法。

+ +

尽管这有利于选择一种方法,这种方法可能是每个调用的更好匹配,但它确实对性能有影响,因为每次调用时都要做更多的工作。事实上,这种性能代价在实际应用中并不明显。

+ +

因为重载决议发生在运行时,它可能在运行时失败。例如,如果我们用两个整数调用重载方法g,我们就会得到一个错误,因为方法的两个形式都比另一个更接近参数类型:

+ +
js> o.g(3,4)
+js:"<stdin>", line 2: The choice of Java method Overload.g
+matching JavaScript argument types (number,number) is ambiguous;
+candidate methods are:
+class java.lang.String g(java.lang.String,int)
+class java.lang.String g(int,java.lang.String)
+
+ +

http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html 提供了一个更精确的重载语义定义

+ +

  实现Java接口

+ + + +

现在我们可以访问Java类,创建Java对象,并访问这些对象的字段、方法和属性,我们就可以轻松掌握大量的功能。但是,在少数情况下是不够用的:Java中的很多API通过提供客户端必须实现的接口来工作。其中一个例子就是Thread类:其构造函数Runnable包含一个run方法,这个方法在新线程启动时被调用。

+ +

为了满足这种需求,Rhino提供了创建新的Java对象实现的接口的能力。首先,我们必须定义一个JavaScript对象,其中的函数属性的名称与Java接口所需的方法名称相匹配。要实现一个Runnable ,我们只需要定义一个不带参数的run单方法。如果你还记得第3章,可以用{ propertyName: value}符号定义一个JavaScript对象。我们可以在这里结合函数表达式使用这个语法来用一个 run方法定义一个JavaScript对象:

+ +
js> obj = { run: function () { print("\nrunning"); } }
+[object Object]
+js> obj.run()
+
+running
+
+ + + +

现在我们可以通过构建一个 Runnable 来实现 Runnable 接口的对象:

+ +
js> r = new java.lang.Runnable(obj);
+ + + +
js> r = new java.lang.Runnable(obj);
+[object JavaObject]
+
+ +

在Java中,不可能在接口上使用new运算符,因为没有可用的实现。Rhino从JavaScript对象中获取实现obj现在我们有一个对象实现Runnable,我们可以创建Thread并运行它。我们定义的函数run 将在新线程上调用。

+ +
js> t = new java.lang.Thread(r)
+Thread[Thread-2,5,main]
+js> t.start()
+js>
+
+running
+
+ + + +

最终js提示和新线程的输出可能以任意顺序显示,具体取决于线程调度。

+ +

在后台,Rhino为一个新的Java类生成字节码,该类实现 Runnable 并转发对其 run方法的所有调用,并转发给关联的JavaScript对象。实现此类的对象称为Java适配器。因为转发到JavaScript是在运行时发生的,所以可能会延迟定义实现接口的方法直到它们被调用。虽然省略必要的方法对大编程来说是一种糟糕的做法,但它对小脚本和探索性编程很有用。

+ + + +

JavaAdapter构造函数

+ +

在前面的章节中,我们使用 new 运算符与Java接口创建Java适配器。这种方法有其局限性:不可能实现多个接口,也不能扩展非抽象类。因为这些原因,有一个 JavaAdapter 构造函数。

+ +

JavaAdapter构造函数的语法是:

+ +
new JavaAdapter(javaIntfOrClass, [javaIntf, ..., javaIntf,] javascriptObject)
+
+ +

这里javaIntfOrClass是一个实现的接口或一个扩展的类,并且javaIntf是实现接口的接口。而javascriptObject 则包含从Java适配器调用的方法的JavaScript对象。

+ +

在实践中,几乎不需要JavaAdapter 直接调用构造函数。大多数情况下,使用new运算符之前的语法就足够了。

+ +

作为Java接口的JavaScript函数

+ +

通常我们只需要使用一种方法实现一个接口,就像前面的 Runnable 例子或者提供各种事件监听器实现一样。为了方便这个,Rhino允许在这种接口传递JavaScript函数。该函数被称为接口方法的实现。

+ +

这里是简化的 Runnable 实例:

+ +
js> t = java.lang.Thread(function () { print("\nrunning"); });
+Thread[Thread-0,5,main]
+js> t.start()
+js>
+running
+
+ +

如果所有的方法都具有相同的签名,Rhino还允许使用JavaScript函数作为Java接口的实现方法。当调用函数时,Rhino将方法的名称作为附加参数传递。函数可以使用它来代表被调用的方法:

+ +
js> var frame = new Packages.javax.swing.JFrame();
+js> frame.addWindowListener(function(event, methodName) {
+	if (methodName == "windowClosing") {
+            print("Calling System.exit()..."); java.lang.System.exit(0);
+	}
+    });
+js> frame.setSize(100, 100);
+js> frame.visible = true;
+true
+js> Calling System.exit()...
+
+ +

创建Java数组

+ +

Rhino不提供创建Java数组的特殊语法。你必须使用这个 java.lang.reflect.Array 类来达到这个目的。要创建一个由五个Java字符串组成的数组,可以进行以下调用:

+ +
js> a = java.lang.reflect.Array.newInstance(java.lang.String, 5);
+[Ljava.lang.String;@7ffe01
+
+ +

要创建一个基本类型数组,我们必须使用 java.lang 包中相关对象类中定义的特殊TYPE字段。例如,要创建一个字节数组,我们必须使用特殊字段 java.lang.Byte.TYPE:

+ +
js> a = java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 2);
+[C@7a84e4
+
+ +

而且结果值是允许被使用在该类型的Java数组的任何地方。

+ +
js> a[0] = 104
+104
+js> a[1] = 105
+105
+js> new java.lang.String(a)
+hi
+
+ +

Java字符串和JavaScript字符串

+ +

请记住,Java字符串和JavaScript字符串是一样的。Java字符串类型的实例,java.lang.String ,并具有由该类定义的所有方法。JavaScript字符串具有由...定义的方法,String.prototype. 最常见的绊脚石是 length, 这是Java字符串方法和JavaScript字符串的动态属性:

+ +
js> javaString = new java.lang.String("Java")
+Java
+js> jsString = "JavaScript"
+JavaScript
+js> javaString.length()
+4
+js> jsString.length
+10
+
+ +

Rhino 在减少这两种类型之间的差异方面提供了一些帮助。首先,您可以将JavaScript字符串传递给需要Java字符串的Java方法,Rhino将执行转换。实际上,我们在前面java.lang.String 例子中构造函数调用中看到了这个特性

+ +

如果java.lang.String 类尚未定义它们,Rhino还会使JavaScript方法可用于Java字符串。例如:

+ +
js> javaString.match(/a.*/)
+ava
+
+ +

JavaImporter 构造函数

+ +

JavaImporter是一个新的全局构造函数,它允许在脚本化Java时省略显式的包名称:

+ +
var SwingGui = JavaImporter(Packages.javax.swing,
+                            Packages.javax.swing.event,
+                            Packages.javax.swing.border,
+                            java.awt.event,
+                            java.awt.Point,
+                            java.awt.Rectangle,
+                            java.awt.Dimension);
+...
+
+with (SwingGui) {
+    var mybutton = new JButton(test);
+    var mypoint = new Point(10, 10);
+    var myframe = new JFrame();
+...
+}
+
+ +

以前,这样的功能仅适用于将 org.mozilla.javascript.ImporterTopLevel 用作顶级作用域的嵌入。这个类提供额外的 importPackage() 和importClass() 全局函数的脚本,但其广泛的使用有污染Java类名的全局命名空间的趋势,还有防止垃圾收集加载类。

+ +

详情请参阅 Bugzilla 245882.

+ +

Java 异常

+ + + +

JavaScript代码使用 try ... catch 语句可以捕获Java方法抛出的异常Rhino将Java异常封装到具有以下属性的错误对象中:

+ + + +

instanceof运算符可用于查询异常的类型:

+ + + +
try {
+    java.lang.Class.forName("NonExistingClass");
+} catch (e) {
+    if (e.javaException instanceof java.lang.ClassNotFoundException) {
+       print("Class not found");
+    }
+}
+
+ +

Rhino 还支持对 try... catch 语句的扩展,允许定义条件捕获异常:

+ +
function classForName(name) {
+    try {
+        return java.lang.Class.forName(name);
+    } catch (e if e.javaException instanceof java.lang.ClassNotFoundException) {
+        print("Class " + name + " not found");
+    } catch (e if e.javaException instanceof java.lang.NullPointerException) {
+        print("Class name is null");
+    }
+}
+
+classForName("NonExistingClass");
+classForName(null);
+
diff --git a/files/zh-cn/mozilla/projects/rhino/shell/index.html b/files/zh-cn/mozilla/projects/rhino/shell/index.html new file mode 100644 index 0000000000..d5a4b779a9 --- /dev/null +++ b/files/zh-cn/mozilla/projects/rhino/shell/index.html @@ -0,0 +1,179 @@ +--- +title: Shell +slug: Mozilla/Projects/Rhino/Shell +translation_of: Mozilla/Projects/Rhino/Shell +--- +

JavaScript的外壳提供了一个简单的方法来在批处理模式下或编程的一个探索性的互动环境运行脚本.

+

调用Shell

+

<big>java org.mozilla.javascript.tools.shell.Main {{ mediawiki.external('options') }} script-filename-or-url {{ mediawiki.external('script-arguments') }} </big>

+

这里是一些选项 options

+

-e script-source

+

script-source  作为 JavaScript 执行.

+

-f script-filename-or-url

+

读取script-filename-or-url 的内容并作为JavaScript执行.

+

-opt optLevel / -O optLevel

+

优化等级 optLevel, 必须是 -1 或 [0-9]之间的整数. 参考Rhino Optimization 或许详情.

+

-version versionNumber

+

制定语言编译版本. 字符串 versionNumber 必须是 100, 110, 120, 130, 140, 150, 160170. 参考JavaScript Language Versions获取更多的语言版本信息.

+

-strict

+

开启strict 模式.

+

-continuations

+

启用continuation的实验支持,建立优化级别为-1强制解释模式. 从Rhino 1.7 开始这个选项不再可用.

+

注意

+

如果shell被使用设置为true的系统属性rhino.use_java_policy_security调用,一个安全管理将被安装, shell限制脚本通过基于根据URL访问Java安全选项的权限.如果JVM实现Java2的安全模型才可以用.

+

预定义的属性

+

在shell中呗执行的脚本访问顶层定义的一些属性.

+

arguments

+

当shell被调用时,arguments 对象是一个包含所有通过命令行输入的字符串的数组

+

environment

+

返回当前环境对象.

+

history

+

显示命令行中执行命令的历史.

+

help()

+

获取帮助信息.

+

defineClass(className)

+

定义一个使用Java类命名的扩展,参数 className是个类名的字符串. 使用 ScriptableObject.defineClass() 定义扩展.

+

deserialize(filename)

+

从指定的文件恢复以前通过调用一个被serialize的对象.

+

gc()

+

运行垃圾回收器.

+

load([filename, ...])

+

载入字符串命名的参数JavaScript源码文件. 如果有多个参数被传递,那么每一个参数都会被读取并执行.

+

loadClass(className)

+

载入并执行字符串className.表示的类.这个类必须是已实现的脚本接口, 就像任何被编译的脚本 Rhino JavaScript Compiler.

+

print([expr ...])

+

评估并打印表达式. 评估每一个表达式, 把结果转化为字符串并打印.

+

readFile(path [, characterCoding])

+

读取给定的文件并使用指定的编码把字节转换为字符串,如果没有制定编码就用默认编码.

+

readUrl(url [, characterCoding])

+

打开指定的url,读取所有的字节并用指定的编码转化为数组,如果没有指定编码就是用默认的.

+

runCommand(commandName, [arg, ...] [options])

+

执行参数中给定的命令,作为一个独立的进程选项并返回该进程的退出状态.

+

Usage:

+
runCommand(command)
+runCommand(command, arg1, ..., argN)
+runCommand(command, arg1, ..., argN, options)
+
+

All except the last arguments to runCommand are converted to strings and denote command name and its arguments. If the last argument is a JavaScript object, it is an option object. Otherwise it is converted to string denoting the last argument and options objects assumed to be empty.

+

The following properties of the option object are processed:

+ +

seal(object)

+

Seal the specified object so any attempt to add, delete or modify its properties would throw an exception.

+

serialize(object, filename)

+

Serialize the given object to the specified file.

+

spawn(functionOrScript)

+

Run the given function or script in a different thread.

+

sync(function)

+

creates a synchronized function (in the sense of a Java synchronized method) from an existing function. The new function synchronizes on the this object of its invocation.

+

quit()

+

退出shell. 如果文件字符是在提示符下键入,shell将也退出在交互模式下.

+

version([number])

+

设置或获取JavaScript的版本号. 如果没有参数,就返回当前的版本. 如果有参数,参数要在 100, 110, 120, 130, 140, 150, 160 或 170范围内,它们分别对应 JavaScript1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6 or 1.7.

+

例子

+

调用

+

Here the shell is invoked three times from the command line. (The system command prompt is shown as $.) The first invocation executes a script specified on the command line itself. The next invocation has no arguments, so the shell goes into interactive mode, reading and evaluating each line as it is typed in. Finally, the last invocation executes a script from a file and accesses arguments to the script itself.

+
$ java org.mozilla.javascript.tools.shell.Main -e print('hi')
+hi
+$ java org.mozilla.javascript.tools.shell.Main
+js> print('hi')
+hi
+js> 6*7
+42
+js> function f() {
+  return a;
+}
+js> var a = 34;
+js> f()
+34
+js> quit()
+$ cat echo.js
+for (i in arguments) {
+  print(arguments[i])
+}
+$ java org.mozilla.javascript.tools.shell.Main echo.js foo bar
+foo
+bar
+$
+
+

spawn 和 sync 

+

下面的例子创建了2个线程 via spawn 和 uses sync 去创建同步的函数test test版本.

+
js> function test(x) {
+  print("entry");
+  java.lang.Thread.sleep(x*1000);
+  print("exit");
+}
+js> var o = { f : sync(test) };
+js> spawn(function() {o.f(5);});
+Thread[Thread-0,5,main]
+entry
+js> spawn(function() {o.f(5);});
+Thread[Thread-1,5,main]
+js>
+exit
+entry
+exit
+
+

运行命令

+

这是在Linux下调用 runCommand 的例子.

+
js> runCommand('date')
+Thu Jan 23 16:49:36 CET 2003
+0
+// Using input option to provide process input
+js> runCommand("sort", {input: "c\na\nb"})
+a
+b
+c
+0
+js> // Demo of output and err options
+js> var opt={input: "c\na\nb", output: 'Sort Output:\n'}
+js> runCommand("sort", opt)
+0
+js> print(opt.output)
+Sort Output:
+a
+b
+c
+js> var opt={input: "c\na\nb", output: 'Sort Output:\n', err: ''}
+js> runCommand("sort", "--bad-arg", opt)
+2
+js> print(opt.err)
+/bin/sort: unrecognized option `--bad-arg'
+Try `/bin/sort --help' for more information.
+
+js> runCommand("bad_command", "--bad-arg", opt)
+js: "<stdin>", line 18: uncaught JavaScript exception: java.io.IOException: bad_command: not found
+js> // Passing explicit environment to the system shell
+js> runCommand("sh", "-c", "echo $env1 $env2", { env: {env1: 100, env2: 200}})
+100 200
+0
+js> // Use args option to provide additional command arguments
+js> var arg_array = [1, 2, 3, 4];
+js> runCommand("echo", { args: arg_array})
+1 2 3 4
+0
+
+

Windows下的例子也差不多:

+
js> // Invoke shell command
+js> runCommand("cmd", "/C", "date /T")
+27.08.2005
+0
+js> // Run sort collectiong the output
+js> var opt={input: "c\na\nb", output: 'Sort Output:\n'}
+js> runCommand("sort", opt)
+0
+js> print(opt.output)
+Sort Output:
+a
+b
+c
+js> // Invoke notepad and wait until it exits
+js> runCommand("notepad")
+0
+
+

{{ languages( { "zh-cn": "zh-cn/Shell" } ) }}

diff --git a/files/zh-cn/mozilla/projects/social_api/index.html b/files/zh-cn/mozilla/projects/social_api/index.html new file mode 100644 index 0000000000..55d8b5525e --- /dev/null +++ b/files/zh-cn/mozilla/projects/social_api/index.html @@ -0,0 +1,97 @@ +--- +title: Social API +slug: Mozilla/Projects/Social_API +tags: + - API + - Landing + - Mozilla + - NeedsTranslation + - Social + - TopicStub +translation_of: Archive/Social_API +--- +

The Social API is an architecture that makes it easier for web browsers to integrate with social media services, using standard web technologies as the API. Once a social service provider is implemented for Firefox, it becomes possible for the browser to integrate web resources from a service, in-chrome user controls and information related to that service. The following articles explain how to implement a social service provider.
+
+ The Social API supports specific vertical use cases centered around social interactions, but does not tightly constrain those use cases, allowing flexibility and creativity for 3rd parties. Specific features supported are notifications, share, bookmarking (or save-for-later), sidebars and communications (e.g. chat and video).

+ +
+
+

Social API documentation

+ +
+
Social API glossary
+
Provides definitions of key terms you'll need to understand when using the Social API.
+
Social service manifest
+
A description of—(TBD: and guide to building)—the manifest required.
+
Social service worker API reference {{obsolete_inline(48)}}
+
A reference to the social service worker API.
+
Social service content API: MozSocial {{obsolete_inline(51)}}
+
A reference to the social service content API, which is provided by the {{domxref("navigator.MozSocial")}} object.
+
Social share API
+
A reference to the Share API.
+
Social bookmarks API {{obsolete_inline(51)}}
+
A reference to the Social Bookmarks API.
+
Social status API {{obsolete_inline(51)}}
+
A reference to the Status API.
+
Social service widgets
+
A guide to the widgets provided by the social service.
+
+ +

How to create a SocialAPI Provider

+ +

A step-by-step guide to create a simple Social API provider.

+ +
+
First Steps
+
The basics of getting an installable social provider running.
+
Adding ambient notifications {{obsolete_inline(51)}}
+
A short guide to implementing ambient notifications using the Social API.
+
Implementing status and notifications {{obsolete_inline(51)}}
+
A guide to implementing a status panel with notifications using the Social API.
+
Adding bookmark support {{obsolete_inline(51)}}
+
A short guide to implementing social bookmarks using the Social API.
+
Implementing share
+
A guide to implementing a share panel using the Social API.
+
Supporting chat {{obsolete_inline(51)}}
+
A guide to implementing chat features using the Social API.
+
+ +

View All...

+
+ +
+

Getting help from the community

+ +

Need help on a Social API related problem and can't find the solution in the documentation?

+ +
    +
  • Ask your question on the Mozilla IRC channel: #socialdev
  • +
+ +

Don't forget about the netiquette...

+ +

Tools and demos

+ + + +

View All...

+ + + +

Try out any of several providers on the SocialAPI Directory site (Firefox 29 or later required)

+ + + + + +
+
+ +

 

diff --git a/files/zh-cn/mozilla/projects/social_api/share/index.html b/files/zh-cn/mozilla/projects/social_api/share/index.html new file mode 100644 index 0000000000..844ac9d693 --- /dev/null +++ b/files/zh-cn/mozilla/projects/social_api/share/index.html @@ -0,0 +1,86 @@ +--- +title: Share +slug: Mozilla/Projects/Social_API/Share +translation_of: Archive/Social_API/Share +--- +

这一篇只是初步草案,可能会被改变。分享从 [TBD: Firefox 23] 开始可用。

+ +

A service provider may choose to provide a Share panel that users can use to share content from the current browser tab with their friends.  The Share panel is slightly different from other Social UI in the browser.  The Share panel itself contains a list of providers that support the share functionality.  When a user shares a page, they can choose which provider they want to share with.  Each provider may have differing functionality, such as simply providing a comment box to extensive functionlality allowing for image selection and more.

+ +

Share is initiated by the user either through the share button in the toolbar or a context menu.  The user can select an image or text in a page to be shared, or share the page itself.  Links within a page may also be shared without visiting the link.

+ +

A provider implementing support for share may choose to use a URL template that is compatible with OExchange, however the browser also sends a DOM event to the page after load containing details of the share.  In some circumstances, such as sharing a link on the page, the browser will not have detailed information.  Using the DOM event allows the provider to display information about the page being shared without needing to fetch it themselves and parse the page for information.  The browser includes certain META tags, including OpenGraph tags in the event data.

+ +

A User Experience Flow for Share

+ +

SocialAPI content works different than typical web pages.  The are presented as primary UI in the browser, and may be confined in size, live longer than a browser tab, and more.  How your user will interact with your share panel is unique and you will need to take into account how a user should experience your share panel.

+ +

[TODO: describe the expected flow here]

+ +

OpenGraphData DOM Event

+ +

The share page can listen for the OpenGraphData DOM Event.

+ +
addEventListener("OpenGraphData", function(e) {
+  var shareData = JSON.parse(e.detail);
+  $("#shared").text(shareData.url);
+})
+
+ +

Attributes

+ +

The event detail can contain the following attributes which are retreived from META tags and other tags within HEAD, such as the TITLE tag:

+ + + +

Share URL Template

+ +

While we prefer the use of the DOM event, many sites have existing endpoints that allow users to share to that site.  SocialAPI supports using a URL template to make implementation easy for sites that already have this functionality.  In your manifest, you can define your shareURL in this format:

+ +
"shareURL": "https://yoursite.com/share?u=%{url}&t=%{title}
+ +

The %{name} values will be replaced with the following attributes if available.  Otherwise that parameter is removed from the final url used to load your share endpoint.

+ + + +

How to properly size your share panel

+ +

Your share panel is presented in a door hanger from the browser toolbar.  While it can be flexible in size, there is a minimum and a maximum size that the panel will allow.  You also need to implement a couple items to help the browser identify the size you need for your panel.  There are a few ways you can define the proper size for your panel, here are some examples:

+ +

Styling the BODY element

+ +

By default the browser will look at the body.style.width and body.style.height, also taking into account the margin.  It will try to size the panel to show your full page.

+ +
<html>
+<body style="width: 300px; height: 400px">
+</body>
+</html>
+
+ +

Identifying a content element

+ +

The browser will also look to see if you have defined a primary content element.  If you have, then it will use the width and height styles from that element to size the panel.  You will need to make sure that your content element is properly placed.

+ +
<html>
+<body contentid="content">
+<div id="content" style="width: 300px; height: 400px; top: 0; left: 0;"/>
+</body>
+</html>
diff --git a/files/zh-cn/mozilla/projects/spidermonkey/build_documentation/index.html b/files/zh-cn/mozilla/projects/spidermonkey/build_documentation/index.html new file mode 100644 index 0000000000..ecb793016e --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/build_documentation/index.html @@ -0,0 +1,294 @@ +--- +title: SpiderMonkey Build Documentation +slug: Mozilla/Projects/SpiderMonkey/Build_Documentation +translation_of: Mozilla/Projects/SpiderMonkey/Build_Documentation +--- +
{{SpiderMonkeySidebar("General")}}
+ +

构建 SpiderMonkey

+ +

使用本说明来构建最新的 SpiderMonkey 源码.

+ +

在构建前, 确保有适合你计算机的构建工具: Linux, Windows, Mac, others. 当构建的版本低于28, 你还需要外加 NSPR.

+ +

以及理所当然地, 你需要 获取 SpiderMonkey 源代码。

+ +

非开发者 (优化) 模式构建

+ +

如果你想在生产环境中安装使用SpiderMonkey或运行标准性能测试,可以使用此步骤。 (如果你想在你的C++应用中把 SpiderMonkey 作为库使用, 或从事改进 SpiderMonkey 本身的工作, 按之后的描述,使用 开发者/调试 模式构建.)

+ +
cd js/src
+autoconf2.13
+
+# This name should end with "_OPT.OBJ" to make the version control system ignore it.
+mkdir build_OPT.OBJ
+cd build_OPT.OBJ
+../configure
+# Use "mozmake" on Windows
+make
+
+ +

一些注意事项:

+ + + +
+

Note: If you are on Mac and getting an error similar to

+ +

"checking whether the C compiler (gcc-4.2  ) works... no
+ configure: error: installation or configuration problem: C compiler cannot create executables.
"

+ +

You can try configuring like so:

+ +
CC=clang CXX=clang++  ../configure
+ +

It is also possible that baldrdash  may fail to compile with

+ +
/usr/local/Cellar/llvm/7.0.1/lib/clang/7.0.1/include/inttypes.h:30:15: fatal error: 'inttypes.h' file not found
+
+/usr/local/Cellar/llvm/7.0.1/lib/clang/7.0.1/include/inttypes.h:30:15: fatal error: 'inttypes.h' file not found, err: true
+ +

This is because, starting from Mohave, headers are no longer installed in /usr/include. Refer the release notes  under Command Line Tools -> New Features

+ +

The release notes also states that this compatibility package will no longer be provided in the near future, so the build system on macOS will have to be adapted to look for headers in the SDK
+
+ Until then, the following should help,

+ +
open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pk
+
+
+ +

This builds an executable named js in the directory build-release/dist/bin. You can test it with dist/bin/js --help, which displays a help page. At this point, you're ready to run and try out the shell.

+ +

On Mac, Linux, or UNIX, you can install SpiderMonkey on your system with the additional command make install. This installs the shared library to /usr/local/lib, the C header files to /usr/local/include, and the js executable to/usr/local/bin.

+ +

开发者 (调试) 模式构建

+ +

For developing and debugging SpiderMonkey itself, it is best to have both a debug build (for everyday debugging) and an optimized build (for performance testing), in separate build directories. Thus, in addition to following the steps above, you should also create a debug build using these steps:

+ +
cd js/src
+autoconf2.13
+
+# This name should end with "_DBG.OBJ" to make the version control system ignore it.
+mkdir build_DBG.OBJ
+cd build_DBG.OBJ
+../configure --enable-debug --disable-optimize
+# Use "mozmake" on Windows
+make
+
+ +

You can also build debug builds of SpiderMonkey with the JS_GC_ZEAL option, which adds a new built-in function to SpiderMonkey that lets you configure zealous garbage collection.  This can help debug memory leaks and other memory-related problems. See JS_SetGCZeal() for details.

+ +

For a list of other available build options, type (assuming the current working directory is one of the above-created build directories):

+ +
../configure --help
+
+ +

生成编译数据库

+ +

Some tools (like IDEs, static analyzers and refactoring tools) consume a file called compile_commands.json which contains a description of all the pieces required to build a piece of software so that tools don't have to also understand a build system.

+ +

To generate a compile_commands.json with the SpiderMonkey configure script, enable the CompileDB backend, like this:

+ +
 ../configure <options> --enable-build-backends=CompileDB,RecursiveMake
+
+ +

(RecursiveMake is there as you'd likely also want to be able to build!)

+ +

Windows Builds

+ +
+

Since version 28, threadsafe builds are the default, and should work out of the box on all POSIX platforms. Hence, the following instructions should only be relevant if you're on Windows or compiling an older version of SpiderMonkey.

+
+ +

The MozillaBuild batch file you used to open your shell (e.g. start-shell-msvc2013.bat or start-shell-msvc2013-x64.bat) determines whether the compiler toolchain will target 32-bit or 64-bit builds. To create a 64-bit build, note that you must configure with --target=x86_64-pc-mingw32 --host=x86_64-pc-mingw32.

+ +

Since the POSIX NSPR emulation is not available for Windows, a working version of NSPR must be available to your build. The easiest option is to configure with --enable-nspr-build. This configure option builds the in-tree version of NSPR which is probably what you want; because SpiderMonkey uses newer NSPR symbols, the NSPR that ships with your operating system probably does not work.

+ +

If --enable-nspr-build does not work, explicitly tell configure where to find NSPR using the --with-nspr-cflags and --with-nspr-libs configure options. For example, assuming your local NSPR has been installed to C:/mozilla-build/msys/local:

+ +
./configure --with-nspr-cflags="-IC:/mozilla-build/msys/local/include" \
+            --with-nspr-libs="C:/mozilla-build/msys/local/lib/libnspr4.a \
+                              C:/mozilla-build/msys/local/lib/libplds4.a \
+                              C:/mozilla-build/msys/local/lib/libplc4.a"
+
+ +

If you get symbol loading or dynamic library errors, you can force the correct NSPR to load with:

+ +
PATH="$PATH;C:/mozilla-build/msys/local/lib/" ./js
+ +

指定安装目录

+ +

make install puts files in the following directories by default. You can override this by passing options to the configure script:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
What it isWhere it gets putconfigure option
executables, shell scripts/usr/local/bin--bindir
libraries, data/usr/local/lib--libdir
architecture-independent data/usr/local/share--sharedir
C header files/usr/local/include--includedir
+ +

For convenience, you can pass the configure script an option of the form --prefix=<PREFIXDIR>, which substitutes <PREFIXDIR> for /usr/local in all the settings above, in one step. This is usually the least troublesome thing to do, as it preserves the typical arrangement of lib, bin, and the rest.

+ +
Note: All directories you pass to configure are recorded in the generated makefile, so you don't need to specify them again until you re-run configure.
+ +

构建 SpiderMonkey 作为静态库

+ +

默认情况下, SpiderMonkey 会构建为共享库. However, you can build SpiderMonkey as a static library by specifying the --disable-shared-js flag when you run configure.

+ +

指定编译器及编译标签

+ +

If you want to use a compiler other than the one the configure script chooses for you by default, you can set the CXX variable in the environment when you run configure. This will save the values you specify in the generated makefile, so once you've set it, you don't need to do so again until you re-run configure.

+ +

If you'd like to pass certain flags to the compiler, you can set the CXXFLAGS environment variable when you run configure. For example, if you're using the GNU toolchain, the following will pass the -g3 flag to the compiler, causing it to emit debug information about macros. Then you can use those macros in gdb commands:

+ +
$ CXXFLAGS=-g3 $SRC/configure
+...
+checking whether the C++ compiler (c++ -g3 ) works... yes
+...
+$
+
+ +

交叉编译选项

+ +

For cross-compiling you will need a cross-compiling compiler. That tends to be easier with clang as clang has cross-compiling support built in. You may need other libraries though.  For example on debian linux you'll need the following to cross compile from x86_64 to x86.

+ +
apt install clang libstdc++-8-dev-i386-cross binutils-i686-gnu zlib1g-dev:i386
+ +

You'll also need rust, in addition to having normal rust set up you'll need to add another target to your existing rust toolchain (don't add a new toolchain spidermonkey will use only one toolchain and use it for both host and target code:

+ +
rustup target add i686-unknown-linux-gnu
+ +

To build a 32-bit version on a 64-bit Linux system, you can use the following:

+ +
PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig CC="gcc -m32 -mfpmath=sse -msse -msse2" CXX="g++ -m32 -mfpmath=sse -msse -msse2" AR=ar \
+$SRC/configure --target=i686-pc-linux
+
+ +

Or for clang.

+ +
$SRC/configure --target=i686-pc-linux-gnu
+ +

To build a 32-bit arm version on a 64-bit Linux system, that runs in the arm simulator, you can use the following:

+ +
   AR=ar CC="gcc -m32 -mfpmath=sse -msse -msse2" CXX="g++ -m32 -mfpmath=sse -msse -msse2" \
+    $SRC/configure --target=i686-pc-linux --enable-simulator=arm
+
+ +

To build a 32-bit version on a 64-bit Mac system (the target version is specific to your OS/X SDK), you can use the following:

+ +
$SRC/configure --target=i386-apple-darwin16.7.0 # Choose the appropriate SDK version for your version of OS/X
+ +

To build a 64-bit version on a 32-bit Mac system (e.g. Mac OS X 10.5), you can use the following:

+ +
AR=ar CC="gcc -m64" CXX="g++ -m64" ../configure --target=x86_64-apple-darwin10.0.0
+
+ +

To build a 64-bit Windows version, you can use the following:

+ +
$SRC/configure --host=x86_64-pc-mingw32 --target=x86_64-pc-mingw32
+
+ +
Note: You must have started your MozillaBuild shell with the proper -x64.bat script in order for the 64-bit compilers to be in your PATH.
+ +

Whatever compiler and flags you pass to configure are recorded in the generated makefile, so you don't need to specify them again until you re-run configure.

+ +

Building your application

+ +

While "How to build your complete application" is clearly out of scope for this document, here are some tips that will help get you on your way:

+ + + +

Using the js-config script

+ +

In addition to the SpiderMonkey libraries, header files, and shell, the SpiderMonkey build also produces a shell script named js-config which other build systems can use to find out how to compile code using the SpiderMonkey APIs, and how to link with the SpiderMonkey libraries.

+ +
Note: In SpiderMonkey 1.8.5, the js-config script is not generated properly on many platforms. If the instructions below do not work, you can try this workaround.
+ +

When invoked with the --cflags option, js-config prints the flags that you should pass to the C compiler when compiling files that use the SpiderMonkey API. These flags ensure the compiler will find the SpiderMonkey header files.

+ +
$ ./js-config --cflags # Example output: -I/usr/local/include/js -I/usr/include/nspr
+
+ +

When invoked with the --libs option, js-config prints the flags that you should pass to the C compiler when linking an executable or shared library that uses SpiderMonkey. These flags ensure the compiler will find the SpiderMonkey libraries, along with any libraries that SpiderMonkey itself depends upon (like NSPR).

+ +
$ ./js-config --libs # Example output: -L/usr/local/lib -lmozjs -L/usr/lib -lplds4 -lplc4 -lnspr4 -lpthread -ldl -ldl -lm  -lm -ldl
+ +

Testing SpiderMonkey

+ + + +

Building SpiderMonkey 1.8 or earlier

+ +

Use these instructions to build SpiderMonkey from an official source release or from the old CVS repository. To build the latest SpiderMonkey sources from Mercurial, see Building SpiderMonkey above.

+ +

SpiderMonkey is easy to build from source if you have the usual Mozilla build prerequisites installed. Before you begin, make sure you have right build tools for your computer: LinuxWindowsMacothers.

+ +

First, download a SpiderMonkey source distribution, such as SpiderMonkey 1.8 Release Candidate 1.

+ +

To build, use these commands:

+ +
tar xvzf js-1.8.0-rc1.tar.gz
+cd js/src
+make -f Makefile.ref
+
+ +

This builds a debug version of SpiderMonkey. All build files are created in a subdirectory named depending on your system (for example,Linux_All_DBG.OBJ if you are on Linux). To install this build on your system, see SpiderMonkey installation instructions.

+ +

To build an optimized (non-debug) version of SpiderMonkey:

+ +
make BUILD_OPT=1 -f Makefile.ref
+ +

To build a thread-safe version of SpiderMonkey:

+ +
make JS_DIST=/full/path/to/directory/containing/nspr JS_THREADSAFE=1 -f Makefile.ref
+
diff --git a/files/zh-cn/mozilla/projects/spidermonkey/comparision_of_js_engines/index.html b/files/zh-cn/mozilla/projects/spidermonkey/comparision_of_js_engines/index.html new file mode 100644 index 0000000000..934e38ad7a --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/comparision_of_js_engines/index.html @@ -0,0 +1,105 @@ +--- +title: JS 引擎比较 +slug: Mozilla/Projects/SpiderMonkey/Comparision_of_JS_engines +--- +

概述

+

本页用来纪录各个开源 JS 引擎(SpiderMonkey、V8、JavaScriptCore)在算法、未来趋势上的比较。除非额外说明,内存相关的数据假设系统为 32 位

+

类、函数、词汇比较表

+

为了让懂得其中一个 JS 引擎的程序员迅速了解另外一个引擎,以下整理这些引擎共同概念的实现比较(把鼠标放在类/函数上面可以找到定义该类/函数的文件):

+

常见

+ + + + + + + + + + + + + + + + + + + + + + + + + +
SpiderMonkeyV8备注
ValueMaybeObject *代表一个 JS 值(数值、字符串、对象……)的类。SpiderMonkey 是用 nun-boxing,总是一个 double 的大小(因此在 32 位的系统下,传值需要两个 cycle)。V8 是用 tagged pointer,总是一个指针的大小,浮点数存在堆上。MaybeObject 还是很多非 JS 语言对象(代码块等等)的父类
 ObjectImplJSObjectJS 对象(obj instanceof Object)的实现类。SpiderMonkey 与 V8 皆是把部分属性存放在对象行内,部分用外链的一个数组储存的模式。SpiderMonkey 也将小数组的数据存在行内(但是不会分两半),而 V8 的 JS 数组对象(貌似)都是将数据存在外链的数组上。在 SpiderMonkey 中,只有在 new space 的 JS 对象的外链数组的空间由虚拟机分配,其他情况的外链数组的空间malloc 分配(因此内存会比较分裂?)。ObjectImpl 除了有连接到 Shape 的指针之外,还有一个链到 TypeObject 的指针:16 B(ObjectImpl)vs. 12 B(JSObject)。在 SpiderMonkey 中,数据用 Value 存,也就是说,对于一个有 k 个行内属性的 JS 对象来说,内存占用是:16 B + k * 8 B(ObjectImpl)vs. 12 B + k * 4 B(JSObject),行外的情形 V8 则会再多用 8 B(FixedArray 的标头)。
ShapeTypeObjectClassMap隐藏类的实现类。在 SpiderMonkey 中,属性名存在 Shape 上(因此带有 V8 的 DescriptorArray 的作用),JS 对象的原型存在 TypeObject 上,特殊属性的处理方法存在 Class 上(Class 对象不是 JS 堆里的对象,大部分都共用:JSObject::class_JSFunction::class_……)。由于 V8 的 Map 有 SM 三个类的作用,因此占用内存也比较多:24 B(Shape)vs. 40 B(Map)。
+

内存布局与对象创建

+

运行时

+ + + + + + + + + + + + + +
SpiderMonkeyV8备注
Interpret(无)解释器的主回圈。V8 没有字节码与解释器。
+

堆与 GC

+ + + + + + + + + + + + + +
SpiderMonkeyV8备注
NurseryNewSpace 
+

调优

+

一个容易调优的 JS 引擎应该具备有以下条件(从重要的到不重要的):

+ +

参见

+ +

跟 “JS 引擎” 比较无关,但是中文的 JS 引擎相关的博文也比较少,这里搜集一下:

+ +

代码美观

+

这件事实在不应该是决定使用哪个 JS 引擎的因素,不过……

+

如果(不幸的)需要以 SpiderMonkey 作为基础调优则会碰到以下问题:

+
    +
  1. C 与 C++ 代码混用。SpiderMonkey 原先是 C 写成的,后来大规模的以 C++ 改进,但是留下了很多残骸:宏、不是宏但是名称是大写的函数。(参见 JS::Value 的说明。)
  2. +
  3. 成员变量、方法命名缺乏规则。ObjectImpl::slotsObjectImpl::shape_ 同时存在(前面那个应该加底线)。这个或许是可以修复的 bug。
  4. +
  5. 混入 JavaScriptCore、V8 代码。SpiderMonkey 的组译器是 JavaScriptCore 的,那些类的成员变量是 m_buffer 等等,又增加了成员变量命名的。另外还有 WTF_* 宏,真是 WTF。再批。妈的,WTF_CPU_ARM_THUMB2 跟本不可能为真,这里有大量的死代码(所有代码完全没有用到 JSC::MacroAssembler,用到的是 js::jit::MacroAssembler)。另外,
  6. +
  7. 混乱的名称空间。
  8. +
  9. structclass 混用。
  10. +
  11. 文档命名缺少规则。C 时代的档名是 jsobj.h,C++ 时代的档名是 Value.h 。请自重。
  12. +
  13. 过渡滥用宏。
  14. +
diff --git a/files/zh-cn/mozilla/projects/spidermonkey/index.html b/files/zh-cn/mozilla/projects/spidermonkey/index.html new file mode 100644 index 0000000000..468fafa0cb --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/index.html @@ -0,0 +1,132 @@ +--- +title: SpiderMonkey +slug: Mozilla/Projects/SpiderMonkey +tags: + - SpiderMonkey + - Update +translation_of: Mozilla/Projects/SpiderMonkey +--- +

SpiderMonkey 是Mozilla使用C/C++编写的JavaScript 引擎。它被用于包括Firefox在内的多个Mozilla产品中,使用的是MPL 2授权协议.

+ +

独立的源代码版本可以在发布页上找到

+ + + + + + + + +
+

文档

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

General

+
SpiderMonkey Build Documentation如何获取到SpiderMonkey源代码,编译,并运行测试套.
Introduction to the JavaScript shell如何获取,构建,并使用JavaScript shell.
Running Automated JavaScript Tests如何运行JavaScript测试套件.
Creating JavaScript tests如何为JavaScript测试套件添加测试.
New to SpiderMonkeySpiderMonkey的hacking指南.
Setting up CDT to work on SpiderMonkey如何配置CDT,使之在SpiderMonkey代码上工作.
+

JSAPI

+
JSAPI User Guide本指南简要介绍了SpiderMonkey,还介绍了如何可以将SpiderMonkey嵌入到你的应用程序中.
JSAPI Phrasebook一些常用的JavaScript表达式和语句的JSAPI翻译.
JSAPI ReferenceSpiderMonkey API 参考.
Bytecode ReferenceSpiderMonkey 字节码参考.
JS Debugger API Guide在Gecko 8.0中引入的新的JavaScript调试器API{{ geckoRelease("8.0") }}.
JS Debugger API ReferenceSpiderMonkey 1.8.6(Gecko 8.0 )中引入的Debugger对象的API参考, {{ geckoRelease("8.0") }}.
JSDBGAPI Reference +

SpiderMonkey调试API参考;SpiderMonkey 1.8.5之前版本的调试API, 虽然它并没有被删除.

+
+

提示,技巧和理念

+
How to embed the JavaScript engine如何嵌入SpiderMonkey的基础教程
SpiderMonkey Garbage Collection Tips如何避免垃圾回收时出现的问题.
SpiderMonkey Internals设计概况和实现版本介绍
SpiderMonkey Internals: GC关于垃圾回收的独立的内部文章.
SpiderMonkey Internals: Thread SafetySpiderMonkey的请求模型的内部工作原理.
+
+ + + + + +

社区

+ +

有问题? 在IRC上提问!

+ +

查看 Infomonkey.

+ +

有bug? 提交bugCore -> JavaScript Engine

+
diff --git a/files/zh-cn/mozilla/projects/spidermonkey/internals/bytecodes/index.html b/files/zh-cn/mozilla/projects/spidermonkey/internals/bytecodes/index.html new file mode 100644 index 0000000000..7c47ffb7ae --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/internals/bytecodes/index.html @@ -0,0 +1,30 @@ +--- +title: 字节码 +slug: Mozilla/Projects/SpiderMonkey/Internals/Bytecodes +tags: + - SpiderMonkey +translation_of: Mozilla/Projects/SpiderMonkey/Internals/Bytecodes +--- +
{{SpiderMonkeySidebar("Internals")}}
+ +

背景知识

+ +

SpiderMonkey字节码是JavaScript引擎使用的标准代码表示形式。JavaScript前端根据源文本构建AST,然后根据JSScript数据结构的一部分从AST生成基于堆栈的字节码。字节码可以引用原子和对象(通常通过数组索引),这些原子和对象也包含在JSScript数据结构中。

+ +

在引擎内,所有字节码都在堆栈帧内执行。堆栈帧与全局(顶级)代码和eval代码相关联。堆栈上的框架为几个不同类别的JavaScript值(标记值格式)留出空间。单个JavaScript值空间称为“插槽”,类别为:

+ + + +

还有一些保留给专用功能的插槽,用于处理thiscallee返回值。.

+ +

总有一个“堆栈顶部”(TOS),它对应于推入表达式堆栈的最新值。所有字节码都根据该位置隐式运行。

+ +

字节码列表

+ +

所有操作码都用 [-popcount, +pushcount] 标注,以表示整个执行的堆栈效果。

+ +

字节码列表已移至 SpiderMonkey Internals: Bytecode Descriptions 页面。

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/internals/functions/index.html b/files/zh-cn/mozilla/projects/spidermonkey/internals/functions/index.html new file mode 100644 index 0000000000..91d96b22eb --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/internals/functions/index.html @@ -0,0 +1,73 @@ +--- +title: Functions +slug: Mozilla/Projects/SpiderMonkey/Internals/Functions +translation_of: Mozilla/Projects/SpiderMonkey/Internals/Functions +--- +
{{SpiderMonkeySidebar("Internals")}}
+ +

There are several flavors of JavaScript function. All are JSObjects of the same class, js_FunctionClass.

+ +

这里有些Javscript函数,它们属于JSObjects

+ +

(But note that objects of other classes can be callable and can even have typeof obj == "function".)

+ +

(也存在其他可被Call的对象)

+ +

Script functions

+ +

Functions written in JavaScript and compiled to bytecode. There are four variations that affect how NameExpressions are evaluated. (NameExpressions are basic expressions like String and x that would eat up a huge amount of run time if the engine weren't smart enough to avoid symbol table lookups.)

+ +

General closures are the base case. When the function object is created, its parent is set to the first object on the scope chain. When a name is evaluated that doesn't refer to a local variable, the interpreter consults the scope chain to find the variable. When with or eval are used, we have to do this for correctness.

+ +

This is slow, not only because walking the scope chain is a drag, but also because we'd rather avoid actually creating the scope chain at all, if possible. General closures force the interpreter to verify the whole scope chain. So we optimize this when we can.

+ +

These optimizations depend on being sure that we will never have to walk the scope chain, so with and eval inhibit them all.

+ +

Null closures. If we can prove at compile time that a function does not refer to any locals or arguments of enclosing functions, it is a null closure. Since it will never need to walk the scope chain, its parent is the global object. This is the best case. Barring with and eval, all outermost functions are null closures.

+ +

Null closures with upvars. A nested function is algol-like if it is only ever defined and called, and it isn't accessed in any other way (and it is not a generator-function). Such a function is guaranteed never to be called again after the enclosing function exits. An algol-like function may read the local variables and arguments of its immediate enclosing function from the stack, as if by magic. (JSContext::display caches the enclosing function's stack frame.) If that function is also algol-like, its child can read locals and variables from the next enclosing function, and so on. The compiler detects these cases and makes such functions null closures too.

+ +

Flat closures. Suppose a function reads some variables from enclosing functions but is not algol-like. If the function does not assign to any closed-on vars/args, and it only reads closed-on local variables and arguments that never change value after the function is created, then the function can be implemented as a flat closure. When a flat closure is created, all the closed-on values are copied from the stack into reserved slots of the function object. To evaluate a name, instead of walking the scope chain, we just take the value from the reserved slot. The function object's parent is the global object.

+ +

Flat closures and Null closures have been removed:

+ +

https://bugzilla.mozilla.org/show_bug.cgi?id=730497

+ +

https://bugzilla.mozilla.org/show_bug.cgi?id=739808

+ +

Name lookups

+ +

In order of speed, fastest to slowest.

+ +
    +
  1. +

    ARG and LOCAL instructions. If a name definitely refers to an argument or local variable of the immediately enclosing function, it can be accessed using JSOP_{GET,SET,CALL}{ARG,LOCAL} instructions. Some of these can even be fused with other operations into combo instructions like JSOP_GETARGPROP, JSOP_FORLOCAL, and JSOP_INCLOCAL. Because arguments and locals can't be deleted, this optimization is available to all functions, and eval does not interfere with it. But a with block can:

    + +
    function f(s) {
    +    eval(s);
    +    print(s);  // s can be loaded with GETARG
    +    with (obj) {
    +        print(s);  // no GETARG here; s might refer to obj.s
    +    }
    +}
    +
    +
  2. +
  3. +

    UPVAR instructions. JSOP_{GET,CALL}UPVAR (in algol-like functions only, I think?) TODO

    +
  4. +
  5. +

    DSLOT instructions. JSOP_{GET,CALL}DSLOT (in flat closures only) TODO

    +
  6. +
  7. +

    GVAR instructions. Outside all functions, if a name definitely refers to a global for which we have seen a var, const, or function declaration, then we emit a JS_DEFVAR instruction in the script prelude and access the global using JSOP_{GET,SET,CALL}GVAR. This is fast if the global either doesn't exist before the script runs (the script creates it) or it's a non-configurable data property (which amounts to the same thing). Otherwise the GVAR instructions are as slow as NAME instructions.

    + +

    There are also combo instructions JSOP_{INC,DEC}GVAR and JSOP_GVAR{INC,DEC}.

    +
  8. +
  9. +

    NAME instructions. In the worst case we emit JSOP_{,SET,CALL}NAME. These are totally general. They can still be optimized via the property cache; in the worst case we walk the scope chain.

    + +

    In some cases, the JIT can optimize a JSOP_NAME instruction that refers to a variable in an enclosing scope to pull the value directly out of the Call object's dslots.

    + +

    For the expression delete name we always emit JSOP_DELNAME. It's not worth optimizing.

    +
  10. +
diff --git a/files/zh-cn/mozilla/projects/spidermonkey/internals/index.html b/files/zh-cn/mozilla/projects/spidermonkey/internals/index.html new file mode 100644 index 0000000000..03228c312f --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/internals/index.html @@ -0,0 +1,292 @@ +--- +title: SpiderMonkey Internals +slug: Mozilla/Projects/SpiderMonkey/Internals +tags: + - Guide + - JavaScript + - NeedsMarkupWork + - NeedsTranslation + - SpiderMonkey + - TopicStub +translation_of: Mozilla/Projects/SpiderMonkey/Internals +--- +

Design walk-through

+ +

At heart, SpiderMonkey is a fast interpreter that runs an untyped bytecode and operates on values of type jsval—type-tagged double-sized values that represent the full range of JavaScript values. In addition to the interpreter, SpiderMonkey contains a Just-In-Time (JIT) compiler, a garbage collector, code implementing the basic behavior of JavaScript values, a standard library implementing ECMA 262-3 §15 with various extensions, and a few public APIs.

+ +

Interpreter

+ +

Like many portable interpreters, SpiderMonkey's interpreter is mainly a single, tremendously long function that steps through the bytecode one instruction at a time, using a switch statement (or faster alternative, depending on the compiler) to jump to the appropriate chunk of code for the current instruction. A JS-to-JS function call pushes a JavaScript stack frame without growing the C stack. But since JS-to-C-to-JS call stacks are common, the interpreter is reentrant.

+ +

Some SpiderMonkey bytecode operations have many special cases, depending on the type of their arguments. Common cases are inlined in the interpreter loop, breaking any abstractions that stand in the way. So optimizations such as dense arrays and the property cache are, alas, not transparently tucked away in the jsarray.* and jsobj.* files. Both guest-star in jsinterp.cpp (to thunderous applause from Firefox users).

+ +

All state associated with an interpreter instance is passed through formal parameters to the interpreter entry point; most implicit state is collected in a type named JSContext. Therefore, almost all functions in SpiderMonkey, API or not, take a JSContext pointer as their first argument.

+ +

Compiler

+ +

The compiler consumes JavaScript source code and produces a script which contains bytecode, source annotations, and a pool of string, number, and identifier literals. The script also contains objects, including any functions defined in the source code, each of which has its own, nested script.

+ +

The compiler consists of: a random-logic rather than table-driven lexical scanner, a recursive-descent parser that produces an AST, and a tree-walking code generator. Semantic and lexical feedback are used to disambiguate hard cases such as missing semicolons, assignable expressions ("lvalues" in C parlance), and whether / is the division symbol or the start of a regular expression. The compiler attempts no error recovery; it bails out on the first error. The emitter does some constant folding and a few codegen optimizations; about the fanciest thing it does is to attach source notes to the script for the decompiler's benefit.

+ +

The decompiler implements Function.toSource(), which reconstructs a function's source code. It translates postfix bytecode into infix source by consulting a separate byte-sized code, called source notes, to disambiguate bytecodes that result from more than one grammatical production.

+ +

Garbage collector

+ +

The GC is a mark-and-sweep, non-conservative (exact) collector. It is used to hold JS objects and string descriptors (but not property lists or string bytes), and double-precision floating point numbers. It runs automatically only when maxbytes (as passed to JS_NewRuntime) bytes of GC things have been allocated and another thing-allocation request is made. JS API users should call JS_GC or JS_MaybeGC between script executions or from the branch callback, as often as necessary.

+ +

Because the GC is exact, C/C++ applications must ensure that all live objects, strings, and numbers are GC-reachable. Many techniques are available; see SpiderMonkey Garbage Collection Tips.

+ +

JavaScript values

+ +

The type jsval represents a JavaScript value.

+ +

The representation is 64 bits and uses NaN-boxing on all platforms, although the exact NaN-boxing format depends on the platform. NaN-boxing is a technique based on the fact that in IEEE-754 there are 2**47 different bit patterns that all represent NaN. Hence, we can encode any floating-point value as a C++ double (noting that JavaScript NaN must be represented as one canonical NaN format). Other values are encoded as a value and a type tag:

+ + + +

Only JIT code really depends on the layout--everything else in the engine interacts with values through functions like JSVAL_IS_INT. Most parts of the JIT also avoid depending directly on the layout: the files PunboxAssembler.h and NunboxAssembler.h are used to generate native code that depends on the value layout.

+ +

Objects consist of a possibly shared structural description, called the map or scope; and unshared property values in a vector, called the slots. Each property has an id, either a nonnegative integer or an atom (unique string), with the same tagged-pointer encoding as a jsval.

+ +

The atom manager consists of a hash table associating strings uniquely with scanner/parser information such as keyword type, index in script or function literal pool, etc. Atoms play three roles: as literals referred to by unaligned 16-bit immediate bytecode operands, as unique string descriptors for efficient property name hashing, and as members of the root GC set for exact GC.

+ +

Standard library

+ +

The methods for arrays, booleans, dates, functions, numbers, and strings are implemented using the JS API. Most are JSNatives. Most string methods are customized to accept a primitive string as the this argument. (Otherwise, SpiderMonkey converts primitive values to objects before invoking their methods, per ECMA 262-3 §11.2.1.)

+ +

Error handling

+ +

SpiderMonkey has two interdependent error-handling systems: JavaScript exceptions (which are not implemented with, or even compatible with, any kind of native C/C++ exception handling) and error reporting. In general, both functions inside SpiderMonkey and JSAPI callback functions signal errors by calling JS_ReportError or one of its variants, or JS_SetPendingException, and returning JS_FALSE or NULL.

+ +

Public APIs

+ +

The public C/C++ interface, called the JSAPI, is in most places a thin (but source-compatible across versions) layer over the implementation. See the JSAPI User Guide. There is an additional public API for JavaScript debuggers, JSDBGAPI, but {{Source("js/jsd/jsdebug.h")}} might be a better API for debuggers. Another API, JSXDRAPI, provides serialization for JavaScript scripts. (XUL Fastload uses this.)

+ +

Just-In-Time compiler

+ +

{{jsapi_minversion_inline("1.8.5")}} SpiderMonkey contains a just-in-time compiler, code-named JägerMonkey, that converts bytecode to machine code for faster execution. The JIT works by detecting commonly executed functions or functions containing hot loops and then compiling these methods into machine code.

+ +

A second JIT, code-named IonMonkey was enabled in Firefox 18.

+ +

Self-hosting of builtin functions in JS

+ +

Starting with Firefox 17, SpiderMonkey has the ability to implement builtin functions in self-hosted JS code. This code is compiled in a special compilation mode that gives it access to functionality that's not normally exposed to JS code, but that's required for safe and specification-conformant implementation of builtin functions.

+ +

All self-hosted code lives in .js files under builtin/. For details on implementing self-hosted builtins, see self-hosting.

+ +

File walkthrough

+ +

jsapi.cpp, jsapi.h

+ +

The public API to be used by almost all client code.

+ +

jspubtd.h, jsprvtd.h

+ +

These files exist to group struct and scalar typedefs so they can be used everywhere without dragging in struct definitions from N different files. The jspubtd.h file contains public typedefs, and is included automatically when needed. The jsprvtd.h file contains private typedefs and is included by various .h files that need type names, but not type sizes or declarations.

+ +

jsdbgapi.cpp, jsdbgapi.h

+ +

The debugging API. Provided so far:

+ +

Traps, with which breakpoints, single-stepping, step over, step out, and so on can be implemented. The debugger will have to consult jsopcode.def on its own to figure out where to plant trap instructions to implement functions like step out, but a future jsdbgapi.h will provide convenience interfaces to do these things. At most one trap per bytecode can be set. When a script (JSScript) is destroyed, all traps set in its bytecode are cleared.

+ +

Watchpoints, for intercepting set operations on properties and running a debugger-supplied function that receives the old value and a pointer to the new one, which it can use to modify the new value being set.

+ +

Line number to PC and back mapping functions. The line-to-PC direction "rounds" toward the next bytecode generated from a line greater than or equal to the input line, and may return the PC of a for-loop update part, if given the line number of the loop body's closing brace. Any line after the last one in a script or function maps to a PC one byte beyond the last bytecode in the script. An example, from perfect.js:

+ +
function perfect(n) {
+  print("The perfect numbers up to " + n + " are:");
+  // We build sumOfDivisors[i] to hold a string expression for
+  // the sum of the divisors of i, excluding i itself.
+  var sumOfDivisors = new ExprArray(n+1,1);
+  for (var divisor = 2; divisor <= n; divisor++) {
+    for (var j = divisor + divisor; j <= n; j += divisor) {
+      sumOfDivisors[j] += " + " + divisor;
+    }
+    // At this point everything up to 'divisor' has its sumOfDivisors
+    // expression calculated, so we can determine whether it's perfect
+    // already by evaluating.
+    if (eval(sumOfDivisors[divisor]) == divisor) {
+      print("" + divisor + " = " + sumOfDivisors[divisor]);
+    }
+  }
+  delete sumOfDivisors;
+  print("That's all.");
+}
+ +

The line number to PC and back mappings can be tested using the js program with the following script:

+ +
load("perfect.js");
+print(perfect);
+dis(perfect);
+print();
+for (var ln = 0; ln <= 40; ln++) {
+    var pc = line2pc(perfect, ln);
+    var ln2 = pc2line(perfect, pc);
+    print("\tline " + ln + " => pc " + pc + " => line " + ln2);
+}
+
+ +

The result of the for loop over lines 0 to 40 inclusive is:

+ +
line 0 => pc 0 => line 16
+line 1 => pc 0 => line 16
+line 2 => pc 0 => line 16
+line 3 => pc 0 => line 16
+line 4 => pc 0 => line 16
+line 5 => pc 0 => line 16
+line 6 => pc 0 => line 16
+line 7 => pc 0 => line 16
+line 8 => pc 0 => line 16
+line 9 => pc 0 => line 16
+line 10 => pc 0 => line 16
+line 11 => pc 0 => line 16
+line 12 => pc 0 => line 16
+line 13 => pc 0 => line 16
+line 14 => pc 0 => line 16
+line 15 => pc 0 => line 16
+line 16 => pc 0 => line 16
+line 17 => pc 19 => line 20
+line 18 => pc 19 => line 20
+line 19 => pc 19 => line 20
+line 20 => pc 19 => line 20
+line 21 => pc 36 => line 21
+line 22 => pc 53 => line 22
+line 23 => pc 74 => line 23
+line 24 => pc 92 => line 22
+line 25 => pc 106 => line 28
+line 26 => pc 106 => line 28
+line 27 => pc 106 => line 28
+line 28 => pc 106 => line 28
+line 29 => pc 127 => line 29
+line 30 => pc 154 => line 21
+line 31 => pc 154 => line 21
+line 32 => pc 161 => line 32
+line 33 => pc 172 => line 33
+line 34 => pc 172 => line 33
+line 35 => pc 172 => line 33
+line 36 => pc 172 => line 33
+line 37 => pc 172 => line 33
+line 38 => pc 172 => line 33
+line 39 => pc 172 => line 33
+line 40 => pc 172 => line 33
+
+ +

jsconfig.h

+ +

Various configuration macros defined as 0 or 1 depending on how JS_VERSION is defined (as 10 for JavaScript 1.0, 11 for JavaScript 1.1, etc.). Not all macros are tested around related code yet. In particular, JS 1.0 support is missing from SpiderMonkey.

+ +

js.cpp, jsshell.msg

+ +

The "JS shell", a simple interpreter program that uses the JS API and more than a few internal interfaces (some of these internal interfaces could be replaced by jsapi.h calls). The js program built from this source provides a test vehicle for evaluating scripts and calling functions, trying out new debugger primitives, etc.

+ +

A look at the places where jsshell.msg is used in js.cpp shows how error messages can be handled in JSAPI applications. These messages can be localized at compile time by replacing the .msg file; or, with a little modification to the source, at run time.

+ +

More information on the JavaScript shell.

+ +

js.msg

+ +

SpiderMonkey error messages.

+ +

jsarray.*, jsbool.*, jsdate.*, jsfun.*, jsmath.*, jsnum.*, jsstr.*

+ +

These file pairs implement the standard classes and (where they exist) their underlying primitive types. They have similar structure, generally starting with class definitions and continuing with internal constructors, finalizers, and helper functions.

+ +

jsobj.*, jsscope.*

+ +

These two pairs declare and implement the JS object system. All of the following happen here:

+ + + +

The details of a native object's map (scope) are mostly hidden in jsscope.{{mediawiki.external('ch')}}.

+ +

jsatom.cpp, jsatom.h

+ +

The atom manager. Contains well-known string constants, their atoms, the global atom hash table and related state, the js_Atomize() function that turns a counted string of bytes into an atom, and literal pool (JSAtomMap) methods.

+ +

jsarena.cpp, jsarena.h

+ +

Last-In-First-Out allocation macros that amortize malloc costs and allow for en-masse freeing. See the paper mentioned in jsarena.h's major comment.

+ +

jsgc.cpp, jsgc.h

+ +

The garbage collector and tracing routines.

+ +

jsinterp.*, jscntxt.*, jsinvoke.cpp

+ +

The bytecode interpreter, and related functions such as Call and AllocStack, live in jsinterp.cpp. The JSContext constructor and destructor are factored out into jscntxt.cpp for minimal linking when the compiler part of JS is split from the interpreter part into a separate program.

+ +

jsinvoke.cpp is a build hack used on some platforms to build js_Interpret under different compiler options from the rest of jsinterp.cpp.

+ +

jstracer.*, nanojit/*

+ +

The tracing JIT. The interface between the JIT and the rest of SpiderMonkey is conceptually small—the interpreter calls into the trace recorder—but as with everything else, there are tendrils everywhere.

+ +

jsemit.*, jsopcode.tbl, jsopcode.*, jsparse.*, jsscan.*, jsscript.*

+ +

Compiler and decompiler modules. The jsopcode.tbl file is a C preprocessor source that defines almost everything there is to know about JS bytecodes. See its major comment for how to use it. For now, a debugger will use it and its dependents such as jsopcode.h directly, but over time we intend to extend jsdbgapi.h to hide uninteresting details and provide conveniences. The code generator is split across paragraphs of code in jsparse.cpp, and the utility methods called on JSCodeGenerator appear in jsemit.cpp. Source notes generated by jsparse.cpp and jsemit.cpp are used in jsscript.cpp to map line number to program counter and back.

+ +

jstypes.h

+ +

Fundamental representation types and utility macros. This file alone among all .h files in SpiderMonkey must be included first by .cpp files. It is not nested in .h files, as other prerequisite .h files generally are, since it is also a direct dependency of most .cpp files and would be over-included if nested in addition to being directly included.

+ +

jsbit.h, jslog2.cpp

+ +

Bit-twiddling routines. Most of the work here is selectively enabling compiler-specific intrinsics such as GCC's __builtin_ctz, which is useful in calculating base-2 logarithms of integers.

+ +

jsutil.cpp, jsutil.h

+ +

The JS_ASSERT macro is used throughout the source as a proof device to make invariants and preconditions clear to the reader, and to hold the line during maintenance and evolution against regressions or violations of assumptions that it would be too expensive to test unconditionally at run-time. Certain assertions are followed by run-time tests that cope with assertion failure, but only where I'm too smart or paranoid to believe the assertion will never fail...

+ +

jsclist.h

+ +

Doubly-linked circular list struct and macros.

+ +

jscpucfg.cpp

+ +

This standalone program generates jscpucfg.h, a header file containing bytes per word and other constants that depend on CPU architecture and C compiler type model. It tries to discover most of these constants by running its own experiments on the build host, so if you are cross-compiling, beware.

+ +

jsdtoa.cpp, jsdtoa.h, dtoa.c

+ +

dtoa.c contains David Gay's portable double-precision floating point to string conversion code, with Permission To Use notice included. jsdtoa.cpp #includes this file.

+ +

jshash.cpp, jshash.h, jsdhash.cpp, jsdhash.h

+ +

Portable, extensible hash tables. These use multiplicative hash for strength reduction over division hash, yet with very good key distribution over power of two table sizes. jshash resolves collisions via chaining, so each entry burns a malloc and can fragment the heap. jsdhash uses open addressing.

+ +

jslong.cpp, jslong.h

+ +

64-bit integer emulation, and compatible macros that use intrinsic C types, like long long, on platforms where they exist (most everywhere, these days).

+ +

jsprf.*

+ +

Portable, buffer-overrun-resistant sprintf and friends. For no good reason save lack of time, the %e, %f, and %g formats cause your system's native sprintf, rather than JS_dtoa(), to be used. This bug doesn't affect SpiderMonkey, because it uses its own JS_dtoa() call in jsnum.cpp to convert from double to string, but it's a bug that we'll fix later, and one you should be aware of if you intend to use a JS_*printf() function with your own floating type arguments - various vendor sprintf's mishandle NaN, +/-Inf, and some even print normal floating values inaccurately.

+ +

prmjtime.c, prmjtime.h

+ +

Time functions. These interfaces are named in a way that makes local vs. universal time confusion likely. Caveat emptor, and we're working on it. To make matters worse, Java (and therefore JavaScript) uses "local" time numbers (offsets from the epoch) in its Date class.

+ +

jsfile.cpp, jsfile.h, jsfile.msg

+ +

Obsolete. Do not use these files.

+ +

Makefile.in, build.mk

+ +

Mozilla makefiles. If you're building Gecko or Firefox, the larger build system will use these files. They are also used for current standalone builds.

+ +

Makefile.ref, rules.mk, config.mk, config/*

+ +

Obsolete SpiderMonkey standalone makefiles from 1.8 and earlier. See SpiderMonkey Build Documentation.

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/introduction_to_the_javascript_shell/index.html b/files/zh-cn/mozilla/projects/spidermonkey/introduction_to_the_javascript_shell/index.html new file mode 100644 index 0000000000..b570b78d56 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/introduction_to_the_javascript_shell/index.html @@ -0,0 +1,382 @@ +--- +title: JavaScript shell 介绍 +slug: Mozilla/Projects/SpiderMonkey/Introduction_to_the_JavaScript_shell +tags: + - SpiderMonkey + - 蜘蛛猴 +translation_of: Mozilla/Projects/SpiderMonkey/Introduction_to_the_JavaScript_shell +--- +
{{SpiderMonkeySidebar("General")}}
+ +
+

JavaScript shell 是一个命令行程序,它被包含在SpiderMonkey源代码中。它在 JavaScript 中类似于 Python 命令行、Lisp 读取执行循环和 Ruby 中的 irb 。这篇文章解释如何使用 shell 去测试 JavaScript 代码和执行 JavaScript 程序。

+
+ +

要获取 SpiderMonkey JavaScript shell, 请参见 SpiderMonkey 构建文档 或根据你的平台从 Nightly Builds 下载二进制文件。

+ +

对于其他的 JavaScript shells, 参考 JavaScript shells.

+ +
+

注意: 从 SpiderMonkey 44 开始,默认情况下使用标准的、与 Web 兼容的 JavaScript 版本(不再使用JS1.7 +)。 内置的 version() 内置函数仍然可以用来测试遗留功能。

+
+ +

执行JavaScript shell

+ +

jsshell 提供两种操作模式。你既可以交互式操作 shell, 在此模式你可以输入JavaScript 代码并执行。便于实验和测试新特性。你也可以在命令行参数指定一个 JavaScript 代码文件,此文件会自动运行。

+ +

在安装 jsshell 之后,你可以执行以下命令打开交互式终端:

+ +
js
+
+ +
+

注意:如果你在预编译程序执行中遇到
+ "symbol lookup error: ./js: undefined symbol: PR_SetCurrentThreadName"
+ 这样的错误, 请尝试用 run-mozilla.sh 文件执行它:
+ run-mozilla.sh ./js  
+ ——我测试过有效

+
+ +

如果运行 foo.js file中的JavaScript代码,你可以使用以下命令:

+ +
js foo.js
+
+ +

如果想运行 foo.js 然后进入交互模式:

+ +
js -f foo.js -i
+
+ +

说明

+ +
注意: 因为JavaScript shell 用来给 JavaScript 引擎做测试环境, 可用的选项和内置函数可能改变。
+ +

命令行选项

+ +

有许多命令行选项可以控制shell,以下为总结。使用-h选项显示帮助

+ +
+
-c, --compileonly
+
仅编译不执行代码,这是一种方便的检查语法错误的方式。
+
-e script
+
运行指定脚本,script 是将要执行的代码字符串。
+
-f filename
+
执行指定的代码文件。
+
-i
+
启用交互模式。(如果参数中没有文件名这个选项默认打开)
+
--no-ion
+
禁用优化的 JIT 编译器。
+
--no-baseline
+
禁用基准的 JIT 编译器。
+
-P
+
如果文件的第一行是 "/usr/bin/env js -P",文件内容将通过 JavaScript 引擎解释执行。
+
这将允许你在 unix 和 OS X 系统上执行 JavaScript 文件。
+
-s
+
启用严格警告模式.
+
-w, --warnings
+
显示警告消息.
+
-W, --nowarnings
+
隐藏警告消息.
+
+ +

环境选项

+ +

如果设置了这些环境变量,它们将会影响 js shell 的行为。

+ +
+
JS_STDOUT=file
+
将标准输出重定向到文件file
+
JS_STDERR=file
+
将标准输入重定向到文件file
+
+ +

内置函数

+ +

为了使 JavaScript shell 更加实用, 我们提供了一些内置的函数供 JavaScript 程序(包括交互模式下)使用。

+ +
+

注意:这个列表是不完整的而且与 Shell 全局对象 重复。请参见{{Source("js/src/shell/js.cpp")}} (在 shell_functions 附近) 以获取详细信息。

+
+ +

build()

+ +

返回 JavaScript shell 构建的日期和时间.

+ +
Note: clear() 函数如果不带任何参数,将清除包括所有内置方法在内的所有东西。
+ +

clone(function, [scope])

+ +

克隆指定函数对象。如果未指定具体域,新对象的父本和原始对象的相同。否则,新对象被放置于指定域。

+ +

countHeap([start[, kind]])

+ +

{{ jsapi_minversion_inline("1.8") }}   计算堆中活动的回收垃圾数量,或计算给定且不为 null 的可从 start 到达的对象的数量。kind 是“all”(默认)以计算所有事物,或者是“ object”,“ double”,“ string”,“ function”,“ qname”,“ namespace”,“ xml”之一以仅计算此类事物

+ +

dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])

+ +

{{ jsapi_minversion_inline("1.8") }} 转储所有现存对象的数据 (或有关联的子数据) 到文件。详情参见本函数的C/C++版本: JS_DumpHeap.

+ +

evalcx(string[, object])

+ +

执行 string 中的 JavaScript 代码。如果设置了参数 object,代码将在这个对象中执行,将其视为一个沙盒。

+ +

string 为空且没有设置 object 时,evalcx() 将会返回一个具有“eager” 标准类的新对象

+ +

string 为 "lazy" 且没有设置 object 时,evalcx() 将会返回一个具有“lazy” 标准类的新对象

+ +
注意: evalcx() 仅对进行 JavaScript 引擎极低层工作的开发者有用,用于在 shell 中测试类evalInSandbox 环境
+ +

gc()

+ +

运行垃圾收集器释放内存。

+ +

gcparam(name[, value])

+ +

{{ jsapi_minversion_inline("1.8") }} 读取或配置垃圾收集器参数。

+ +

名称必须是参数key之一 (例如 'maxBytes', 'maxMallocBytes''gcNumber').

+ +

如果value未指定,gcparam()返回与GC参数名name相关联的当前值

+ +

如果value被指定,其必须可转换为uint32,gcparam()将GC参数名设置为value。

+ +

For more information, see the C/C++ functions  JS_SetGCParameter and JS_SetGCParameter.

+ +

gczeal(level)

+ +

{{ jsapi_minversion_inline("1.8") }} DEBUG only. 设置GC zeal级别, 这是一个调试特性。0 是正常的周期性垃圾收集,1是频繁的GC, 2是及其频繁的GC. 除了0以外的都将使JavaScript运行极其缓慢但是可能有助于发现GC相关的 bug. For more information, see the C/C++ version of this function, JS_SetGCZeal.

+ +

getpda(object)

+ +

返回指定对象的属性描述

+ +

getslx(object)

+ +

返回脚本行范围,这是包含指定对象的代码行数

+ +

help([command ...])

+ +

显示有关指定命令或所有可用功能的简要帮助信息(如果未指定命令将显示所有帮助信息)。

+ +

intern(string)

+ +

将指定的字符串 内化到atom表中。每个字符串都有一个唯一的标识符,称为atom。这个系统使得对字符串进行比较变得更加容易。

+ +
Note: This function is intended only for use when testing the JavaScript engine.
+ +

line2pc([function, ] line)

+ +

返回对应于指定行的代码行的程序计数器值。如果指定了函数,那么行就是指定函数的偏移量.

+ +

load(filename1 [filename])

+ +

加载带有指定名称的JavaScript文件.

+ +
Note: For loading non-JavaScript files, use read().
+ +

options([option ...])

+ +

让你设置或获取选项。如果您在命令行上指定选项,那么调用options的结果将指示您所请求的选项。您还可以传递新的选项来设置.

+ +

The available options are:

+ + + + + + + + + + + + + + + + + + + + +
Option NameDescription
strict严格模式 is enabled.
werrorWarnings should be treated as errors.
atlineWhen atline is enabled, 表单的注释 //@line num set the number of the following line to num.
+ +

pc2line(function, [pc])

+ +

返回对应于指定函数的第一行的JavaScript代码的行号. If you specify a program counter offset into the function, the line number of the line of code containing that offset is returned.

+ +

print([expression ...])

+ +

Evaluates the expression(s) and displays the result(s) on stdout, 分隔 by spaces (" ") and 终止 by a newline ("\n").

+ +

putstr(expression)

+ +

Evaluates the expression and displays the result on stdout.

+ +

quit([status])

+ +

Exits the shell. 如果省略,状态默认为0。

+ +

read(filename[, type])

+ +

Reads and returns the contents of file. If type is "binary" returns an Uint8Array, otherwise returns an UTF-8 decoded string.

+ +

readline()

+ +

Reads a single line of input from stdin, returning it to the caller. You can use this to create interactive shell programs in JavaScript.

+ +

Reflect.parse()

+ +

See Parser API.

+ +
Note: This function is intended only for use when testing the JavaScript engine.
+ +

seal(object[, deep])

+ +

密封指定的对象, or an object graph if deep is true. 通过封住对象或对象图,可以禁用这些对象的修改.

+ +

sleep(dt)

+ +

{{ jsapi_minversion_inline("1.8") }} Only in JS_THREADSAFE builds. Sleep for dt seconds. Fractions of a second are supported. Returns true on success, false if the sleep was interrupted.

+ +

stackQuota([number]) {{obsolete_inline}}

+ +

{{ jsapi_minversion_inline("1.8") }} 获取或设置脚本堆栈配额.

+ +

throwError()

+ +

Throws an error from the JS_ReportError() function.

+ +
Note: This function is intended only for use when testing the JavaScript engine.
+ +

trap([function, [pc,]] expression)

+ +

在JavaScript代码的特定点设置trap. 当由pc在函数函数中指定的偏移量即将被执行时,表达式将被求值。

+ +

这是一种强大的调试机制,与line2pc()一起使用. 例如, 如果你想在函数的第6行中显示一条消息, doSomething() 被执行, you can enter the following:

+ +
trap(doSomething, line2pc(doSomething, 6), "print('line 6!\n')");
+
+ +
Note: 当设置陷阱时,程序中的相应字节码将被trap字节码替换,直到您使用untrap() 来移除陷阱。
+ +

untrap(function [, pc])

+ +

Removes a trap from the specified function at the offset pc. If pc isn't specified, the trap is removed from the function's entry point.

+ +

This function has no effect if there is no trap at the specified location.

+ +

version([number])

+ +

The version() function lets you get or set the JavaScript version number. This may be useful for gaining access to syntax only available in certain versions of JavaScript (for example, see Using JavaScript 1.7).

+ +

调试方法

+ +

These built-in functions are only available in DEBUG builds.

+ +

dis([function])

+ +

为整个程序或指定的函数分解JavaScript字节码

+ +

For example, if you enter the JavaScript function below:

+ +
function test() {
+  var i = 3;
+  print(i+2);
+}
+
+ +

Then run the command dis(test);, you get this output:

+ +
main:
+00000:  uint16 3
+00003:  setvar 0
+00006:  pop
+00007:  name "print"
+00010:  pushobj
+00011:  getvar 0
+00014:  uint16 2
+00017:  add
+00018:  call 1
+00021:  pop
+00022:  stop
+
+Source notes:
+  0:     0 [   0] newline
+  1:     3 [   3] decl     offset 0
+  2:     7 [   4] newline
+  3:    18 [  11] xdelta
+  4:    18 [   0] pcbase   offset 11
+
+ +

dissrc([function])

+ +

Disassembles the JavaScript bytecode for the entire program, or for the specified function, showing the source lines. This function only works with programs loaded from files, either using the -f flag on launching the shell, or by using the load() function.

+ +

If your program includes a function, doStuff(), like this:

+ +
function doStuff(input) {
+	print("Enter a number: ");
+	var n1 = readline();
+	print("Enter another one: ");
+	var n2 = readline();
+
+	print("You entered " + n1 + " and " + n2 + "\n");
+}
+
+ +

Calling dissrc(doStuff) function would give this output:

+ +
;-------------------------  10:         print("Enter a number: ");
+00000:  10  name "print"
+00003:  10  pushobj
+00004:  10  string "Enter a number: "
+00007:  10  call 1
+00010:  10  pop
+;-------------------------  11:         var n1 = readline();
+00011:  11  name "readline"
+00014:  11  pushobj
+00015:  11  call 0
+00018:  11  setvar 0
+00021:  11  pop
+;-------------------------  12:         print("Enter another one: ");
+00022:  12  name "print"
+00025:  12  pushobj
+00026:  12  string "Enter another one: "
+00029:  12  call 1
+00032:  12  pop
+;-------------------------  13:         var n2 = readline();
+00033:  13  name "readline"
+00036:  13  pushobj
+00037:  13  call 0
+00040:  13  setvar 1
+00043:  13  pop
+;-------------------------  14:
+;-------------------------  15:         print("You entered " + n1 + " and " + n2 + "\n");
+00044:  15  name "print"
+00047:  15  pushobj
+00048:  15  string "You entered "
+00051:  15  getvar 0
+00054:  15  add
+00055:  15  string " and "
+00058:  15  add
+00059:  15  getvar 1
+00062:  15  add
+00063:  15  string "\\n"
+00066:  15  add
+00067:  15  call 1
+00070:  15  pop
+00071:  15  stop
+
+ +

dumpheap(([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])

+ +

Dump GC information. This is a thin wrapper for JS_DumpHeap.

+ +

gczeal(zeal)

+ +

Enable extra-frequent GC, to help find GC hazards. zeal is an integer. The meaning is the same as for the parameter to JS_SetGCZeal.

+ +

notes([function])

+ +

Shows the source notes for the specified function. Source notes contain information that map the bytecode to the source code, which is used when decompiling the code, such as when using the dissrc() function.

diff --git "a/files/zh-cn/mozilla/projects/spidermonkey/javascript-c\345\274\225\346\223\216\345\265\214\345\205\245\345\274\200\345\217\221\346\214\207\345\215\227/index.html" "b/files/zh-cn/mozilla/projects/spidermonkey/javascript-c\345\274\225\346\223\216\345\265\214\345\205\245\345\274\200\345\217\221\346\214\207\345\215\227/index.html" new file mode 100644 index 0000000000..4752df82f3 --- /dev/null +++ "b/files/zh-cn/mozilla/projects/spidermonkey/javascript-c\345\274\225\346\223\216\345\265\214\345\205\245\345\274\200\345\217\221\346\214\207\345\215\227/index.html" @@ -0,0 +1,11 @@ +--- +title: JavaScript-C引擎嵌入开发指南 +slug: Mozilla/Projects/SpiderMonkey/JavaScript-C引擎嵌入开发指南 +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_User_Guide +--- +

查看Nirvana Studio上的翻译 +


+

+
+
+{{ languages( { "en": "en/JSAPI_User_Guide", "ja": "ja/Embedding_SpiderMonkey" } ) }} diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/boolean_to_jsval/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/boolean_to_jsval/index.html new file mode 100644 index 0000000000..80747881fd --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/boolean_to_jsval/index.html @@ -0,0 +1,53 @@ +--- +title: BOOLEAN_TO_JSVAL +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/BOOLEAN_TO_JSVAL +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/BOOLEAN_TO_JSVAL +--- +
{{SpiderMonkeySidebar("JSAPI")}}
+ +
{{ obsolete_header("jsapi42") }}
+ +
+

Cast a C integer to a boolean {{jsapixref("JS::Value")}} without any type checking or error handling.

+
+ +
+

Please use {{jsapixref("JS::BooleanValue")}}/{{jsapixref("JS::TrueValue")}}/{{jsapixref("JS::FalseValue")}} instead in SpiderMonkey 45 or later.

+
+ +

Syntax

+ +
jsval
+BOOLEAN_TO_JSVAL(bool b);
+
+ + + + + + + + + + + + + + +
NameTypeDescription
bboolC integer value to be converted to a boolean jsval.
+ +

Description

+ +

BOOLEAN_TO_JSVAL converts a bool argument, b, to a boolean jsval.

+ +

If b is false, the result is JSVAL_FALSE.

+ +

If b is true, the result is JSVAL_TRUE.

+ +

See Also

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/index.html new file mode 100644 index 0000000000..d076928fba --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/index.html @@ -0,0 +1,646 @@ +--- +title: JSAPI 参考 +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference +--- +

JSAPI SpiderMonkey JavaScript 引擎的C 语言应用程序接口(API)。要了解如何使用JSAPI ,请看 JSAPI User Guide and the JSAPI Phrasebook

+


+ Alphabetical List

+

运行时和上下文

+ + + + + +

Locale callbacks:

+ +

Locale callback types:

+ +

脚本

+

Just running some JavaScript code is straightforward:

+

只是运行一些JavaScript代码很简单:

+ +

You can instead compile JavaScript code into a JSScript which you can then execute multiple times.

+

你可以将JavaScript代码编译后保存在JSScript类型的变量中,这样就可以多次执行。

+

typedef JSScript

+ +

You can also compile JavaScript code into a function:

+ +

 

+

错误处理

+ +

The following functions allow C/C++ functions to throw and catch JavaScript exceptions:

+ + +

These functions translate errors into exceptions and vice versa:

+ +

值和类型

+ +

jsval constants:

+ +

Function and macros for checking the type of a jsval:

+ +

High-level type-conversion routines for packing and unpacking function arguments.

+ + +

The following functions convert JS values to various types. They can be safely applied to jsvals of any type. They may return new objects. For example, JS_ValueToObject(cx, s) where s is a string creates a new String wrapper object. These functions may call JavaScript methods. For example, JS_ValueToString(cx, obj) may call obj.toString().

+ +

Fast, unchecked type-casting macros. These macros must not be applied to values that are not known to be the right type. Like C casts, they may cause crashes if applied to incorrect values. They never create new objects or call into JavaScript code.

+ +

And:

+ +

Memory management

+

These functions act like the Standard C malloc family of functions, except that errors are reported using the SpiderMonkey error APIs rather than errno. These functions also allow SpiderMonkey to account the number of bytes allocated:

+ +

JavaScript objects, strings, and floating-point numbers are garbage collected. These functions provide access to the garbage collector:

+ +

The rest of these APIs help protect objects from being destroyed by the garbage collector before the application is done using them.

+

If a variable is a root, then anything it points to will not be freed by the garbage collector. Failure to root objects is a very common cause of mysterious crashes.

+ +

Local root scopes are another way of protecting objects from the garbage collector.

+ +

{{ Jsapi_minversion_inline("1.8 (not yet released)") }} If an object contains references to other GC things that are not stored in SpiderMonkey data structures ("slots"), it must implement the JSTraceOp hook to enable the garbage collector to traverse those references. Otherwise the garbage collector will not find all reachable objects and may collect objects that are still reachable, leading to a crash. (In SpiderMonkey 1.7 and earlier, the JSMarkOp hook is used instead. This will be deprecated when SpiderMonkey 1.8 is released.)

+

The tracing APIs are used by the garbage collector and JSTraceOp hooks. JSAPI applications may also use them to examine the object graph. (For example, these APIs support very smooth integration between the JS garbage collector and other garbage collectors.)

+ +

Miscellaneous GC APIs:

+ +

Numbers

+ +

字符串

+ + +

Interning strings tells the SpiderMonkey engine to reuse existing string objects when possible.

+ +

The character data for external strings is stored in memory provided by the application. Applications can use this to avoid copying data back and forth between SpiderMonkey's heap and application memory.

+ +

对象

+ + +

属性

+

These functions correspond directly to the ways scripts access object properties:

+ +

The following functions are lower-level, allowing the JSAPI application more access to details of how properties are implemented. "Define" is a lower-level version of "set" that provides access to extra settings and does not call setters. Similarly, "lookup" is a lower-level version of "get" that offers extra options and does not call getters.

+ +

The following functions behave like JS_GetProperty except when operating on E4X XML objects.

+ +

A SpiderMonkey extension allows a native function to return an lvalue—that is, a reference to a property of an object:

+ +

A jsid is kind of like a jsval, only different. A handful of APIs use jsids instead of jsvals for property names: JS_CheckAccess, JS_Enumerate, JS_GetMethodById, and JS_NextProperty.

+ +

Classes

+

These API features are used to define custom classes—object types that are implemented in C/C++ code but accessible from JavaScript.

+ +

Adding native properties and methods to classes:

+ +

JSFastNative methods use these macros:

+ +

The behavior of a JSClass and its instances can be customized in many ways using callback functions.

+

JSClass method types:

+ +

JSExtendedClass method types:

+ +

JSObjectOps method types:

+ +

JSXMLObjectOps method types:

+ +

These stub functions can be used when creating a custom JSClass:

+ +

The behavior of a JSClass can be customized using these flags:

+ +

Arrays

+ + + +

Functions

+

Calling a function or a method of an object:

+ +

Function accessors:

+ +

Creating functions:

+ +

RegExps

+ +

Security

+ + +

Threading

+

The following functions support the SpiderMonkey threading model. They are only available in JS_THREADSAFE builds.

+ +

The following functions exist in all builds, but in non-JS_THREADSAFE builds, they do nothing:

+ +

Time

+ +

Callback Types

+

Native function types:

+ +

Other callback types:

+ +

See also Classes, above.

+

Macros

+ +

Preprocessor conditionals

+ +

These defines are useful for tuning SpiderMonkey performance:

+ +

C++ features

+ +

{{ languages( { "ja": "ja/JSAPI_Reference", "pl": "pl/Dokumentacja_JSAPI" } ) }}

+

JSAPI 参考

+

 

+

数据结构

+ diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_defineconstdoubles/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_defineconstdoubles/index.html new file mode 100644 index 0000000000..82835b714d --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_defineconstdoubles/index.html @@ -0,0 +1,59 @@ +--- +title: JS DefineConstDoubles +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_DefineConstDoubles +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_DefineConstDoubles +--- +

摘要

+

为对象创建一个或多个包含双浮点值的属性。

+

语法

+
  JSBool JS_DefineConstDoubles(JSContext *cx, JSObject *obj,
+    JSConstDoubleSpec *cds);
+
+ + + + + + + + + + + + + + + + + + + + + + + +
名称类型描述
cxJSContext *指向JS运行时信息内容的指针。
objJSObject *指向新建的属性的对象指针。
cdsJSConstDoubleSpec *指向创建的包含双浮点属性值和属性名的结构化数组的指针。最后一个数组元素必须包含一个为零值的成员。
+

描述

+

JS_DefineConstDoubles为特定的对象创建一个或多个成员变量,obj, 每个成员变量包含一个双浮点类型的值。每个成员变量在JSConstDoubleSpec结构中的flags字段被自动声名并由cds传递指针。 如果flags被设为0值, 成员变量的属性会自动被设为JSPROP_PERMANENT 或 JSPROP_READONLY

+

cds 是一个指向具有JSConstDoubleSpec结构的数组的第一个元素的指针。每个数组元素定义独立的变量名和变量值。数组的最后一个元素的name字段必须是0。JS_DefineConstDoubles为数组中的每一个名称字段不为零的元素建立一个成员变量。

+

通常情况下, JS_DefineConstDoubles 返回 JS_TRUE, 表明它在数组中已经建立了所有的属性列表。除此之外的情况下它返回JS_FALSE

+

更多参考

+ + + + + + + + + + + + + + + +
新闻组Functions
文档LXRSearch
章节 +

JSConstDoubleSpec, JS_DefineElement, JS_DefineFunction, JS_DefineFunctions, JS_DefineObject, JS_DefineProperties, JS_DefineProperty, JS_DefinePropertyWithTinyId

+
+

 

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_call/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_call/index.html new file mode 100644 index 0000000000..a0c3d1239a --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_call/index.html @@ -0,0 +1,92 @@ +--- +title: 'JS::Call' +slug: 'Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS::Call' +translation_of: 'Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS::Call' +--- +
{{SpiderMonkeySidebar("JSAPI")}}
+ +
{{ jsapi_minversion_header("17") }}
+ + +
+

调用指定的JS函数。

+
+ +

句法

+ +
bool
+JS::Call(JSContext *cx, JS::HandleObject thisObj, JS::HandleFunction fun,
+         const JS::HandleValueArray &args, JS::MutableHandleValue rval);
+
+bool
+JS::Call(JSContext *cx, JS::HandleObject thisObj, const char *name,
+         const JS::HandleValueArray& args, JS::MutableHandleValue rval);
+
+bool
+JS::Call(JSContext *cx, JS::HandleObject thisObj, JS::HandleValue fun,
+         const JS::HandleValueArray& args, JS::MutableHandleValue rval);
+
+bool
+JS::Call(JSContext *cx, JS::HandleValue thisv, JS::HandleValue fun,
+         const JS::HandleValueArray& args, JS::MutableHandleValue rval);
+
+bool
+JS::Call(JSContext *cx, JS::HandleValue thisv, JS::HandleObject funObj,
+         const JS::HandleValueArray& args, JS::MutableHandleValue rval);
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型描述
cx{{jsapixref("JSRuntime", "JSContext *")}}指向JS上下文的指针,从中可以派生运行时信息。{{Jsapi-requires-request()}}
thisObj{{jsapixref("JSObject", "JS::HandleObject")}} / {{jsapixref("JS::Value", "JS::HandleValue")}}The "current" object on which the function operates; the object specified here is "this" when the function executes.
fun / funObj{{jsapixref("JSFunction", "JS::HandleFunction")}} / {{jsapixref("JS::Value", "JS::HandleValue")}} / {{jsapixref("JSObject", "JS::HandleObject")}}Pointer to the function to call. Should be a native function or JSAPI-compiled function.
nameconst char *Pointer to the function name to call.
args{{jsapixref("JS::HandleValueArray", "JS::HandleValueArray &")}}Arguments to pass to the function.
rval{{jsapixref("JS::Value", "JS::MutableHandleValue")}}Out parameter. On success, *rval receives the return value from the function call.
+ +

Description

+ +

JS::Callfun在对象上调用指定的函数thisObj在函数执行方面,该对象被视为this

+ +

有关更多详细信息,请参阅{{jsapixref("JS_CallFunction")}},{{jsapixref("JS_CallFunctionName")}}和{{jsapixref("JS_CallFunctionValue")}}。

+ +

也可以看看

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_ordinarytoprimitive/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_ordinarytoprimitive/index.html new file mode 100644 index 0000000000..b09164ee56 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_doublecolon_ordinarytoprimitive/index.html @@ -0,0 +1,66 @@ +--- +title: 'JS::OrdinaryToPrimitive' +slug: 'Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS::OrdinaryToPrimitive' +translation_of: 'Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS::OrdinaryToPrimitive' +--- +
{{SpiderMonkeySidebar("JSAPI")}}
+ +

{{ jsapi_minversion_header("38") }}

+ +
+

将普通对象转换为原始值

+
+ +

语法说明

+ +
bool
+JS::OrdinaryToPrimitive(JSContext *cx, JS::HandleObject obj, JSType type,
+                        JS::MutableHandleValue vp);
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型描述
cx{{jsapixref("JSRuntime", "JSContext *")}}执行转换的上下文. {{ Jsapi-requires-request() }}
obj{{jsapixref("JSObject", "JS::HandleObject")}}要转换的对象。
type{{jsapixref("JSType")}}转换后值的类型。
vp{{jsapixref("JS::Value", "JS::MutableHandleValue")}}输出参数. 成功, *vp 收到转换后的值
+ +

描述

+ +

JS::OrdinaryToPrimitive 通过ES6 draft rev 28(2014年10月14日)7.1.1第二算法中指定的算法将JavaScript对象转换为指定的类型值。

+ +

Most users should not call this -- use {{jsapixref("JS::ToNumber")}}, {{jsapixref("JS::ToBoolean")}}, or {{jsapixref("JS::ToString")}} instead. This should only be called from custom convert hooks. It implements the default conversion behavior shared by most objects in JS, so it's useful as a fallback.

+ +

On success, JS::OrdinaryToPrimitive stores the converted value in *vp and returns true. On error or exception, it returns false, and the value left in *vp is undefined.

+ +

了解其他

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_evaluatescript/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_evaluatescript/index.html new file mode 100644 index 0000000000..94454ee794 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_evaluatescript/index.html @@ -0,0 +1,69 @@ +--- +title: SpiderMonkey/JSAPI_参考/JS_EvaluateScript +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_EvaluateScript +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_EvaluateScript +--- +

编译并执行一个脚本。

+

语法

+
JSBool JS_EvaluateScript(JSContext *cx, JSObject *obj,
+    const char *src, uintN length, const char *filename,
+    uintN lineno, jsval *rval);
+
+JSBool JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+    const jschar *src, uintN length, const char *filename,
+    uintN lineno, jsval *rval);
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称数据类型描述
cxJSContext *脚本运行的上下文. {{ Jsapi-requires-request() }}
objJSObject *The scope in which to execute the script. This parameter is documented in detail at JS_ExecuteScript.
srcconst char * or const jschar *包含要编译和执行的脚本的字符串.
lengthuintNsrc的长度, in characters.
filenameconst char *Name of file or URL containing the script. Used to report filename or URL in error messages.
linenouintNLine number. Used to report the offending line in the file or URL if an error occurs.
rvaljsval *Out parameter. On success, *rval receives the value of the last-executed expression statement processed in the script.
+

描述

+

JS_EvaluateScript compiles and executes a script in the specified scope, obj. On successful completion, rval is a pointer to a variable that holds the value from the last executed expression statement processed in the script. JS_EvaluateUCScript is the Unicode version of the function.

+

src is the string containing the text of the script. length indicates the size of the text version of the script in characters.

+

filename is the name of the file (or URL) containing the script. This information is used in messages if an error occurs during compilation. Similarly, lineno is used to report the line number of the script or file where an error occurred during compilation.

+

If a script compiles and executes successfully, *rval receives the value from the last-executed expression statement in the script, and JS_EvaluateScript or JS_EvaluateUCScript returns JS_TRUE. Otherwise it returns JS_FALSE and the value left in *rval is undefined.

+

See Also

+

{{ LXRSearch("ident", "i", "JS_EvaluateScript") }}
+ {{ LXRSearch("ident", "i", "JS_EvaluateUCScript") }}

+

JS_CompileFile, JS_CompileScript, JS_DecompileScript, JS_DestroyScript, JS_EvaluateScriptForPrincipals

+

{{ languages( { "ja": "ja/JS_EvaluateScript" } ) }}

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_getversion/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_getversion/index.html new file mode 100644 index 0000000000..a2b2888958 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_getversion/index.html @@ -0,0 +1,29 @@ +--- +title: SpiderMonkey/JSAPI_参考/JS_GetVersion +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_GetVersion +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_GetVersion +--- +

Retrieves the JavaScript version number used within a specified executable script context.

+

语法

+
JSVersion JS_GetVersion(JSContext *cx);
+
+ + + + + + + + + + + + + +
参数名称类型描述
cxJSContext *要查询的上下文.
+

描述

+

JS_GetVersion returns the JavaScript version currently used by the given JSContext, cx. The result is one of the JSVersion constants.

+

When a context is created, its version is initially JSVERSION_DEFAULT. Scripts are compiled using the latest version of the JavaScript language. To configure a context to run scripts using a specific version of JavaScript, use JS_SetVersion.

+

请参阅

+

{{ LXRSearch("ident", "i", "JS_GetVersion") }}

+

JS_VersionToString, JS_StringToVersion

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_hasownproperty/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_hasownproperty/index.html new file mode 100644 index 0000000000..ed6e760796 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_hasownproperty/index.html @@ -0,0 +1,73 @@ +--- +title: JS_HasOwnProperty +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_HasOwnProperty +tags: + - 中文 +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_HasOwnProperty +--- +
{{SpiderMonkeySidebar("JSAPI")}}
+ +

{{ jsapi_minversion_header("45") }}

+ +
+

Determine whether a JavaScript object has a specified own property.

+
+ +

Syntax

+ +
bool
+JS_HasOwnProperty(JSContext* cx, HandleObject obj, const char* name,
+                  bool* foundp)
+
+bool
+JS_HasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id,
+                      bool* foundp)
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
cx{{jsapixref("JSRuntime", "JSContext *")}}A context. {{ Jsapi-requires-request() }}
obj{{jsapixref("JSObject", "JS::HandleObject")}}Object to search on for the property.
name or idconst char * or {{jsapixref("jsid", "JS::HandleId")}}Name of the property to look up.
foundpbool *Non-null pointer to a variable of type bool. On success, JS_HasOwnProperty stores true in this variable if obj has an own property with the given name, and false if not.
+ +

Description

+ +

JS_HasOwnProperty searches an object, obj, for an own property with the specified name. It behaves like the JavaScript expression Object.hasOwnProperty(obj, name). JS_HasOwnPropertyById is the same but takes a {{jsapixref("jsid", "JS::HandleId")}} for the property name.

+ +

If the property exists, this function sets *foundp to true and returns true.

+ +

If the object obj has no such property, the function sets *foundp to false and returns true (to indicate that no error occurred).

+ +

If an error occurs during the search, the function returns false, and the value of *foundp is undefined.

+ +

See Also

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_newruntime/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_newruntime/index.html new file mode 100644 index 0000000000..885bb3dd6e --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_newruntime/index.html @@ -0,0 +1,33 @@ +--- +title: JS_NewRuntime +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_NewRuntime +tags: + - JSAPI_Reference + - SpiderMonkey +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_NewRuntime +--- +

Initializes the JavaScript runtime.

+

Syntax

+
JSRuntime * JS_NewRuntime(uint32 maxbytes);
+
+ + + + + + + + + + + + + +
NameTypeDescription
maxbytesuint32Maximum number of allocated bytes after which garbage collection is run.
+

Description

+

JS_NewRuntime initializes the JavaScript runtime environment. Call JS_NewRuntime before making any other API calls. JS_NewRuntime allocates memory for the JSRuntime and initializes certain internal runtime structures. maxbytes specifies the number of allocated bytes after which garbage collection is run.

+

Generally speaking, most applications need only one JSRuntime. In a JS_THREADSAFE build, each runtime is capable of handling multiple execution threads, using one JSContext per thread, sharing the same JSRuntime. You only need multiple runtimes if your application requires completely separate JS engines that cannot share values, objects, and functions.

+

On success, JS_NewRuntime returns a pointer to the newly created runtime, which the caller must later destroy using JS_DestroyRuntime. Otherwise it returns NULL.

+

Notes

+

Ordinarily, JS_NewRuntime should be the first JSAPI call in an application, and JS_DestroyRuntime and JS_ShutDown should be the last ones.

+

{{ LXRSearch("ident", "i", "JS_NewRuntime") }}

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_seterrorreporter/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_seterrorreporter/index.html new file mode 100644 index 0000000000..e04127a541 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_seterrorreporter/index.html @@ -0,0 +1,61 @@ +--- +title: SpiderMonkey/JSAPI_参考/JS_SetErrorReporter +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_SetErrorReporter +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_SetErrorReporter +--- +

指定一个程序的错误报告途径.

+

语法

+
JSErrorReporter JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
+
+ + + + + + + + + + + + + + + + + + +
形式参数类型描述
cxJSContext *Pointer to a JS context from which to derive runtime information.
erJSErrorReporter在你的程序中用于报告错误的自定义函数, 见下面的描述.
+

  回调函数语法

+
typedef void (*JSErrorReporter)(
+    JSContext *cx, const char *message, JSErrorReport *report);
+
+ + + + + + + + + + + + + + + + + + + + + + + +
形式参数类型描述
cxJSContext *错误发生的上下文。
messageconst char *一个错误信息。
reportJSErrorReport *一个包含错误额外的详细资料报告记录。
+

描述

+

JS_SetErrorReporter enables you to define and use your own error reporting mechanism in your applications. The reporter you define is automatically passed a JSErrorReport structure when an error occurs and has been parsed by JS_ReportError.

+

Typically, the error reporting mechanism you define should log the error where appropriate (such as to a log file), and display an error to the user of your application. The error you log and display can make use of the information passed about the error condition in the JSErrorReport structure.

+

Like all other SpiderMonkey callbacks, the error reporter callback must not throw a C++ exception.

+

{{ LXRSearch("ident", "i", "JS_SetErrorReporter") }}

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_valuetostring/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_valuetostring/index.html new file mode 100644 index 0000000000..ab0e6654a4 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/js_valuetostring/index.html @@ -0,0 +1,45 @@ +--- +title: SpiderMonkey/JSAPI_参考/JS_ValueToString +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_ValueToString +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS_ValueToString +--- +

把一个jsval值 转换成一个 JSString.

+ +

 

+ +

语法

+ +
JSString * JS_ValueToString(JSContext *cx, jsval v);
+
+ + + + + + + + + + + + + + + + + + + +
NameTypeDescription
cxJSContext *The context in which to perform the conversion. {{ Jsapi-requires-request() }}
vjsval转换的jsval值.
+ +

描述

+ +

JS_ValueToString converts a specified JS value, v, to a JS string. It implements the ToString operator specified in ECMA 262-3 §9. If v is an object, the actual conversion is performed by its JSClass.convert callback, which may call the JavaScript methods v.toString() and/or v.valueOf(). On success, JS_ValueToString returns a pointer to a string. On error or exception, it returns NULL. This happens, for example, if v is an object and v.toString() throws an exception.

+ +

The resulting JSString is subject to garbage collection unless you protect it using a local root, an object property, or the JS_AddRoot function.

+ +

See Also

+ +

{{ LXRSearch("ident", "i", "JS_ValueToString") }}

+ +

JS_ConvertArguments, JS_ConvertValue, JS_GetTypeName, JS_TypeOfValue, JS_ValueToBoolean, JS_ValueToFunction, JS_ValueToInt32, JS_ValueToNumber, JS_ValueToObject

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsclass/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsclass/index.html new file mode 100644 index 0000000000..dd119aba3f --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsclass/index.html @@ -0,0 +1,137 @@ +--- +title: JSClass +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSClass +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSClass +--- +

摘要

+

数据结构 定义一个基本类用于建立和维护JS对象。

+

语法

+
struct JSClass {
+    char *name;
+    uint32 flags;
+    /* Mandatory non-null function pointer members. */
+    JSPropertyOp addProperty;
+    JSPropertyOp delProperty;
+    JSPropertyOp getProperty;
+    JSPropertyOp setProperty;
+    JSEnumerateOp enumerate;
+    JSResolveOp resolve;
+    JSConvertOp convert;
+    JSFinalizeOp finalize;
+    /* Optionally non-null members start here. */
+    JSGetObjectOps getObjectOps;
+    JSCheckAccessOp checkAccess;
+    JSNative call;
+    JSNative construct;
+    JSXDRObjectOp xdrObject;
+    JSHasInstanceOp hasInstance;
+    JSMarkOp mark;
+    JSReserveSlotsOp reserveSlots;
+};
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型描述
namechar *类名
flagsuint32类的属性(成员变量)。0表明属性不是一个集合. 属性值可以是下面这些值中的一个或多个: + +
addPropertyJSPropertyOp为类增加属性的函数。
delPropertyJSPropertyOp从类中删除属性的函数。
getPropertyJSPropertyOp获取属性值的函数。
setPropertyJSPropertyOp设置属性值的函数
enumerateJSEnumerateOp枚举类所有属性的函数。
resolveJSResolveOpMethod for resolving property ambiguities.
convertJSConvertOp进行属性值转换的函数。
finalizeJSFinalizeOp将类设为不可修改(finalizing)的函数。
getObjectOpsJSGetObjectOps为类定义重载方法指向一个可选的结构。如果你不想重载类的默认方法,可以将getObjectOps 设为 NULL
checkAccessJSCheckAccessOp为类或对象操作结构指定可选的自定义请求控制方法。如果你不想提供自定义的请求控制,设置此值为NULL
callJSNative为对象提供替换这个类的方法。
constructJSNative为对象提供方法去替换这个类的构造器。
xdrObjectJSXDRObjectOp指向一个可选的XDR对象和它的方法。如果你不想使用XDR, 设置这个值为 NULL
hasInstanceJSHasInstanceOpPointer to an optional hasInstance method for this object. If you do not provide a method for hasInstance, set this pointer to NULL.
markJSMarkOpPointer to an optional mark method for this object. If you do not provide a method for mark, set this pointer to NULL.
reserveSlotsJSReserveSlotsOpPointer to an optional reserveSlots method for this object. If you do not provide a method for reserveSlots, set this pointer to NULL.
+

 

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsconstdoublespec/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsconstdoublespec/index.html new file mode 100644 index 0000000000..509d3b12ed --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsconstdoublespec/index.html @@ -0,0 +1,56 @@ +--- +title: JSConstDoubleSpec +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSConstDoubleSpec +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSConstDoubleSpec +--- +

摘要

+

数据结构

+

定义一个双浮点类型的变量并进行赋值。

+

语法

+
struct JSConstDoubleSpec {
+    jsdouble dval;
+    const char *name;
+    uint8 flags;
+    uint8 spare[3];
+};
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
名称类型描述
dvaljsdouble双浮点类型的值。
nameconst char *给双浮点类型定义的名称。
flagsuint8双浮点类型的属性。这里可以是0或者是下面这些值之中的一个: + +
spareuint8{{ mediawiki.external(3) }}为以后的扩展保留的属性。
+

描述

+

JS双浮点型的构造规范 典型应用于定义一个双浮点值集合,并使用JS_DefineConstDoubles对生成的对象进行赋值。使用JS_DefineConstDouble为指定的对象创建一个或多个双浮点类型属性。

+

JS_DefineConstDoubles为一类由JSConstDoubleSpecs定义的数组提供证明。为每个数据元素定义独立的属性名和设置独立的属性值。数组的最后一个元素必须包括0值(zero-valued)的属性。JS_DefineConstDoubles 为数组中每个非0值(non-zero)元素创建一个属性值。

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jserrorreport/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jserrorreport/index.html new file mode 100644 index 0000000000..7246c3c416 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jserrorreport/index.html @@ -0,0 +1,6 @@ +--- +title: JSErrorReport +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSErrorReport +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSErrorReport +--- +

Media:Example.ogg

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsproperty/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsproperty/index.html new file mode 100644 index 0000000000..16f0cca090 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsproperty/index.html @@ -0,0 +1,29 @@ +--- +title: JSProperty +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSProperty +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSProperty +--- +
{{SpiderMonkeySidebar("JSAPI")}}
+ +

{{deprecated_header("jsapi16")}}

+ +
+

限内部使用。{{jsapixref("JSObjectOps")}}层使用的JavaScript对象属性的类型。

+
+ +

语法

+ +
struct JSProperty {
+    jsid id;
+};
+
+ +

Description

+ +

JSProperty 是所有对象属性的抽象基类。 它在 {{jsapixref("JSObjectOps.lookupProperty")}}, {{jsapixref("JSObjectOps.getAttributes", "getAttributes")}}, {{jsapixref("JSObjectOps.getAttributes", "setAttributes")}}, 和 {{jsapixref("JSObjectOps.dropProperty", "dropProperty")}}中内部使用。

+ +

See Also

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jspropertydescriptor/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jspropertydescriptor/index.html new file mode 100644 index 0000000000..9f35d49fdb --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jspropertydescriptor/index.html @@ -0,0 +1,69 @@ +--- +title: JSPropertyDescriptor +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSPropertyDescriptor +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSPropertyDescriptor +--- +
{{SpiderMonkeySidebar("JSAPI")}}
+ +
描述符是一个用于声明一个属性是否可以被修改,是否可以被删除,是否可以被枚举的一个对象
+ +

内容

+ +

每一个属性只拥有一个描述符对象,但是这个对象中拥有多个键值,用来描述这个属性,下表说明了描述符中可以拥有的键值.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameDescription
getterget 语法为属性绑定一个函数,每当查询该属性时便调用对应的函数,查询的结构为该函数的返回值
setter如果试着改变一个属性的值,那么对应的 setter 函数将被执行
value描述指定属性的值 , 可以是任何有效的 Javascript 值(函数 , 对象 , 字符串 ...).
configurable当且仅当该属性的 configurable 为 true 时,该属性 描述符 才能够被改变, 同时该属性也能从对应的对象上被删除.
enumerable描述指定的属性是否是 可枚举 的.
writable当且仅当该属性的 writabletrue 时, value 才能被赋值运算符改变。
+ +

描述

+ +

描述符 是描述对象属性的属性 , 对象里目前存在的属性描述符有两种主要形式:数据描述符 存取描述符. 可以通过 Object.getOwnPropertyDescriptor() 函数来获取某个对象下指定属性的对应的 描述符 .

+ +

示例

+ +

下面将演示通过 Object.defineProperty() 函数定义一个对象的属性.

+ +
var language = {}; // 定义一个空对象 language
+
+Object.defineProperty(language, 'log', { // 定义 language 对象下的 log 属性
+    value : ['CN','EN'],
+    writable : true,
+    enumerable : true,
+    configurable : true
+})
+ +

此时这是一个可读可写可枚举的属性 此时我们将这三个值都设为了 true 此时上面这段代码等价于:

+ +
var language = {}; // 定义一个空对象 language
+
+languange.log = ['CN','EN']; // 定义 language 对象下的 log 属性
+
diff --git a/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsruntime/index.html b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsruntime/index.html new file mode 100644 index 0000000000..daabc3f876 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/jsapi_reference/jsruntime/index.html @@ -0,0 +1,29 @@ +--- +title: JSRuntime +slug: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSRuntime +translation_of: Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSRuntime +--- +
{{SpiderMonkeySidebar("JSAPI")}}
+ +
+

在JSAPI中,JSRuntime是代表JavaScript引擎实例的顶级对象。一个程序通常只有一个JSRuntime,即使它有很多线程。JSRuntime是JavaScript对象所居住的世界;他们不能去其他人JSRuntime

+ +

所有JavaScript代码和大多数JSAPI调用都在内运行JSContextJSContext是对一个孩子JSRuntime上下文可以运行脚本。它包含全局对象和执行堆栈。异常处理错误报告和某些语言选项是基于Per-的JSContext创建上下文后,可以将上下文多次用于不同的脚本或JSAPI查询。例如,浏览器可能会为每个HTML页面创建一个单独的上下文。页面中的每个脚本都可以使用相同的上下文。

+ +

对象在同一个 JSRuntimeJSContext之间可以共享。对象与创建对象的上下文之间没有固定的关联。

+ +

设置和拆卸a JSRuntime和a的示例代码JSContextJSAPI用户指南中

+
+ +

线程

+ +

只有一个线程可以使用JSContext JSRuntime较早的版本允许使用  JS_ClearContextThread 和其他功能将a JSContext 从一个线程移动  到另一个线程。此功能已被删除。

+ +

相关文档

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/parser_api/index.html b/files/zh-cn/mozilla/projects/spidermonkey/parser_api/index.html new file mode 100644 index 0000000000..03b00c9b00 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/parser_api/index.html @@ -0,0 +1,1625 @@ +--- +title: Parser API +slug: Mozilla/Projects/SpiderMonkey/Parser_API +translation_of: Mozilla/Projects/SpiderMonkey/Parser_API +--- +

{{ jsapi_minversion_header("1.8.5") }}

+ +

最近构建的独立的SpiderMonkey shell包含了SpiderMonkey解析器的反射,可以通过JavaScript API来访问. 这使得我们更容易的用JavaScript写出处理JavaScript源代码的工具, 比如语法高亮工具,静态分析工具, 翻译器,编译器,混淆器等等.

+ +

例子:

+ +
> var expr = Reflect.parse("obj.foo + 42").body[0].expression
+> expr.left.property
+({loc:null, type:"Identifier", name:"foo"})
+> expr.right
+({loc:{source:null, start:{line:1, column:10}, end:{line:1, column:12}}, type:"Literal", value:42})
+
+ +

Reflect也可以使用在Firefox 7及以上版本中,但必须要导入一个模块:

+ +
Components.utils.import("resource://gre/modules/reflect.jsm")
+
+ +

如果不想用Reflect全局对象,也可以指定一个对象名称:

+ +
Components.utils.import("resource://gre/modules/reflect.jsm", obj)
+
+ +

内置对象

+ +

无论是SpiderMonkey shell还是Firefox (导入模块之后),全局对象Reflect目前都只有一个parse方法.

+ +

Reflect对象的属性

+ +

Reflect对象目前只有一个方法.

+ +

Reflect.parse(src[, options])

+ +

将SRC强制转为字符串,并将结果作为javascript程序进行分析。默认情况下,解析返回一个表示被解析的抽象语法树(AST)的程序对象(见下文)

+ +

可通过options对象提供其他选项, 可以使用的属性如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
locBooleanDefault: true
如果loctrue,则解析器会在返回的AST节点中包含上源码的位置信息.
sourceStringDefault: null
A description of the input source; typically a filename, path, or URL. This string is not meaningful to the parsing process, but is produced as part of the source location information in the returned AST nodes.
lineNumberDefault: 1
初始行号,用在源码位置信息上.
builderBuilderDefault: null
+

A builder object, which can be used to produce AST nodes in custom data formats. The expected callback methods are described under Builder Objects.

+
+ +

If parsing fails due to a syntax error, an instance of SyntaxError is thrown. The syntax error object thrown by Reflect.parse() has the same message property as the syntax error that would be thrown by eval(src). The lineNumber and fileName properties of the syntax error object indicate the source location of the syntax error.

+ +

节点对象

+ +

默认情况下, Reflect.parse() 生成Node对象, 即普通的JavaScript对象 (i.e., 它们的原型来自标准的Object原型). 所有的节点类型都实现了以下的接口:

+ +
interface Node {
+    type: string;
+    loc: SourceLocation | null;
+}
+
+ +

type 字段是一个字符串,代表AST变量类型.节点的每个子类型在下面的文档中都用其  type 字段特定的字符串标注出来了. 你可以使用这个字段去决定一个节点要实现的接口.

+ +

loc 字段代表节点的源位置信息. 如果解析器未生成有关节点的源位置信息,  null 字段为空;否则它是一个对象, 包括一个起始位置 (the position of the first character of the parsed source region) 和一个结束位置 (the position of the first character after the parsed source region):ss

+ +
interface SourceLocation {
+    source: string | null;
+    start: Position;
+    end: Position;
+}
+
+ +

每个 Position 包括一个 line 数字 (1-indexed) 和 column 数字 (0-indexed):

+ +
interface Position {
+    line: uint32 >= 1;
+    column: uint32 >= 0;
+}
+ +

Programs

+ +
interface Program <: Node {
+    type: "Program";
+    body: [ Statement ];
+}
+
+ +

A complete program source tree.

+ +

函数

+ +
interface Function <: Node {
+    id: Identifier | null;
+    params: [ Pattern ];
+    defaults: [ Expression ];
+    rest: Identifier | null;
+    body: BlockStatement | Expression;
+    generator: boolean;
+    expression: boolean;
+}
+
+ +

A function declaration or expression. The body of the function may be a block statement, or in the case of an expression closure, an expression.

+ +
注: Expression closures 是SpiderMonkey特有的.
+ +

If the generator flag is true, the function is a generator function, i.e., contains a yield expression in its body (other than in a nested function).

+ +
注: Generators 是SpiderMonkey特有的.
+ +

If the expression flag is true, the function is an expression closure and the body field is an expression.

+ +

语句

+ +
interface Statement <: Node { }
+
+ +

任意语句.

+ +
interface EmptyStatement <: Statement {
+    type: "EmptyStatement";
+}
+
+ +

一个空语句,也就是,一个孤立的分号.

+ +
interface BlockStatement <: Statement {
+    type: "BlockStatement";
+    body: [ Statement ];
+}
+
+ +

一个语句块,也就是由大括号包围的语句序列.

+ +
interface ExpressionStatement <: Statement {
+    type: "ExpressionStatement";
+    expression: Expression;
+}
+
+ +

一个表达式语句,也就是,仅有一个表达式组成的语句.

+ +
interface IfStatement <: Statement {
+    type: "IfStatement";
+    test: Expression;
+    consequent: Statement;
+    alternate: Statement | null;
+}
+
+ +

一个if语句.

+ +
interface LabeledStatement <: Statement {
+    type: "LabeledStatement";
+    label: Identifier;
+    body: Statement;
+}
+
+ +

一个标签语句,也就是, a statement prefixed by a break/continue label.

+ +
interface BreakStatement <: Statement {
+    type: "BreakStatement";
+    label: Identifier | null;
+}
+
+ +

一个break语句.

+ +
interface ContinueStatement <: Statement {
+    type: "ContinueStatement";
+    label: Identifier | null;
+}
+
+ +

一个continue语句.

+ +
interface WithStatement <: Statement {
+    type: "WithStatement";
+    object: Expression;
+    body: Statement;
+}
+
+ +

with statement.

+ +
interface SwitchStatement <: Statement {
+    type: "SwitchStatement";
+    discriminant: Expression;
+    cases: [ SwitchCase ];
+    lexical: boolean;
+}
+
+ +

一个switch语句. The lexical flag is metadata indicating whether the switch statement contains any unnested let declarations (and therefore introduces a new lexical scope).

+ +
interface ReturnStatement <: Statement {
+    type: "ReturnStatement";
+    argument: Expression | null;
+}
+
+ +

一个return语句.

+ +
interface ThrowStatement <: Statement {
+    type: "ThrowStatement";
+    argument: Expression;
+}
+
+ +

一个throw语句.

+ +
interface TryStatement <: Statement {
+    type: "TryStatement";
+    block: BlockStatement;
+    handlers: [ CatchClause ];
+    finalizer: BlockStatement | null;
+}
+
+ +

一个try语句.

+ +
注: 多个catch子句是SpiderMonkey特有的.
+ +
interface WhileStatement <: Statement {
+    type: "WhileStatement";
+    test: Expression;
+    body: Statement;
+}
+
+ +

一个while语句.

+ +
interface DoWhileStatement <: Statement {
+    type: "DoWhileStatement";
+    body: Statement;
+    test: Expression;
+}
+
+ +

一个do/while语句.

+ +
interface ForStatement <: Statement {
+    type: "ForStatement";
+    init: VariableDeclaration | Expression | null;
+    test: Expression | null;
+    update: Expression | null;
+    body: Statement;
+}
+
+ +

一个for语句.

+ +
interface ForInStatement <: Statement {
+    type: "ForInStatement";
+    left: VariableDeclaration |  Expression;
+    right: Expression;
+    body: Statement;
+    each: boolean;
+}
+
+ +

一个for/in语句, or, if each is true, a for each/in statement.

+ +
注: for each语法是SpiderMonkey特有的.
+ +
interface LetStatement <: Statement {
+    type: "LetStatement";
+    head: [ { id: Pattern, init: Expression | null } ];
+    body: Statement;
+}
+
+ +

一个let语句.

+ +
注: let语句形式是SpiderMonkey特有的.
+ +
interface DebuggerStatement <: Statement {
+    type: "DebuggerStatement";
+}
+
+ +

一个debugger语句.

+ +
注: debugger语句是ECMAScript 5中的新语法,尽管SpiderMonkey已经支持它很多年了.
+ +

声明

+ +
interface Declaration <: Statement { }
+
+ +

Any declaration node. Note that declarations are considered statements; this is because declarations can appear in any statement context in the language recognized by the SpiderMonkey parser.

+ +
注: 任意嵌套作用域下的声明是SpiderMonkey特有的.
+ +
interface FunctionDeclaration <: Function, Declaration {
+    type: "FunctionDeclaration";
+    id: Identifier;
+    params: [ Pattern ];
+    defaults: [ Expression ];
+    rest: Identifier | null;
+    body: BlockStatement | Expression;
+    generator: boolean;
+    expression: boolean;
+}
+
+ +

一个函数声明.

+ +
注: id字段不能为null.
+ +
interface VariableDeclaration <: Declaration {
+    type: "VariableDeclaration";
+    declarations: [ VariableDeclarator ];
+    kind: "var" | "let" | "const";
+}
+
+ +

一个变量声明,可以通过var, let, 或const.

+ +
interface VariableDeclarator <: Node {
+    type: "VariableDeclarator";
+    id: Pattern;
+    init: Expression | null;
+}
+
+ +

一个变量声明符.

+ +
注: id字段不能为null.
+ +
注: letconst是SpiderMonkey特有的.
+ +

表达式

+ +
interface Expression <: Node, Pattern { }
+ +

任意表达式节点. Since the left-hand side of an assignment may be any expression in general, an expression can also be a pattern.

+ +
interface ThisExpression <: Expression {
+    type: "ThisExpression";
+}
+
+ +

一个this表达式.

+ +
interface ArrayExpression <: Expression {
+    type: "ArrayExpression";
+    elements: [ Expression | null ];
+}
+ +

一个数组表达式.

+ +
interface ObjectExpression <: Expression {
+    type: "ObjectExpression";
+    properties: [ { key: Literal | Identifier,
+                    value: Expression,
+                    kind: "init" | "get" | "set" } ];
+}
+ +

一个对象表达式. A literal property in an object expression can have either a string or number as its value. Ordinary property initializers have a kind value "init"; getters and setters have the kind values "get" and "set", respectively.

+ +
interface FunctionExpression <: Function, Expression {
+    type: "FunctionExpression";
+    id: Identifier | null;
+    params: [ Pattern ];
+    defaults: [ Expression ];
+    rest: Identifier | null;
+    body: BlockStatement | Expression;
+    generator: boolean;
+    expression: boolean;
+}
+
+ +

一个函数表达式.

+ +
interface SequenceExpression <: Expression {
+    type: "SequenceExpression";
+    expressions: [ Expression ];
+}
+ +

一个序列表达式,也就是一个由逗号分割的表达式序列.

+ +
interface UnaryExpression <: Expression {
+    type: "UnaryExpression";
+    operator: UnaryOperator;
+    prefix: boolean;
+    argument: Expression;
+}
+ +

A unary operator expression.

+ +
interface BinaryExpression <: Expression {
+    type: "BinaryExpression";
+    operator: BinaryOperator;
+    left: Expression;
+    right: Expression;
+}
+ +

一个二元运算符表达式.

+ +
interface AssignmentExpression <: Expression {
+    type: "AssignmentExpression";
+    operator: AssignmentOperator;
+    left: Expression;
+    right: Expression;
+}
+ +

An assignment operator expression.

+ +
interface UpdateExpression <: Expression {
+    type: "UpdateExpression";
+    operator: UpdateOperator;
+    argument: Expression;
+    prefix: boolean;
+}
+ +

An update (increment or decrement) operator expression.

+ +
interface LogicalExpression <: Expression {
+    type: "LogicalExpression";
+    operator: LogicalOperator;
+    left: Expression;
+    right: Expression;
+}
+ +

一个逻辑运算符表达式.

+ +
interface ConditionalExpression <: Expression {
+    type: "ConditionalExpression";
+    test: Expression;
+    alternate: Expression;
+    consequent: Expression;
+}
+ +

一个条件运算符表达式, i.e., a ternary ?/: expression.

+ +
interface NewExpression <: Expression {
+    type: "NewExpression";
+    callee: Expression;
+    arguments: [ Expression ] | null;
+}
+ +

A new expression.

+ +
interface CallExpression <: Expression {
+    type: "CallExpression";
+    callee: Expression;
+    arguments: [ Expression ];
+}
+ +

A function or method call expression.

+ +
interface MemberExpression <: Expression {
+    type: "MemberExpression";
+    object: Expression;
+    property: Identifier | Expression;
+    computed : boolean;
+}
+ +

一个member表达式. If computed === true, the node corresponds to a computed e1[e2] expression and property is an Expression. If computed === false, the node corresponds to a static e1.x expression and property is an Identifier.

+ +
interface YieldExpression <: Expression {
+    argument: Expression | null;
+}
+
+ +

yield expression.

+ +
注: yield expressions 是SpiderMonkey特有的.
+ +
interface ComprehensionExpression <: Expression {
+    body: Expression;
+    blocks: [ ComprehensionBlock ];
+    filter: Expression | null;
+}
+
+ +

An array comprehension. The blocks array corresponds to the sequence of for and for each blocks. The optional filter expression corresponds to the final if clause, if present.

+ +
注: Array comprehensions 是SpiderMonkey特有的.
+ +
interface GeneratorExpression <: Expression {
+    body: Expression;
+    blocks: [ ComprehensionBlock ];
+    filter: Expression | null;
+}
+
+ +

A generator expression. As with array comprehensions, the blocks array corresponds to the sequence of for and for each blocks, and the optional filter expression corresponds to the final if clause, if present.

+ +
注: Generator expressions 是SpiderMonkey特有的.
+ +
interface GraphExpression <: Expression {
+    index: uint32;
+    expression: Literal;
+}
+
+ +

graph expression, aka "sharp literal," such as #1={ self: #1# }.

+ +
注: Graph expressions 是SpiderMonkey特有的.
+ +
interface GraphIndexExpression <: Expression {
+    index: uint32;
+}
+
+ +

一个graph索引表达式,又称为"井号变量",比如#1#.

+ +
注: Graph索引表达式
+ +
Graph索引表达式是SpiderMonkey特有的.
+ +
interface LetExpression <: Expression {
+    type: "LetExpression";
+    head: [ { id: Pattern, init: Expression | null } ];
+    body: Expression;
+}
+
+ +

一个let表达式.

+ +
注: let表达式是SpiderMonkey特有的.
+ +

模式

+ +
interface Pattern <: Node { }
+
+ +

JavaScript 1.7 introduced destructuring assignment and binding forms. All binding forms (such as function parameters, variable declarations, and catch block headers), accept array and object destructuring patterns in addition to plain identifiers. The left-hand sides of assignment expressions can be arbitrary expressions, but in the case where the expression is an object or array literal, it is interpreted by SpiderMonkey as a destructuring pattern.

+ +

Since the left-hand side of an assignment can in general be any expression, in an assignment context, a pattern can be any expression. In binding positions (such as function parameters, variable declarations, and catch headers), patterns can only be identifiers in the base case, not arbitrary expressions.

+ +
interface ObjectPattern <: Pattern {
+    type: "ObjectPattern";
+    properties: [ { key: Literal | Identifier, value: Pattern } ];
+}
+
+ +

An object-destructuring pattern. A literal property in an object pattern can have either a string or number as its value.

+ +
interface ArrayPattern <: Pattern {
+    type: "ArrayPattern";
+    elements: [ Pattern | null ];
+}
+
+ +

An array-destructuring pattern.

+ +

子句

+ +
interface SwitchCase <: Node {
+    type: "SwitchCase";
+    test: Expression | null;
+    consequent: [ Statement ];
+}
+
+ +

一个case (if test is an Expression) or default (if test === null) clause in the body of a switch语句.

+ +
interface CatchClause <: Node {
+    type: "CatchClause";
+    param: Pattern;
+    guard: Expression | null;
+    body: BlockStatement;
+}
+
+ +

catch clause following a try block. The optional guard property corresponds to the optional expression guard on the bound variable.

+ +
注: The guard expression is SpiderMonkey-specific.
+ +
interface ComprehensionBlock <: Node {
+    left: Pattern;
+    right: Expression;
+    each: boolean;
+}
+
+ +

for or for each block in an array comprehension or generator expression.

+ +
注: Array comprehensions and generator expressions 是SpiderMonkey特有的.
+ +

杂项

+ +
interface Identifier <: Node, Expression, Pattern {
+    type: "Identifier";
+    name: string;
+}
+
+ +

An identifier. Note that an identifier may be an expression or a destructuring pattern.

+ +
interface Literal <: Node, Expression {
+    type: "Literal";
+    value: string | boolean | null | number | RegExp;
+}
+
+ +

A literal token. Note that a literal can be an expression.

+ +
enum UnaryOperator {
+    "-" | "+" | "!" | "~" | "typeof" | "void" | "delete"
+}
+
+ +

A unary operator token.

+ +
enum BinaryOperator {
+    "==" | "!=" | "===" | "!=="
+         | "<" | "<=" | ">" | ">="
+         | "<<" | ">>" | ">>>"
+         | "+" | "-" | "*" | "/" | "%"
+         | "|" | "^" | "in"
+         | "instanceof" | ".."
+}
+
+ +

A binary operator token.

+ +
注: The .. operator is E4X-specific.
+ +
enum LogicalOperator {
+    "||" | "&&"
+}
+
+ +

A logical operator token.

+ +
enum AssignmentOperator {
+    "=" | "+=" | "-=" | "*=" | "/=" | "%="
+        | "<<=" | ">>=" | ">>>="
+        | "|=" | "^=" | "&="
+}
+
+ +

An assignment operator token.

+ +
enum UpdateOperator {
+    "++" | "--"
+}
+
+ +

An update (increment or decrement) operator token.

+ +

E4X

+ +

下面介绍一下为E4X提供支持的节点类型.

+ +
注: E4X不是ECMAScript规范(ECMA-262)的一部分,它是一个单独的标准(ECMA-357).
+ +

声明

+ +
interface XMLDefaultDeclaration <: Declaration {
+    type: "XMLDefaultDeclaration";
+    namespace: Expression;
+}
+
+ +

一个默认xml命名空间声明

+ +

表达式

+ +
interface XMLAnyName <: Expression {
+    type: "XMLAnyName";
+}
+
+ +

The special E4X wildcard pseudo-identifier *.

+ +
interface XMLQualifiedIdentifier <: Expression {
+    type: "XMLQualifiedIdentifier";
+    left: Identifier | XMLAnyName;
+    right: Identifier | Expression;
+    computed: boolean;
+}
+
+ +

An E4X qualified identifier, i.e., a pseudo-identifier using the namespace separator ::. If the qualified identifier has a computed name (i.e., the id::[expr] form), then computed is true and the right property is an expression.

+ +
interface XMLFunctionQualifiedIdentifier <: Expression {
+    type: "XMLFunctionQualifiedIdentifier";
+    right: Identifier | Expression;
+    computed: boolean;
+}
+
+ +

An E4X identifier qualified by the function keyword, e.g. function::id.

+ +
注: function-qualified identifiers 是SpiderMonkey特有的.
+ +
interface XMLAttributeSelector <: Expression {
+    type: "XMLAttributeSelector";
+    attribute: Expression;
+}
+
+ +

An E4X attribute selector expression, i.e., an @ expression.

+ +
interface XMLFilterExpression <: Expression {
+    type: "XMLFilterExpression";
+    left: Expression;
+    right: Expression;
+}
+
+ +

An E4X list filter expression, i.e., an expression of the form expr.(expr).

+ +
interface XMLElement <: XML, Expression {
+    type: "XMLElement";
+    contents: [ XML ];
+}
+
+ +

An E4X literal representing a single XML element.

+ +
interface XMLList <: XML, Expression {
+    type: "XMLList";
+    contents: [ XML ];
+}
+
+ +

An E4X literal representing a list of XML elements.

+ +

XML

+ +
interface XML <: Node { }
+
+ +

XML data.

+ +
interface XMLEscape <: XML {
+    type "XMLEscape";
+    expression: Expression;
+}
+
+ +

XML data with an escaped JavaScript expression.

+ +
interface XMLText <: XML {
+    type: "XMLText";
+    text: string;
+}
+
+ +

Literal XML text.

+ +
interface XMLStartTag <: XML {
+    type: "XMLStartTag";
+    contents: [ XML ];
+}
+
+ +

An XML start tag.

+ +
interface XMLEndTag <: XML {
+    type: "XMLEndTag";
+    contents: [ XML ];
+}
+
+ +

An XML end tag.

+ +
interface XMLPointTag <: XML {
+    type: "XMLPointTag";
+    contents: [ XML ];
+}
+
+ +

An XML point tag.

+ +
interface XMLName <: XML {
+    type: "XMLName";
+    contents: string | [ XML ];
+}
+
+ +

An XML name.

+ +
interface XMLAttribute <: XML {
+    type: "XMLAttribute";
+    value: string;
+}
+
+ +

An XML attribute value.

+ +
interface XMLCdata <: XML {
+    type: "XMLCdata";
+    contents: string;
+}
+
+ +

An XML CDATA node.

+ +
interface XMLComment <: XML {
+    type: "XMLComment";
+    contents: string;
+}
+
+ +

An XML comment.

+ +
interface XMLProcessingInstruction <: XML {
+    type: "XMLProcessingInstruction";
+    target: string;
+    contents: string | null;
+}
+
+ +

An XML processing instruction.

+ +

Builder objects

+ +

The optional builder parameter to Reflect.parse() makes it possible to construct user-specified data from the parser, rather than the default Node objects. Builder objects may contain any of the callback methods described in this section.

+ +

Each callback can produce any custom, user-defined datatype; these are referred to below as CustomExpression, CustomStatement, etc.

+ +
注: Because this library uses null for optional nodes, it is recommended that user-defined datatypes not use null as a representation of an AST node.
+ +

If the loc option is enabled (see the Reflect.parse() options above), then each callback is provided with the source location information of the parsed node as an extra parameter.

+ +

All builder callbacks are optional. When a callback is missing, the default format is used, but the provided builder methods are still used recursively for sub-nodes.

+ +

Programs

+ +
program(body[, loc])
+ +
body: [ CustomStatement ]
+loc: SourceLocation
+
+ +

返回: CustomProgram

+ +

Callback to produce a custom program node.

+ +

Statements

+ +
emptyStatement([loc])
+ +
loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom empty statement node.

+ +
blockStatement(body[, loc])
+ +
body: CustomStatement
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom block statement node.

+ +
expressionStatement(expr[, loc])
+ +
expr: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom expression statement node.

+ +
labeledStatement(label, body[, loc])
+ +
label: CustomIdentifier
+body: CustomStatement
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom labeled statement node.

+ +
ifStatement(test, cons, alt[, loc])
+ +
test: CustomExpression
+cons: CustomStatement
+alt: CustomStatement | null
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom if statement node.

+ +
switchStatement(disc, cases, isLexical[, loc])
+ +
disc: CustomExpression
+cases: [ CustomSwitchCase ]
+isLexical: boolean
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom switch statement node. The isLexical flag is metadata indicating whether the switch statement contains any unnested let declarations (and therefore introduces a new lexical scope).

+ +
whileStatement(test, body[, loc])
+ +
test: CustomExpression
+body: CustomStatement
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom while statement node.

+ +
doWhileStatement(body, test[, loc])
+ +
body: CustomStatement
+test: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom do-while statement node.

+ +
forStatement(init, test, update, body[, loc])
+ +
init: CustomVariableDeclaration | CustomExpression | null
+test: CustomExpression | null
+update: CustomExpression | null
+body: CustomStatement
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom for statement node.

+ +
forInStatement(left, right, body, isForEach[, loc])
+ +
left: CustomVariableDeclaration | CustomExpression
+right: CustomExpression
+body: CustomStatement
+isForEach: boolean
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom for-in statement node. The isForEach flag indicates whether the node is a for each statement.

+ +
breakStatement(label[, loc])
+ +
label: CustomIdentifier | null
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom break statement node.

+ +
continueStatement(label[, loc])
+ +
label: CustomIdentifier | null
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom continue statement node.

+ +
withStatement(obj, body[, loc])
+ +
obj: CustomExpression
+body: CustomStatement
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom with statement node.

+ +
returnStatement(arg[, loc])
+ +
arg: CustomExpression | null
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom return statement node.

+ +
tryStatement(body, handlers, fin[, loc])
+ +
body: CustomStatement
+handlers: [ CustomCatchClause ]
+fin: CustomStatement | null
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom try statement node.

+ +
throwStatement(arg[, loc])
+ +
arg: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom throw statement node.

+ +
debuggerStatement([loc])
+ +
loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom debugger statement node.

+ +
letStatement(head, body[, loc])
+ +
head: [ CustomDeclarator ]
+body: CustomStatement
+loc: SourceLocation
+
+ +

返回: CustomStatement

+ +

Callback to produce a custom let statement node.

+ +

声明

+ +
functionDeclaration(name, args, body, isGenerator, isExpression[, loc])
+ +
name: string
+args: [ CustomPattern ]
+body: CustomStatement | CustomExpression
+isGenerator: boolean
+isExpression: boolean
+loc: SourceLocation
+
+ +

返回: CustomDeclaration

+ +

Callback to produce a custom function declaration node.

+ +
variableDeclaration(kind, dtors[, loc])
+ +
kind: "const" | "let" | "var"
+dtors: [ CustomDeclarator ]
+loc: SourceLocation
+
+ +

返回: CustomDeclaration

+ +

Callback to produce a custom variable declaration node.

+ +
variableDeclarator(patt, init[, loc])
+ +
patt: CustomPattern
+init: CustomExpression | null
+loc: SourceLocation
+
+ +

返回: CustomDeclarator

+ +

Callback to produce a custom variable declarator node.

+ +

表达式

+ +
sequenceExpression(exprs[, loc])
+ +
exprs: [ CustomExpression ]
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom sequence expression node.

+ +
conditionalExpression(test, cons, alt[, loc])
+ +
test: CustomExpression
+cons: CustomExpression
+alt: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom conditional expression node.

+ +
unaryExpression(op, arg, isPrefix[, loc])
+ +
op: UnaryOperator
+arg: CustomExpression
+isPrefix: boolean
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom unary expression node.

+ +
binaryExpression(op, left, right[, loc])
+ +
op: BinaryOperator
+left: CustomExpression
+right: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom binary expression node.

+ +
assignmentExpression(op, left, right[, loc])
+ +
op: AssignmentOperator
+left: CustomExpression
+right: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom assignment expression node.

+ +
logicalExpression(op, left, right[, loc])
+ +
op: LogicalOperator
+left: CustomExpression
+right: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom logical expression node.

+ +
updateExpression(op, arg, isPrefix[, loc])
+ +
op: UpdateOperator
+arg: CustomExpression
+isPrefix: boolean
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom update expression node.

+ +
newExpression(callee, args[, loc])
+ +
callee: CustomExpression
+args: [ CustomExpression ]
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom new-expression node.

+ +
callExpression(callee, args[, loc])
+ +
callee: CustomExpression
+args: [ CustomExpression ]
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom function call node.

+ +
memberExpression(obj, prop, isComputed[, loc])
+ +
obj: CustomExpression
+prop: CustomIdentifier | CustomExpression
+isComputed: boolean
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom member expression node.

+ +
functionExpression(name, args, body, isGenerator, isExpression[, loc])
+ +
name: CustomIdentifier | null
+args: [ CustomPattern ]
+body: CustomStatement | CustomExpression
+isGenerator: boolean
+isExpression: boolean
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom function expression node.

+ +
arrayExpression(elts[, loc])
+ +
elts: [ CustomExpression | null ]
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom array expression node.

+ +
objectExpression(props[, loc])
+ +
props: [ CustomObjectProperty ]
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom object expression node.

+ +
thisExpression([loc])
+ +
loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom this expression node.

+ +
graphExpression(index, expr[, loc])
+ +
index: uint32 >= 1
+expr: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom graph expression node.

+ +
graphIndexExpression(index[, loc])
+ +
index: uint32 >= 1
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom graph index expression node.

+ +
comprehensionExpression(body, blocks, filter[, loc])
+ +
body: CustomExpression
+blocks: [ CustomComprehensionBlock ]
+filter: CustomExpression | null
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom comprehension expression node.

+ +
generatorExpression(body, blocks, filter[, loc])
+ +
body: CustomExpression
+blocks: [ CustomComprehensionBlock ]
+filter: CustomExpression | null
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom generator expression node.

+ +
yieldExpression(arg[, loc])
+ +
arg: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom yield expression node.

+ +
letExpression(head, body[, loc])
+ +
head: [ CustomDeclarator ]
+body: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomExpression

+ +

Callback to produce a custom let expression node.

+ +

Patterns

+ +
arrayPattern(elts[, loc])
+ +
elts: [ CustomPattern | null ]
+loc: SourceLocation
+
+ +

返回: CustomPattern

+ +

Callback to produce a custom array destructuring pattern node.

+ +
objectPattern(props[, loc])
+ +
props: [ CustomPropertyPattern ]
+loc: SourceLocation
+
+ +

返回: CustomPattern

+ +

Callback to produce a custom object destructuring pattern node.

+ +
propertyPattern(key, patt[, loc])
+ +
key: CustomLiteral | CustomIdentifier
+patt: CustomPattern
+loc: SourceLocation
+
+ +

返回: CustomPropertyPattern

+ +

Callback to produce a custom object property destructuring pattern node.

+ +

Clauses

+ +
switchCase(test, cons[, loc])
+ +
test: CustomExpression | null
+cons: [ CustomStatement ]
+loc: SourceLocation
+
+ +

返回: CustomSwitchCase

+ +

Callback to produce a custom case or default clause node. The test argument is null if and only if the node is a default clause.

+ +
catchClause(arg, guard, body[, loc])
+ +
arg: CustomPattern
+guard: CustomExpression
+body: CustomStatement
+loc: SourceLocation
+
+ +

返回: CustomCatchClause

+ +

Callback to produce a custom catch clause node.

+ +
comprehensionBlock(left, right, isForEach[, loc])
+ +
left: CustomPattern
+right: CustomExpression
+isForEach: boolean
+loc: SourceLocation
+
+ +

返回: CustomComprehensionBlock

+ +

Callback to produce a custom comprehension block node. The isForEach flag indicates whether the node is a for each block.

+ +

Miscellaneous

+ +
identifier(name[, loc])
+ +
name: string
+loc: SourceLocation
+
+ +

返回: CustomIdentifier/CustomPattern/CustomExpression

+ +

Callback to produce a custom identifier node.

+ +
literal(val[, loc])
+ +
val: string | boolean | null | number | RegExp
+loc: SourceLocation
+
+ +

返回: CustomLiteral / CustomExpression

+ +

Callback to produce a custom literal node.

+ +
property(kind, key, val[, loc])
+ +
kind: "init" | "get" | "set"
+key: CustomLiteral | CustomIdentifier
+val: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomObjectProperty

+ +

Callback to produce a custom object property initializer node.

+ +

E4X

+ +

Declarations

+ +
xmlDefaultDeclaration(ns[, loc])
+ +
loc: SourceLocation
+
+ +

返回: CustomDeclaration

+ +

Callback to produce a custom XML default namespace declaration node.

+ +

Expressions

+ +
xmlAnyName([loc])
+ +
loc: SourceLocation
+
+ +

返回: CustomXMLAnyName/CustomXML/CustomExpression

+ +

Callback to produce a custom XML node for the wildcard pseudo-identifier *.

+ +
xmlAttributeSelector(expr[, loc])
+ +
expr: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomXML/CustomExpression

+ +

Callback to produce a custom XML attribute selector node.

+ +
xmlFilterExpression(left, right[, loc])
+ +
left: CustomExpression
+right: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomXML/CustomExpression

+ +

Callback to produce a custom XML filter expression node.

+ +
xmlQualifiedIdentifier(left, right, isComputed[, loc])
+ +
left: CustomIdentifier | CustomXMLAnyName
+right: CustomIdentifier | CustomExpression
+isComputed: boolean
+loc: SourceLocation
+
+ +

返回: CustomXML/CustomExpression

+ +

Callback to produce a custom qualified identifier node.

+ +
xmlFunctionQualifiedIdentifier(right, isComputed[, loc])
+ +
right: CustomIdentifier | CustomExpression
+isComputed: boolean
+loc: SourceLocation
+
+ +

返回: CustomXML/CustomExpression

+ +

Callback to produce a custom XML function-qualified identifier node.

+ +
xmlElement(contents[, loc])
+ +
contents: [ CustomXML ]
+loc: SourceLocation
+
+ +

返回: CustomXML / CustomExpression

+ +

Callback to produce a custom XML element node.

+ +
xmlList(contents[, loc])
+ +
contents: [ CustomXML ]
+loc: SourceLocation
+
+ +

返回: CustomXML/CustomExpression

+ +

Callback to produce a custom XML list node.

+ +

XML

+ +
xmlEscape(expr[, loc])
+ +
expr: CustomExpression
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML escape node.

+ +
xmlText(text[, loc])
+ +
text: string
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML text node.

+ +
xmlStartTag(contents[, loc])
+ +
contents: [ CustomXML ]
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML start-tag node.

+ +
xmlEndTag(contents[, loc])
+ +
contents: [ CustomXML ]
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML end-tag node.

+ +
xmlPointTag(contents[, loc])
+ +
contents: [ CustomXML ]
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML point tag node.

+ +
xmlName(contents[, loc])
+ +
contents: string | [ CustomXML ]
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML name node.

+ +
xmlAttribute(value[, loc])
+ +
value: string
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML attribute node.

+ +
xmlCdata(contents[, loc])
+ +
contents: string
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML CDATA node.

+ +
xmlComment(contents[, loc])
+ +
contents: string
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML comment node.

+ +
xmlProcessingInstruction(target, contents[, loc])
+ +
target: string
+contents: string | null
+loc: SourceLocation
+
+ +

返回: CustomXML

+ +

Callback to produce a custom XML processing instruction node.

diff --git a/files/zh-cn/mozilla/projects/spidermonkey/releases/index.html b/files/zh-cn/mozilla/projects/spidermonkey/releases/index.html new file mode 100644 index 0000000000..fd88b37529 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/releases/index.html @@ -0,0 +1,42 @@ +--- +title: SpiderMonkey releases +slug: Mozilla/Projects/SpiderMonkey/Releases +translation_of: Mozilla/Projects/SpiderMonkey/Releases +--- +
{{SpiderMonkeySidebar("Releases")}}
+ +
+

本页开列了 SpiderMonkey 的版本记录.

+
+ +
+

注意: 独立的 SpiderMonkey 并不是官方产品. Our continuous integration system does produce a tarball that is built into a binary that runs our smoke tests, but we do not maintain it nor actively test its suitability for general embedding. We have periodically created "releases", but they are best-effort and incomplete. We do happily accept patches, and make some effort to keep the tip of the Gecko tree minimally working as an embeddable source package. We are very limited in our ability to support older versions, including those labeled as "releases" on this page.

+
+ +

The easiest way to fetch the version corresponding to the current Firefox release is to visit the treeherder page for the release repository and click on the first SM(pkg) link you see. That will open a small window in the bottom left with a line like " mozjs-57.0.1.tar.bz2".

+ +

当前版本

+ + + +

Future release

+ + + +

过往版本

+ + diff --git a/files/zh-cn/mozilla/projects/spidermonkey/split_object/index.html b/files/zh-cn/mozilla/projects/spidermonkey/split_object/index.html new file mode 100644 index 0000000000..86d82e7d58 --- /dev/null +++ b/files/zh-cn/mozilla/projects/spidermonkey/split_object/index.html @@ -0,0 +1,72 @@ +--- +title: Split object +slug: Mozilla/Projects/SpiderMonkey/Split_object +translation_of: Mozilla/Projects/SpiderMonkey/Split_object +--- +

In SpiderMonkey, a split object is made up of two JSObjects: an inner object and an outer object.

+ +

Each half of a split object always has a pointer to the other half. Inner objects implement the JSExtendedClass.outerObject hook, which returns a pointer to the corresponding outer object. Outer objects implement the JSExtendedClass.innerObject hook. But the association is not fixed. An outer object may be associated with different inner objects at different times.

+ +

This feature is complicated. Programs other than Mozilla that embed SpiderMonkey should avoid using split objects.

+ +

The window object

+ +

Split objects were introduced to resolve a problem posed by the window object. Three interrelated requirements on the window object seemed to conflict.

+ + + + + + + +

Split objects were the solution. The inner window object is different for each page a browser window visits. It serves as the "globals" object and provides the JSPrincipals for scripts on that page. Access to inner window properties is fast. The outer window object is the object returned by window.open. It represents the window or tab itself and survives as the user navigates in that window or tab. The window object's JSClass.resolve hook ensures that properties of the inner object are visible via the outer object, if the running code has the right principals to access them. This privilege check may be slow.

+ +

See {{ interwiki('wikimo', 'Gecko:SplitWindow', 'wikimo:Gecko:SplitWindow') }} and {{ Bug(296639) }} for more discussion.

+ +

See also http://groups.google.com/group/mozil...81825b338fb84f

+ +

Details

+ +

This section describes split objects as a feature of the JSAPI. It catalogues (and tries to explain) the subtle ways in which split objects affect SpiderMonkey's behavior.

+ +

Split objects are only useful for implementing objects that will be on the scope chain of functions. SpiderMonkey assumes that inner and outer objects are dangerous in two different and complementary ways.

+ +

Inner objects are dangerous because they have fast property accessors that do not perform security checks. Therefore, no function may be allowed to see an inner object that has different JSPrincipals. Apart from the security issue, if one page directly or indirectly gets a reference to another page's window object, that window object must appear to behave like the outer window and navigate from page to page. SpiderMonkey arranges this by not allowing JS code to see inner objects at all. To enforce this rule:

+ + + +

Outer objects are dangerous because their JSPrincipals may change over time. Because a Function inherits the JSPrincipals of its lexical scope (specifically, the nearest principals-aware object in its scope chain), untrusted code must never be able to make an outer object appear in a Function's scope chain. Again, SpiderMonkey enforces a slightly stronger rule: outer objects may never appear in a scope chain at all, except when put there by an explicit C-level JSAPI call (to JS_SetParent or equivalent). (Several objects, such as window.location and window.navigator, are intentionally parented to the outer window object using such APIs.) To enforce this rule:

+ + + + + +

Inner and outer objects are in certain other respects the same object:

+ + + +

Note that none of the rules listed here affects ordinary property accesses. SpiderMonkey's split object support, by itself, does not cause inner object properties to appear on the outer object or vice versa. Split objects that need this behavior must implement it in custom JSClass hooks. In the case of window, each half has custom hooks.

diff --git a/files/zh-cn/mozilla/rust/index.html b/files/zh-cn/mozilla/rust/index.html new file mode 100644 index 0000000000..f2964058fb --- /dev/null +++ b/files/zh-cn/mozilla/rust/index.html @@ -0,0 +1,40 @@ +--- +title: Rust编程语言 +slug: Mozilla/Rust +translation_of: Mozilla/Rust +--- +

Rust logoRust 是一个全新的开源系统编程语言,由Mozilla和社区的义务劳动者创造,它帮助开发者创造高速与安全的应用,同时能享受到现代多核处理器的强大特性。Rust使用易懂的语法避免了段错误(segmentation faults)并保证了线程安全。

+ +

不仅如此,Rust提供了零成本抽象,更多语义,内存安全保证,不会发生竞争的线程,基于特性(trait)的泛型,模式匹配,类型推导,高效的C绑定,和最小运行时大小。

+ +

想了解更多Rust,你可以:

+ + + +

Rust 与系统编程的未来

+ +

{{EmbedYouTube("8EPsnf_ZYU0")}}

+ +

用Rust解锁并行的力量

+ +

{{EmbedYouTube("cNeIOt8ZdAY")}}

+ +

给Web开发者的Rust

+ +

{{EmbedYouTube("FfoXFnzZbBM")}}

+ +

用Rust实现安全系统编程

+ +

{{EmbedYouTube("P3sfNGtpuxc")}}

+ +

成长中的Rust社区

+ +

{{EmbedYouTube("duv0tuPAnO0")}}

+ +

Mozilla将Rust用于生产

+ +

{{EmbedYouTube("2RhbYpgVpg0")}}

diff --git a/files/zh-cn/mozilla/tech/index.html b/files/zh-cn/mozilla/tech/index.html new file mode 100644 index 0000000000..2e4f7a5d64 --- /dev/null +++ b/files/zh-cn/mozilla/tech/index.html @@ -0,0 +1,7 @@ +--- +title: Mozilla 私有技术 +slug: Mozilla/Tech +translation_of: Mozilla/Tech +--- +

Mozilla has several technologies used as components of its projects. These are documented here. (flesh out this text).

+

{{LandingPageListSubpages}}

diff --git a/files/zh-cn/mozilla/tech/toolkit_api/extisessionstorage/index.html b/files/zh-cn/mozilla/tech/toolkit_api/extisessionstorage/index.html new file mode 100644 index 0000000000..7d49c345e7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/toolkit_api/extisessionstorage/index.html @@ -0,0 +1,48 @@ +--- +title: extISessionStorage +slug: Mozilla/Tech/Toolkit_API/extISessionStorage +translation_of: Mozilla/Tech/Toolkit_API/extISessionStorage +--- +

+

+

该条目记录了 Thunderbird 3 引入的新特性

+

+


extISessionStorage 允许一个扩展程序存储数据,该数据会在应用程序的整个生命周期内可用(比如浏览器). extISessionStorage 被定义在 toolkit/components/exthelper/extIApplication.idl.

+

通过XPCOM服务实现的 extIApplication: 查看相关指南在 FUEL (Firefox), STEEL (Thunderbird) 和 SMILE (SeaMonkey) 页面.

+

方法概述

+

这些方法通常是通过Application.storage来访问的.

+ +
返回值类型 方法
boolean has(in AString aName)
void set(in AString aName, in nsIVariant aValue)
nsIVariant get(in AString aName, in nsIVariant aDefaultValue)
+

属性

+ +
属性名 类型 描述
events readonly attribute extIEvents The events object for the storage supports: "change"
+

方法

+

has()

+

判断一个指定名称的存储项是否已经存在.

+
boolean has(in AString aName)
+
+
参数
+
aName
存储项名称
+
+
返回值
+

如果这个存储项已经存在,则返回true,否则返回false.

+

set()

+

为一个指定名称的存储项赋值.

+
void set(in AString aName, in nsIVariant aValue)
+
+
参数
+
aName
存储项名称
aValue
任意类型的值
+
+
返回值
+

+

get()

+

获取一个指定名称的存储项的值.如果该存储项不存在,则返回一个默认值.

+
nsIVariant get(in AString aName, in nsIVariant aDefaultValue)
+
+
参数
+
aName
存储项名称
+
+
返回值
+

指定存储项的值或者一个默认的返回值.

相关链接

+

 FUEL (Firefox), STEEL (Thunderbird) and SMILE (SeaMonkey)

+

diff --git a/files/zh-cn/mozilla/tech/toolkit_api/index.html b/files/zh-cn/mozilla/tech/toolkit_api/index.html new file mode 100644 index 0000000000..7ba5906994 --- /dev/null +++ b/files/zh-cn/mozilla/tech/toolkit_api/index.html @@ -0,0 +1,18 @@ +--- +title: Toolkit API +slug: Mozilla/Tech/Toolkit_API +translation_of: Mozilla/Tech/Toolkit_API +--- +

 

+

Mozilla Toolkit 是建立在Gecko上的应用程序接口集(APIs),用来提供对XUL应用的高级服务. 这些服务包含:

+ +

更多信息

+

下面的开发者页面包含特别主题的例子和讨论:

+

XUL; XUL Overlays; Developing Extensions; XULRunner; Developing Themes; DOM; RDF; Storage; Creating Help Documentation

diff --git a/files/zh-cn/mozilla/tech/viewing_and_searching_mozilla_source_code_online/index.html b/files/zh-cn/mozilla/tech/viewing_and_searching_mozilla_source_code_online/index.html new file mode 100644 index 0000000000..80965735d2 --- /dev/null +++ b/files/zh-cn/mozilla/tech/viewing_and_searching_mozilla_source_code_online/index.html @@ -0,0 +1,26 @@ +--- +title: 在线搜索并浏览Mozilla源代码 +slug: Mozilla/Tech/Viewing_and_searching_Mozilla_source_code_online +tags: + - 开发Mozilla + - 需要更新 +translation_of: Mozilla/Tech/Viewing_and_searching_Mozilla_source_code_online +--- +

托管在Mercurial资源库中的所有Mozilla项目的源代码都可以使用Searchfox在线搜索和查看,Searchfox是一个运行在AWS上的快速索引搜索引擎。

+ +

请勿通过Searchfox下载源码;你可以通过下载tarball或使用Mercurial。

+ +

Searchfox索引多个分支和模块。

+ +

值得注意的几个Searchfox 有:

+ + + +

Mozilla 源代码目录结构 在每个源码目录树中拥有一段简短的描述。

+ +
+

你既可以浏览每个特定版本的源码,也可以下载他们. 每个版本连着源码,都在这归档

+
diff --git a/files/zh-cn/mozilla/tech/xpcom/glue/index.html b/files/zh-cn/mozilla/tech/xpcom/glue/index.html new file mode 100644 index 0000000000..58bfdc731e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/glue/index.html @@ -0,0 +1,71 @@ +--- +title: XPCOM Glue +slug: Mozilla/Tech/XPCOM/Glue +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Glue +--- +

The XPCOM Glue is a static library which component developers and embedders can link against. It allows developers to link only against the frozen XPCOM method symbols and maintain compatibility with multiple versions of XPCOM.

+

Compiling or linking against XPCOM headers

+

There are three ways to compile/link against XPCOM headers/libraries:

+

Frozen linkage: dependent glue (dependent on xpcom.dll)

+

Code which wishes to use only frozen symbols but can tolerate a load-time dependency on xpcom.dll should link against xpcom.lib and xpcomglue_s.lib. This is the case for XPCOM components.

+

Frozen linkage: standalone glue (no DLL dependencies)

+

Embedding code which wishes to use only frozen symbols and cannot tolerate a load-time dependency on <tt>xpcom.dll</tt> should <tt>#define XPCOM_GLUE 1</tt> while compiling, and link against <tt>xpcomglue.lib</tt>. It should + + not + link against <tt>xpcomglue_s.lib</tt> or <tt>xpcom.lib</tt>.

+

In order to use XPCOM, the embedding application first needs to find where the XPCOM runtime is located. This is typically done using GRE_GetGREPathWithProperties. Then, the code must call XPCOMGlueStartup, which will dynamically link against the XPCOM runtime. Only then can the embedding application initialize and use XPCOM.

+

This linkage strategy is used when an embedder needs to bootstrap an embedding app by finding a compatible GRE. Extension or XULRunner application components should use the dependent glue.

+

Embedders using the standalone glue typically also need to avoid linking against NSPR as well.

+

Emlak ilanlar

+

Using Mozilla internal linkage

+

Mozilla internal code defines MOZILLA_INTERNAL_API while compiling and links against xpcom.lib and xpcom_core.lib. In almost all cases embedders should *not* use internal linkage. Components using internal linkage will have shared-library dependencies against non-frozen symbols in the XPCOM libraries, and will not work with any other versions of XPCOM other than the one it was compiled against.

+

Internal linkage will be unavailable to extension authors in XULRunner 1.9 (Firefox 3) because the nonfrozen symbols will not be exported from libxul. Extension and application authors currently using internal linkage should read the guide on Migrating from Internal Linkage to Frozen Linkage.

+

Threadsafe nsISupports implementations

+

When using glue libraries from Gecko 1.8 or later, a special step needs to be taken to use NS_IMPL_THREADSAFE_ISUPPORTS + + n + . This is because it forces a dependency on the NSPR library, which can otherwise be avoided. As described in bug 299664, the preprocessor symbol XPCOM_GLUE_USE_NSPR needs to be defined.

+

Sample Compiler/Linker Flags

+

Code compiled using XPCOM headers should always <tt>#include "xpcom-config.h"</tt> from the SDK, to ensure that XPCOM #defines are correct.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Linking StrategyCompiler FlagsLinker Flags
WindowsMacLinux
Dependent Glue<tt style="white-space: pre">#include "xpcom-config.h"</tt><tt>-LIBPATH:c:/path/to/sdk/lib xpcomglue_s.lib xpcom.lib nspr4.lib</tt><tt>-L/path/to/sdk/lib -L/path/to/sdk/bin -Wl,-executable-path,/path/to/sdk/bin -lxpcomglue_s -lxpcom -lnspr4</tt><tt>-L/path/to/sdk/lib -L/path/to/sdk/bin -Wl,-rpath-link,/path/to/sdk/bin -lxpcomglue_s -lxpcom -lnspr4</tt>
Standalone Glue<tt style="white-space: pre">#include "xpcom-config.h"
+ #define XPCOM_GLUE 1</tt>
<tt>-LIBPATH:c:/path/to/sdk/lib xpcomglue.lib</tt><tt>-L/path/to/sdk/lib -lxpcomglue</tt><tt>-L/path/to/sdk/lib -lxpcomglue</tt>
+

Notes

+ +

See Also

+ diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/arrays/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/arrays/index.html new file mode 100644 index 0000000000..53939ba6c0 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/arrays/index.html @@ -0,0 +1,573 @@ +--- +title: Array +slug: Mozilla/Tech/XPCOM/Guide/Arrays +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Arrays +--- +

 

+

Introduction

+

Array types

+

Mozilla has many array classes because each array is optimized for a particular usage pattern. This guide describes the available arrays as well as the enumerator classes that can be used to get to them. In this document the term Array refers to a container for multiple objects with a numeric, zero-based index.

+

The standard array classes are:

+ +

This handy chart may make it easier to understand the different arrays:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ClassData TypeScriptable?Typesafe?Can be modified?Built in buffer?Ownership
nsIArrayXPCOM objectYesNoNoNoReference Counted, Weak/Strong
nsIMutableArrayXPCOM objectYesNoYesNoReference Counted, Weak/Strong
nsCOMArray<T>XPCOM objectNoYesYes*NoReference Counted, Strong
nsTArray<T>Any that has a default constructor and copy constructorNoYesYes*NoCan hold objects directly, in which case it owns them. When holding pointers, doesn't own the pointer.
nsVoidArrayAnyNoNoYes*NoWeak / None
nsStringArray
+ nsCStringArray
nsString
+ nsCString
NoYesYes*NoPrivate (copies strings)
nsAutoVoidArrayAnyNoNoYes*YesWeak / None
nsSmallVoidArrayAnyNoNoYes*NoWeak / None
nsISupportsArrayXPCOM ObjectYesNoYes*NoReference Counted, Strong
+

(*) Note: Concrete C++ arrays can be made read-only by declaring them const. For example:

+
// HandleList cannot modify the array because of const
+void HandleList(const nsVoidArray&);
+
+

In-place enumeration

+

Most of the arrays presented here provide callback-style means to enumerate members of an array. Instead of incrementally accessing each element of the array by its index, the arrays provide a way to pass in a callback function that will be called for each element in the array.

+

For most concrete C++ classes like nsVoidArray and nsCOMArray<T>, indexing should be faster than the callback-style enumeration, because accessing an indexed member of such an array is usually very fast, while enumeration has slight function call overhead. In the case of scriptable arrays like nsIArray however, the enumeration mechanism is often preferred because it avoids the AddRef / Release overhead that comes from accessing each object.

+

The only functional drawback to in-place enumeration is that you cannot manipulate the array itself during the enumeration. For example, you should not delete elements of an array during the enumeration as this will often confuse the loop which is enumerating the array.

+

Enumerators

+

Most arrays provide access to an object which is used to enumerate members of the array. These Enumerators maintain state about the current position in the array. Enumerators are used to access the elements in an ordered way, without relying on the underlying array type. These enumerators include:

+ +

Obsolete arrays / enumerators

+

There are some deprecated classes which should not be used by new code.

+ +

Which Array should I use?

+

Do not use nsISupportsArray; it is deprecated.

+

Does your array need to be scriptable? If so, use nsIArray.

+

Example: an array attribute in an IDL file would be nsIArray.

+

Will your array store non-refcounted objects and need automatic resizing? If so, use nsTArray<T>.

+

Example: an array of integers or an array of strings.

+

Will your array store non-refcounted objects and be a fixed size? If so, just use a native C++ array unless you need the enumeration options on nsTArray<T>.

+

Example: an array of error message static const char* pointers.

+

Are all the things you are storing interface pointers to instances of the same interface? If so, use nsCOMArray.

+

Example: a content node's list of nsIContent children.

+

Otherwise use nsIArray and make liberal use of QueryElementAt().

+

The point of nsCOMArray is that it's a template, and all the pointers in it must be pointers to the same type; it's nice to be able to use it because you get type-safety and don't have to spend time and code QIing (like you have to with nsIArray).

+

Array Guidelines

+

Here are a few simple rules which will keep your code clean and your developers happy:

+ +

Scriptable Arrays

+

nsIArray / nsIMutableArray

+

Usage

+

nsIArray is useful if you need to pass arrays of COM objects through interfaces or require a scriptable array. It can hold strong or weak references to its container objects. This basic interface only allows querying of existing elements in the array. The methods that modify the array have been broken out into nsIMutableArray.

+

An nsIArray implementation can be created from C++ with the function NS_NewArray(nsIMutableArray**);. The created array implements nsIMutableArray and nsIArray. Since nsIArray derives from nsIMutableArray, the resulting array can be cast to a read-only array.

+
void GetList(nsIArray** aResult) {
+  nsCOMPtr<nsIMutableArray> array;
+  NS_NewArray(getter_AddRefs(array));
+
+  // append some elements
+  ...
+
+  // return it to the caller
+  *aResult = array;
+  NS_ADDREF(*aResult);
+}
+
+

Access to elements

+

Since nsIArray is a regular XPCOM object, its interfaces follows the standard conventions of ownership. Access to specific elements is through QueryElementAt, which is similar to QueryInterface, but it takes a specific index.

+
void NotifyObservers(nsIArray* aArray) {
+  PRUint32 length;
+  aArray->GetLength(&length);
+  for (PRUint32 i=0; i<length; ++i) {
+    nsCOMPtr<nsIMyObserver> element;
+    aArray->QueryElementAt(i, NS_GET_IID(nsIElement),
+                                getter_AddRefs(element));
+    element->Observe();
+  }
+}
+
+

A simpler option is to use the helper do_QueryElementAt which is typesafe.

+
void NotifyObservers(nsIArray* aArray) {
+  PRUint32 length;
+  aArray->GetLength(&length);
+  for (PRUint32 i=0; i<length; ++i) {
+    nsCOMPtr<nsIMyObserver> element =
+    do_QueryElementAt(aArray, i);
+     element->Observe();
+  }
+}
+
+

Passing as a parameter

+

Since nsIArray is an XPCOM object, it should be passed as a pointer. To distinguish between read-only arrays and writable arrays, you should make sure to pass a nsIArray or nsIMutableArray as appropriate.

+

When the array can or should be modified, then use nsIMutableArray:

+
// array is read-only because it uses nsIArray
+void PrintSize(nsIArray* elements) {
+  PRUint32 count;
+  elements->GetLength(&count);
+  printf("There are %d elements.\n", count);
+}
+
+// using nsIMutableArray, so callee may modify
+void TweakArray(nsIMutableArray* elements) {
+  elements->RemoveElementAt(0);
+  elements->AppendElement(newElement, PR_FALSE);
+}
+
+

While it is usually possible to call QueryInterface on an nsIArray to get access to the nsIMutableArray interface, this is against convention and it should be avoided.

+
// no need for the double-pointer, and this violates XPCOM rules
+// which expect acess to a new object
+void TweakArray(nsIMutableArray** elements) {
+  // ugh, extra indirection!
+  *elements->RemoveElementAt(0);
+  *elements->AppendElement(newElement, PR_FALSE);
+}
+
+

In-place enumeration

+

When accessing all members of an nsIArray, in-place enumeration is preferred over indexed access. However, I seem to have forgotten to implement that. Good thing the interface is under review. Sorry!

+

Enumerators

+

Creating an enumerator from an nsIArray is easy. The method Enumerate() returns a nsISimpleEnumerator which accesses all the elements in the array. Often, simply accessing an array by index, using QueryElementAt is faster. See the section on Enumerators to learn when to properly use enumerators.

+

For example, if you need to iterate an array returned from another object, you might use Enumerate().

+
...
+// get the array
+nsCOMPtr<nsIArray> array;
+foo->GetElements(getter_AddRefs(array));
+
+// make an enumerator
+nsCOMPtr<nsISimpleEnumerator> enumerator;
+array->Enumerate(getter_AddRefs(enumerator));
+
+// now enumerate the elements
+...
+
+

Typesafe Arrays

+

nsCOMArray<T>

+

nsCOMArray<T> is a typesafe wrapper around nsVoidArray, so it has a similar API. It enforces both typesafety and XPCOM reference counting by keeping an owning reference to each element in the array.

+

Usage

+

It is most often used as a member of a C++ class to store a list of well-typed XPCOM objects. It is also usually declared as an inline member rather than a pointer. As a class member, nsCOMArray<T> is preferred over nsIArray when access to the array is confined to the class itself.

+

For example, here is its use in a class:

+
class NodeContainer {
+public:
+  void AddNode(nsINode* node);
+
+private:
+  nsCOMArray<nsINode> mNodes;
+};
+
+// typesafety of mNodes ensures that we only append an nsINode*
+void NodeContainer::AddNode(nsINode* node) {
+  mNodes.AppendObject(node);
+}
+
+
+

nsCOMArray<T> can also be declared on the stack to collect a temporary list of objects and manipulate them. When the object goes out of scope, all its members are released.

+
void ProcessVisibleItems()
+{
+  // temporary stack-based nsCOMArray
+  nsCOMArray<nsIFoo> fooItems;
+  GetCompleteList(fooItems);
+
+  // now filter out non visible objects
+  // doing this backwards
+  PRUint32 i = fooItems.Count();
+  while (i > 0) {
+    --i;
+    PRBool isVisible;
+    fooItems[i]->GetIsVisible(&isVisible);
+    if (!isVisible) {
+      fooItems.RemoveObjectAt(i);
+    }
+  }
+
+  // now deal with the processed list
+  ProcessList(fooItems);
+
+  // fooItems will release all its members
+  // when it goes out of scope
+}
+
+

Access to elements

+

nsCOMArray<T> is a concrete C++ class, and so the [] operator is used to access its members. When using the [] operator, the reference count is unchanged. This allows direct processing of array elements without worrying about calling Release().

+

For example, this code calls the same method on each member:

+
void NotifyObservers(const nsCOMArray<nsIMyObserver>& observers) {
+  // Using [] doesn't leak!
+  for (PRInt32 i = observers.Count() - 1; i >= 0 ; i--)
+    observers[i]->Observe();
+}
+
+

Be careful with this though, you could end up with a weak pointer if you're converting from non-nsCOMArray code.

+
// old version, relied on automatic addref
+// mElements is an nsISupportsArray*
+void GetFirstObject(nsIElement** aResult) {
+  // no need to call NS_ADDREF - this does it for you
+  mElements->QueryElementAt(0, NS_GET_IID(nsIElement),
+  (void**)aResult);
+}
+
+// new version, make sure to call NS_ADDREF()
+// mElements is now a nsCOMArray<nsIElement>
+void GetFirstObject(nsIElement** aResult) {
+  *aResult = mElements[0];
+  NS_ADDREF(*aResult);
+}
+
+

Passing as a parameter

+

When passing nsCOMArray<T> among functions, the convention is to pass by reference. Also be sure to use const if you want to enforce that the array is read-only.

+

Here is an example with a read-only and a writable array:

+
// array is read-only because of const
+void PrintSize(const nsCOMArray<nsIElements>& elements) {
+ printf("There are %d elements.\n", elements.Count());
+}
+
+// no const, so we can modify the array
+void TweakArray(nsCOMArray<nsIElement>& elements, nsIElement* newElement) {
+  elements.RemoveObjectAt(0);
+  elements.AppendObject(newElement);
+}
+
+

In-place enumeration

+

The callback-based enumeration in nsCOMArray<T> is about as fast as, if not faster than, standard loop-based iteration. The callback mechanism can be useful when integrating with existing callback-style code however.

+

One particularly nice thing about the callback mechanism is that it is typesafe. For instance:

+
PR_CALLBACK PRBool getFirstVisible(nsIElement* element, void* closure)   {
+ PRBool isVisible;
+ element->IsVisible(&isVisible);
+
+ // stop at first object
+ if (isVisible) {
+  NS_STATIC_CAST(ClosureObject*,closure)->element = element;
+  return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
+...
+// enumerate to find the object
+ClosureObject closureObject = { 0 };
+if (!mElements.EnumerateForwards(getFirstVisible, closureObject))
+             processElement(closureObject->element);
+...
+
+

Enumerators

+

A nsISimpleEnumerator can be created to provide access to a nsCOMArray<T>. When the enumerator is created, it takes a snapshot of the elements in the array, so that the enumerator can outlive the array.

+

To create the enumerator, use NS_NewArrayEnumerator(nsISimpleEnumerator**, const nsCOMArray<T>&). For example:

+
// mElements is an nsCOMArray<nsIElement>
+nsFoo::GetElements(nsISimpleEnumerator** aResult) {
+  return NS_NewArrayEnumerator(aResult, mElements);
+}
+
+

nsTArray<T>

+

nsTArray<T> is a typesafe array for holding various objects. It can be used to hold objects directly, not just pointers to objects.

+

Usage

+

It is most often used as a member of a C++ class to store a list of well-typed objects. It is also usually declared as an inline member rather than a pointer. As a class member, nsTArray<T> is preferred over nsVoidArray.

+

For example, here is its use in a class:

+
class MediaList {
+public:
+  void AddMedium(const nsString& aMedium);
+
+private:
+  nsTArray<nsString> mMedia;
+};
+
+// typesafety of mMedia ensures that we only append an nsString
+void NodeContainer::AddMedium(const nsString& aMedium) {
+  mMedia.AppendElement(aMedium);
+}
+
+
+

nsTArray<T> can also be declared on the stack to collect a temporary list of objects and manipulate them. When the object goes out of scope, all its members have their destructors called. Note that if the nsTArray<T> holds pointers to objects, the objects will not be deleted (and hence not have their destructors called).

+
void ProcessVisibleItems()
+{
+  // temporary stack-based nsTArray
+  nsTArray<FooStruct> fooItems;
+  GetCompleteList(fooItems);
+
+  // now filter out non visible objects
+  // doing this backwards
+  PRUint32 i = fooItems.Length();
+  while (i > 0) {
+    --i;
+    PRBool isVisible;
+    fooItems[i]->GetIsVisible(&isVisible);
+    if (!isVisible) {
+      fooItems.RemoveElementAt(i);
+    }
+  }
+
+  // now deal with the processed list
+  ProcessList(fooItems);
+
+  // fooItems will call the destructors of all the FooStruct objects
+  // when it goes out of scope
+}
+
+

Access to elements

+

nsTArray<T> is a concrete C++ class, and so the [] operator is used to access its members.

+

For example, this code calls the same method on each member:

+
void NotifyObservers(const nsTArray<ObserverClass*>& observers) {
+  for (PRUint32 i = observers.Length(); i > 0 ; ) {
+    --i;
+    observers[i]->Observe();
+  }
+}
+
+

Passing as a parameter

+

When passing nsTArray<T> among functions, the convention is to pass by reference. Also be sure to use const if you want to enforce that the array is read-only.

+

Here is an example with a read-only and a writable array:

+
// array is read-only because of const
+void PrintSize(const nsTArray<nsElement>& elements) {
+ printf("There are %d elements.\n", elements.Length());
+}
+
+// no const, so we can modify the array
+void TweakArray(nsTArray<nsElement>& elements,
+                const nsElement& newElement) {
+  elements.RemoveElementAt(0);
+  elements.AppendElement(newElement);
+}
+
+

In-place enumeration

+

There are no enumerator objects that work on an nsTArray<T>.

+

C++ Arrays

+

nsVoidArray

+

nsVoidArray is a concrete C++ class that allows for storage of any arbitrary object. The base type for all objects is void *. When converting to/from a void *, use NS_STATIC_CAST to ensure that no const-ness is lost.

+

Note that nsVoidArray defines no semantics of ownership of its objects. Depending on its use, the array may either own the objects that it points to, or its member may be pointers to existing objects that are owned by another data structure. Because nsVoidArray itself does not define any ownership rules, it is up to the consumer to know when it is appropriate to free objects out of the array.

+

This implies that when an nsVoidArray goes out of scope, seperate code must free any memory that is semantically owned by the array. This should always be documented in the declaration of the array instance.

+

nsCOMArray<T> was designed to eliminate some of the overhead of using nsVoidArray when using COM objects. If your code is using nsVoidArray to keep references to COM objects, consider converting it to nsCOMArray<T>.

+

Usage

+

nsVoidArray is often used as a member variable in a class. Remember to document ownership!

+
struct FooElement {
+ ...
+};
+
+class nsFoo : nsIFoo {
+ ...
+ virtual ~nsFoo();
+ ...
+
+ private:
+ // mElements owns a list of FooElement structs,
+ // which must be deleted when this object goes away
+ nsVoidArray mElements;
+
+ // mVisibleElements contains weak (non-owning) references
+ // to elements in mElements, and does not need to be cleaned up
+ nsVoidArray mVisibleElements;
+};
+
+nsFoo::~nsFoo() {
+ // mVisibleElements is fine, but
+ // don't forget to clean up mElements!
+ PRUint32 i, count = mElements.Count();
+ for (i=0; i<count; ++i)
+  delete NS_STATIC_CAST(FooElement*, mElements[i]);
+ }
+
+
+

As you can see, nsVoidArray has some context-specific overhead to make sure memory is cleaned up appropriately.

+

Access to elements

+

The [] operator is used to access member variables. Don't forget to use NS_STATIC_CAST().

+
for (i=0; i<count; ++i) {
+ FooElement* element = NS_STATIC_CAST(FooElement*,mElements[i]);
+ // now manipulate element
+}
+
+
+

Passing as a parameter

+

Like other concrete C++ classes, passing by reference using the & syntax is preferred.

+

In-place enumeration

+

Enumerators

+

nsStringArray / nsCStringArray

+

Usage

+

Access to elements

+

Passing as a parameter

+

In-place enumeration

+

Enumerators

+

nsAutoVoidArray

+

Usage

+

Access to elements

+

Passing as a parameter

+

In-place enumeration

+

Enumerators

+

nsSmallVoidArray

+

Usage

+

Access to elements

+

Passing as a parameter

+

In-place enumeration

+

Enumerators

+

Enumerators

+

Enumerators are very simple, structure-free objects for visiting each member of a set of objects. The enumerators are used as a generic interface for arrays, hashtables, and other constructs which contain one or more objects. When designing public interfaces, enumerators are the preferred mechanism for accessing these structures because they hide the details of the implementation behind the interface.

+

nsISimpleEnumerator

+

nsISimpleEnumerator is a generic enumerator for enumerating a list of any XPCOM object. There are many implementations of nsISimpleEnumerator, including one that enumerates nsIArray objects, and another one for nsCOMArray. It is very common for other interfaces which support nsISimpleEnumerator to make their own implementations.

+

nsIStringEnumerator

+

String enumerators provide an easy way to pass a list of strings around with minimal copying. Both unicode strings and UTF8-encoded strings are supported. For more information about the different types of strings, see the String Guide.

+

String enumerators can be created from nsStringArray or nsCStringArray objects. The implementation of the string enumerator interfaces for nsStringArray and nsCStringArray supports conversion between UTF8 and Unicode, and can be QueryInterface'd back and forth between nsIStringEnumerator and nsIUTF8StringEnumerator.

+

To create an nsIStringEnumerator for an nsStringArray, you can use one of the variations of NS_NewStringEnumerator. There are also corresponding enumerators and helpers for UTF8 strings. In the examples below, NS_NewUTF8StringEnumerator can be used along with nsIUTF8StringEnumerator and nsCStringArray.

+

This first example demonstrates the case where a class which owns an nsStringArray, and are returns an nsIStringEnumerator to a caller. You can use the variation of NS_NewStringEnumerator that ensures the owner of the array outlives the enumerator. This is necessary because nsStringArray is not reference counted. Without holding a reference to the owner, the enumerator could be left with a dangling pointer to a deleted nsStringArray.

+
class nsFoo : nsIFoo {
+...
+private:
+  nsStringArray mElementNames;
+};
+
+nsFoo::GetElementNames(nsIStringEnumerator** aResult)
+{
+  // pass in "this" to make sure the enumerator
+  // holds a reference to "this"
+  return NS_NewStringEnumerator(aResult, mElementNames, this);
+}
+
+

One variant of NS_NewStringEnumerator does not require an owner, but should only be used when the lifetime of the enumerator is known to be shorter than that of the array. Often this is used when a method must take a nsIStringEnumerator rather than an nsStringArray, due to some sort of interface constraint.

+
class nsFoo : nsIFoo {
+ ...
+ // when ProcessElements returns, the enumerator is at the
+ // end of the list, and can be released.
+ NS_IMETHODIMP ProcessNames(nsIStringEnumerator*);
+ private:
+
+ nsStringArray mElementNames;
+};
+
+...
+nsCOMPtr<nsIStringEnumerator> enumerator;
+NS_NewStringEnumerator(getter_AddRefs(enumerator), mElementNames);
+
+// now call a method on "this" that has a known behavior
+ProcessNames(enumerator);
+// now enumerator is used up, and can be released
+...
+
+

The last version of nsIStringEnumerator takes ownership of an nsStringArray and is responsible for freeing the array when the enumerator is used up.

+
void GetNames(nsIStringEnumerator** aResult)
+{
+ nsStringArray *resultArray = new nsStringArray;
+ resultArray->AppendString(str1);
+ resultArray->AppendString(str2);
+
+ // enumerator will free resultArray
+ return NS_NewAdoptingStringEnumerator(aResult, resultArray);
+}
+
+

As noted above, these implementations of nsIStringEnumerator can also be QueryInterface'd between nsIStringEnumerator and nsIUTF8StringEnumerator. The implementations will properly convert back and forth between UTF8 and Unicode. To ensure that you get the right implementation and the conversion is done in the right direction, make sure that you call the version of NS_NewStringEnumerator or NS_NewUTF8StringEnumerator that corresponds to the array type, not the enumerator type.

+

For example, if a class has an internal nsCStringArray of UTF8 strings, but needs to implement an interface which returns an nsIStringEnumerator, it should use NS_NewStringEnumerator:

+
class nsFoo : nsIFoo {
+ ...
+ NS_IMETHOD GetStrings(nsIStringEnumerator** aResult);
+
+
 private:
+ nsCStringArray mElementNames;
+};
+
+NS_IMETHODIMP
+nsFoo::GetStrings(nsIStringEnumerator** aResult) {
+ nsresult rv;
+ nsCOMPtr<nsIUTF8StringEnumerator> enumerator
+ rv = NS_NewUTF8StringEnumerator(getter_AddRefs(enumerator),
+                                       mElementNames, this);
+ return CallQueryInterface(enumerator, aResult);
+}
+
+

Obsolete Arrays and Enumerators

+

nsISupportsArray

+

nsIEnumerator (includes nsIBidirectionalEnumerator)

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/an_overview_of_xpcom/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/an_overview_of_xpcom/index.html new file mode 100644 index 0000000000..64bf41704f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/an_overview_of_xpcom/index.html @@ -0,0 +1,535 @@ +--- +title: 创建_XPCOM_组件/XPCOM_简介 +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/An_Overview_of_XPCOM +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/An_Overview_of_XPCOM +--- +

+

« 上一页下一页 »

+

+ +

这是一本关于 XPCOM 的书. 这本书是以编写一个 XPCOM 组件的方式来组织的, 但是这个过程涵盖了 XPCOM 组件模型主要的出发点, 概念和术语.

+ +

本章以 XPCOM 的快速导览开始, 简单介绍了 XPCOM 和组件开发的基本概念和技术. 本章的大部分内容从一个很高的角度介绍了这些概念, 这些概念将在创建一个称为 WebLock 的 Mozilla 组件过程中逐渐透彻的讲述.

+ +

XPCOM 解决方案

+ +

Cross Platform Component Object Module (XPCOM) 是一个允许开发人员把一个大的工程划分成小的模块的框架. 这些小模块称为组件, 它们在运行时刻组装在一起.

+ +

XPCOM 的目标是使软件的不同部分分别开发, 相互独立. 为了是应用的不同组件之间能够互操作, XPCOM 把组件的实现接口(后面讨论接口)分开. 同时 XPCOM 还提供了加载和操纵这些组件的库和工具以及服务, 以帮助开发人员编写跨平台的代码和组件版本管理; 因此组件可以在不破坏应用或者重新生成应用的同时被替换被更新. 通过使用 XPCOM, 开发人员创建的组件可以在不同的应用中被重用, 或者替换当前应用中的组件以改变应用的功能.

+ +

XPCOM 不只提供组件软件开发的支持, 它同时提供一个开发平台的大多数功能的支持:

+ + + +

我们将在后面的章节中详细讨论上面的条目, 但是现在, 仅仅把 XPCOM 想象成一个 组件开发平台, 它提供了上面的这些特性.

+ +

Gecko

+ +

XPCOM 尽管在许多方面类似于 Microsoft COM, 但 XPCOM 被设计成主要应用于应用层. XPCOM 的最重要的应用是 Gecko, 一个开源的, 遵循标准的, 嵌入式 web 浏览器和 工具包.

+ +

XPCOM 是访问 Gecko 库和嵌入或扩展 Gecko 的方法. 本书着重于后者 - 扩展 Gecko - 但是本书中描述的基本思想对嵌入 Gecko 的开发人员也很重要.

+ +

Gecko 应用在许多 internet 程序中, 主要是浏览器. 包括 Gateway/AOL Instant AOL device 和 Nokia Media Terminal. Gecko 最近还被应用于的 Compuserve 客户端, AOL for Mac OS X, Netscape 7, 当然还包括 Mozilla 客户端. Gecko 是目前而言主流的开源浏览器.

+ +

组件

+ +

XPCOM 允许把一个大的工程分解为一些小部分. 这些小部分称为组件, 通常是一些小的可重用的二进制库(在 Windows 下表现为一个 DLL (动态联接库), Unix 下为一个 DSO (分布式共享对象), 这些二进制库可以包含一个或多个组件. 当多个相关组件被封装到一个二进制库, 这个库也称为模块.

+ +

把软件划分成不同的组件可以使开发和维护工作变得更容易. 除了这个好处, 模块化组件化的编程还有下面的优势:

+ + + + + + + + + + + + + + + + + + + + + + + + +
优点描述
重用模块化的代码可以在其他应用和环境中被重用.
更新在不需要重新编译整个应用的情况下更新组件.
性能代码按照模块化组织, 模块就不必要立刻被加载, 而是以 "lazy" 方式加载, 或者根本不需要加载. 这样就可以提升应用的整体性能.
维护甚至在不更新组件的情况下, 按照模块化的方式设计应用也能够使你对感兴趣的部分的维护变得更容易.
+ +

Mozilla 有几百万行代码, 没有那个人能够彻底搞明白整个代码的细节. 面对这样的一个系统, 最好的方式是把它划分成一些小的, 更容易管理的部分; 同时使用组件模型来编程, 把相关组件组织到各个模块中去. 比如说, Mozilla 的网络库就包含了 HTTP, FTP, 及其他协议的组件, 这些组件被塞到一个单独的库里. 这个库就是网络模块, 也就是通常所说的 "necko."

+ +

但是把事物划分开来并不一定就好, 有许多事物作为一个整体组织起来才是最好的方式, 或者根本就不能划分开来. 比如说, 一个小孩就可能不吃没有果酱的三明志, 对于他来说, 果酱和三明志是缺一不可的整体. 同样的情形也会存在于某些软件中, 某些需要紧耦合的仅仅在内部使用的部分就并不需要费力去把它拆开成为小的模块.

+ +

Gecko 中的 HTTP (超文本传输协议)  组件并不会暴露它内部的类, 它是作为一个整体来使用. 组件内部的事物不应该暴露给 XPCOM. 在 Mozilla 早期的开发中, 有些组件的创建并不适当, 但是随着开发的深入, 这些部分会被逐渐移出 XPCOM.

+ +

接口

+ +

把软件划分成组件通常一个好的解决方法, 但是我们该怎么做呢? 基本的思路是按照功能进行划分, 理解这些功能块之间的如何进行通信. 这些组件之间的通信通道就构成了各个组件的边界, 这些边界形式的描述为接口.

+ +

接口并不是编程中的一个新的概念. 从我们的第一个 "HelloWorld" 程序开始我们就一直在不知不觉的使用它, 这里的接口就存在于我们的应用程序和打印程序之间. 应用程序使用 stdio 库提供的接口来把 "hello world" 字符串打印到屏幕上. XPCOM 与 "HelloWorld" 程序的不同之处在于 XPCOM 会在运行时刻找到这个屏幕打印的功能, 而 XPCOM 事前根本就不需要在编译的时刻了解 stdio 库提供了什么东西.

+ +

接口允许开发人员把功能的具体实现封装在组件内部, 而客户程序不需要了解这个功能是如何实现的, 它只需要使用它就行了.

+ +
+

接口与按照契约(Contract)编程

+ +

一个接口在组件与客户程序之间达成契约. 并没有任何强制措施保证认同这个契约, 但是忽略它会是致命的. 在基于组件的编程中, 组件保证它提供的接口是不变的 - 不同版本的组件都要提供同样的访问方法 - 这就与使用它的客户程序达成了一种契约. 从这种角度来说, 基于组件的编程通常也称为按照契约编程.

+
+ +

接口与封装

+ +

组件边界之间的抽象对软件的可维护性与可重用性是致关重要的. 举个例子来说, 考虑下面一个没有很好封装的类. 在下面的例子中, 使用可自由访问的 public 的初始化方法可能会出问题.

+ +

SomeClass类初始化

+ +
class SomeClass
+{
+  public:
+    // Constructor
+    SomeClass();
+
+    // Virtual Destructor
+    virtual ~SomeClass();
+
+    // init method
+    void Init();
+
+    void DoSomethingUseful();
+};
+
+ +

系统要工作正常, 客户程序员必须注意到组件程序员建立的潜规则. 这就是这个未很好封装的类的契约: 这是一套关于何时该调用一个方法, 调用这个方法之前应该做什么的规则. 这个规则可能指出 DoSomethingUseful 方法只能在调用 Init() 之后被使用. DoSomethingUseful 方法可能会做某些检查工作以保证条件满足 - Init 已经被调用.

+ +

除了在代码中给出注释告诉客户程序员关于 Init() 规则之外, 程序员可以使他的契约更明晰. 首先对象的构造函数可以封装起来, 然后向客户程序员提供一个声明 DoSomethingUseful 方法的虚基类. 通过这种方式, 构造函数和初始化函数被隐藏起来. 在这种半封装条件下, 这个类只向客户程序暴露一些良好定义的可调用方法(或者称为接口). 一旦按照这种方式封装一个类, 客户程序只能看到的是下面的接口:

+ +

SomeInterface封装

+ +
class SomeInterface
+{
+  public:
+    virtual void DoSomethingUseful() = 0;
+};
+
+ +

实现类就可以从这个虚基类派生, 实现接口的功能. 客户程序使用类厂(factory pattern)模式来创建对象(参看类厂), 而封装类的内部实现. XPCOM 以这种方式把客户程序屏蔽在组件的内部工作之外, 而客户程序也只依赖于提供所需要功能的接口.

+ +

nsISupports 基接口

+ +

组件与基于接口的编程的两个最基本的问题是: 一个是组件生存期, 也称为对象所属关系; 另一个是接口查询, 它是在运行时刻确定接口能够提供哪些接口. 这一节介绍基接口 nsISupports - 它是 XPCOM 中所有接口的父接口, 它提供了上面两个问题的解决方案.

+ +
对象所属关系
+ +

在 XPCOM 中, 由于组件可以实现任意多的不同接口, 接口必须是引用计数的. 组件在内部跟踪客户程序对它的接口引用了多少次, 当接口计数为零的时候组件就会卸载它自己.

+ +

当一个组件创建后, 组件内部有一个整数在跟踪这个引用计数值. 客户程序实例化组件就会自动对这个引用计数加一; 在组件的整个生存期内, 引用计数或加或减, 总是大于零的. 如果在某个时刻, 所有的客户程序对该组件都失去了兴趣, 引用计数减到零, 组件就会卸载自己.

+ +

客户程序使用相关接口是一个非常直接的过程. XPCOM 有一些工具让我们更方便的使用接口, 我们会在后面讲述. 如果客户程序在使用接口的时候忘记对接口的引用计数进行相关操作, 就会对组件的维护工作带来某些问题. 此时, 由于组件的引用计数始终不为零, 它就永远不会释放, 从而导致内存泄漏. 引用计数系统就象 XPCOM 的许多其他事物一样, 是客户与组件之间的契约. 如果遵守这些契约, 就会工作得很正常, 反之不然. 由创建接口指针的函数负责对初始化的接口引用加1, 这个引用也称为所属引用.

+ +
+

XPCOM中的指针

+ +

XPCOM 中的指针术语指的是接口指针. 它与常规指针相比有细微的差别, 毕竟它们都指向的是某个内存区域. 但是 XPCOM 指针指向的都是从 nsISupports 基接口派生而来的接口实现, 这个基接口包括三个基本的方法: AddRef, Release, 和 QueryInterface.

+
+ +

nsISupports 接口提供了对接口查询与引用计数基本的支持. 这个接口的成员方法包括: QueryInterface, AddRef, 和 Release. 这些方法提供了从一个对象获取正确接口的基本方法, 加引用计数, 释放不再使用的对象. nsISupports 接口的声明如下:

+ +

nsISupports 接口

+ +
class Sample: public nsISupports
+{
+  private:
+    nsrefcnt mRefCnt;
+  public:
+    Sample();
+    virtual ~Sample();
+
+    NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
+    NS_IMETHOD_(nsrefcnt) AddRef(void);
+    NS_IMETHOD_(nsrefcnt) Release(void);
+};
+
+ +

接口中使用的各种数据类型见XPCOM 类型一节. nsISupports 接口的实现代码如下:

+ +

nsISupports 接口实现

+ +
Sample::Sample()
+{
+  // initialize the reference count to 0
+  mRefCnt = 0;
+}
+Sample::~Sample()
+{
+}
+
+// typical, generic implementation of QI
+NS_IMETHODIMP Sample::QueryInterface(const nsIID &aIID,
+                                  void **aResult)
+{
+  if (aResult == NULL) {
+    return NS_ERROR_NULL_POINTER;
+  }
+  *aResult = NULL;
+  if (aIID.Equals(kISupportsIID)) {
+    *aResult = (void *) this;
+  }
+  if (*aResult == NULL) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+  // add a reference
+  AddRef();
+  return NS_OK;
+}
+
+NS_IMETHODIMP_(nsrefcnt) Sample::AddRef()
+{
+  return ++mRefCnt;
+}
+
+NS_IMETHODIMP_(nsrefcnt) Sample::Release()
+{
+  if (--mRefCnt == 0) {
+    delete this;
+    return 0;
+  }
+  // optional: return the reference count
+  return mRefCnt;
+}
+
+ +
对象接口的发现
+ +

继承是面向对象编程中另一个非常重要的话题. 继承是通过一个类派生另一个类的方法. 当一个类继承另一个类, 继承类可以重载基类的缺省动作, 而不需要拷贝基类的代码, 从而创建更加专有的类. 如下所示:

+ +

简单类继承

+ +
class Shape
+{
+  private:
+    int m_x;
+    int m_y;
+
+  public:
+    virtual void Draw() = 0;
+    Shape();
+    virtual ~Shape();
+};
+
+class Circle : public Shape
+{
+  private:
+    int m_radius;
+  public:
+    virtual Draw();
+    Circle(int x, int y, int radius);
+    virtual ~Circle();
+};
+
+ +

CircleShape 类派生. Circle 本身也是一个 Shape, 但是 Shape 并不一定是 Circle. 在这种情况下, Shape基类, CircleShape 的子类.

+ +

在 XPCOM 中, 所有的类都派生自 nsISupports 接口, 这样所有的对象都提供 nsISupports接口, 但是这些对象是更专有的类, 在运行时刻必须能找到它. 比如说在简单类继承例子中, 如果对象是一个 Circle, 你就可以调用 Shape 类的方法. 就是为什么在 XPCOM 中, 所有的对象都派生自 nsISupports 接口: 它允许客户程序根据需要发现和访问不同的接口.

+ +

在 C++ 中, 我们可以使用 dynamic_cast<> 来把一个 Shape 对象的指针强制转化成一个 Circle 指针, 如果不能转化就抛出异常. 但是在 XPCOM 中, 由于性能开销和平台兼容性问题, 采用 RTTI (运行时刻类型信息) 的方法是不行的.

+ +
+

XPCOM 中的异常

+ +

XPCOM 并不直接支持 C++ 的异常处理. 在 XPCOM 中, 所有的异常必须在组件内部处理, 而不能跨越接口的边界. 然后接口方法返回一个 nsresult 错误值(这些错误码请参考 XPCOM API Reference). 客户程序根据这些错误码进行"异常"处理.

+
+ +

XPCOM 没有采用 C++ RTTI 机制来实现对象指针的动态转化, 它使用 QueryInterface 方法来把一个对象指针 cast 成正确的接口指针.

+ +

每个接口使用称为 "uuidgen" 的工具来生成专有ID. 这个 ID 是一个全局唯一的 128-bit 值. 在接口的语境中, 这个 ID 又称为 IID. (组件语境中, 这个 ID 代表的是一个契约)

+ +

当客户程序想查询一个对象是否支持某个接口, 它把接口的 IID 值传递给这个对象的 QueryInterface 方法. 如果对象支持这个接口, 它就会对自己的引用计数加1, 然后返回指向那个专有接口的指针. 反之, 如果不支持这个接口, 它会返回一个错误码.

+ +
class nsISupports {
+  public:
+    long QueryInterface(const nsIID & uuid,
+                        void **result) = 0;
+    long AddRef(void) = 0;
+    long Release(void) = 0;
+};
+
+ +

QueryInterface 的第一个参数是一个 nsIID 类型的引用, 它封装了 IID. nsIID 类有三种方法: Equals, Parse, 和 ToString. Equals 在接口查询中是最重要的, 它用来比较两个 nsIID 对象是否相同.

+ +

在客户以 IID 调用 nsISupports 接口的 QueryInterface 方法时, 我们必须保证返回一个有效的 result 参数(在Using XPCOM Utilities to Make Things Easier 一章中, 我们将看到怎样更方便的实现一个 nsIID 类). QueryInterface 方法应该支持该组件所有接口的查询.

+ +

QueryInterface 方法的实现中, IID 参数与组件支持 nsIID 类进行比较. 如果匹配, 对象的 this 指针转化为 void 指针, 引用计数加1, 把 void 指针返回给客户程序.

+ +

在上面的例子中, 仅仅使用 C 方式的类型转化就足够了. 但是在把 void 指针 cast 成接口指针的时候, 还有更多的问题, 因为返回的接口指针必须与 vtable (virtual table) 相对应. 当出现菱形多重继承的时候, 可能这种接口转化就会有问题.

+ +

XPCOM 的ID

+ +

除了上一节中的接口 IID, XPCOM 还使用两种 ID 来区分类与组件.

+ +
+

XPCOM ID类

+ +

nsIID 类实际上是一种 nsID 类. 其他的 nsID, CID 和 IID, 分别指的是一个实体类和一个专有的接口.

+ +

nsID 类提供 Equals 类似的方法, 来比较 ID. 请参考 Identifiers in XPCOM 一节, 其中对 nsID 类有更多的讨论.

+
+ +

CID

+ +

CID 是一个唯一的 128-bit 值, 类似于 IID, 它用于全局标识唯一的类或者组件. nsISupports 的 CID 就象:

+ +

00000000-0000-0000-c000-000000000046

+ +

由于 CID 比较长, 通常我们都使用#define来定义它:

+ +
#define SAMPLE_CID \
+{ 0x777f7150, 0x4a2b, 0x4301, \
+{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}}
+
+ +

我们将会看到许多 NS_DEFINE_CID 的定义. 下面的宏用 CID 定义了一个静态变量:

+ +
static NS_DEFINE_CID(kWebShellCID, NS_WEB_SHELL_CID);
+
+ +

CID 有时也称为类 ID. 如果一个类实现了多个接口, 当CID 在该类发布后, 就与该类的 IID 一起被冻结了.

+ +

契约 ID

+ +

契约 ID 是一个用于访问组件的可读(to humen)的字符串. 一个 CID 或者一个契约 ID 可以用于从一个组件管理器获取组件. 下面是一个用于 LDAP 操作组件的契约 ID:

+ +
"@mozilla.org/network/ldap-operation;1"
+
+ +

契约 ID 的格式是: 用斜杠分开的组件的, 模块, 组件名, 版本号.

+ +

与 CID 类似, 契约 ID 指的是组件实现而不是接口. 但是契约 ID 并不像CID那样,被限定为某个专有实现, 它更通用. 一个契约 ID 只是指明需要实现的一组接口,可以通过任意数量的CID满足这个需要. 契约 ID 与 CID 的这种不同, 使得组件重写成为可能.

+ +

类厂

+ +

把代码划分成组件, 客户代码通常使用 new 操作符来构造实例对象:

+ +
SomeClass* component = new SomeClass();
+
+ +

这种模式或多或少地需要客户对组件有一定的了解,至少要知道组件的大小. 类厂设计模式此时可以用来封装对象的构造过程. 类厂模式的目的是在不暴露对象的实现和初始化的前提下创建对象. 在 SomeClass 例子中, 可以按照类厂模式把 SomeClass 对象的构造和初始化封装在 New_SomeInterface 函数中:

+ +

封装构造函数

+ +
int New_SomeInterface(SomeInterface** ret)
+{
+  // create the object
+  SomeClass* out = new SomeClass();
+  if (!out) return -1;
+
+  // init the object
+  if (out->Init() == FALSE)
+  {
+    delete out;
+    return -1;
+  }
+
+  // cast to the interface
+  *ret = static_cast<SomeInterface*>(out);
+  return 0;
+}
+
+ +

类厂本身是一个管理组件实例化的类. 在 XPCOM 中, 类厂要实现 nsIFactory 接口, 它们就象上面的代码一样要使用类厂设计模式来封装对象的构造和初始化.

+ +

封装构造函数 的例子是一个简单的无状态的类厂版本, 实际的编程要复杂一些, 一般的类厂都需要保存状态. 类厂至少应该保存那些对象已经被创建了的信息. 如果类厂管理的实例被存放在一个动态联接库中, 还需要知道什么时候可以卸载这个动态联接库. 当类厂保存了这样的信息, 就可以向类厂查询一个对象是否已经被创建.

+ +

另一个需要保存的信息是关于单件(singleton). 如果一个类厂已经创建了一个单件类型的类, 后续的创建该单件的函数调用将返回已经创建的对象. 尽管有更好的工具和方式来管理单件(在讨论 nsIServiceManager 会看到), 开发人员可能仍然需要通过这种方式来保证只有一个单件对象被创建.

+ +

厂模式可以完全利用函数来做, 状态可以保存在全局变量中; 但是使用类的方式来实现厂模式还有更多的好处. 其一是: 我们可以管理从 nsISupports 接口派生而来的类厂本身的生存期. 当我们试图把多个类厂划分成一组, 然后确定是否能卸载这一组类厂的时候, 这一点非常重要. 另一个好处是: 类厂可以引入其他需要支持的接口. 在我们后面讨论 nsIClassInfo 接口的时候, 我们会看到某些类厂使用这个接口支持信息查询, 诸如这个对象是用什么语言写的, 对象支持的接口等等. 这种派生自 nsISupports 的 "future-proofing" 特性非常关键.

+ +

XPIDL 与类型库

+ +

定义接口的简单而强劲的方法是使用接口定义语言(IDL) - 这实际上是在一个跨平台而语言无关开发环境下定义接口的需求. XPCOM 使用的是源自于 CORBA OMG 接口定义语言(IDL)的变体, 称为 XPIDL, 来定义接口, XPIDL 可以定义接口的方法, 属性, 常量, 以及接口继承.

+ +

采用 XPIDL 定义接口还存在一些缺陷. 它不支持多继承, 同时 XPIDL 定义的方法名不能相同,你不能有两个相同名字但是所接受的参数不同的函数. - 不能像 C++ 语言的成员函数一样通过参数不同重载, 毕竟接口同时要支持类似于 C 这样的语言.

+ +
void FooWithInt(in int x);
+void FooWithString(in string x);
+void FooWithURI(in nsIURI x);
+
+ +

然而尽管有这些问题, XPIDL 的功能仍然是非常强大的. XPIDL 能自动生成以 .xpt 为后缀的类型库, 或者说 typelibs. 类型库是接口的二进制表示, 它向非 C++ 语言提供接口的访问与控制. 非 C++ 语言通过类型库来了解接口支持哪些方法, 如何调用这些方法, 这称为 XPConnect. XPConnect 是 XPCOM 向类似于 JavaScript 这样的语言提供组件访问的 Wrapper. 参看Connecting to Components from the Interface获取更多关于 XPConnect 的信息.

+ +

从其他类型的语言访问接口, 常常说成是接口被反射(reflected)到这种语言. 每一个被反射的接口必须提供相应的类型库. 当前可以使用 C, C++, 和 JavaScript 来编写组件.

+ +
+

使用其他语言编写组件

+ +

在使用其他语言创建组件的时候, 不需要利用 XPCOM 提供给 C++ 程序员的工具(诸如一些宏, 智能指针等等, 我们可以方便的利用到这种语言本身来创建组件. 比如说, 基于 Python 的 XPCOM 组件可以从 JavaScript 来调用.

+ +

参看 Resources 获取更多使用其他语言来创建组件的信息.

+
+ +

所有的 XPCOM 接口都用 XPIDL 语法来定义. xpidl 编译器会从这个 IDL 文件产生类型库和 C++ 头文件. 在Defining the WebLock Interface in XPIDL 一节详细描述了 XPIDL 语法.

+ +

XPCOM 服务

+ +

当客户需要某个组件提供的功能的时候, 通常都是实例化一个新的组件对象. 比如说, 客户程序需要某些处理文件, 这里每个组件就代表一个文件, 客户可能会同时处理多个这样的组件.

+ +

但是在某些情况下对象表示的是一种服务, 这种服务只能有一个拷贝(尽管会有多个服务同时运行). 每次客户程序访问服务提供的功能时, 客户程序都是与同一个服务实例在打交道. 比如说, 一个用户查询公司的电话号码数据库, 数据库作为一个对象对用户来说都是同一的. 如若不然的话, 就需要维护两个数据库拷贝, 这种开销将非常大, 而且还存在数据内容不一致的问题. 单件设计模式就是提供系统中需要的这种单点访问功能.

+ +

XPCOM 不仅提供了对组件的支持和管理服务, 它还包含了许多编写跨平台组件所需要的其他服务. 其中包括: 跨平台文件抽象, 向 XPCOM 开发人员提供同一而强大的文件访问功能. 目录服务, 提供应用和特定系统定位信息. 内存管理, 保证所有对象使用同样的内存分配器. 事件通知机制, 允许传递简单消息. 本教程将在后面展现如何使用这些服务, XPCOM API Reference 一节有完整的接口索引列表.

+ +

XPCOM 类型

+ +

XPCOM 声明了许多数据类型和简单宏, 这些东西将在我们后面的例子中看到. 大多数的宏都是简单的重定义, 下一节我们会描述一些最常用的数据类型.

+ +

方法类型

+ +

下面的类型用在 XPCOM 方法调用的参数和返回值定义中.

+ + + + + + + + + + + + + + + + + + + + + + + + +
NS_IMETHOD声明方法返回值. XPCOM 的方法缺省的返回值声明.
NS_IMETHODIMP方法实现返回值. XPCOM 方法函数返回的时候缺省采用这种类型的返回值.
NS_IMETHODIMP_(type)特定类型的方法实现返回值. 诸如 AddRefRelease 的方法不返回缺省类型, 这种返回值的不一致虽然有点不舒服, 但是必需的.
NS_IMPORT共享库内部使用的符号局部声明
NS_EXPORT共享库导出的符号声明.
+ +

引用计数

+ +

下面的宏提供对引用计数的基本操作.

+ + + + + + + + + + + + + + + + + + + + +
NS_ADDREF调用 nsISupports 对象的 AddRef 方法.
NS_IF_ADDREF与上一个方法类似, 不同之处在于这个宏在AddRef之前会检查对象指针是否为空(虚函数指针).
NS_RELEASE调用 nsISupports 对象的 Release 方法.
NS_IF_RELEASE与上一个方法类似, 不同之处在于这个宏在调用Release之前会检查空指针.
+ +

状态码

+ +

下面的宏测试状态码.

+ + + + + + + + + + + + +
NS_FAILED如果传递的状态码为失败, 则返回真.
NS_SUCCEEDED如果传递的状态码为成功, 则返回真.
+ +

变量映射

+ + + + + + + + + + + + + + + + +
nsrefcnt缺省的引用计数类型, 是一个 32-bit 整数.
nsresult缺省数据类型, 是一个 32-bit 整数.
nsnull缺省 null 类型.
+ +

通用 XPCOM 错误码

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NS_ERROR_NOT_INITIALIZED如果实例未初试化, 返回该值.
NS_ERROR_ALREADY_INITIALIZED如果实例已初试化, 返回该值.
NS_ERROR_NOT_IMPLEMENTED如果方法未实现, 返回该值.
NS_ERROR_NO_INTERFACE如果组件不支持某种类型接口, 返回该值.
NS_ERROR_NULL_POINTER如果指针指向 nsnull, 返回该值 .
NS_ERROR_FAILURE如果某个方法失效, 返回该值, 这时一个通用的错误值.
NS_ERROR_UNEXPECTED如果一个未预料的错误发生, 返回该值.
NS_ERROR_OUT_OF_MEMORY如果无法进行内存分配, 返回该值.
NS_ERROR_FACTORY_NOT_REGISTERED如果一个请求的类型未注册, 返回该值.
+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/building_the_weblock_ui/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/building_the_weblock_ui/index.html new file mode 100644 index 0000000000..51f544fb16 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/building_the_weblock_ui/index.html @@ -0,0 +1,297 @@ +--- +title: Building the WebLock UI +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Building_the_WebLock_UI +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Building_the_WebLock_UI +--- +

+

« 上一页下一页 »

+

+ +

到目前为止我们建立了一个可以安装到Gecko应用中的组件。你所使用的XPCOM接口和工具是通用的跨平台的,可以被Gecko Runtime Environment或者任何Mozilla1.2以后任何基于Gecko的应用(这时GRE已经可用)。

+ +

本章,我们将建立WebLock组件的用户接口,这就意味着添加到现有的 Mozilla 浏览器[other-mozlike-browsers]. 他使用 XUL, 这是一个Gecko知道如何呈现用户界面的XML语言, 同时它也跟特定的Mozilla用户界面交互, 为此它要把自己作为UI的扩展安装起来. Specifically, the user interface we create in this chapter will beoverlaid into the statusbar of the browser component, where it will provide a small icon the user can click to access the web lock interface.

+ +

WebLock Indicator in Browser

+ +

Image:web-lock-ui.png

+ +

User Interface Package List

+ +

本章所描述的用户界面包括4个文件:

+ + + +

下面章节描述每个文件的功能。. In the following chapter we'll describe how you can take these files and create apackage , an installable archive that includes the WebLock component and the new UI.

+ +

因为这些步骤 (特别是 overlay section) 与Mozilla非常相关, the chapter is divided up into a couple of different sections. 第二部分, XUL, 描述XML-based 用户接口语言 (XUL) 以及他如何创建一个对话框访问WebLock 组件和它的服务. 第三部分, Overlaying New User Interface Into Mozilla, 描述如何建立一个overlay到浏览器以便Mozilla build能访问这个对话框. 在overlay section, 我们讨论如何从Mozilla导入scripts, images, 和其他资源到你的 UI, 这会是比较复杂的部分.

+ +

If the WebLock component is being installed in Mozilla or another Gecko-based browser, then this third section shows you how to create the entry point in the browser for controlling the web locking. If you are planning on deploying the WebLock component in some other application, you'll have to devise a different means of access (e.g., native widgetry that instantiates and controls the WebLock component).

+ +

Client Code Overview

+ +

在我们开始实际用户界面以前,我们应该首先建立访问WebLock组件和它的接口来控制browser的Web locking的客户代码.

+ +

首先, it's important to be able to 表达Lock的基本状态as soon as it's loaded. 如同安全网页icon, weblock icon 在browser右下角,提示browser是否当前是锁定的. Since the WebLock component is always initialized as unlocked, we can have the 客户代码 - 接口中的JavaScript代码 - 表达并跟踪状态 as the user manipulates the iWebLock interface. A boolean wLocked variable can do this:

+ +
// initialize the wLocked variable as unlocked
+var wLocked = 0;
+
+ +

Then the functions that get called from the interface and call through to the lock and unlock methods of the WebLock component must also adjust this variable accordingly:

+ +
function wLock()
+{
+  // check to see if locking is on or off
+  weblock.lock();
+  wLocked = 1;
+}
+
+function wUnLock()
+{
+  // check to see if locking is on or off
+  weblock.unlock();
+  wLocked = 0;
+}
+
+ +

这些函数的前提是WebLock 组件对于 JavaScript可见,in the form of the weblock object being used in the snippets above. As you can see, weblock is initialized as a global JavaScript variable, available in the scope of these functions and others:

+ +
var weblock = Components.classes["@dougt/weblock"]
+                        .getService()
+                        .QueryInterface(Components.interfaces.iWebLock);
+
+ +

In addition to this basic setup, you must also write JavaScript that uses the AddSite method to add new sites to the white list. This is a bit more complicated, because it requires that you work with the currently loaded page or provide other UI (e.g., a textfield where you can enter an arbitrary URL) for specifying URLs. In the XUL section we'll go into how the user interface is defined. This section describes the functions that are called from the interface and how they interact with the WebLock component.

+ +

The URL that the AddSite method expects is a string, so we can pass a string directly in from the user interface, or we can do a check on the string and verify that it's a valid URL. In this tutorial, focusing as it is on the WebLock functionality (rather than the UI), we'll assume the strings we get from the UI itself are URLs we actually want to write to the white list:

+ +
function addThisSite()
+{
+  var tf = document.getElementById("dialog.input");
+  // weblock is global and declared above
+  weblock.AddSite(tf.value);
+}
+
+ +

这段javascript可以直接被 XUL widget调用, where the input string is retrieved as the value property of the textbox element.

+ +

你还需要建立一个函数当用户点击weblock icon的时候来显示WebLock 窗口. That function uses the openDialog method from the window object and takes the URL to the XUL file in which the dialog is defined:

+ +
function loadWebLock()
+{
+  window.openDialog("chrome://weblock/weblock.xul");
+}
+
+ +

XUL

+ +

The entire user interface of the Mozilla browser and all of the applications that go with it, including the mail client, the IRC client, and others, have been defined in an XML language called XUL. Elements in the XUL markup map to widgets in the interface that Gecko renders in a fairly straightforward way - so, for instance, the root element of an application window is the element <window/>, the root element of the dialog we'll be creating here is <dialog/>, and so forth. Within a XUL application file, elements like <button/>, menu/>, and checkbox/> can be hooked up to an event model, to scripts, and to the XPCOM interfaces that carry out a lot of the browser functionality in Mozilla.

+ +

In Using XPCOM Components you saw how XPCOM objects are reflected into the interface layer as JavaScript objects. In this chapter, now that we've created the WebLock component and made it available to XPCOM, we create the UI that actually instantiates the WebLock component and uses its methods to control page loading in the browser.

+ +

In the previous section, we outlined the JavaScript that interacts with the WebLock component. In this section, we are going to create the XUL interface that calls the JavaScript methods when the user interacts with it.

+ +

The XUL Document

+ +

The first thing to do is create the actual XUL document in which the user interface for the dialog and the events that initiate interaction with the web locking are defined. At the top of all XUL documents, an XML declaration is followed by the root element for the document, which is usually <window/> 对于对话框,也可以是<dialog/>. The "shell" for the XUL file, then, looks like this:

+ +
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<dialog id="weblock_ui"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Web Lock Manager"
+        persist="screenX screenY"
+        screenX="24" screenY="24">
+
+</dialog>
+
+ +

注意这部分XUL文件也包含了stylesheet declaration, which imports CSS rules and applies them to particular parts of the interface. In Gecko, CSS 被用来几乎控制所有的XUL界面表现 - its color, position, style, and to some extent its behavior as well. The web lock manager dialog does not deviate from the look of a standard dialog, so it can use a single declaration to import the "global" skin from the browser and make it available to the widgets you define in weblock.xul.

+ +

You can save this first, 最外层的web lock dialog部分称为weblock.xul, 你要把它放在附录B所描述的安装包里.

+ +
+

注意这个文件包含了当用户/管理员点击web locking icon的时候弹出的对话框. 这部分UI - 需要动态地装载到Mozilla runtime - 在Overlaying New User Interface Into Mozilla.

+
+ +

描述

+ +

最终的对话框看起来是.

+ +

Web Lock Manager Dialog

+ +

Image:Weblock-sitelist-ui.png

+ +

As you can see, it's a simple interface, providing just enough widgetry to lock and unlock the browser and to add new sites to the list. The entire XUL file for the web lock manager dialog is defined in weblock.xul below.

+ +

The Locking UI

+ +

Once you have the basic XUL wrapper set up for your interface, the next step is to define that part of the interface that locks and unlocks the browser. One of the most efficient ways to expose this is to use radio buttons, which allow the user to toggle a particulart state, as the figure above illustrates.

+ +

In XUL individual <radio/> elements are contained within a parent element called <radiogroup/>. Grouping radio elements together creates the toggling UI by requiring that one or another of the elements be selected, but not both.

+ +

The XUL that defines the radiogroup in the web lock manager dialog is this:

+ +
<radiogroup>
+   <radio label="lock"/>
+   <radio label="unlock" selected="true"/>
+</radiogroup>
+
+ +

Since the WebLock component always starts up in the unlocked position, you can add the selected="true" attribute and value on the unlock radio button and reset it dynamically as the user takes action.

+ +

Site Adding UI

+ +

The next step is to create that part of the user interface that lets you add a new site to the white list. There are other, more sophisticated ways to do this; you may also want to include some UI that lets you view the white list or edit it as a list. In this part of the tutorial, however, we only provide the means of adding an URL provided as a string (which is not checked for validity) and passing it through to the AddSite API we defined in the earlier part of the tutorial.

+ +
<separator class="thin"/>
+
+<hbox align="center">
+  <textbox id="url.input" flex="1"/>
+  <button label="Add this URL" oncommand="addThisSite();"/>
+</hbox>
+
+ +

This snippet introduces a couple of new general layout widgets in XUL. The separator that appears at the top of this snippet creates a little divider between widgets like the kind you see in menus that divide sets of functionality available there. The parent of the textbox that users enter an URL into is something called an <hbox/>, which is a layout widget - often invisible - that controls the way its child elements are rendered. In this case the <hbox/> centers the textbox and the button children, and it orients them horizontally (in contrast to the <vbox/>, which orients its children vertically).

+ +

Notice also that when it's clicked, the button executes a JavaScript function called addThisSite(), which we've already defined in the weblock.js file in Client Code Overview above.

+ +

weblock.xul

+ +
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<dialog id="weblock_mgg"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	title="Web Lock Manager"
+        style="width: 30em;"
+        persist="screenX screenY"
+        screenX="24" screenY="24">
+
+  <script src="chrome://weblock/content/weblock.js"/>
+
+  <hbox>
+    <separator orient="vertical" class="thin"/>
+    <vbox flex="1">
+      <separator class="thin"/>
+      <hbox align="center">
+        <textbox id="dialog.input" flex="1"/>
+        <button label="Add this URL"
+                oncommand="addThisSite();"/>
+      </hbox>
+      <hbox align="center">
+        <radiogroup onchange="toggleLock();">
+          <radio label="lock"/>
+          <radio label="unlock"/>
+        </radiogroup>
+        <spacer flex="1"/>
+      </hbox>
+    </vbox>
+  </hbox>
+
+</dialog>
+
+ +

Overlaying New User Interface Into Mozilla

+ +

你已经有了一个可以跟WebLock组件交互的对话框, 但是你怎么把它装到browser中? 然后你怎么访问它呢? 当安装和准备好以后,WebLock 组件已经可以用了: XPCOM finds it and adds it to the list of registered components, and then WebLock observes the XPCOM startup event and initializes itself.

+ +

But you still have to add your new UI into the browser so it can call the component, and the Mozilla overlay mechanism is the way to do this. Overlays 是 XUL文件可以用来注册他们自己以便动态地嵌入到Browser UI合适的位置.

+ +

webLockOverlay.xul

+ +

The XUL that defines the new icon is small: 这是一个调用JavaScript function来装载前面我们定义的weblock.xul 文件的小图表. The icon is actually a separate <statusbarpanel/> element that gets overlaid into the main browser, along with some JavaScript and some CSS to control the behavior and appearance of the element, respectively. Here is that XUL file in its entirety:

+ +

The WebLock Overlay

+ +
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://navigator/content/weblock.css" type="text/css"?>
+
+<overlay id="weblockOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <script type="application/x-javascript"
+          src="chrome://weblock/content/weblock.js"/>
+
+  <statusbar id="status-bar">
+    <statusbarpanel class="statusbarpanel-iconic"
+                    id="weblock-status"
+                    insertbefore="offline-status"
+                    oncommand="loadWebLock();"
+                    status="none"/>
+  </statusbar>
+
+</overlay>
+
+ +

文件的根元素不是<window/> 而是<overlay/>. In overlays 被 XUL elements用来把他们和其他元素相区分的id属性被设置称为browser中他们要嵌入部分的值. In this case, the weblock <statusbarpanel/> appears as a child of the <statusbar/> element with id "status-bar". This id is the same one used by the <statusbar/> in navigator.xul, which means that the overlay mechanism will merge the new UI here (i.e., the weblock statusbarpanel) and the UI already defined within that browser <statusbar/> at runtime.

+ +

Other Resources

+ +

这部分描述剩下的需要添加和打包到WebLock组件来提供web locking用户界面的文件。

+ +
+

Other Front End Resources

+ +

在某些UI包中, 本地化 resources are also defined. These include DTDs in which the language in which the UI is labelled can be extracted into external files, which are swapped with DTDs for other languages. For example, user interface packages often include an English DTD that defines labels and strings for button and menus and other elements in the interface. When the user selects a differentlanguage pack , all of the English that's been externalized in these files is dynamically replaced with the new choice. In addition to DTDs, the localization parts of a user interface may also include string bundles in which strings that are used in the interface JavaScript can be similarly replaced. 有一些技术通过单独的文件来提供这种功能. 包含bindings in XML files,metadata in RDF files, whole collections of CSS files calledskins , and others.

+
+ +

weblock.css

+ +

The following style rules are defined in weblock.css, a CSS file that is loaded by the overlay and applied to the icon in the browser that reflects the current status of the web lock and provides access to the web lock manager dialog.

+ +
statusbarpanel#weblock-status
+{
+  list-style-image: url("chrome://weblock/wlock.gif");
+}
+
+statusbarpanel#weblock-status[status="locked"]
+{
+  list-style-image: url("chrome://weblock/wl-lock.gif");
+}
+
+statusbarpanel#weblock-status[status="unlocked"]
+{
+  list-style-image: url("chrome://weblock/wl-un.gif");
+}
+
+ +

The style rules are distinguished by the state of the status attribute on the element in the XUL with the id "weblock-status." As you can see above, when the status of the element is set to "locked", the image wl-lock.gif is used to show the state, and when the web locking is unlocked, it uses wl-un.gif. (Note: We include three images to represent the state of the weblock, but wlock.gif and wl-lock.gif are identical, since weblock is presumed to be unlocked when it's loaded. This tutorial makes use of only two different states, but you can further customize the look of the weblock using the three images if you wish.)

+ +

Since the presentation of the weblock manager dialog itself doesn't require any special styles, these are all the rules you need in the weblock.css. Note that the weblock.xul file in which the manager is defined imports only the global skin:

+ +
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+ +

Save weblock.css in your working directory.

+ +

You should now have the four files listed at the top of this chapter as the "packing list" for the WebLock package (see User Interface Package List). Don't worry for now about where these files are. 下一章, Packaging WebLock, 我们讨论如何打包这些文件以便 WebLock 组件或者别的资源利用它们.

+ +

Image Resources

+ +

如果你学习本教程并且希望使用WebLock组件在statusbar中的图片,你可以从 http://www.brownhen.com/weblock下载他们和其他weblock相关资源. The GIF files that represent the various states are:

+ + + +
    +
  1. Note: other-mozlike-browsers
    或者你可能会很喜欢这些东西. 还有一些基于 Gecko的browsers ,例如Beonex 和 IBM Web Browser 也会共享很多Mozilla用户界面成分, 你也可能装载 WebLock 组件和用户界面到其中. 不过请注意, WebLock有可能还不能保证完全安装到Mozilla Firefox,因为firefox有一些新的变化 (这本书是2003的版本).
  2. +
+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/component_internals/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/component_internals/index.html new file mode 100644 index 0000000000..d29da9a71d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/component_internals/index.html @@ -0,0 +1,217 @@ +--- +title: Component Internals +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Component_Internals +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Component_Internals +--- +

+

« 上一页下一页 »

+
前几章以组件使用者的角度介绍了XPCOM 组件, 本章将以软件开发者的角度讨论XPCOM.您可以继续阅读以明白XPCOM的一般实现方式, 或者您也可以跳到下一章, 在下一章,以WebLock为例向一步一步您介绍 组件的开发过程。 XXX mediawiki...XXX sucks

+ +

使用C++创建组件

+ +

让我们开始研究怎样用c++创建XPCOM组件. 最常见的组件是以C++编写并编译成共享库(如Windows平台的DLL或者Unix平台的DSO)。

+ +

The illustration below shows the basic relationship between the shared library containing the component implementation code you write and the XPCOM framework itself. In this diagram, the outer boundary is that of the module, the shared library in which a component is defined.

+ +

A Component in the XPCOM Framework

+ +

Image:component-internals-framework.png

+ +

When you build a component or module and compile it into a library, it must export a single method named NSGetModule. This NSGetModule function is the entry point for accessing the library. It gets called during registration and unregistration of the component, and when XPCOM wants to discover what interfaces or classes the module/library implements. In this chapter we will outline this entire process.

+ +

As A Component in the XPCOM Framework illustrates, in addition to the NSGetModule entry point, there are nsIModule and nsIFactory interfaces that control the actual creation of the component, and also the string and XPCOM glue parts, which we'll discuss in some detail in the next section (see XPCOM Glue). These latter supply ease-of-development utilities like smart pointers, generic modules support, and simple string implementations. The largest and possibly most complex part of a component is the code specific to the component itself.

+ +
+

But Where Are the Components?

+ +

Components reside in modules, and those modules are defined in shared library files that typically sit in the components directory of an XPCOM application.

+ +

A set of default libraries stored in this components directory makes up a typical Gecko installation, providing functionality that consists of networking, layout, composition, a cross-platform user interface, and others.

+ +

Another, even more basic view of this relationship of components to the files and interfaces that define them is shown in Onion Peel View of XPCOM Component Creation in the next chapter. The component is an abstraction sitting between the actual module in which it is implemented and the objects that its factory code creates for use by clients.

+
+ +

XPCOM Initialization

+ +

To understand why and when your component library gets called, it is important to understand the XPCOM initalization process. When an application starts up, that application may initialize XPCOM. The sequence of events that kicks off this XPCOM initialization may be triggered by user action or by the application startup itself. A web browser that embeds Gecko, for example, may initialize XPCOM at startup through the embedding APIs. Another application may delay this startup until XPCOM is needed for the first time. In either case, the initialization sequence within XPCOM is the same.

+ +

XPCOM starts when the application makes a call to initialize it. Parameters passed to this startup call allow you to configure some aspects of XPCOM, including the customization of location of specific directories. The main purpose of the API at this point is to change which components directory XPCOM searches when it looks for XPCOM components. This is how the API is used, for example, in the Gecko Runtime Environment (GRE).

+ +
+

XPCOM Startup

+ +

The six basic steps to XPCOM startup are as follows:

+ +
    +
  1. Application starts XPCOM.
  2. +
  3. XPCOM sends a notification that it's beginning startup.
  4. +
  5. XPCOM finds and processes the component manifest (see Component Manifests below).
  6. +
  7. XPCOM finds and processes the type library manifest (see Type Library Manifests below).
  8. +
  9. If there are new components, XPCOM registers them: +
      +
    1. XPCOM calls autoregistration start.
    2. +
    3. XPCOM registers new components.
    4. +
    5. XPCOM calls autoregistration end.
    6. +
    +
  10. +
  11. Complete XPCOM startup: XPCOM notifies that it's begun.
  12. +
+ +

Component manifests and type library manifests are described in the following section, XPCOM Registry Manifests.

+
+ +

XPCOM Registry Manifests

+ +

XPCOM uses special files called manifests to track and persist information about the components to the local system. There are two types of manifests that XPCOM uses to track components:

+ +
Component Manifests
+ +

When XPCOM first starts up, it looks for the component manifest, which is a file that lists all registered components, and stores details on exactly what each component can do. XPCOM uses the component manifest to determine which components have been overridden. Starting with Mozilla 1.2, this file is named compreg.dat and exists in the components directory, but there are efforts to move it out of this location to a less application-centric (and thus more user-centric) location. Any Gecko-based application may choose to locate it elsewhere. XPCOM reads this file into an in-memory database.

+ +
+

Component Manifests

+ +

The component manifest is a mapping of files to components and components to classes. It specifies the following information:

+ + + +

The component manifest maps component files to unique identifiers for the specific implementations (class IDs), which in turn are mapped to more general component identifiers (contract IDs).

+
+ +
Type Library Manifests
+ +

Another important file that XPCOM reads in is the type library manifest file. This file is also located in the components directory and is named xpti.dat. It includes the location and search paths of all type library files on the system. This file also lists all known interfaces and links to the type library files that define these interface structures. These type library files are at the core of XPCOM scriptablity and the binary component architecture of XPCOM.

+ +
+

Type Library Manifests

+ +

Type library manifests contain the following information:

+ + +
+ +

Using the data in these two manifests, XPCOM knows exactly which component libraries have been installed and what implementations go with which interfaces. Additionally, it relates the components to the type libraries in which the binary representations of the interfaces they support are defined.

+ +

The next section describes how to hook into the XPCOM startup and registration process and make the data about your component available in these manifests, so that your component will be found and registered at startup.

+ +

Registration Methods in XPCOM

+ +
+

What Is XPCOM Registration?

+ +

In a nutshell, registration is the process that makes XPCOM aware of your component(s). As this section and the next describe, you can register your component explicitly during installation, or with the regxpcom program, or you can use the autoregistration methods in the Service Manager to find and register components in a specified components directory:

+ + + +

The registration process is fairly involved. This section introduces it in terms of XPCOM initialization, and the next chapter describes what you have to do in your component code to register your component with XPCOM.

+
+ +

Once the manifest files are read in, XPCOM checks to see if there are any components that need to be registered. There are two supported ways to go about registering your XPCOM component. The first is to use XPInstall, which is an installation technology that may or may not come with a Gecko application and provides interfaces for registering your component during installation. Another, more explicit way to register your component is to run the application regxpcom, which is built as part of Mozilla and is also available in the Gecko SDK. regxpcom registers your component in the default component registry.

+ +

A Gecko embedding application may also provide its own way of registering XPCOM components using the interface that is in fact used by both XPInstall and regxpcom, nsIComponentRegistrar. An application, for example, could provide a "registration-less" component directory whose components are automatically registered at startup and unregistered at shutdown. Component discovery does not currently happen automatically in non-debug builds of Gecko, however.

+ +

When the registration process begins, XPCOM broadcasts to all registered observers a notification that says XPCOM has begun the registration of new components. After all components are registered, another notification is fired saying that XPCOM is done with the registration step. The nsIObserver interface that handles this notification is discussed in Starting WebLock.

+ +

Once registration is complete and the notifications have fired, XPCOM is ready to be used by the application. If XPCOM registered your component, then it will be available to other parts of the XPCOM system. The XPCOM Initialization section in this chapter describes registration in more detail.

+ +

Autoregistration

+ +

The term autoregistration is sometimes used synonymously with registration in XPCOM. In the What Is XPCOM Registration? note, we describe the three ways you can register components with XPCOM. Sometimes, applications use the nsIComponentRegistrar interface and create their own code for watching a particular directory and registering new components that are added there, which is what's often referred to as autoregistration. You should always know what the installation and registration requirements are for the applications that will be using your component.

+ +

The Shutdown Process

+ +

When the application is ready to shutdown XPCOM, it calls NS_ShutdownXPCOM. When that method is called, the following sequence of events occurs:

+ +
    +
  1. XPCOM fires a shutdown notification to all registered observers.
  2. +
  3. XPCOM closes down the Component Manager, the Service Manager and associated services.
  4. +
  5. XPCOM frees all global services.
  6. +
  7. NS_ShutdownXPCOM returns and the application may exit normally.
  8. +
+ +
+

The Unstoppable Shutdown

+ +

Note that shutdown observation is unstoppable. In other words, the event you observe cannot be used to implement something like a "Are you sure you want to Quit?" dialog. Rather, the shutdown event gives the component or embedding application a last chance to clean up any leftovers before they are released. In order to support something like an "Are you sure you want to quit" dialog, the application needs to provide a higher-level event (e.g., startShutdown()) which allows for cancellation.

+ +

Note also that XPCOM services may deny you access once you have received the shutdown notification. It is possible that XPCOM will return an error if you access the nsIServiceManager at that point, for example, so you may have to keep a reference-counted pointer to the service you are interested in using during this notification.

+
+ +

Component Loaders

+ +

Components can be written in many languages. So far this book has been focusing on "native components," shared libraries exporting a NSGetModule symbol. But if there is a component loader for Javascript installed, then you can also write a JavaScript component.

+ +

To register, unregister, load and manage various component types, XPCOM abstracts the interface between the XPCOM component and XPCOM with the Component Loader. This loader is responsible for initialization, loading, unloading, and supporting the nsIModule interface on behalf of each component. It is the Component Loader's responsibility to provide scriptable component support.

+ +

When building a "native" component, the component loader looks for an exported symbol from the components shared library. "Native" here includes any language that can generate a platform native dynamically loaded library. Scripting languages and other "non-native" languages usually have no way to build native libraries. In order to have "non-native" XPCOM components work, XPCOM must have a special component loader which knows how to deal with these type of components.

+ +

XPConnect, for example, provides a component loader that makes the various types, including the interfaces and their parameters, available to JavaScript. Each language supported by XPCOM must have a component loader.

+ +

Three parts of a XPCOM Component Library

+ +

XPCOM is like an onionor a parfait! Everybody likes parfaits. XPCOM components have at least three layers. From the innermost and moving outward these layers include:

+ + + +

The core XPCOM object is the object that will implement the functionality you need. For example, this is the object that may start a network download and implement interfaces that will listen to the progress. Or the object may provide a new content type handler. Whatever it does, this object is at the core of the XPCOM component, and the other layers are supporting it, plugging it into the XPCOM system. A single library may have many of these core objects.

+ +

One layer above the core object is the factory code. The factory object provides a basic abstraction of the core XPCOM object. An Overview of XPCOM discussed the factory design pattern that's used in a factory object. At this layer of the XPCOM Component Library, the factory objects are factories for the core XPCOM objects of the layer below.

+ +

One more layer outward is the module code. The module interface provides yet another abstraction - this time of the factories - and allows for multiple factory objects. From the outside of the component library, there is only the single entry point, NSGetModule(). This point of entry may fan out to any number of factories, and from there, to any number of XPCOM objects.

+ +

The factory design pattern in XPCOM is represented by the nsIFactory interface. The module layer is represented by the nsIModule interface. Most component libraries only need these two interfaces, along with the nsISupports interface, to have XPCOM load, recognize, and use their core object code.

+ +

In the next section, we'll be writing the code that actually compiles into a component library, and you will see how each layer is implemented and how each interface is used. Following this initial, verbose demonstration of the APIs, we will introduce a faster more generic way of implementing the module and factory code using macros, which can make components much easier to create.

+ +

XPCOM Glue

+ +

XPCOM contains a lot of stuff. Most XPCOM interfaces are not frozen and are only meant to be used by the Gecko internals and not by clients. XPCOM provides many data structures from linked lists to AVL trees. It's tempting to reuse nsVoidArray or another publicly available class instead of writing your own linked list, but this may prove to be a fatal mistake. The class can change at any time and give you unexpected behavior.

+ +

XPCOM makes for a very open environment. At runtime you can acquire any service or component by merely knowing a CID or Contract ID along with an IID. At last count there were over 1300 interfaces defined in XPIDL. Of those 1300 interfaces, less than 100 were frozen, which means that a developer is likely to stumble upon useful interfaces that aren't frozen. Unless an interface is explicitly marked "FROZEN" in the IDL comments, your component may possibly break or crash along with a version change.

+ +

The Glue Library

+ +

In general, you should avoid any interfaces, symbols in XPCOM, or other part of Gecko libraries that aren't frozen. However, there are some unfrozen tools in XPCOM that are used so often they are practically required parts of component programming.

+ +

The smart pointer class, nsCOMPtr, for example, which makes reference counting less tedious and error-prone, is not actually frozen, and neither is nsDebug, a class for aiding in tracking down bugs, nor is nsMemory, a class to ensure that everyone uses the same heap, generic factory, and module. Instead of asking every developer to find and copy these various files into their own application, XPCOM provides a single library of "not-ready-to-freeze-but-really-helpful" classes that you can link into your application, as the following figure demonstrates.

+ +

XPCOM Glue and Tools

+ +

Image:xpcom-glue-tools.png

+ +

This is the glue library. It provides a bridge, or "glue" layer, between your component and XPCOM.

+ +

A version of the glue library is built into XPCOM, and when your component uses it, it links a snapshot of this library: it includes a copy of these unfrozen classes directly, which allows the XPCOM library version to change without affecting the software. There is a slight footprint penalty to linking directly, but this gives your component freedom to work in any recent environment. If footprint is a big issue in your component or application, you can trim out the pieces you don't need.

+ +

XPCOM String Classes

+ +

The base string types that XPCOM uses are nsAString and nsACString. These classes are described in the Mozilla String Guide (see Gecko Resources).

+ +

The string classes that implement these abstract classes are another set of helpful, unfrozen classes in XPCOM. Most components and embedding applications need to link to some string class or other in order to utilize certain Gecko APIs, but the string code that Mozilla uses is highly complex and even more expensive than the glue code in terms of footprint (~100k). nsEmbedString and nsEmbedCString are available as very lightweight string implementations for component development, especially in small embedded applications. This string implementation does the bare minimum to support the nsAString/nsACString functionality.

+ +

In your own component, you can go "slim" and restrict yourself to the nsEmbedString or go "hog wild" and use any of the the other strings. WebLock restricts itself to using the simple nsEmbedString family of classes.

+ +

String Classes and XPCOM

+ +

Image:strings-in-xpcom.png

+ +

The glue library provides stub functions for the public functions that XPCOM provides (see xpcom/build/nsXPCOM.h). When the glue library is initialized, it dynamically loads these symbols from the XPCOM library, which allows the component to avoid linking directly with the XPCOM library. You shouldn't have to link to the XPCOM library to create a XPCOM component - in fact, if your component has to, then something is wrong.

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/creating_the_component_code/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/creating_the_component_code/index.html new file mode 100644 index 0000000000..a4aa535eca --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/creating_the_component_code/index.html @@ -0,0 +1,727 @@ +--- +title: Creating the Component Code +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Creating_the_Component_Code +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Creating_the_Component_Code +--- +

 

+ +

+

« 上一页下一页 »

+

+ +

这一章叙述处理你的组件和XPCOM之间关联的基本代码。让组件被找到和注册是这个章节的目的。在后续章节中,我们开始建立WebLock组件本身的功能。

+ +

注:有些部分采用英汉对照的方式。避免翻译的不准确!

+ +
+

Use the Calculator (After Learning Long Division)

+ +

You have to write a fair amount of code to create a component library that gets loaded into XPCOM. 一个XPCOM组件起码要实现三个XPCOM要求的接口, 通常还有其他一些. 这一章包含了可能你不会需要的更多代码,不过Using XPCOM Utilities to Make Things Easier会教你一些更简单和优雅的使用通用宏建立XPCOM组件的方式, 本章主要讲述基本的内容。 As in grade school when you learned long division, better tools like calculators come after you figure out what's actually happening. In this case, the long-hand implementation gives us an opportunity to talk about various features of XPCOM.

+
+ +

What We'll Be Working On

+ +

The component we'll be working on in this book controls a special mode in your browser that prevents users from leaving the current domain or a set of safe domains. Once enabled, this weblock mode is password protected and persists until it is turned off by the password holder. It can be used to make the browser into a safe viewer for children, or for targeted "kiosk browsing," where the content is restricted to a particular server. Web Lock User Interface shows the icon that is used to activate the web lock mode (leftmost in the status bar) once you have installed the WebLock component and the extra user interface.

+ +

 接下来的内容

+ +

文章后续的内容,将向读者描述一个使浏览器处在受控模式(web lock mode)的组件,该组件采用密码保护的方式防止用户从当前域或者一组安全的域中离开。这个组件可以使用在为未成年人提供受限内容或者是在一些小型电子浏览器中防止页面跳出特定服务内容。在用户安装了WebLock组件和额外的用户接口后,在状态栏的最左边,如图Web Lock User Interface,可以用图标来激活受控模式(web lock mode)

+ +

Web Lock User Interface

+ +

Image:web-lock-ui.png

+ +

实际上组件WebLock做的大多数事情是准备组件本身,找到需要的XPCOM接口, 并且挂接到现有的Gecko Browser功能.

+ +

Component Registration 组件注册

+ +

All XPCOM components - whether they're stored in shared libraries (DLLs, DSOs or dylibs), JavaScript files, or some other file - need to be registered before they can be used. Registration is a process that happens in all XPCOM applications, whether they're embedded Gecko clients, Mozilla, Netscape 7, Compuserve, or any other software that uses XPCOM. Registration provides the information that applications need in order to use components properly.

+ +

所有的XPCOM 组件- 无论是存储在shared libraries (DLLs, DSOs 还是 dylibs), JavaScript文件,或者其他文件 - 使用前需要被注册. 使用XPCOM的Gecko clients, Mozilla, Netscape 7, Compuserve, 或者其他程序,都需要注册,才能获得合适的组件信息。

+ +

The WebLock component must do a number of things to register itself. Specifically, the component library has to contain implementations for the component-related interfaces described in this chapter: nsIModule and nsIFactory, which are entry points for your implementation code.

+ +

想要注册 WebLock 组件必须做许多事情. 特别是, 组件库需要包含本章介绍的组件定义的接口: nsIModule and nsIFactory, 这是你的代码入口.

+ +

Once your component implements these interfaces, the rest of the registration process itself is simple. Applications typically use regxpcom, described in the next section.

+ +

如果你的组件实现了这些接口,注册将变的很容易. 应用中通常使用regxpcom注册, 在下一节描述.

+ +

regxpcom 程序

+ +

一个明确的注册组件方法是运行regxpcom. 不带任何参数启动regxpcom时, 程序把组件注册在缺省的组件注册表. 我们建议你如果是运行应用, 你可以拷贝你的组件到对应程序安装目录下的components目录. 拷贝好以后,运行regxpcom将注册包含你的组件在内的所有那个目录中的组件.

+ +

regxpcom在1.4 或更高版本有一些新的参数. 参看 regxpcom 加<code>-h 选项。

+ +

另外的注册方法

+ +

Gecko embedding 应用可能提供其他注册组件的方法. XPInstall, 是一个跨平台的安装技术,Mozilla用来安装浏览器和其他组件,这是一个选择。参看Packaging WebLock. 你可以询问你想要扩展的应用的作者看是否有其他扩展方法.

+ +

WebLock Module 源代码概览

+ +

As we mentioned in the previous section, components have layers. There are three main parts to every XPCOM component. From the innermost and moving outward, the first object is the XPCOM object. This is the object that contains the business logic, that implements functionality such as starting a network download, implementing interfaces that listen to the download progress, or providing a new content type handler. In Weblock, this is the part that brings together various Gecko services and prevents users from leaving the list of acceptable domains. In a way, the factory and module layers are glue to plug the XPCOM object into the larger XPCOM system.

+ +

在前面的章节我们提到,组件是分层的.每一个XPCOM组件都有三部分.从内到外, 第一个对象是XPCOM对象. 这个对象包含了交互逻辑, 负责载入network, 执行一个监听载入过程或新content type的接口。. 在Weblock中, 这部分综合了各种Gecko服务并且防止用户离开允许的一些domain. In a way, the factory and module layers are glue to plug the XPCOM object into the larger XPCOM system.

+ +

One layer above the object itself is the nsIFactory object. This object provides basic abstraction of the XPCOM object itself. As you can see in Onion Peel View of XPCOM Component Creation , the main accessor for the XPCOM object is CreateInstance, which is expected to return the object that matches a given CID and IID pair.

+ +

XPCOM的上层是 nsIFactory 对象. nsIFactory是对XPCOM的基本抽象. 如同你在 Onion Peel View of XPCOM Component Creation中看到的, 通过CreateInstance与XPCOM对象进行交互, 返回一个匹配给定的CID 和IID 的两个对象.

+ +

Moving another layer outward is the nsIModule. This interface provides yet another abstraction of the nsIFactory object, and may allow for multiple nsIFactory objects. The key to this interface is that the return type of getClassObject does not have to be an nsIFactory. Instead, the nsIModule can ask for implementation details about the XPCOM object. This is very useful if the caller is required to know information about the component like its threading module, whether or not it's a singleton, its implementation language, and so forth. The interface used in this case is nsIClassInfo. Starting from the outside in, Onion Peel View of XPCOM Component Creation represents the sequence for constructing an XPCOM object.

+ +

最外层是nsIModule对象. 他提供了对nsIFactory 的进一步抽象, 而且可能允许多个nsIFactory对象. 关键点是这个接口的方法getClassObject返回的不一定非要是nsIFactory. nsIModule 也可以用来询问 XPCOM 对象的细节. This is very useful if the caller is required to know information about the component like its threading module, whether or not it's a singleton, its implementation language, and so forth. 这是可以使用接口nsIClassInfo. 从外到内, Onion Peel View of XPCOM Component Creation 表示了建立XPCOM对象的顺序.

+ +

Onion Peel View of XPCOM Component Creation

+ +

Image:xpcom-is-an-onion.png

+ +

Before we begin looking at the various parts of the component and how they'll be implemented in the source, let's look at the module in weblock.cpp as a whole to see where we're going. The source we're referring to is listed in its entirety at the end of this chapter (see webLock1.cpp).

+ +

WebLock 组件的源代码包含三个类. 为了让WebLock组件工作在 Mozilla中, 你要为WebLock组件建立一个接口, iWebLock, where the actual work specific to the the web locking features happens. 建立 WebLockModule 实现nsIModule接口, 你也要建立 WebLockFactory实现 nsIFactory来建立一个为你的客户处理组件实例的工厂. These three interface implementations - of the component functionality, of the nsIModule interface, and of the nsIFactory interface that creates and manages instances for clients - are the basic sets of code you need to write to create an XPCOM component.

+ +
+

Basic Structure of the WebLock Component Source

+ +

The weblock1.cpp source file that defines these classes and the code you need to create a basic component has the following structure:

+ +
   * required includes and constants
+   * WebLock: public iWebLock
+   * WebLockFactory: public nsIFactory
+   * WebLockModule: public nsIModule
+
+ +

在XPCOM中, 所有这些类要实现 nsISupports.

+
+ +

更进一步: 需要的 Includes and Constants

+ +

Let's take a look at the first several lines of code in the component and discuss what they mean in XPCOM. The includes and definitions at the top of an XPCOM source file can give you an idea about some of the data types and techniques we'll be discussing more in the upcoming chapters.

+ +

介绍一下XPCOM的component代码里面前几行的意思。

+ +

例如,MOZILLA_STRICT_API是一个变量,它用来遮蔽某些私有的、非XPCOM的头文件。 For example, MOZILLA_STRICT_API is a variable that shields you from certain private, non-XPCOM headers. For example, including nsIComponentManager.idl without MOZILLA_STRICT_API defined will include the following headers, which are not supported across versions (unfrozen):

+ + + +

These variables are picked up by files that do not specify themselves as MOZILLA_STRICT_API.

+ +

Includes and Constants in weblock1.cpp

+ +
#include <stdio.h>
+
+// may be defined at the project level
+// in the makefile
+#define MOZILLA_STRICT_API
+
+#include "nsIModule.h"
+#include "nsIFactory.h"
+
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+
+// use classes to handle IIDs
+// classes provide methods for comparison: Equals, etc.
+static const nsIID kIModuleIID   = NS_IMODULE_IID;
+static const nsIID kIFactoryIID   = NS_IFACTORY_IID;
+static const nsIID kISupportsIID = NS_ISUPPORTS_IID;
+static const nsIID kIComponentRegistrarIID = NS_ICOMPONENTREGISTRAR_IID;
+
+
+// generate unique ID here with uuidgen
+#define SAMPLE_CID \
+{ 0x777f7150, 0x4a2b, 0x4301, \
+{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}}
+
+static const nsCID kSampleCID = SAMPLE_CID;
+
+ +

nsIModule.h and nsIFactory.h are required to build your module successfully. They define the module and factory interfaces, and they contain a couple of important macros as well (see the following chapter for information about using these macros). The two other includes, nsIComponentManager.h and nsIComponentRegistrar.h, provide functions such as RegisterFactoryLocation that are required to implement the module and factory classes in your code.

+ +

标识符 in XPCOM

+ +

一组 nsIID 变量实际上是一些处理XPCOM用来支持客户和组件之间关系的128-bit标识符. The variable kIFactoryIID, for example, provides methods like Equals() that can be used to facilitate comparisons in the code, as in the following example from the Mozilla source:

+ +

Using Class Methods to Handle Identifiers

+ +
if (aIID.Equals(NS_GET_IID(nsISupports)))
+{
+  *aInstancePtr = (void*)(nsISupports*)this;
+  NS_ADDREF_THIS();
+  return NS_OK;
+}
+
+ +

最后, SAMPLE_CID 是一个唯一标示组件的 CID . 所有的XPCOM中使用的128-bit数字 - 类和接口 IDs - 都是 UUIDs的例子, or universal unique identifiers, which were discussed in Object Interface Discovery.

+ +
+

Generating CIDs

+ +

为组件建立一个CID,你可以使用大多数Unix版本以及Miscrosoft Visual C++都包含的uuidgen 工具. uuidgen is a command-line tool that returns a unique 128-bit number when you call it with no arguments:

+ +
$ uuidgen
+ce32e3ff-36f8-425f-94be-d85b26e634ee
+
+ +

On Windows, a program called guidgen.exe does the same thing and also provides a graphical user interface if you'd rather point and click. Or you can use one of the special "bots" on IRC in #developers, where you can also get help from human beings.

+ +
irc irc.mozilla.org
+/join #developers
+/msg mozbot uuid
+
+ +

This command makes the bot generate and return a UUID, which you can then copy into your component source code.

+
+ +

Now that we've looked at the preliminaries, it's time to discuss the classes that this module provides and the way that they define the relationships of the component in XPCOM.

+ +

Coding for the Registration Process

+ +

当 XPCOM 第一次发现你的组件(via XPInstall or regxpcom, both of which are discussed in Component Installation Overview), 第一件事是装载你的库并找到符号NSGetModule. 当这个专用的入口被调用, 它被传送XPCOM's Component Manager和组件存在的共享库位置.

+ +

Component Manager是一个是XPCOM实现的用来包含建立对象和提供一些所有组件的综合信息的接口。磁盘的位置是通过另外一个接口 nsIFile传送的. This interface is XPCOM's abstraction of files and directories. An nsIFile object is usually a file or directory on a local volume, but it may represent something on a network volume as well.

+ +
nsresult NSGetModule(nsIComponentManager *servMgr,
+                     nsIFile* location,
+                     nsIModule** result);
+
+ +

XPCOM 需要成功调用 NSGetModule并返回接口nsIModule. 当你写一个 XPCOM 组件, 你实现了 nsIModule to do all of the necessary registration, unregistration, and object creation. nsIModule 有4个方法必须实现.nsIModule has four methods that must be implemented.

+ +

The Registration Methods

+ +

Two closely related registration methods are declared below.

+ +
NS_IMETHOD RegisterSelf(nsIComponentManager *aCompMgr,
+                        nsIFile *aLocation,
+                        const char *aLoaderStr,
+                        const char *aType) = 0;
+
+NS_IMETHOD UnregisterSelf(nsIComponentManager *aCompMgr,
+                          nsIFile *aLocation,
+                          const char *aLoaderStr) = 0;
+
+ +

RegisterSelf 在组件第一次被XPCOM注册的时候调用. 他只执行一次, which gives you a chance to add any one time setup functionality. The RegisterSelf 允许你的组件告诉XPCOM 你将支持什么功能. 注意所有你在 RegisterSelf 中做的都应该在 UnregisterSelf中撤销.

+ +

首先, NSGetModule入口从你的库中被调用, 返回一个指向nsIModule的实现. 然后XPCOM调用RegisterSelf, passing parameters that we'll examine here.

+ +
The RegisterSelf Method
+ +

The first parameter is the nsIComponentManager, which provides a kind of entry point into managing the registration process. 你可以调用QueryInterface 来查找访问下面所述的其他组件管理接口.

+ +
+

The Many Faces of the XPCOM Component Manager

+ +

三个主要的组件管理接口, nsIComponentManager, nsIServiceManager, and nsIComponentRegistrar, are described below:

+ + +
+ +

Your RegisterSelf method may call QueryInterface on the nsIComponentManager interface parameter to obtain the nsIComponentRegistrar or nsIServiceManager. nsIServiceManager can be used to obtain a singleton service, which can be useful if you have to register with a service other than the nsIComponentRegistrar if necessary. For example, you may want to get the service that is responsible for an event you want to be notified about. See Getting Called at Startup for an example of this.

+ +

第二个参数RegisterSelf是正在注册组件的位置. This parameter is useful when the component needs to know where it has been installed or registered - as, for example, when other files must be stored or accessed relative to the component. This method is only called once, so you have to persist the location if you are going to use it later.

+ +

The next two parameters are usually passed into the nsIComponentRegistrar methods and used by XPCOM to determine how to handle the component's registration. The aLoaderStr parameter, which is opaque and should not be modified, distinguishes components that are loaded from the same location specified by the nsIFile parameter. A single ZIP archive may store several XPCOM components, where every component in the archive has the same nsIFile parameter but the aLoaderStr parameter can be used to refer to the location within the ZIP archive.

+ +

The last parameter specifies what kind of loader to use on the component. This is reserved as an optimization, for the most part, but it can be a useful way to extend XPCOM. Since XPCOM already knows internally what kind of file it has just loaded and called RegisterSelf on, passing this value to the registration methods is a shortcut for determining what kind of component is being registered.

+ +
nsIComponentRegistrar Methods
+ +

为了告诉XPCOM这个组件库实现了什么,调用方法:

+ +
NS_IMETHOD RegisterFactoryLocation(const nsCID & aClass,
+                                   const char *aClassName,
+                                   const char *aContractID,
+                                   nsIFile *aFile,
+                                   const char *aLoaderStr,
+                                   const char *aType) = 0;
+
+ +

The last three parameters are the same as the three passed into the RegisterSelf method of nsIModule objects. All you have to do is forward these parameters from your RegisterSelf call into this method, leaving just the first three parameters.

+ +

For any class that implements an XPCOM interface, the implementation must have a class identifier if it is to be shared with other parts of code via XPCOM. This identifier, called a CID, uniquely specifies the implementation. This CID can be created via the tool uuidgen on most operating systems, as in The Many Faces of the XPCOM Component Manager above. Given a CID and an IID, you can refer to any class in XPCOM. Consider the following:

+ +

Referencing Objects by ID

+ +

Image:referencing-objects-by-id.png

+ +

In this case, you have two implementations of the nsISupports interface. Each implementation has a separate CID. The interface also as an IID which is the same for both implementations. When specifying implementation A, the two required pieces of information are the CID of A and the IID of the interface that A supports. The code to register such an object is simple:

+ +
NS_IMETHODIMP
+SampleModule::RegisterSelf(nsIComponentManager *aCompMgr,
+                           nsIFile* aPath,
+                           const char* registryLocation,
+                           const char* componentType)
+{
+    printf("Hello Mozilla Registration!\n\n");
+    nsIComponentRegistrar* compReg = nsnull;
+    nsresult rv =
+      aCompMgr->QueryInterface(kIComponentRegistrarIID,(void**)& compReg);
+    if (NS_FAILED(rv))
+        return rv;
+    rv = compReg->RegisterFactoryLocation(kSampleCID,
+                                          "Sample Class",
+                                          nsnull,
+                                          aPath,
+                                          registryLocation,
+                                          componentType);
+    compReg->Release();
+    return rv;
+}
+
+ +

Unregistration follows the same logic. To unregister, all you have to do is pass the CID and the file which is passed into UnregisterSelf.

+ +

建立你的组件的一个实例

+ +

上面的例子用了 CID, 一旦注册以后,任何使用 XPCOM 的客户都可以访问你的组件,通过contract ID or CID. (Note that RegisterSelf method above does not register a contract ID - it simply passes null. This prevents clients from ever accessing the component with a contract ID.)

+ +

为了让其他人访问, 你要公开组件包括它支持的接口的 CID 和/或者 contract ID. 上面的例子中,某人可能通过下面的方法建立一个 Sample对象 :

+ +
nsIComponentManager* compManager;  // assume initialized
+
+nsISupports* sample;
+compManager->CreateInstance(kSampleCID,
+                            nsnull,
+                            kISupportsIID,
+                            (void**)&sample);
+
+ +

In the above snippet, we assume that the component manager has been initialized. In many cases this value is passed in or easily accessible. 如果还没有建立组件管理者,你总可以调用NS_GetComponentManager()来建立它. XPCOM API Reference中列出了一些全局的XPCOM方法.

+ +

The first parameter of the call to CreateInstance specifies the component the client code is looking for, which is the same value passed to RegisterFactoryLocation. The next parameter is for aggregation, which the WebLock component does not support. The third parameter is the interface used to talk to the component. The last parameter is the out variable which will contain a valid object if and only if the method succeeds[non-null-out]. The implementation of CreateInstance will ensure that the result will support the passed IID, kISupportsIID. The type of the variable sample should match the IID passed in as kISupportsIID.

+ +

CreateInstance 被调用, XPCOM 查询所有的注册组件来匹配CID. XPCOM然后会装载对应的匹配 CID的组件,如果他还没有被装载的话. XPCOM 然后调用库的 NSGetModule. 最后它调用模块上的 GetClassObject. 这个方法是你来实现的,返回匹配 CID/IID 对的nsIFactory. To prepare your component code, you need to create a factory object for each object that you have registered with XPCOM.

+ +

The main function that must be implemented in the nsIFactory interface is CreateInstance. The implementation follows a simple algorithm:

+ +
    +
  1. Create the raw object.
  2. +
  3. If that fails, return an out of memory error code.
  4. +
  5. Call QueryInterface on the new object.
  6. +
  7. If that fails, null the out param and free the new object.
  8. +
  9. Return the nsresult value from QueryInterface.
  10. +
+ +

Often, you don't have to create the object first because the factory implicitly knows what IIDs are supported. When this is not the case, however, doing it this way further abstracts the factories from their concrete classes. If you have a factory that knows every IID supported by the concrete base class, for example, then when you go to add a new supported interface you add this IID comparison in both the factory and the QueryInterface implementation in the concrete class.

+ +
NS_IMETHODIMP
+SampleFactory::CreateInstance(nsISupports *aOuter,
+                              const nsIID & iid,
+                              void * *result)
+{
+  if (!result)
+    return NS_ERROR_INVALID_ARG;
+
+  Sample* sample = new Sample();
+  if (!sample)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  nsresult rv = sample->QueryInterface(iid, result);
+
+  if (NS_FAILED(rv)) {
+    *result = nsnull;
+    delete sample;
+  }
+
+  return rv;
+}
+
+ +

webLock1.cpp

+ +

Before any of the improvements and XPCOM tools we describe in the following chapter are brought in, the source code for the WebLock component that implements all the necessary interfaces looks like this.

+ +
#include <stdio.h>
+
+#define MOZILLA_STRICT_API
+
+#include "nsIModule.h"
+#include "nsIFactory.h"
+
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+
+static const nsIID kIModuleIID = NS_IMODULE_IID;
+static const nsIID kIFactoryIID = NS_IFACTORY_IID;
+static const nsIID kISupportsIID = NS_ISUPPORTS_IID;
+static const nsIID kIComponentRegistrarIID = NS_ICOMPONENTREGISTRAR_IID;
+
+
+#define SAMPLE_CID \
+{ 0x777f7150, 0x4a2b, 0x4301, \
+{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}}
+
+static const nsCID kSampleCID = SAMPLE_CID;
+
+class Sample: public nsISupports {
+  private:
+    nsrefcnt mRefCnt;
+  public:
+    Sample();
+    virtual ~Sample();
+
+    NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
+    NS_IMETHOD_(nsrefcnt) AddRef(void);
+    NS_IMETHOD_(nsrefcnt) Release(void);
+
+};
+
+Sample::Sample()
+{
+  mRefCnt = 0;
+}
+
+Sample::~Sample()
+{
+}
+
+NS_IMETHODIMP
+Sample::QueryInterface(const nsIID &aIID,
+                       void **aResult)
+{
+  if (aResult == NULL) {
+    return NS_ERROR_NULL_POINTER;
+  }
+  *aResult = NULL;
+  if (aIID.Equals(kISupportsIID)) {
+    *aResult = (void *) this;
+  }
+  if (*aResult == NULL) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+  AddRef();
+  return NS_OK;
+}
+
+NS_IMETHODIMP_(nsrefcnt) Sample::AddRef()
+{
+  return ++mRefCnt;
+}
+
+NS_IMETHODIMP_(nsrefcnt) Sample::Release()
+{
+  if (--mRefCnt == 0) {
+    delete this;
+    return 0;
+  }
+  return mRefCnt;
+}
+
+
+
+// factory implementation class for component
+class SampleFactory: public nsIFactory{
+  private:
+    nsrefcnt mRefCnt;
+  public:
+    SampleFactory();
+    virtual ~SampleFactory();
+
+    NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
+    NS_IMETHOD_(nsrefcnt) AddRef(void);
+    NS_IMETHOD_(nsrefcnt) Release(void);
+
+    NS_IMETHOD CreateInstance(nsISupports *aOuter, const nsIID & iid, void * *result);
+    NS_IMETHOD LockFactory(PRBool lock);
+
+};
+
+SampleFactory::SampleFactory()
+{
+  mRefCnt = 0;
+}
+SampleFactory::~SampleFactory()
+{
+}
+
+NS_IMETHODIMP
+SampleFactory::QueryInterface(const nsIID &aIID,
+                              void **aResult)
+{
+  if (aResult == NULL) {
+    return NS_ERROR_NULL_POINTER;
+  }
+  *aResult = NULL;
+  if (aIID.Equals(kISupportsIID)) {
+    *aResult = (void *) this;
+  }
+  else if (aIID.Equals(kIFactoryIID)) {
+    *aResult = (void *) this;
+  }
+
+  if (*aResult == NULL) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+  AddRef();
+  return NS_OK;
+}
+
+NS_IMETHODIMP_(nsrefcnt) SampleFactory::AddRef()
+{
+  return ++mRefCnt;
+}
+
+NS_IMETHODIMP_(nsrefcnt) SampleFactory::Release()
+{
+  if (--mRefCnt == 0) {
+    delete this;
+    return 0;
+  }
+  return mRefCnt;
+}
+
+
+NS_IMETHODIMP
+SampleFactory::CreateInstance(nsISupports *aOuter,
+                              const nsIID & iid,
+                              void * *result)
+{
+  if (!result)
+    return NS_ERROR_INVALID_ARG;
+
+  Sample* sample = new Sample();
+  if (!sample)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  nsresult rv = sample->QueryInterface(iid, result);
+
+  if (NS_FAILED(rv)) {
+    *result = nsnull;
+    delete sample;
+  }
+
+  return rv;
+}
+
+
+NS_IMETHODIMP
+SampleFactory::LockFactory(PRBool lock)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+
+
+
+
+// Module implementation
+class SampleModule : public nsIModule
+{
+  public:
+    SampleModule();
+    virtual ~SampleModule();
+
+  // nsISupports methods:
+  NS_IMETHOD QueryInterface(const nsIID & uuid, void * *result);
+  NS_IMETHOD_(nsrefcnt) AddRef(void);
+  NS_IMETHOD_(nsrefcnt) Release(void);
+
+  // nsIModule methods:
+  NS_IMETHOD GetClassObject(nsIComponentManager *aCompMgr,
+                            const nsCID & aClass,
+                            const nsIID & aIID,
+                            void * *aResult);
+  NS_IMETHOD RegisterSelf(nsIComponentManager *aCompMgr,
+                          nsIFile *aLocation,
+                          const char *aLoaderStr,
+                          const char *aType);
+  NS_IMETHOD UnregisterSelf(nsIComponentManager *aCompMgr,
+                            nsIFile *aLocation,
+                            const char *aLoaderStr);
+  NS_IMETHOD CanUnload(nsIComponentManager *aCompMgr,
+                       PRBool *_retval);
+
+  private:
+    nsrefcnt mRefCnt;
+};
+
+
+//----------------------------------------------------------------------
+
+SampleModule::SampleModule()
+{
+  mRefCnt = 0;
+}
+
+SampleModule::~SampleModule()
+{
+}
+
+
+// nsISupports implemention
+NS_IMETHODIMP_(nsrefcnt)
+SampleModule::AddRef(void)
+{
+  return ++mRefCnt;
+}
+
+
+NS_IMETHODIMP_(nsrefcnt)
+SampleModule::Release(void)
+{
+  if (--mRefCnt == 0) {
+    mRefCnt = 1; /* stabilize */
+    delete this;
+    return 0;
+  }
+  return mRefCnt;
+}
+
+NS_IMETHODIMP
+SampleModule::QueryInterface(REFNSIID aIID,
+                             void** aInstancePtr)
+{
+  if (!aInstancePtr)
+    return NS_ERROR_NULL_POINTER;
+
+  nsISupports* foundInterface;
+
+  if (aIID.Equals(kIModuleIID)) {
+    foundInterface = (nsIModule*) this;
+  }
+  else if ( aIID.Equals(kISupportsIID) ) {
+    foundInterface = (nsISupports*) this;
+  }
+  else {
+    foundInterface = 0;
+  }
+
+  if (foundInterface) {
+    foundInterface->AddRef();
+    *aInstancePtr = foundInterface;
+    return NS_OK;
+  }
+
+  *aInstancePtr = foundInterface;
+  return NS_NOINTERFACE;
+}
+
+
+// Create a factory object for creating instances of aClass.
+NS_IMETHODIMP
+SampleModule::GetClassObject(nsIComponentManager *aCompMgr,
+                             const nsCID& aClass,
+                             const nsIID& aIID,
+                             void** result)
+{
+
+  if (!kSampleCID.Equals(aClass))
+    return NS_ERROR_FACTORY_NOT_REGISTERED;
+
+  if (!result)
+    return NS_ERROR_INVALID_ARG;
+
+  SampleFactory* factory = new SampleFactory();
+  if (!factory)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  nsresult rv = factory->QueryInterface(aIID, result);
+
+  if (NS_FAILED(rv)) {
+    *result = nsnull;
+    delete factory;
+  }
+
+  return rv;
+}
+
+
+//----------------------------------------
+
+
+NS_IMETHODIMP
+SampleModule::RegisterSelf(nsIComponentManager *aCompMgr,
+                           nsIFile* aPath,
+                           const char* registryLocation,
+                           const char* componentType)
+{
+
+  nsIComponentRegistrar* compReg = nsnull;
+
+  nsresult rv =
+    aCompMgr->QueryInterface(kIComponentRegistrarIID, (void**)&compReg);
+  if (NS_FAILED(rv))
+    return rv;
+
+  rv = compReg->RegisterFactoryLocation(kSampleCID,
+                                        "Sample Class",
+                                        nsnull,
+                                        aPath,
+                                        registryLocation,
+                                        componentType);
+
+  compReg->Release();
+
+  return rv;
+}
+
+NS_IMETHODIMP
+SampleModule::UnregisterSelf(nsIComponentManager* aCompMgr,
+                             nsIFile* aPath,
+                             const char* registryLocation)
+{
+
+  nsIComponentRegistrar* compReg = nsnull;
+
+  nsresult rv = aCompMgr->QueryInterface(kIComponentRegistrarIID, (void**)&compReg);
+  if (NS_FAILED(rv))
+    return rv;
+
+  rv = compReg->UnregisterFactoryLocation(kSampleCID, aPath);
+
+  compReg->Release();
+
+  return rv;
+}
+
+NS_IMETHODIMP
+SampleModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
+{
+  *okToUnload = PR_FALSE; // we do not know how to unload.
+  return NS_OK;
+}
+
+//----------------------------------------------------------------------
+
+extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
+                                          nsIFile* location,
+                                          nsIModule** return_cobj)
+{
+  nsresult rv = NS_OK;
+
+  // Create and initialize the module instance
+  SampleModule *m = new SampleModule();
+  if (!m) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  // Increase refcnt and store away nsIModule interface to m in return_cobj
+  rv = m->QueryInterface(kIModuleIID, (void**)return_cobj);
+  if (NS_FAILED(rv)) {
+    delete m;
+  }
+  return rv;
+}
+
+ +
    +
  1. Note: non-null-out
    The CreateInstance method guarantees that if the out variable is non-null, it is valid.
  2. +
+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/finishing_the_component/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/finishing_the_component/index.html new file mode 100644 index 0000000000..3be93d89f5 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/finishing_the_component/index.html @@ -0,0 +1,337 @@ +--- +title: Finishing the Component +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Finishing_the_Component +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Finishing_the_Component +--- +

+

« 上一页下一页 »

+

+ +

At this point you have created most of the infrastructure of the component. The component will be recognized by XPCOM and registered with the Category Manager so that it starts up when XPCOM initializes. When the component starts up, it populates a list of URLs read in from a file stored next to the Gecko binary on the local system.

+ +

Using Frozen Interfaces

+ +

The core functionality of blocking sites is still missing, however. The interfaces needed to block certain URLs from loading are not frozen, and there is still some debate about how exactly this functionality should be exposed to embedders and component developers, so the APIs are not ready to be published. This puts you in the same situation as many developers using Mozilla - you want to use some specific functionality, but the interfaces seem to change on a daily basis.

+ +

All of the Mozilla source code is publicly available, and interfaces can be used easily enough. Grab the right headers, use the Component or Service Manager to access the interface you want, and the XPCOM object(s) that implement that interface will do your bidding. With this huge amount of flexibility, however, you lose compatibility. If you use "stuff" that isn't frozen, that stuff is subject to change in future versions of Gecko.

+ +

If you want to be protected against changes in Gecko, you must only use interfaces and APIs that are clearly marked as FROZEN. The marking is made in the comments above the interface declaration. For example, take a look at the nsIServiceManager:

+ +
/**
+ * The nsIServiceManager manager interface provides a means to obtain
+ * global services in an application. The service manager depends
+ * on the repository to find and instantiate factories to obtain
+ * services.
+ *
+ * Users of the service manager must first obtain a pointer to the
+ * global service manager by calling NS_GetServiceManager. After that,
+ * they can request specific services by calling GetService.
+ * When they are finished they can NS_RELEASE() the service as usual.
+ *
+ * A user of a service may keep references to particular services
+ * indefinitely and only must call Release when it shuts down.
+ *
+ * @status FROZEN
+ */
+
+ +

These frozen interfaces and functions are part of the Gecko SDK. The rule of thumb is that interfaces outside of the SDK are considered "experimental" or unfrozen. See the following sidebar for information about how frozen and unfrozen interfaces can affect your component development, and for technical details about how interface changes beneath your code can cause havoc.

+ +
+

The Danger of Using Unfrozen Interfaces

+ +

Suppose that you need to use the interface nsIFoo that isn't frozen. You build your component using this interface, and it works great with the version of Gecko that you have tested against. However, some point in the future, the nsIFoo interface requires a major change, and methods are reordered, some are added, others are removed. Moreover, since this interface was never supposed to be used by clients other than Gecko or Mozilla, the maintainers of the interface don't know that it's being used, and don't change the IID of the interface. When your component runs in a version of Gecko in which this interface is updated, your method calls will be routed through a different v-table than the one the component expected, most likely resulting in a crash.

+ +

Below, the component is compiled against a version of the nsIFoo interface that has three methods. The component calls the method TestA and passes an integer, 10. This works fine in any Gecko installation where a contract guarantees that the interface that was compiled against has the same signature. However, when this same component is used in a Gecko installation where this interface has changed, the method TestA does not exist in the nsIFoo interface; the first entry in the v-table is in fact IsPrime(). When this method call is made, the code execution treats the IsPrime method as TestA. Needless to say, this is a bad thing. Furthermore, there is no way easy way to realize this error at runtime.

+ +

Image:vtable-of-altered-interface.png

+ +

Gecko developers could change the interface's IID, and some do. This can prevent many errors like this. But unfrozen interfaces are not supported in any formal way, and relying upon a different IID for any change in the interface is not a good idea either.

+ +

When using frozen interfaces, you are guaranteed compatibility with future versions of Gecko. The only trouble occurs when the compiler itself changes its v-table layout, which can happen when the compiler changes its ABI. For example, in 2002 the GNU Compiler Collection (GCC), version 3.2 changed the C++ ABI, and this caused problems between libraries compiled with GCC 3.2 and applications compiled with an earlier version and vice versa. Similar problems occurred with GCC 4.0, which underwent similar ABI changes.

+
+ +

Before attempting to use unfrozen interfaces, you should contact the developers who are responsible for the code you're trying to use (i.e.,module owners ) and ask them how best to do what you are trying to do. Be as precise you possibly can. They may be able to suggest a supported alternative, or they may be able to notify you about pending changes.

+ +

The interface that we need for this project is something called nsIContentPolicy. At the time this book was written, this interface was under review. An interface reaches this state when a group of module owners and peers are actively engaged in discussion about how best to expose it. Usually there are only minor changes to interfaces marked with such a tag. Even with interfaces marked "under review," however, it's still a good idea to contact the module owners responsible for the interfaces you are interested in using.

+ +

Copying Interfaces into Your Build Environment

+ +

To get and implement interfaces that are not part of Gecko in your component, simply create a new directory in the Gecko SDK named unfrozen. Copy the headers and IDL files that you need from the content/base/public source directory of the Gecko build into this new directory. (For WebLock, all you need are the headers for nsIContentPolicy and the nsIContentPolicy.idl.) Then, using the same steps you used to create the Weblock.h, create a header from this IDL file using the xpidl compiler. Once you have these interface and header files, you can modify the WebLock class to implement the nsIContentPolicy interface. The Weblock class will then support four interfaces: nsISupports, nsIObserver, nsIContentPolicy, and iWeblock.

+ +

Image:weblock-implemented-ifaces.png

+ +

WebLock Interfaces

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Interface NameDefined byStatusSummary
nsISupportsXPCOMFrozenProvides interface discovery, and object reference counting
nsIObserverXPCOMFrozenAllows messaging passing between objects
nsIContentPolicyContentNot FrozenInterface for policy control mechanism
iWeblockWeb LockNot FrozenEnables and disables Weblock. Also, provides access to the URL that are whitelisted.
+ +

Implementing the nsIContentPolicy Interface

+ +

To implement the new interface, you must #include the unfrozen nsIContentPolicy, and you must also make sure the build system can find the file you've brought over. The location of the file and the steps for adding that location to the build system vary depending on how you build this component.

+ +

Once you have made sure that your component builds with the new header file, you must derive the Weblock class from the interface nsIContentPolicy, which you can do by simply adding a public declaration when defining the class. At the same time, you can add the macro NS_DECL_NSICONTENTPOLICY to the class declaration that provides all of the methods defined in the interface nsIContentPolicy. The updated WebLock class looks as follows:

+ +
class WebLock: public nsIObserver, public iWeblock, public nsIContentPolicy
+{
+  public:
+    WebLock();
+    virtual ~WebLock();
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIOBSERVER
+    NS_DECL_IWEBLOCK
+    NS_DECL_NSICONTENTPOLICY
+
+  private:
+    urlNode* mRootURLNode;
+    PRBool   mLocked;
+};
+
+ +

Remember to change the nsISupports implementation macro to include nsIContentPolicy so that other parts of Gecko will know WebLock supports the nsIContentPolicy interface without modifying this macro.

+ +
NS_IMPL_ISUPPORTS3(WebLock, nsIObserver, iWeblock, nsIContentPolicy);
+
+ +

Receiving Notifications

+ +

To receive notifications, you must register as a new category. You have already registered as a category to receive startup notification. This time, the category name to use is "content-policy". To add the WebLock component to this category, modify the WebLockRegistration callback function so that it looks like this:

+ +
static NS_METHOD WebLockRegistration(nsIComponentManager *aCompMgr,
+                                     nsIFile *aPath,
+                                     const char *registryLocation,
+                                     const char *componentType,
+                                     const nsModuleComponentInfo *info)
+{
+  nsresult rv;
+  nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
+  if (NS_FAILED(rv))
+    return rv;
+
+  nsCOMPtr<nsICategoryManager> catman;
+  servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
+                                  NS_GET_IID(nsICategoryManager),
+                                  getter_AddRefs(catman));
+  if (NS_FAILED(rv))
+    return rv;
+
+  char* previous = nsnull;
+  rv = catman->AddCategoryEntry("xpcom-startup",
+                                "WebLock",
+                                WebLock_ContractID,
+                                PR_TRUE,
+                                PR_TRUE,
+                                &previous);
+  if (previous)
+    nsMemory::Free(previous);
+
+  rv = catman->AddCategoryEntry("content-policy",
+                                "WebLock",
+                                WebLock_ContractID,
+                                PR_TRUE,
+                                PR_TRUE,
+                                &previous);
+  if (previous)
+    nsMemory::Free(previous);
+  return rv;
+}
+
+ +

This code adds a new category entry under the topic "content-policy," and it calls AddCategoryEntry in the same way we did in Registering for Notifications. A similar step is required for unregistration.

+ +

Implementing the nsIContentPolicy

+ +

At this point, you can take the WebLock component and install it into a Gecko installation. When the component is loaded, Gecko calls the nsIContentPolicy implementation in WebLock on every page load, and this prevents pages from displaying by returning the proper value when the load method is called.

+ +

The web locking policy that we are going to put into place is quite simple: for every load request that comes through, we will ensure that the URI is in the list of "good" URLs on the white list.

+ +
+

If you care to extend this implementation so that the list of URLs is held remotely on a server somewhere - as might be the case when the WebLock component is used in a corporate intranet, for example - there are Networking APIs in Gecko that will support this. Or you could implement the web lock so that instead of blocking any site, the component would simply log all URLs that are loaded. In any case, the process to make the XPCOM component is the same.

+
+ +

The method that handles the check before page loading and the only method we care about in our own implementation of nsIContentPolicy is ShouldLoad(). The other method on the nsIContentPolicy interface is for blocking processing of specific elements in a document, but our policy is more restrictive: if the URL isn't on the white list, the entire page should be blocked. In the WebLock component, the ShouldLoad method looks like this:

+ +
NS_IMETHODIMP WebLock::ShouldLoad(PRInt32 contentType,
+                                  nsIURI *contentLocation,
+                                  nsISupports *ctxt,
+                                  nsIDOMWindow *window,
+                                  PRBool *_retval)
+
+ +

Uniform Resource Locators

+ +

The method passes in an interface pointer of type nsIURI, which is based on the Uniform Resource Identifier, or URI. This type is defined by the World Wide Web Consortium as:

+ + + +

In this context, URIs are the strings used refer to places or things on the web. This specific form of URI is called a Uniform Resource Locator, or URL. See the intro to the HTML 4 specification for more information about URIs and URLs.

+ +

Gecko encapsulates these identifiers into two interfaces, nsIURI and nsIURL. You can QueryInterface between these two interfaces. The networking library, Necko, deals only with these interfaces when handling requests. When you want to download a file using Necko, for example, all you probably have is a string that represents the URI of the file. When you pass that string to Necko, it creates an object that implements at least the nsIURI interface (and perhaps other interfaces as well).

+ +

Currently, the WebLock implementation of the ShouldLoad method compares the in parameter with each string in the white list. But it only should do this comparison for remote URLs, because we don't want to block the application from loading local content that it requires, like files it gets via the resource:// protocol. If URIs of this kind are blocked, then Gecko will not be able to start up, so we'll restrict the content policy to the HTTP and FTP protocols.

+ +

Instead of extracting the string spec out of the nsIURI to do a string comparison, which would require you to do the parsing yourself, you can compare the nsIURI objects with each other, as in the following section. This ensures that the URLs are canonical before they are compared.

+ +

Checking the White List

+ +

The WebLock implementation of the ShouldLoad method starts by extracting the scheme of the incoming nsIURI. If the scheme isn't "http", "https", or "ftp", it immediately returns true, which continues the loading process unblocked.

+ +

These three are the only kinds of URI that Weblock will try to block. When it has one, it walks the linked list and creates a new nsIURI object for each string URL in the list. From each object, ShouldLoad() extracts the host and compares it to the URI. If they match, the component allows the load to continue by returning true. If these two strings do not match, then the component returns return false and blocks the load.

+ +
+

URI Caching

+ +

Caching the URI would make this method implementation much faster by avoiding the need to create and destroy so many objects. This points out an important drawback of XPCOM, which is that you cannot create an object on the stack.

+ +

Creating this many objects is OK in a tight loop if the buffer of memory that holds the contents of the URLs is guaranteed to be valid for the lifetime of the object. But regardless of how optimized the implementation is with respect to is memory usage, a heap allocation will be made for every XPCOM object created.

+
+ +

The string comparison with the URL type "http", "https", and "ftp" looks like this:

+ +
nsEmbedCString scheme;
+contentLocation->GetScheme(scheme);
+
+if (strcmp("http", scheme.get())  != 0 &&
+    strcmp("https", scheme.get()) != 0 &&
+    strcmp("ftp", scheme.get())   != 0)
+{
+  // this isn't a type of URI that we deal with.
+  *_retval = PR_TRUE;
+  return NS_OK;
+}
+
+ +

Creating nsIURI Objects

+ +

To create an nsIURI, use nsIIOService. nsIIOService is the part of the networking library ("necko") that's responsible for kicking off network requests, managing protocols such as http, ftp, or file, and creating nsIURIs. Necko offers tremendous network functionality, but all the WebLock component needs is to create the nsIURI object that can be compared with the URIs on the white list.

+ +

Use the Service Manager to acquire the nsIIOService. Since this object is going to be used for the life of the component, it can also be cached. A good place to get an nsIIOService is in the component's Observe() method, which already has a pointer to the Service Manager. The code for getting the IO service from the Service Manager looks like this:

+ +
// Get a pointer to the IOService
+rv = servMan->GetServiceByContractID("@mozilla.org/network/io-service;1",
+                                     NS_GET_IID(nsIIOService),
+                                     getter_AddRefs(mIOService));
+
+ +

Once you have this interface pointer, you can easily create nsIURI objects from a string, as in the following snippet:

+ +
nsCOMPtr<nsIURI> uri;
+nsEmbedCString urlString(node->urlString);
+mIOService->NewURI(urlString,
+                   nsnull,
+                   nsnull,
+                   getter_AddRefs(uri));
+
+ +

This code wraps a C-string with a nsEmbedCString, which you'll recall is a string class that many of the Gecko APIs require. See String Classes in XPCOM for more information about strings.

+ +

Once the URL string is wrapped in a nsEmbedCString, it can be passed to the method NewURI. This method expects to parse the incoming string and create an object which implements an nsIURI interface. The two nsnull parameters passed to NewURI are used to specify the charset of the string and any base URI to use, respectively. We are assuming here that the charset of the URL string is UTF-8, and also assuming that every URL string is absolute. See the intro to the HTML 4 specification for more information about relative URLs.

+ +

Here is the complete implementation of the ShouldLoad() method:

+ +
NS_IMETHODIMP
+WebLock::ShouldLoad(PRInt32 contentType,
+                    nsIURI *contentLocation,
+                    nsISupports *ctxt,
+                    nsIDOMWindow *window,
+                    PRBool *_retval)
+{
+  if (!contentLocation)
+    return NS_ERROR_FAILURE;
+
+
+  nsEmbedCString scheme;
+  contentLocation->GetScheme(scheme);
+
+  if (strcmp("http", scheme.get())  != 0 &&
+      strcmp("https", scheme.get()) != 0 &&
+      strcmp("ftp",  scheme.get())  != 0)
+  {
+    // this isn't a type of URI that we deal with
+    *_retval = PR_TRUE;
+    return NS_OK;
+  }
+
+  nsEmbedCString hostToLoad;
+  contentLocation->GetHost(hostToLoad);
+
+  // Assume failure.  Do not allow this nsIURI to load.
+  *_retval = PR_FALSE;
+
+  nsresult rv;
+
+  urlNode* node = mRootURLNode;
+  PRBool match = PR_FALSE;
+
+  while (node)
+  {
+    nsCOMPtr<nsIURI> uri;
+    nsEmbedCString urlString(node->urlString);
+    rv = mIOService->NewURI(urlString, nsnull,  nsnull, getter_AddRefs(uri));
+
+    // if anything bad happens, just abort
+    if (NS_FAILED(rv))
+      return rv;
+
+    nsEmbedCString host;
+    uri->GetHost(host);
+
+    if (strcmp(hostToLoad.get(), host.get()) == 0)
+    {
+      // match found.  Allow this nsIURI to load
+      *_retval = PR_TRUE;
+      return NS_OK;
+    }
+    node = node->next;
+  }
+  return NS_OK;
+}
+
+ +

At this point, all of the backend work is complete. You can of course improve this backend in many ways, but this example presents the basic creation of what is commonly referred to as a "browser helper object" like WebLock. The next chapter looks at how to tie this into the front end - specifically, how to use XPConnect to access and control this component from JavaScript in the user interface.

+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/index.html new file mode 100644 index 0000000000..13fd6aff60 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/index.html @@ -0,0 +1,278 @@ +--- +title: 创建_XPCOM_组件 +slug: Mozilla/Tech/XPCOM/Guide/Creating_components +tags: + - XPCOM + - 'XPCOM:索引' + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components +--- +

 

+ +

+

下一页 »

+

+ +

前言

+ +
+
谁该读这本书
+
本教程的组织
+
按照例子来学习
+
本书的体例
+
致谢
+
+ +

XPCOM 简介

+ +
+
XPCOM 解决方案
+
Gecko
+
组件
+
接口 +
+
接口与封装
+
nsISupports 基接口
+
+
+
XPCOM 的ID +
+
CID
+
契约 ID
+
+
+
类厂 +
+
XPIDL 与类型库
+
+
+
XPCOM 服务
+
XPCOM 类型 +
+
方法类型
+
引用计数
+
状态码
+
变量映射
+
通用 XPCOM 错误码
+
+
+
+ +

使用 XPCOM 组件

+ +
+
组件的例子 + +
+
Cookie 管理器
+
WebBrowserFind 组件
+
WebLock 组件
+
+
+
Mozilla 中使用的组件 +
+
查找 Mozilla 组件
+
在 Cpp 代码中使用 XPCOM 组件
+
XPConnect: 在脚本中使用 XPCOM 组件
+
+
+
+ +

组件内幕

+ +
+
用Cpp书写组件
+
XPCOM初始化 +
+
XPCOM注册描述
+
XPCOM注册的方法
+
自动注册
+
The Shutdown Process
+
XPCOM组件库的三个部分
+
+
+
XPCOM Glue +
+
The Glue Library
+
XPCOM String Classes
+
+
+
+ +

建立组件代码

+ +
+
我们将做什么
+
组件注册 +
+
The regxpcom Program
+
其他的注册途径
+
+
+
概览WebLock Module Source
+
深度挖掘: 需要的Includes和常量 +
+
XPCOM中的标识符
+
注册过程的代码
+
注册用的方法
+
建立你的组件的接口
+
+
+
webLock1.cpp
+
+ +

使用XPCOM工具类让事情变得简单

+ +
+
XPCOM 宏 + +
+
通用XPCOM模块宏
+
基本实现宏
+
声明宏
+
+
+
webLock2.cpp
+
XPCOM中的字符串类 +
+
使用字符串
+
nsEmbedStringnsEmbedCString
+
+
+
智能指针
+
+ +

开始WebLock

+ +
+
启动时被调用 + +
+
注册到消息
+
访问Category Manager
+
+
+
提供WebLock访问
+
建立WebLock编程接口
+
在XPIDL中定义WebLock接口 +
+
XPIDL书写格式
+
脚本化接口
+
实现nsISupports
+
Web Locking 接口
+
+
+
实现WebLock +
+
声明宏
+
在XPCOM中表达返回值
+
XPIDL代码生成
+
从客户端获取WebLock Service
+
实现iWebLock接口
+
The Directory Service
+
nsIFile改变路径
+
nsIFile操作文件
+
nsILocalFile读取数据
+
处理White List Data
+
+
+
iWebLock方法列举 +
+
Lock and Unlock
+
AddSite
+
RemoveSite
+
SetSites
+
GetNext
+
GetSites
+
HasMoreElements
+
+
+
+ +

Finishing the Component

+ +
+
Using Frozen Interfaces + +
+
Copying Interfaces Into Your Build Environment
+
Implementing the nsIContentPolicy Interface
+
Receiving Notifications
+
+
+
Implementing the nsIContentPolicy +
+
Uniform Resource Locators
+
Checking the White List
+
Creating nsIURI Objects
+
+
+
+ +

Building the WebLock UI

+ +
+
User Interface Package List
+
Client Code Overview
+
XUL +
+
The XUL Document
+
The Locking UI
+
Site Adding UI
+
weblock.xul
+
+
+
Overlaying New User Interface Into Mozilla +
+
webLockOverlay.xul
+
+
+
Other Resources +
+
weblock.css
+
Image Resources
+
+
+
+ +

打包 WebLock

+ +
+
组件安装预览
+
资源归档
+
WebLock 安装脚本
+
WebLock 跟踪脚本
+
分发你的组件
+
+ +

附录 A - 建立 Gecko SDK

+ +
+
下载和建立 SDK
+
编译一个 Microsoft Visual Cpp 工程 +
+
创建一个新的工程
+
把 Gecko SDK 添加到工程设置
+
+
+
Unix 下的一个 Makefile
+
+ +

附录B - 资源

+ +
+
WebLock 资源
+
Gecko 资源
+
XPCOM 资源
+
General Development 资源
+
+ +

+

下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

+ +

 

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/packaging_weblock/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/packaging_weblock/index.html new file mode 100644 index 0000000000..3a7744ec03 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/packaging_weblock/index.html @@ -0,0 +1,136 @@ +--- +title: Packaging WebLock +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Packaging_WebLock +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Packaging_WebLock +--- +

+

« 上一页下一页 »

+

+ +

这是教程最后一部分, 我们将把所有的web所有的组件成分打包成可安装到其他应用中的形式 - the library itself, the type library, the header file, and the user interface resources. The first section, Component Installation Overview, describes the general installation process in Mozilla. The following sections describe the steps you can take to organize the WebLock component for distribution and installation.

+ +
+

请注意: 这个教程主要是关注组件开发本身, 所以这部分描述有关打包和安装到Gecko的过程是很简单的. 如果你希望了解详细的打包和安装组件到基于Gecko应用的信息,应该参考http://www.mozilla.org/projects/xpinstall.

+
+ +

Component Installation Overview

+ +

XPInstall是一组JavaScript APIs用来建立安装脚本. 使用XPInstall,你可以为装载到Gecko-based应用,Mozilla extensions,或者individual components的组件建立web-based安装脚本. WebLock component安装脚本也可以用来注册组件到browser(see Registration Methods in XPCOM for more information on registration).

+ +

下面的例子安装脚本使用了Mozilla XPInstall技术来操作安装并且以高层次Javascript对象的方式来跟Mozilla'schrome registry 交互。

+ +
+

What Is the Chrome Registry?

+ +

Like the Windows registry, the chrome registry is a database of information about applications, skins, and other extensions that have been installed in a Gecko application. Since Mozilla and other Gecko-based applications are cross-platform, this database is abstracted above the operating system or any particular platform's registry.

+ +

The chrome registry lives in a series of RDF/XML files in the application directory of Mozilla and other Gecko-based browsers, where new installs, user configurable data, skins, and other information are related to one another and the application itself.

+
+ +

XPInstall中的JavaScript APIs Install 对象下载包含了安装文件的JAR并且调用注册方法来告诉 Mozilla 新的组件和用来调用WebLock组件的UI. WebLock Installation Script 是完整的trigger installation script , 可以从网页触发. 文件被存储在JAR file weblock.jar, 这是一个简单的ZIP文件,以XPI结尾,有时候也可能包含一个内部的安装脚本install.js.

+ +

一旦你把组件和Weblock相关资源正确打包(see the following section, Archiving Resources), WebLock安装脚本是一个简单的事情(see The WebLock Installation Script).

+ +

Archiving Resources

+ +

Once you have compiled all the resources that make up the WebLock component and the files that make up the user interface that will be added to the browser, you can place these within a subdirectory called weblock.

+ +

Place the entire subdirectory into a ZIP archive and name the archive weblock.xpi. The archive, its subdirectory structure, and its contents should look like this:

+ +

weblock.xpi Archive Viewed in WinZIP

+ +

Image:weblock-zipped-package.png

+ +

Note that the top level of the archive holds the install.js installation file, an RDF manifest for the package as a whole, and the component files (weblock.xpt and weblock4.dll). The component files are copied to the components directory of the Gecko application, and the weblock subdirectory gets copied over into the chrome subdirectory, where its UI resources can be added dynamically to the XUL-based Gecko application.

+ +

The next section shows how this process of downloading, copying and registering the necessary files from the XPI can be achieved with an XPInstall installation script.

+ +

The WebLock Installation Script

+ +

安装脚本是一个存储在XPI中的JavaScript文件. 他必须在包的根目录 (i.e., weblock.xpi) itself. 一旦触发 (see The WebLock Trigger Script), 安章脚本将:

+ + + +

The XPInstall API提供了一些核心方法[essential-methods]例如 initInstall, registerChrome, addFile, and others.

+ +

WebLock Installation Script

+ +
// initialize the installation
+var err = initInstall("WebLock", "weblock", 1.0);
+
+var componentsDir = getFolder("Components");
+var cf = getFolder("Chrome");
+
+// add the DLL and say where it'll go
+addFile("weblock.dll", 1.0, "weblock.dll", componentsDir, "");
+
+// add the typelib also
+addFile("weblock.xpt", "1.0", "weblock.xpt", componentsDir, "");
+
+// add the weblock subdirectory of the XPI and specify that
+// it be installed in the chrome application directory
+err = addDirectory("weblock", "1.0", "", chromeDir, "");
+
+// ? have to register component here or with regxpcom?
+
+// register the new UI with the mozilla chrome registry
+
+registerChrome(CONTENT, getFolder(cf,"weblock.xpi"),"weblock");
+registerChrome(SKIN, getFolder(cf, "weblock.xpi"),"weblock");
+
+// perform the installation if there are no errors
+if (err==SUCCESS)
+  performInstall();
+else
+  cancelInstall(err);
+
+ +

The WebLock Trigger Script

+ +

The trigger script is the script placed on a web page that actually initiates an XPInstall installation and calls the installation script that appears in the XPI. The following HTML specifies a complete webpage in which the trigger script is defined as a JavaScript function, installWebLock, that gets called when the user clicks the hyperlink.

+ +
<html>
+<title>WebLock Installation</title>
+<script type="text/javascript">
+/*
+ * Trigger function that downloads the XPI so the
+ * install.js file inside can be read and executed
+ */
+function installWebLock()
+{
+  weblock_xpi = {'WebLock Extension': 'weblock.xpi'};
+  InstallTrigger.install(weblock_xpi);
+}
+</script>
+
+<h1>Install WebLock</h1>
+
+<p><a href="#" onclick="installWebLock();">install weblock</a></p>
+
+</html>
+
+ +

Distributing Your Component

+ +

Once you have the component packaged properly and the necessary installation and trigger scripts, you are ready to distribute your component so others can install it in their Gecko applications.

+ +

In Mozilla and Netscape browsers, XPInstall makes this process especially easy by providing the file format (XPI) and the necessary installation scripts for doing a web-based installation. As WebLock Installation Script demonstrates, XPInstall uses special keywords to refer to common installation directories such as components in a generalized, cross-platform way.

+ +

If you are installing WebLock in an Gecko-based application for which XPInstall is not available, then you will have to devise a separate installation scheme. We leave this as an exercise for the reader.

+ +
    +
  1. Note: install-object-methods
    The methods are available on the main Install object, which is implied in the script below in the same way that the window object is implied in JavaScript manipulation of the DOM of a web page. In other words, the fragment initInstall() from the script is equivalent to Install.initInstall().
  2. +
+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/preface/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/preface/index.html new file mode 100644 index 0000000000..0710f0a701 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/preface/index.html @@ -0,0 +1,83 @@ +--- +title: 前言 +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Preface +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Preface +--- +

 

+ +

+

下一页 »

+
这本书是关于 Gecko, 以及如何创建基于 Gecko 的 XPCOM 组件. 尽管本书的重点是放在把你的 C++ 代码制作成一个使用 Gecko 的组件的步骤之上, 我们还希望这个过程能够讨论到所有构建 XPCOM 的相关工具, 技巧和技术. 因此本书的安排上是作为一个参考书, 使读者能够自己创建组件, 学习不同的 XPCOM 内容. 比如说, 导言中包含了什么是组件的讨论; 第一章中你可以编译基本的源码并注册到 Mozilla 中, 由此讨论了组件于模块之间的关系, 以及一般的注册过程.

+ +

每章的开始会给出这一章的主要内容. Sidebar sections are included to highlight technical details. 在本书的结尾, 如果能够达到本书的目的的话, 读者应该学会如何创建一个组件, Gecko 中的 XPCOM 组件框架.

+ +

谁该读这本书

+ +

创建 XPCOM 组件 是为 C++ 开发人员而写. 尽管你可能会使用 JavaScript, C 或其他的语言来创建 XPCOM 组件, 组件管理的实现是采用 C++, 许多关于如何创建 XPCOM 组件的讨论也是从 C++ 语言开始的. 然而并不要求读者是一个 C++ 语言的专家, 你需要了解的是基本的 C++ 继承和封装的思想, 我们在书中将尽可能的解释这些 C++ 语言的特性的使用. 由于 Mozilla 使用 JavaScript 脚本语言来访问 XPCOM 组件, 所以熟悉 JavaScript 会很有帮助.

+ +

XPCOM 是 Cross Platform Component Object Model (跨平台组件模型)的缩写. 就象它的名字暗示的, XPCOM 类似于 Microsoft 的 COM. 开发 MS COM 的经验大多都可以被应用到 XPCOM. 然而本书假设读者对 COM 一无所知, 本书将包含关于 COM 基本思想的介绍.

+ +

本书将描述一个控制浏览动作的 XPCOM 组件的制作过程. 尽管 XPCOM 的多数应用环境与 web 浏览并没有关系, 但是 XPCOM 现在的主要客户应用是 Gecko, 一个开源的, 遵循标准的嵌入式 web 浏览器, 所以它是最简单的, 而且是最实用的展示 XPCOM 功能的例子. 本教程中关于组件的详细描述在这里 What We'll Be Working On.

+ +

本教程的组织

+ +

下面的列表给出了编制一个称为 WebLock 的 XPCOM 组件的整体步骤, 这个组件向基于 Gecko 的浏览器提供了阻止网站访问的功能. 每个步骤都有各自的章节, 在各个章节中会讨论相关的内容.

+ + + +

按照例子来学习

+ +

安装 XPCOM 到本地机器上的方法有很多, 如果你已经编译了 Mozilla 1.2 或更高的版本源码, 你就已经有了 XPCOM 框架. 如果你还没有下载 Mozilla 源码, 更简单的方法是下载 Gecko SDK, 它包含了 XPCOM 组件框架的库和工具.

+ +

如果有了上面的工具, 你就可以编译自己的组件, 并把这个组件添加到 Gecko 库中. 我们这里讨论的 WebLock 组件是一个实用的浏览器扩展, 编译它需要 1.2 或更高版本的 Gecko SDK / Mozilla 源码.

+ +

本书假设你使用的是 SDK, 下载 SDK, 编译, 和获取可用于编成的 Gecko 组件的方法在本书的附录, 建立 Gecko SDK.

+ +

本书的体例

+ +

下面列出的是格式化文档的习惯,他们用于本书中特定的信息类型并且让信息检索变得简单。目标是使用尽量少的格式类型,同时能辨别不同的信息类型。

+ + + + + + + + + + + + + + + + + + + + + + + + +
FormatDescription
boldcomponent names 显示为粗题文字
monospacecode listings, interface namesmembers of interfaces (e.g., createInstance()) 用monospaced 字体表达. 代码行放在不同的box内. 此外, filenamesdirectories 也用 monospaced 字体.
italicvariables appear in italic. 重要的条目和新的概念第一次在文本中出现的时候也应该是斜体字。这些条目通常会立刻有进一步的解释,或者读者可以在本书的某个地方找到详细的解释。
linkReferences to other sections and to figures and tables are links to those sections.
+ +

致谢

+ +

Thanks to Peter Lubczynski, John Gaunt, Ellen Evans, and Alec Flett for technical reviews. A special thanks goes to Darin Fisher for his very acute observations, close reading, and attention to detail.

+

下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/resources/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/resources/index.html new file mode 100644 index 0000000000..b23e6eb4c2 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/resources/index.html @@ -0,0 +1,10 @@ +--- +title: 资源 +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Resources +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Resources +--- +

Link title + + Italic text +

+
Insert formula here
diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/setting_up_the_gecko_sdk/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/setting_up_the_gecko_sdk/index.html new file mode 100644 index 0000000000..3e8c8516e2 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/setting_up_the_gecko_sdk/index.html @@ -0,0 +1,204 @@ +--- +title: 建立 Gecko SDK +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Setting_up_the_Gecko_SDK +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Setting_up_the_Gecko_SDK +--- +

+

« 上一页下一页 »

+

+ +

这一章提供建立 Gecko SDK 的基本方法, 下面会告诉开发人员如何下载和组织 Gecko SDK, 如何象 WebLock 一样创建一个新的组件工程.

+ +

下载和建立 SDK

+ +

Gecko SDK 提供了编译 XPCOM 组件所需要的所有的工具, 头文件和库. SDK 现在有 Windows 和 Linux 两个版本, 其他操作系统上的 SDK 正在开发. SDK 在下面的地址下载:

+ + + +

注意版号要大于1.4a. 可以在下面的地址获取更新的 SDK 版本 http://ftp.mozilla.org/pub/mozilla/releases/.

+ +

一旦你下载了SDK, 你可以解压缩到任何合适的目录. 在本附录中, 我们建立Windows Gecko SDK 到 c:\gecko-sdk\. 如果你选择其他的位置, 记得调整这里描述的设置指向这个位置(e.g., in the 建立一个Microsoft visual cpp工程 章节) .

+ +

当你解压缩SDK,它的目录结构看起来应该是:

+ +

Layout of the Extracted SDK

+ +

Image:sdk-layout.png

+ +

目录分别代表SDK中的不同模块。例如网络通讯的所有头文件放在necko目录中,而所有XPCOM需要的头文件则放在 XPCOM 目录中。 这个目录结构使得编译脚本变得比较复杂(因为会产生很多include路径)但是他帮助把SKD的部分组织得更有条例。

+ +

两组顶级头文件是比较特别的。mozilla-config.h列出了SDK中使用的所有define,在你的文件中包含着个头文件会保证你创建的组件和Gecko库使用的相同的define。注意mozilla-config.h可能需要在你的组件代码中第一个被include.

+ +

每一个模块的目录都分成三个子目录:

+ +

Module Subdirectories

+ +

Image:module-directory-subdirs.png

+ +

bin目录包含了静态库,动态库, 和一些可能会在开发中使用的tools。idl目录包含了模块所公开的公共的IDL文件。includes目录包含了你的组件使用的C++头文件。

+ +

现在我们应该提到XPCOM公开的一组二进制代码文件。下面的列表罗列了可执行的Windows文件名:

+ + + + + + + + + + + + + + + + + + + + + + + + +
Application NameDescription of functionality
regxpcom.exeRegisters or Unregisters components with XPCOM
xpidl.exeGenerates typelib and C++ headers from XPIDL
xpt_dump.exePrints out information about a given typelib
xpt_link.exeCombines multiple typelibs into a single typelib
+ + + + + + + + + + + + +
Library NameDescription of functionality
xpcomglue.libXPCOM Glue library to be used by xpcom components.
+ +

编译一个 Microsoft Visual Cpp 工程

+ +

一担你建立了Gecko SDK,你可以创建一个Miscrosoft visual c++项目来处理你基于SDK的组件开发。

+ +

创建一个新的工程

+ +

启动Visual c++以后,从文件菜单重选择new。然后在新建对话框中选择"Win32 Dynamic-Link Library"。 使用对话框右边的栏目输入你的项目和位置。(这个例子使用了 "SampleGeckoProject"作为问兼并,位置是C:\ ).

+ +

New Dialog

+ +

Image:new-vcpp-project.png

+ +

选择OK. 在出现的Win32 Dynamic-Link Library 对话框里, 你可以选择缺省的 "An Empty DLL Project" 作为DLL的类型.

+ +

Image:vcpp-dll-dialog.png

+ +

选择Finish. Microsoft Studio 将根据你的设定建立一个新的项目并且展开项目开发视图。

+ +

把 Gecko SDK 添加到工程设置

+ +

为了build使用Gecko的所有信息,你还需要进一步修改项目使得它知道在哪里取得Gecko SDK。为了编辑项目设置, 从项目菜单种选择Settings (or press Alt-F7).

+ +

大部分你在下面步骤中所做的修改方法都适用于所有项目设置的修改(包括Debug和Optimize)。选择从Setting菜单中选择"All Configurations",出现一个下拉菜单:

+ +

Image:vcpp-project-settings.png

+ +

在C/C++ tab,选择Preprocessor组。在这个窗口里你要添加到Gecko SDK的include路径,以及两个 preprocessor defines:

+ + + +

最起码你要加上include nspr, embedstringstring include目录, 和xpcom include 子目录. 如果你的组件适用其他SDK的部分(例如Necko), 你也要添加指向他们的路径.

+ +

假定你使用例子项目的路径,这些路径看起来会是:

+ + + +

Image:vcpp-project-settings-includes.png

+ +

在C++ language组, 禁止异常处理. 正如在 XPCOM中的异常章节所表明的, 异常处理不支持跨越Interface, 所以使用这个功能将可能在开发中引起问题。

+ +

WebLock 组件需要引用必要的库文件以使用XPCOM Glue. 为添加这些库文件,选择Link tab, 然后选择Input category. 在这个面板上不要连接到 nsprembedstringxpcom中的子目录include ,而改用bin子目录.

+ +

我们也会连接到一些Object/library 模块中的库:

+ + + +

这些设定看起来会是:

+ +

Image:vcpp-project-settings.png

+ +

最后一个你需要让Gecko SDK在你的项目中设定成功的修改是"Use run-time library" 设定为 "Multithreaded DLL." 因为这个设置是根据其他设定而确定的,你必须设定Release configuration run-time library 为 release multithreaded DLL runtime, 并且Debug configuration 设定为 the debug multithreaded dll runtime (这个需要澄清一下):

+ +

Image:vcpp-runtime-settings.png

+ +

完成所有这些设定后,选择OK. 这就完成了项目设定并且让你的项目能包含和编译XPCOM组件.

+ +

Unix 下的一个 Makefile

+ +

Linux 下不采用工程而采用 Makefile 来组织代码. Makefile 中放置编译环境中的编译选项, 包括使用 Gecko SDK 编译的路径和配置更新等.

+ +

下面是一个使用 SDK 来编译的 Makefile, 这里对 Makefile 的详细用法不做解释. 它与 Visual C++ 的工程(Building a Microsoft Visual Cpp Project)相类似, 关于 Makefile 的命令请参看 Make 手册.

+ +

Gecko SDK 下的一个 Makefile 例子

+ +
CXX   = c++
+
+CPPFLAGS +=     -fno-rtti              \
+                -fno-exceptions        \
+                -shared
+
+# Change this to point at your Gecko SDK directory.
+GECKO_SDK_PATH = /home/dougt/gecko-sdk
+
+# GCC only define which allows us to not have to #include mozilla-config
+# in every .cpp file.  If your not using GCC remove this line and add
+# #include "mozilla-config.h" to each of your .cpp files.
+GECKO_CONFIG_INCLUDE = -include mozilla-config.h
+
+GECKO_DEFINES  = -DXPCOM_GLUE -DMOZILLA_STRICT_API
+
+GECKO_INCLUDES = -I $(GECKO_SDK_PATH)                    \
+                 -I $(GECKO_SDK_PATH)/xpcom/include      \
+                 -I $(GECKO_SDK_PATH)/nspr/include       \
+                 -I $(GECKO_SDK_PATH)/string/include     \
+                 -I $(GECKO_SDK_PATH)/embedstring/include
+
+GECKO_LDFLAGS =  -L $(GECKO_SDK_PATH)/xpcom/bin -lxpcomglue \
+                 -L $(GECKO_SDK_PATH)/nspr/bin -lnspr4      \
+                 -L $(GECKO_SDK_PATH)/nspr/bin -lplds4      \
+                 -L $(GECKO_SDK_PATH)/embedstring/bin/ -lembedstring
+
+build:
+        $(CXX) -o MozShim.so $(GECKO_CONFIG_INCLUDE) $(GECKO_DEFINES) $(GECKO_INCLUDES) $(GECK\
+O_LDFLAGS) $(CPPFLAGS) $(CXXFLAGS) MozShim.cpp
+        chmod +x MozShim.so
+
+clean:
+        rm MozShim.so
+
+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/starting_weblock/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/starting_weblock/index.html new file mode 100644 index 0000000000..65efd53a72 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/starting_weblock/index.html @@ -0,0 +1,1104 @@ +--- +title: 开始WebLock +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Starting_WebLock +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Starting_WebLock +--- +

+

« 上一页下一页 »

+

+ +

在本章,我们开始设计和实现网络锁定功能本身。我们已经建立了实现多数通用组件功能的模块(例如注册)。这章将关注实际操作网页锁定的功能。

+ +

Getting Called at Startup

+ +

没有人是一个孤岛,组件也一样。你所建立的例子组件到目前为止还没有任何功能。当他被注册以后,他没做任何事情。

+ +

为了当某些事件发生的时候被启动或者通知到,例子组件需要挂接到Mozilla,或者覆盖一个现存组件,或者注册到一些事件上面。WebLock用后面的方式在Gecko Profile Startup发生的时候被调用。当Gecko应用启动的时候,注册的组件被创建或者通过通用观察者接口被提醒nsIObserver

+ +

Observer是一些对象,他们当特定的事件发生的时候被通知。使用这种机制提供了一个相互不必了解而可以在对象之间传送信息的机制。

+ +

通常,一个对象会通知一系列观察者。例如一个对象被创建的时候它的observe方法被调用,或者它可以注册当XPCOM关闭的时候被通知。这个接口的核心是observe方法。

+ +
void observe(in nsISupports aSubject,
+             in string aTopic,
+             in wstring aData);
+
+ +

实际上ovserver方法的参数没有什么限制。这些参数根据事件的类型变化。例如,XPCOM关闭的时候,aSubject和aData被定义,aTopic被定义为“xpcom-shotdown’,如果你的对象希望注册到这些事件上面,他首先要实现nsIObserver接口,一旦你完成这些,实现nsIObserverService的observer服务将会利用接口通知你的对象,如下所示:

+ +

The Observer Interfaces

+ +

Image:observation-overview.png

+ +

上图表现了observer服务管理了所有nsIObserver对象的列表. 当通知产生的时候,nsIObserverService把呼叫者从NotifyObserver()发送出的消息传送给nsIObserverObserve()方法。这是一个让不同的类解藕的办法。nsIObserver是一个通用的接口,用来在两个或多个对象间传递信息,而不必定义一个特定的冻结接口,它也是XPCOM建立扩展的一个方式。

+ +

WebLock组件对nsIObserver接口的实现和对nsIFactory接口是类似的。XXX what is Example 2?下面的例子2中,你改变一个类的定义为支持nsIObserver接口并且改变NS_IMPL_ISUPOORTS1,从而QueryInterface实现知道组件也支持nsIObserver。启动的时候被通知的WebLock类定义如下:

+ +
class WebLock: public nsIObserver {
+  public:
+    WebLock();
+    virtual ~WebLock();
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIOBSERVER
+};
+
+NS_IMPL_ISUPPORTS1(WebLock, nsIObserver);
+
+ +

Observe()最简单的实现仅仅是比较字符串aTopic和对象所接受事件所定义的值. 如果相匹配, 你可以按照你的方式处理事件. 如果对象仅仅注册到一个消息上, 那你可以忽略字符串 aTopic 而仅仅处理事件. 换句话说,对于对象所没有注册的事件,Observe 方法不应该被调用。

+ +
NS_IMETHODIMP
+WebLock::Observe(nsISupports *aSubject,
+                 const char *aTopic,
+                 const PRUnichar *aData)
+{
+  return NS_OK;
+}
+
+ +

从observer service来的消息可能是间接的. 直接获得来自observer service的消息的方法是初始化一个nsIObserver 对象. 大多数情况下这样是可以的,但是要注意当你通过这个消息建立组件的情况. 因为组件还没有被建立,所以不存在初始化的 nsIObserver 对象可以用来传递给 nsIObserverService, 组件代码在他被装载以前不能做什么.

+ +

注册到消息

+ +

nsIObserverService 接口有处理注册和注销一个nsIObserver对象的方法. 这两个方法用来动态添加或者删除一个notification topic上的observer. 但是 WebLock 要被自动初始化和添加到observer service, 这就意味着需要一些数据持久化。(不管怎么说, 我们需要组件在程序每次启动的时候也启动).

+ +

This is where a new service that manages sets of related data comes in handy. This service, the nsICategoryService, is what XPCOM and Gecko embedding applications use to persist lists of nsIObserver components that want to have startup notification.

+ +

The nsICategoryService maintains sets of name-value pairs like the one below.

+ +

The Category Manager

+ +

Image:category-manager-table.png

+ +

Every category is identified by a string that represents the name of the category. Each category contains a set of name-value pairs. For example, you might have a category named "Important People" in which the name-value pairs would be names and phone numbers. The format of the name-value pair is left up to you.

+ +

This data structure is more than enough to support the persisting of components that what to be started up. The category name also maps nicely onto the notion of a notification "topic." The topic name could be something like "xpcom-startup", for instance, and the name-value pair could contain the contract IDs required to create the components requesting startup. In fact, this is exactly how categories are used to handle registration with XPCOM for startup notification. You will see the code which does this in the next section.

+ +

Getting Access to the Category Manager

+ +

Two fields in the nsModuleComponentInfo structure introduced in the last section are addresses for registration and unregistration callbacks. The first callback is called when the component's nsIModule::RegisterSelf method is called. This callback allows the component to execute any one-time registration code it may need. The inverse of this function is the unregistration callback, where it's a good idea to undo whatever the registration function did. The two functions look like this:

+ +
static NS_METHOD
+WebLockRegistration(nsIComponentManager *aCompMgr,
+                    nsIFile *aPath,
+                    const char *registryLocation,
+                    const char *componentType,
+                    const nsModuleComponentInfo *info);
+
+static NS_METHOD
+WebLockUnregistration(nsIComponentManager *aCompMgr,
+                      nsIFile *aPath,
+                      const char *registryLocation,
+                      const nsModuleComponentInfo *info);
+
+ +

The names of the functions can be anything you wish. Both functions are passed the Component Manager and the path to the component, including the opaque registryLocation. These are also parameters in the nsIModule implementation in XXX what is Example 1? link to it hereExample 1. In addition to these parameters, the callback functions are passed the nsModuleComponentInfo struct, which is the same structure initially passed into NS_IMPL_NSGETMODULE.

+ +

During registration, the registration callback is where you get the nsICategoryManager. Once you have it, you can add the component to the category of components that get started automatically. As a service, the nsICategoryManager is accessible via the nsIServiceManager. Also note that the nsIComponentManager is passed into the callback. Since the object that implements the nsIComponentManager interface also implements nsIServiceManager, all you have to do is QueryInterface the nsIComponentManager to nsIServiceManager to get the Service Manager. You can then use the Service Manager to add the component to the category:

+ +
nsresult rv;
+
+nsCOMPtr<nsIServiceManager> servman =
+     do_QueryInterface((nsISupports*)aCompMgr, &rv);
+
+if (NS_FAILED(rv))
+  return rv;
+
+ +
+

do_QueryInterface

+ +

The previous code uses the special nsCOMPtr function do_QueryInterface that lets you QueryInterface without having to worry about reference counting, error handling, and other overhead. The do_QueryInterface knows what interface to QI to based on the nsCOMPtr that is being assigned into. We could have just as easily have used the raw QueryInterface() method, but using nsCOMPtr is much more economical (see Smart Pointers).

+
+ +

Once you have a nsIServiceManager reference, you can ask it for the service you are interested in. This process is similar to using CreateInstance from the nsIComponentManager, but there is no aggregation parameter since the object has already been constructed.

+ +
nsCOMPtr<nsICategoryManager> catman;
+rv = servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
+                                     NS_GET_IID(nsICategoryManager),
+                                     getter_AddRefs(catman));
+if (NS_FAILED(rv))
+  return rv;
+
+ +

There are two service getters on the nsIServiceManager interface: one that takes a CID and another interface that takes a Contract ID. Here we'll use the latter. The first parameter to the GetServiceByContractID is of course the contract ID, which is defined in the nsXPCOM.h header file. The next parameter is a nifty macro that returns the IID for the interface name that you pass in. The last parameter assigns an out interface pointer to a nsCOMPtr. Assuming there weren't any unexpected errors, the variable catman holds the nsICategoryManager interface pointer, which you can use to add the component as a startup observer by calling a method on the nsICategoryManager.

+ +

The next step is to figure out which parameters to pass to the method. There is a category name and a name-value pair, but since the name-value pair meaning is category-specific, you need to figure out which category to use.

+ +

There are two startup notifications, both of which create the observer if it isn't already created. The first is provided by XPCOM. This notification will occur during initialization of XPCOM, where all XPCOM services are guaranteed to be available during the calls. Embedding applications may provide other notifications.

+ +

Common XPCOM Notifications

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryNameValueCreates Component
xpcom-startupAnyContract IDYes
xpcom-shutdownAnyContract IDNo
xpcom-autoregistrationAnyContract IDNo
app-startupAnyservice, Contract ID*
+ +

The table above summarizes the popular persistent notifications registered through the category manager. The name of the category itself is a well defined string, but the name-value pairs can be anything.

+ +

When naming your component in the category, take care to use something that means something and doesn't muddy up the namespace. In this case, "WebLock" is unique and provides context to anyone looking at the category. The value of the name-value part is expected to be the contract ID of the component.

+ +

Since every category can define the name-value pairs, the application "app-startup" category can support not only services but component instances as well. For the app-startup notification, you must explicitly pass the string "service," prior to the component's Contract ID. If you do not, the component will be created and then released after the notification, which may cause the component to be deleted.

+ +

In short, to register the WebLock component as an xpcom-startup observer, do the following:

+ +
char* previous = nsnull;
+rv = catman->AddCategoryEntry("xpcom-startup",
+                              "WebLock",
+                              WebLock_ContractID,
+                              PR_TRUE,  // persist category
+                              PR_TRUE,  // replace existing
+                              &previous);
+if (previous)
+  nsMemory::Free(previous); // free the memory the replaced value might have used
+
+ +

The unregistration, which should occur in the unregistration callback, looks like this:

+ +
rv = catman->DeleteCategoryEntry("xpcom-startup",
+                                 "WebLock",
+                                  PR_TRUE);  // persist
+
+ +

A complete code listing for registering WebLock as a startup observer follows:

+ +
#define MOZILLA_STRICT_API
+
+#include "nsIGenericFactory.h"
+
+#include "nsCOMPtr.h"
+#include "nsXPCOM.h"
+#include "nsIServiceManager.h"
+#include "nsICategoryManager.h"
+
+#include "nsMemory.h"
+
+#include "nsIObserver.h"
+
+#include "nsEmbedString.h"
+
+#define WebLock_CID \
+{ 0x777f7150, 0x4a2b, 0x4301, \
+{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}}
+
+#define WebLock_ContractID "@dougt/weblock"
+
+class WebLock: public nsIObserver
+{
+  public:
+    WebLock();
+    virtual ~WebLock();
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIOBSERVER
+};
+
+WebLock::WebLock()
+{
+  NS_INIT_ISUPPORTS();
+}
+
+WebLock::~WebLock()
+{
+}
+
+NS_IMPL_ISUPPORTS1(WebLock, nsIObserver);
+
+NS_IMETHODIMP
+WebLock::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
+{
+  return NS_OK;
+}
+
+static NS_METHOD WebLockRegistration(nsIComponentManager *aCompMgr,
+                                     nsIFile *aPath,
+                                     const char *registryLocation,
+                                     const char *componentType,
+                                     const nsModuleComponentInfo *info)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
+  if (NS_FAILED(rv))
+    return rv;
+
+  nsCOMPtr<nsICategoryManager> catman;
+  rv = servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
+                                       NS_GET_IID(nsICategoryManager),
+                                       getter_AddRefs(catman));
+
+  if (NS_FAILED(rv))
+    return rv;
+
+  char* previous = nsnull;
+  rv = catman->AddCategoryEntry("xpcom-startup",
+                                "WebLock",
+                                WebLock_ContractID,
+                                PR_TRUE,
+                                PR_TRUE,
+                                &previous);
+  if (previous)
+    nsMemory::Free(previous);
+
+  return rv;
+}
+
+static NS_METHOD WebLockUnregistration(nsIComponentManager *aCompMgr,
+                                       nsIFile *aPath,
+                                       const char *registryLocation,
+                                       const nsModuleComponentInfo *info)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv);
+  if (NS_FAILED(rv))
+    return rv;
+
+  nsCOMPtr<nsICategoryManager> catman;
+  rv = servman->GetServiceByContractID(NS_CATEGORYMANAGER_CONTRACTID,
+                                       NS_GET_IID(nsICategoryManager),
+                                       getter_AddRefs(catman));
+  if (NS_FAILED(rv))
+    return rv;
+
+  rv = catman->DeleteCategoryEntry("xpcom-startup",
+                                   "WebLock",
+                                   PR_TRUE);
+
+  return rv;
+}
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(WebLock)
+
+static const nsModuleComponentInfo components[] =
+{
+  {
+    "WebLock",
+    WebLock_CID,
+    WebLock_ContractID,
+    WebLockConstructor,
+    WebLockRegistration,
+    WebLockUnregistration
+  }
+};
+
+NS_IMPL_NSGETMODULE(WebLockModule, components)
+
+ +

Providing Access to WebLock

+ +

At this point, the component will be called when XPCOM starts up. WebLock has already implemented the nsISupports, nsIFactory, nsIModule, and nsIObserver interfaces that handle generic component functionality including being initialized at startup. And it speaks to the Component Manager, Service Manager, Category Manager, and the Component Registrar to register itself properly with XPCOM.

+ +

The next step is to expose additional functionality to Gecko applications and other clients to query and control the WebLock component. For example, the user interface needs to be able to enable and disable the web locking functionality, see what sites are in the whitelist, and add or remove sites from that list. WebLock needs to provide an API, and it needs to hook into Gecko in order to implement the actual locking functionality.

+ +

译: 下一步是expose另外的功能以使得Gecko应用以及其它clients查询和控制WebLock组件. 例如, user interface(用户接口)要有能力去允许或者禁止web locking(web锁定)功能, 查看哪些站点在白名单列表中, 并向列表中添加或移除站点. WebLock需要提供一个API并挂接到Gecko中进而实现实际的locking功能.

+ +
+

The WebLock User Interface

+ +

The WebLock component in this tutorial uses XUL to define the additional browser UI in a cross-platform way, and XUL uses JavaScript to access and control XPCOM components, but Gecko's pluggable UI allows any user interface to call into Gecko and the components you create as easily as you can from XUL. See XUL for a discussion of how XUL interacts with JavaScript and XPCOM.

+ +

在这个教程中WebLock组件使用XUL来定义跨平台的浏览器UI, XUL使用JavaScript来访问和控制XPCOM组件, 但Gecko的可挂接UI也允许任何user interface调用Gecko和你所创建的组件, 就如同XUL一样容易. XUL讨论了XUL如何与JavaScript和XPCOM交互.

+
+ +

Creating the WebLock Programming Interface

+ +

Design is one of the hardest parts of any programming problem. The question the interface for the WebLock component must answer is: How should WebLock look to the outside world? What, in other words, is the interaction of clients with the WebLock component? In this section, we enumerate the basic functionality the component should expose and create the single interface that organizes and provides this functionality.

+ +

译: 设计是任何编程问题中最困难的部分之一. 问题是WebLock组件必须要回答一些问题: WebLock应该如何look to外面的世界? 换言之, 什么是clients与WebLock的交互? 在这部分列举了组件应该expose的基本功能和create一个组织和提供这些功能的接口.

+ +

Instead of starting with the implementation, developers use XPIDL (see XPIDL and Type Libraries for more information about XPIDL) to define the interface to the component: how the functionality should be organized, expressed, and exposed to its clients.

+ +

译: 开发人员应该使用XPIDL(see XPIDL and Type Libraries for more information about XPIDL)为组件定义接口(定义功能应该如何被组织, 描述和暴露给它的clients)做为开始, 而不应该从实现开始.

+ +

In general, the WebLock service interface needs to include the following functionality:

+ +

译: 通常, WebLock服务接口要包括以下功能:

+ + + +

        译: Lock - 允许web locking, 这样任何Gecko应用中的浏览器被限定只能访问白名单中的web站点域.

+ + + +

        译: Unlock - 禁止web locking. 允许Gecko应该中的浏览器访问任何web站点, 而不去管白名单列表.

+ + + +

        译: AddSite - 添加当前URL到白名单列表.

+ + + +

        译: RemoveSite - 从白名单列表中移除当前URL.

+ + + +

        译: EnumerateSites - 允许列举出所有白名单中的站点. EnumerateSites可能会被user         interface(用户接口/用户界面)所提供的例如显示所有白名单列表的可编辑列表框控件所使用.

+ +

Even this simple outline presents some ambiguity, however. It's certainly not enough to spell out the interface for the WebLock component in this way. For example, AddSite is supposed to add the current URL to the white list, but is the URL an input parameter to the method, is it the topmost web page in the Gecko application, or is it something more random-a URL picked from global history or that's been given context in some other way?

+ +

As a strongly typed and implementation-agnostic language, XPIDL requires that you be quite specific about the APIs, the list of parameters, their order, and their types. XPIDL requires that you spell it all out, in other words. And it's this formality that makes the interfaces in XPCOM effective contracts between services and clients.

+ +

The next section shows the interface of the WebLock component, iWebLock, in XPIDL. Once the interface has been described in the XPIDL language, the interface file can be used to generate the header files needed for the implementation code, the binary type library files that let you use the interface of the WebLock component from JavaScript, and even broken linkjavadoc style HTML documentation.

+ +

Defining the Weblock Interface in XPIDL

+ +

Most interfaces in the XPCOM world are described in XPIDL. The XPIDL file for the iWebLock interface can be used to generate the C++ header file, which you'll need to implement the interface in the component and also a type library that makes the component accessible from JavaScript or other interpreted languages. In Mozilla, JavaScript is the bridge between components and the XUL-based user interface.

+ +

译: 在XPCOM世界里大多数接口都是用XPIDL描述的. iWebLock接口的XPIDL文件可以被用来生成C++ header file(你需要它来在组件中实现接口和用来使组件在JavaScript和其它的解译型语言中可访问的类型库). 在Mozilla中, JavaScript是组件与基于XUL的user interface之间的桥梁.

+ +

The XPIDL Syntax (XPIDL语法)

+ +

The XPIDL syntax is a mix of C++ and Java, and of course it's very much like the OMG IDL upon which it is closely based. The XPIDL for iWebLock appears below:

+ +

iWebLock

+ +
#include "nsISupports.idl"
+interface nsISimpleEnumerator;
+[scriptable, uuid(ea54eee4-9548-4b63-b94d-c519ffc91d09)]
+interface iWeblock : nsISupports
+{
+  void lock();
+  void unlock();
+
+  // assume strings are UTF-8
+  void addSite(in string url);
+  void removeSite(in string url);
+  attribute nsISimpleEnumerator sites;
+};
+
+ +

The first line includes the file nsISupports.idl, which defines the nsISupports interface from which all XPCOM interfaces must derive, and makes it possible for the iWebLock interface to subclass that base interface.

+ +
#include "nsISupports.idl"
+
+ +

The next line of the XPIDL is a forward declaration of the interface nsISimpleEnumerator. Again, this is similar to the forward declare in C++ (except that C++ does not have the interface keyword seen here).

+ +
interface nsISimpleEnumerator;
+
+ +

See the XPCOM resources for more information about the XPIDL syntax.

+ +

Scriptable Interfaces

+ +

The third line in iWebLock is more complex. The first thing it says is that iWebLock will bescriptable .

+ +
[scriptable, uuid(ea54eee4-9548-4b63-b94d-c519ffc91d09)]
+
+ +

The rest of the line provides a UUID for this interface. Recall that every interface has a unique number that is assigned to it. In the case of interfaces, the identifier is an IID. In the case of the components, which also require unique identifiers, the identifier is the CID.

+ +

Subclassing nsISupports

+ +

The next line in iWebLock names the interface and defines its base interface. iWeblock derives from nsISupports. XPIDL has no way to define multiple inheritance - something that all scriptable objects must deal with.

+ +
interface iWebLock : nsISupports
+
+ +

The Web Locking Interface

+ +

The body of the block (the stuff between the curly braces) defines the methods and attributes of our interface. There are basically two functional sets on this interface. The first section of the interface controls whether or not WebLock checks to see if a web page can be loaded. If locked, WebLock will prevent sites not on the white list from loading.

+ +
  void lock();
+  void unlock();
+
+ +

This interface does not enforce any policy with respect to how the user enables or disables this feature. This allows maximum flexibility in the implementation. Any place in the application can acquire this interface via the Service Manager and call unlock or lock. For example, the user interface may bring up a dialog asking the user for a password before calling unlock. Another area of code, such as a "Profile Manager" that starts up and lets users choose which profile to use, may unconditionally call unlock on such a component when switching a profile.

+ +

The next set of functionality manages the white list where acceptable domains are stored:

+ +
  void addSite(in string url);
+  void removeSite(in string url);
+  attribute nsISimpleEnumerator sites;
+
+ +

Operations in this set - add, remove, and enumerate - will be called from a user interface that manages the white list and adds the current website to the white list. There is no policy applied to what sites get added or removed to this list, or who can remove a site.

+ +

The most interesting method definition is the enumerator. First of all, it does not look like a method at all:

+ +
attribute nsISimpleEnumerator sites;
+
+ +

This line defines an attribute in the interface. In C++, this is considered a public variable and "compiled" into a Get method (e.g., getSites). If an attribute is not marked readonly, then both Get and Set methods are generated.

+ +

The getter created by this attribute returns a nsISimpleEnumerator interface pointer. This interface allows you to pass a list of elements between interfaces. It has two methods: hasMoreElements() and getNext().

+ +
[scriptable, uuid(D1899240-F9D2-11D2-BDD6-000064657374)]
+interface nsISimpleEnumerator : nsISupports
+{
+  /**
+   * Called to determine whether or not the enumerator has
+   * any elements that can be returned via getNext(). This method
+   * is generally used to determine whether or not to initiate or
+   * continue iteration over the enumerator, though it can be
+   * called without subsequent getNext() calls. Does not affect
+   * internal state of enumerator.
+   *
+   * @see getNext()
+   * @return PR_TRUE if there are remaining elements in the enumerator.
+   *         PR_FALSE if there are no more elements in the enumerator.
+   */
+  boolean hasMoreElements();
+
+  /**
+   * Called to retrieve the next element in the enumerator. The "next"
+   * element is the first element upon the first call. Must be
+   * preceded by a call to hasMoreElements() which returns PR_TRUE.
+   * This method is generally called within a loop to iterate over
+   * the elements in the enumerator.
+   *
+   * @see hasMoreElements()
+   * @return NS_OK if the call succeeded in returning a non-null
+   *               value through the out parameter.
+   *         NS_ERROR_FAILURE if there are no more elements
+   *                          to enumerate.
+   * @return the next element in the enumeration.
+   */
+  nsISupports getNext();
+};
+
+ +

Implementing WebLock

+ +

Once you have defined the interfaces that the component will implement, you can begin to write the implementation code that will actually carry out the web locking functionality.

+ +

The WebLock component implements three interfaces:

+ + + +

nsISupports is the base interface that all XPCOM objects must implement. The nsIObserver interface is for listening to various events that Gecko generates. Finally, the iWebLock interface is the interface that actually controls the web locking functionality. The first two have already been implemented as part of the generic module code. Recall from Using XPCOM Utilities to Make Things Easier that implementing these basic interfaces can be easy and straightforward if you use the macros and other utilities that XPCOM provides.

+ +

Declaration Macros

+ +

The class declaration for the WebLock class that implements these three interfaces is as follows:

+ +
class WebLock: public nsIObserver, public iWebLock
+{
+  public:
+    WebLock();
+    virtual ~WebLock();
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIOBSERVER
+    NS_DECL_IWEBLOCK
+};
+
+ +

Note that we derive from the nsIObserver interface as well as the iWeblock class. We do not need to explicitly derive from nsISupports as both of these two other interfaces are already subclasses of nsISupports:

+ +

Interface Hierarchy for WebLock

+ +

Image:weblock-interface-hierarchy.png

+ +

The body of the class declaration uses declaration macros that are generated from an XPIDL interface file. Every header generated from an XPIDL file has a similar macro that defines all the methods in that interface. This makes changes to the interface when designing a bit simpler, as you do not have to modify any class declarations.

+ +

There are times, of course, when you cannot use these macros-as when two interfaces share the same method signatures. In these cases you have to manually declare the methods in your class. But in practice, manually declaring class methods in XPCOM is the exception and not the rule. The NS_DECL_IWEBLOCK declaration macro expands into the following:

+ +
  NS_IMETHOD Lock(void);
+  NS_IMETHOD Unlock(void);
+  NS_IMETHOD AddSite(const char *url);
+  NS_IMETHOD RemoveSite(const char *url);
+  NS_IMETHOD GetSites(nsISimpleEnumerator * *aSites);
+  NS_IMETHOD SetSites(nsISimpleEnumerator *aSites);
+
+ +

Representing Return Values in XPCOM

+ +

The code sample above is the C++ version of the iWebLock interface methods. The return result of XPCOM methods generated from XPIDL is always of the type nsresult, and the small macro used in these expansions, NS_IMETHOD, actually represents that return type. nsresult is returned even when in XPIDL you specify that the method return a void. If you require the return result to be something else, the methods are not truly XPCOM methods. If you really want to change the return result type you can use a special flag in your XPIDL that denotes this (see the XPIDL reference). However, we suggest that you simply add an out parameter to the method.

+ +

XPIDL Code Generation

+ +

The XPIDL compiler also generates a stub implementation of the interface in a commented section of the generated header file, in which each method returns NS_ERROR_NOT_IMPLEMENTED. If you copy the stub implementation from the header file into the source, then rename the dummy class name ("_MYCLASS_") to the WebLock class name already defined, you should be able to compile the source successfully.

+ +

Getting the WebLock Service from a Client

+ +

At this point, you can install the XPCOM component and have other systems use it. The component doesn't do anything useful, of course, but you have written enough of the code to have it recognized and accessed as a component in XPCOM. The code snippet below illustrates how to get the WebLock service when the component is present:

+ +
nsCOMPtr<nsIServiceManager> servMan;
+nsresult rv = NS_GetServiceManager(getter_AddRefs(servMan));
+if (NS_FAILED(rv))
+{
+  printf("ERROR: XPCOM error [%x].\n", rv);
+  return -1;
+}
+nsCOMPtr<iWebLock> weblock;
+rv = servMan->GetServiceByContractID("@dougt/weblock",
+                                     NS_GET_IID(iWeblock),
+                                     getter_AddRefs(weblock));
+
+if (NS_FAILED(rv))
+{
+  printf("ERROR: XPCOM obtaining service [%x].\n", rv);
+  return -1;
+}
+
+ +

Implementing the iWebLock Interface (实现iWebLock接口)

+ +

Once the interface is defined, you can focus on implementing the web lock startup functionality itself. The WebLock component starts automatically when XPCOM is started up because it's been registered as a category in XPCOM. When WebLock is called, one of the first things it wants to do is read in a file that lists the URLs that the browser is allowed to load. This file can exist anywhere on the local system, but we've placed it next to the application to keep things simple. The first step in this implementation phase, then, is to create the functionality that accesses this WebLock white list and uses its data to determine which domains are allowed and which are to be blocked. For this, we need to use the file interfaces available in XPCOM.

+ +

一旦接口已被定义, 那你的重点应该放在实现web lock的功能上. 当XPCOM运行后WebLock组件也会被自动运行, 因为它已经被注册成为一个XPCOM中的category. 当WebLock被调用时, 它应该做的第一个事情就是读取一个文件, 这个文件列出了允许被浏览器加载的URLs. 这个文件可以位于本地系统中的任何位置, 但我们需要将其放置在距应用程序不远的地方以便操作起来简单一些. 接下来在实现阶段的第一步是实现两个功能, 一是访问WebLock的白名单, 二是使用这些数据去决定哪些域是被允许, 以及哪些是应该被拦截的. 为此, 我们需要使用XPCOM中的文件接口.

+ +
File Interfaces
+ +

Files and directories are abstracted and encapsulated by interfaces. There are a few reasons for not using strings to represent file locations, but the most important one is that not all file systems can be represented by a series of characters separated by a slash. On the Macintosh platform, for example, files are represented as a triplet - two numbers and one string - so using a string on the Macintosh does not adequately identify files on that operating system.

+ +

文件和目录是通过接口来抽象和封装的. 这里有几个原因说明为什么不使用字符串来表示文件位置, 但更重要的一点是并不是所有的文件系统都能够表示成斜线所分割的字符序列. 例如, 在Macintosh(Apple的系统)平台上, 文件被表示成一个triplet(意思是由三个部分组成), 两个数字一个字符串, 因此在Macintosh系统上使用字符串并不能充分在标识文件.

+ +

nsIFile, the file interface in XPCOM, provides most of the functionally that file handling requires. That interface includes members representing the file name, file attributes, permissions, existence, and others. A related interface called nsILocalFile provides access to operations specific to local files, but the nsIFile functionality is adequate for the WebLock component.

+ +

nsIFile, XPCOM中的文件接口, 提供了大多数操作文件所必须的功能. 这个接口中所包含的成员描述了文件的名字, 属性, 权限, 是否存在等等. 与之相关的接口nsILocalFile提供 操作特定的本地文件, 不过nsIFile的功能对于WebLock组件来说已经足够了.

+ +

File Interface Hierarchy

+ +

Image:file-iface-hierarchy.png

+ +
+

Remote Files and nsIFile

+ +

It is not inconceivable for remote files to be represented by the nsIFile interface. Someone could write an nsIFile implementation that represented FTP files on some server. The existing code would need to change very little for a WebLock implementation to take advantage of files that do not actually exist on disk. This kind of implementation does not exist, but this expandability shows some of the flexibility that interface-based programming can provide.

+ +

并不难想象, 为远程文件使用nsIFile接口来表示它. 某人可以写一个nsIFile的实现用以表示一些服务器上的FTP文件. 已经存在的代码必须要做一些效小的修改以使WebLock的实现可以接受实际上并不是存在于磁盘上的文件. 这种类型的实现虽然还并不存在, 但至少这种扩展性可以显现出一些基于接口的编程带来的灵活性.

+ +

The XPCOM API Reference contains detailed information on nsIFile and other XPCOM interfaces.

+
+ +

The Directory Service (目录服务)

+ +

The file interfaces are most useful when you can use them to find and manipulate files that are relative to the application. The Directory Service provides directory and file locations in a cross platform uniform way to make this easier. This service, available as nsIDirectoryService, stores the location of various common system locations, such as the the directory containing the running process, the user's HOME directory, and others. It can be expanded so that applications and components can define and store their own special locations - an application plugin directory, for example, preference files and/or directories, or other application specific paths. For example, to expose the location of the "white list" file containing all of the URLs that are safe for WebLock, you can add its location to the nsDirectoryService, which clients can then query for this infomation.

+ +

文件接口较有助于当你使用它们去查找和操作与应用相关的文件. 目录服务提供了跨平台的目录与文件定位的统一方法, 这使得进行这种操作变得容易. 这个服务(利用nsIDirectoryService)存储了各种各样通用系统区域的位置, 例如像是包括了正在运行的程序的目录, 用户的HOME目录等等. 因此它可以被扩展为应用程序和组件能够定义并且存储它们自己的特定位置(应用程序插件目录), 例如, 用户自定义的文件和目录, 或者其它的应用程序的特定路径. 比如指定一个"white list"所在的位置, 它包括了所有对于WebLock来讲是安全的URLs, 你可以将这个位置添加到nsDirectoryService中, 使客户端接下来可以查询到这个信息.

+ +

The Directory Service implements the nsIProperties interface, which allows you to Get(), Set(), and Undefine() interface pointers. In the case of WebLock, these interface pointers will be nsIFile objects.

+ +

目录服务实现了nsIProperties接口, 它允许你Get(), Set()以及Undefine()接口指针. 在WebLock中这些接口指针是nsIFile对象.

+ +
[scriptable, uuid(78650582-4e93-4b60-8e85-26ebd3eb14ca)]
+interface nsIProperties : nsISupports
+{
+    /**
+     * Gets a property with a given name.
+     * 用给定的名字(name)取得一个属性(property)
+     *
+     * @return NS_ERROR_FAILURE if a property with that
+     * name doesn't exist.
+     * 如果给定名字的属性不存在, 函数返回NS_ERROR_FAILURE
+     * @return NS_ERROR_NO_INTERFACE if the
+     * found property fails to QI to the
+     * given iid.
+     * 如果取得的属性在以给定的iid于QI方法上调用失败,
+     * 函数返回NS_ERROR_NO_INTERFACE
+     */
+    void get(in string prop,
+             in nsIIDRef iid,
+             [iid_is(iid),retval] out nsQIResult result);
+
+    /**
+     * Sets a property with a given name to a given value.
+     * 用给定的名字和给定的值为设置一个属性
+     */
+    void set(in string prop, in nsISupports value);
+
+    /**
+     * Returns true if the property with the given name exists.
+     * 如果与给定名字的属性存在, 返回true
+     */
+    boolean has(in string prop);
+
+    /**
+     * Undefines a property. 取消一个属性的定义
+     * @return NS_ERROR_FAILURE if a property with that name doesn't
+     * already exist.
+     * 如果给定名字的属性还不存在, 那么函数返回NS_ERROR_FAILURE
+     */
+    void undefine(in string prop);
+
+    /**
+     *  Returns an array of the keys.
+     *  返回一个key的集合
+     */
+    void getKeys(out PRUint32 count,
+                 [array, size_is(count), retval] out string keys);
+};
+
+ +

Directory Service Hierarchy

+ +

Image:directoryservice-iface-hierarchy.png

+ +

There are two steps involved to find directories or files with the Directory Service (nsIDirectoryService). You must know the string key (or property) that refers to the location you are interested in, which is published in the file nsDirectoryServiceDefs.h that comes with the Gecko SDK (for a listing of these locations, see the XPCOM API Reference). The string key for the directory containing the application executable is NS_XPCOM_CURRENT_PROCESS_DIR. Given this key, you can acquire the directory service, call Get(), and pass the key. In the example below, appDir will point to the directory that contains the executable.

+ +

这里有两个步骤有关于通过目录服务(nsIDirectoryService)查找目录或文件. 你必须要知道字符串键(或叫属性)用以引用你所想要的位置, 字符串键(或叫属性)被公开于随Gecko SDK一起提供的nsDirectoryServiceDefs.h文件中(可参见XPCOM API Reference以得到这些位置的一个列表). 包含可执行程序的目录的字符串键是NS_XPCOM_CURRENT_PROCESS_DIR. 给定这个键, 你就可以通过调用Get()并将键传递到函数中以获得目录服务. 在下面的实例中, appDir将指向一个包含了可执行程序的目录.

+ +
nsCOMPtr<nsIServiceManager> servMan;
+nsresult rv = NS_GetServiceManager(getter_AddRefs(servMan));
+if (NS_FAILED(rv)) return -1;
+
+nsCOMPtr<nsIProperties> directoryService;
+rv = servMan->GetServiceByContractID(NS_DIRECTORY_SERVICE_CONTRACTID,
+                                     NS_GET_IID(nsIProperties),
+                                     getter_AddRefs(directoryService));
+
+if (NS_FAILED(rv)) return -1;
+
+nsCOMPtr<nsIFile> appDir;
+rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
+                           NS_GET_IID(nsIFile),
+                           getter_AddRefs(appDir));
+
+if (NS_FAILED(rv)) return -1;
+
+ +

Most of the useful functionality is exposed by the nsIProperties interface, but the directory service also implements nsIDirectoryService. This interface allows you to extend and override nsIFile objects registered with the directory service. There are currently two ways to add a file location to the directory service: directly and using the delayed method. The direct method is to add a new nsIFile object using the nsIProperties interface, in which case you pass the nsIFile object as an nsISupports to the Set() method of the nsIProperties interface.

+ +

大多数有用的功能都是通过nsIProperties接口所提供, 但目录服务还实现了nsIDirectoryService. nsIDirectoryService接口允许利用目录服务你去扩展和重写nsIFile对象的注册. 当前有两种方法添加一个文件位置到目录服务中:立即的与延迟的两种方法. 立即的方法是使用nsIProperties接口添加一个新的nsIFile对象, 在这种情况下你要把nsIFile对象当成一个nsISupports传递给nsIProperties接口的Set()函数.

+ +

In the delayed method, you register to be a callback that can provide an nsIFile. To do this, you must get the implementation like we did above. When you have it, QueryInterface for the nsIDirectoryService interface. In this interface, there is a function which allows you to register an nsIDirectoryServiceProvider interface. The interface callback looks like this:

+ +
[scriptable, uuid(bbf8cab0-d43a-11d3-8cc2-00609792278c)]
+interface nsIDirectoryServiceProvider: nsISupports
+{
+/**
+* getFile
+*
+* Directory Service calls this when it gets the first request for
+* a prop or on every request if the prop is not persistent.
+*
+* @param prop The symbolic name of the file.
+* @param persistent TRUE - The returned file will be cached by Directory
+* Service. Subsequent requests for this prop will
+* bypass the provider and use the cache.
+* FALSE - The provider will be asked for this prop
+* each time it is requested.
+*
+* @return The file represented by the property.
+*
+*/
+nsIFile getFile(in string prop, out PRBool persistent);
+};
+
+ +

Modifying Paths with nsIFile

+ +

The directory service returns an nsIFile object, but that object points to the application directory and not the file itself. To modify this nsIFile so that it points to the file, you must call the Append method of the nsIFile. Append adds the input string to the path already specified in the nsIFile. On Unix, for example, calling Append("b") on an nsIFile modifies that nsIFile representing /u/home/dougt/a to point to /u/home/dougt/a/b. The next operation on the nsIFile returns results associated with the "b" path. If "a" wasn't a directory, further operations would fail, even if the initial Append was successful. This is why Append is considered a string operation.

+ +

目录服务返回一个nsIFile对象, 但nsIFile对象指向的是应用程序目录而并不是文件. 因此为了修改nsIFile对象以指向文件你必须要调用nsIFile的Append函数. Append函数将字符串输入参数追加到已经被指定到nsIFile的路径里. 例如在Unix里, 在一个nsIFile上调用Append("b")将使nsIFile从指向/u/home/dougt/a修改为指向/u/home/dougt/a/b. 在nsIFile上的后续操作返回的结果将是关于"b"这个路径的. 如果"a"不是一个目录, 那么进一步的操作将会失败, 尽管对于Append函数的调用是成功的. 这就是为什么Append函数被认为是对字符串的操作(不进行目录路径的有效性验证).

+ +

The WebLock component manipulates a file named weblock.txt. The following snippet adjusts the theFile object representing that file:

+ +

WebLock组件操作名为weblock.txt的文件, 以下程序片段调整了theFile对象以表示那个文件:

+ +
nsEmbedCString fileName("weblock.txt");
+appDir->AppendNative(fileName);
+
+ +

Manipulating Files with nsIFile

+ +

Once you have an nsIFile object pointing to the file that you're interested in, you can open it and read its contents into memory. There are many ways to do this: You can use Standard ANSI File I/O, or NSPR (see The Netscape Portable Runtime Library below for a brief description of NSPR), or you can use the networking APIs that Gecko provides.

+ +
+

The Netscape Portable Runtime Library

+ +

TheNetscape Portable Runtime Library (NSPR) is a platform-independent library that sits below XPCOM. As a layer of abstraction above the operating system, the NSPR allows Gecko applications to be platform independent by providing the following system-level facilities:

+ + + +

The NSPR is included in the Gecko SDK.

+
+ +

To keep things as simple as possible, we'll read the file into memory using standard ANSI file I/O, but for examples and information about how to usenecko , the Gecko networking libraries, see http://www.mozilla.org/projects/netlib/.

+ +

Using nsILocalFile for Reading Data

+ +

An nsIFile object returned from the directory service may also implement the nsILocalFile interface, which has a method that will return a FILE pointer that can be used in fread(). To implement the actual read, you need to allocate a buffer the length of the file, use the nsILocalFile interface pointer to obtain a FILE *, use this result with fread, and close the file pointer.

+ +

The following code loads the contents of the file referenced by the nsIFile object theFile into the buffer buf:

+ +
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(theFile);
+if (!localFile)
+  return -1;
+
+PRBool exists;
+rv = theFile->Exists(&exists);
+if (NS_FAILED(rv))
+  return -1;
+
+char *buf = NULL;
+
+if (exists)
+{
+  // determine file size:
+  PRUint32 fs, numread;
+  PRInt64 fileSize;
+  rv = theFile->GetFileSize(&fileSize);
+  if (NS_FAILED(rv))
+    return -1;
+
+  // Converting 64 bit value to unsigned int
+  LL_L2UI(fs, fileSize);
+
+  FILE* openFile;
+  rv = localFile->OpenANSIFileDesc("rw", &openFile);
+  if (NS_FAILED(rv))
+    return -1;
+
+  char *buf = (char *)malloc((fs+1) * sizeof(char));
+  if (!buf)
+    return -1;
+
+  numread = fread(buf, sizeof(char), fs, openFile);
+
+  if (numread != fs)
+    // do something useful.
+
+  // ...
+}
+
+if (buf)
+  free(buf);
+
+ +

The first line of the code calls QueryInterface on theFile, and if that succeeds assigns the new interface pointer to localFile. If the QueryInterface call fails, localFile will have a value of NULL.

+ +
+

Note that the out parameter of the method GetFileSize is a 64-bit integer. The type of this variable is PRInt64, but this type is not represented as a primitive on all platforms. On some platforms, PRInt64 is a struct with two fields - a high and a low 32-bit integer. So operations on this type must use special macros that do the right thing on each platform. On Windows or Linux, for example, it is possible to multiply a PRInt64 by a long like this:

+ +
PRInt64 x = 1, y = 2;
+y = x * 2;
+
+ +

However, this same snippet will not compile on a platform like Macintosh OS 9, where you need to use macros to perform the calculation:

+ +
PRInt64 x, y, two;
+LL_I2L(x, 1);
+LL_I2L(y, 2);
+LL_I2L(two, 2);
+LL_MUL(y, x, two);
+
+ +

A full listing of NSPR's long long support can be found at http://www.mozilla.org/projects/nspr/.

+ +

The WebLock component doesn't have to deal with files that are longer than 232 bytes. Truncating this value to whatever can fit into a 32-bit unsigned integer may not work for every application, but in this case it doesn't really matter.

+
+ +

Processing the White List Data

+ +

There are various ways to process the file data itself. The file weblock.txt consists of URL tokens separated by return characters, which makes them easy to read into a data structure.

+ +

The white list file can be read in as soon as the component starts up (i.e., as WebLock intercepts the startup notification in the Observe method of the nsIObserver interface that we implement). Since we have only registered to receive a notification when XPCOM starts up, it's a safe assumption that Observe will only be called during the startup event, so we can read the file data in the callback.

+ +

After you've read the data into memory, you need to store it in some way to make data access quick and efficient.

+ +
+

URL Checking

+ +

The way in which URL checking is implemented in the WebLock component is not at all optimal. The WebLock component manages a simple linked list of URL strings. A linear search through the data in the white list may not be terribly bad if the number of URLs is under a couple of dozen, but it decays as the list grows. There's also a large bottleneck in the network request. URL data is accessed as in the diagram below:

+ +

Image:urldata-access-in-weblock.png

+ +

You might construct hash values for each of the URL strings instead, or add them to some kind of database. But we leave optimizations and real-world performance for web locking to the reader.

+
+ +

iWebLock Method by Method

+ +

The implementation of the iWeblock interface is straightforward. WebLock is designed so that the user interface notifies this service when we should go into lock mode. During this time, any new URL request that is not in our list of "good" URLs will be denied. Through scriptable access to the iWebLock interface, the user interface can also add, remove, and enumerate the list of URLs that it knows about.

+ +

Lock and Unlock

+ +

The lock and unlock methods simply set a Boolean representing state in the object. This Boolean value will be used later to determine if we should be denying URL requests:

+ +
/* void lock (); */
+NS_IMETHODIMP
+WebLock::Lock()
+{
+  mLocked = PR_TRUE;
+  return NS_OK;
+}
+
+/* void unlock (); */
+NS_IMETHODIMP WebLock::Unlock()
+{
+  mLocked = PR_FALSE;
+  return NS_OK;
+}
+
+ +

AddSite

+ +

For AddSite, we add a new node to our linked list. The link list nodes contain a char* which points to the string URL that we care about and, of course, a pointer to the next element in the list.

+ +
+

nsMemory for Cross-component Boundaries

+ +

WebLock maintains ownership of all the memory it allocates, so you can use just about any allocator that you want for WebLock, but this is not always the case. In other places, where allocated buffers cross interface boundaries, you must ensure that the correct allocator is used - namely nsMemory - so that the allocators can match the allocation with the deallocation.

+ +

Suppose you call malloc from object A and pass this buffer to another object B, for example. But if object B is using a special allocator that does garbage collection, then when object B deletes a buffer allocated by object A's allocator, the results are unpredictable: probably an assertion will be raised, possibly a memory leak, or a crash. The nsMemory class is a wrapper around the nsIMemory interface, whose only implementation is part of XPCOM. When you use nsMemory, you are guaranteed to be using this same memory allocator in all cases, and this avoids the problem described here.

+
+ +

RemoveSite

+ +

RemoveSite deletes a node from the linked list:

+ +
// a simple link list.
+struct urlNode
+{
+  char* urlString;
+  struct urlNode* next;
+};
+
+/* void addSite (in string url); */
+NS_IMETHODIMP
+WebLock::AddSite(const char *url)
+{
+  // we don't special-case duplicates here
+  urlNode* node = (urlNode*) malloc(sizeof(urlNode));
+  node->urlString = strdup(url);
+  node->next = mRootURLNode;
+  mRootURLNode = node;
+
+  return NS_OK;
+}
+
+/* void removeSite (in string url); */
+NS_IMETHODIMP
+WebLock::RemoveSite(const char *url)
+{
+  // find our entry.
+  urlNode* node = mRootURLNode;
+  urlNode* prev = nsnull;
+
+  while (node)  // test this!
+  {
+    if (strcmp(node->urlString, url) == 0)
+    {
+      free(node->urlString);
+      if (prev)
+        prev->next = node->next;
+      free(node);
+      return NS_OK;
+    }
+    prev = node;
+    node = node->next;
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
+ +

SetSites

+ +

The purpose of SetSites is to allow clients to pass an enumeration, or set, of URL strings to add to the white list of URLs. SetSites uses an nsISimpleEnumerator and shows how primitive data can be passed as an nsISupports object. The nsISimpleEnumerator interface is shown in The Web Locking Interface.

+ +

The first method returns a Boolean if there are more elements in the set. Internally, the object knows the number of elements it has in its enumeration, and every time a client calls getNext, it decrements a counter - or adjusts a pointer to the next element. When the counter goes to zero or the pointer points to a non-element, hasMoreElements will return false.

+ +

There is no way to reset an nsISimpleEnumerator. For example, you can't re-enumerate the set. If you need random access to the elements in a nsISimpleEnumerator, you can read them from the nsISimpleEnumerator, store them in an array, and access them there. The getNext method returns a nsISupports interface pointer.

+ +

When you want to pass primitive data types like numbers, strings, characters, void *, and others, the solution is to use one of the nsISupportsPrimitive interfaces. These interfaces wrap primitive data types and derive from nsISupports. This allows types like the strings that represent URLs in the WebLock component to be passed though methods that take an nsISupports interface pointer. This becomes clear when when you see the implementation of SetSites:

+ +
NS_IMETHODIMP
+WebLock::SetSites(nsISimpleEnumerator * aSites)
+{
+  PRBool more = PR_TRUE;
+  while (more)
+  {
+    nsCOMPtr<nsISupports> supports;
+    aSites->GetNext(getter_AddRefs(supports));
+
+    nsCOMPtr<nsISupportsCString> supportsString =  do_QueryInterface(supports);
+
+    if (supportsString)
+    {
+      nsEmbedCString url;
+      supportsString->GetData(url);
+      AddSite(url.get());
+    }
+
+        aSites->HasMoreElements(&more);
+  }
+
+  return NS_OK;
+}
+
+ +

GetNext

+ +

GetNext is called with the nsCOMPtr of an nsISupportsCString. nsCOMPtrs are nice because they do whatever QueryInterface calls are necessary under the hood. For example, we know that the GetNext method takes an nsISupports object, but we may not be sure whether the return result supports the interface we want, nsISupportsCString. But after GetNext returns, the nsCOMPtr code takes the out parameter from GetNext and tries to QueryInterface it to the nsCOMPtr's type. In this case, if the out parameter of GetData does not return something that is QueryInterface-able to an nsISupportsCString, the variable will be set to null. Once you know that you have an nsISupportsCString, you can grab the data from the primitive supports interface.

+ +

To get something you can pass into the AddSite method, you need to convert from an nsEmbedCString to a const char*. To do this, you can take advantage of the nsEmbedCString described in String Classes in XPCOM.

+ +

GetSites

+ +

The implementation of GetSites is more involved. You must construct an implementation of nsISimpleEnumerator and return it when GetSites is called. The class needs to walk the list of urlNode's for every call to GetNext, so it makes sense for the constructor itself to take an urlNode:

+ +
class myEnumerator : public nsISimpleEnumerator
+{
+  public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSISIMPLEENUMERATOR
+
+    myEnumerator(urlNode* node) {
+      NS_INIT_ISUPPORTS()
+      mNode = node;
+    }
+    virtual ~myEnumerator(void) {}
+
+  protected:
+    urlNode* mNode;
+    nsCOMPtr<nsIComponentManager> mCompMgr;
+};
+
+NS_IMPL_ISUPPORTS1(myEnumerator, nsISimpleEnumerator);
+
+ +

The myEnumerator class is going to implement the nsISupports interface and also nsISimpleEnumerator. The only state that it needs to maintain is the current URL node - the one that will be return on the next call to GetNext. There is also an nsCOMPtr to the nsIComponentManager, which is used in every call to GetNext so that you can create nsISupportsCString objects and cache the interface pointer as an optimization.

+ +

HasMoreElements

+ +

HasMoreElements is simple. All you need to do is make sure that mNode isn't null:

+ +
NS_IMETHODIMP
+myEnumerator::HasMoreElements(PRBool* aResult)
+{
+  if (!aResult)
+    return NS_ERROR_NULL_POINTER;
+
+  if (!mNode) {
+    *aResult = PR_FALSE;
+    return NS_OK;
+  }
+
+  *aResult = PR_TRUE;
+  return NS_OK;
+}
+
+ +

GetNext needs to create an nsISupportsCString so that you can pass the URL string out through the nsISupports parameter. You must also move mNode to point to the next urlNode.

+ +
static NS_DEFINE_CID(kSupportsCStringCID, NS_SUPPORTS_CSTRING_CID);
+
+NS_IMETHODIMP
+myEnumerator::GetNext(nsISupports** aResult)
+{
+  if (!aResult)
+    return NS_ERROR_NULL_POINTER;
+
+  *aResult = nsnull;
+
+  if (!mNode)
+    return NS_ERROR_FAILURE;
+
+  if (!mCompMgr)
+  {
+    NS_GetComponentManager(getter_AddRefs(mCompMgr));
+    if (!mCompMgr)
+      return NS_ERROR_UNEXPECTED;
+  }
+
+  nsISupportsCString* stringSupports;
+  mCompMgr->CreateInstance(kSupportsCStringCID,
+                           nsnull,
+                           NS_GET_IID(nsISupportsCString),
+                           (void**)&stringSupports);
+  if (!stringSupports)
+    return NS_ERROR_UNEXPECTED;
+
+  nsEmbedCString str(mNode->urlString);
+  stringSupports->SetData(str);
+
+  *aResult = stringSupports; // addref'ed above.
+
+  mNode = mNode->next;
+
+  return NS_OK;
+}
+
+ +

在实际的GetSites呼叫中, 你需要做的就是产生一个myEnumerator实例并且返回它.

+ +

此前,我们建立了一个类并且把它注册到组件管理器。当一个客户端需要获取某个接口的实现时,实际上的对象建立过程隐藏在XPCOM代码中。 但是其中, 你要初始化你自己的nsISimpleEnumerator实现. 这是一个简单的事情,但是你需要注意NS_ADDREF.

+ +
NS_IMETHODIMP
+WebLock::GetSites(nsISimpleEnumerator * *aSites)
+{
+  myEnumerator* enumerator = new myEnumerator(mRootURLNode);
+  if (!enumerator)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  NS_ADDREF(*aSites = enumerator);
+  return NS_OK;
+}
+
+ +
+

AddRef, Releasing, and Deleting Objects

+ +

永远不要忘记调用你通过new建立的XPCOM对象的AddRef方法。所有的代码或者活动组件都应该有一个起码一个引用计数。忘记这点可能引起麻烦。

+ +

一个相关的警示试你不要忘记永远不要用delete删除一个XPCOM. 当系统的一部分不是释放而是删除一个XPCOM对象的时候,可能会引起几个小时的资源搜索并且引起崩溃。

+
+ +

注意上面的实现中,当其他的线程访问链接表的时候myEnumerator 可能变得非法。枚举仅仅表现了访问URL字符串链接表的一个方法。如果你需要枚举成为URL字符串链表的一个快照,你需要重构这个实现让枚举持有一个链表的copy。

+ +

当组件中止的时候,你也需要把链表写到磁盘里并且释放空间。我们把这个作为练习留给读者。

+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_components/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_components/index.html new file mode 100644 index 0000000000..a0a5b301ba --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_components/index.html @@ -0,0 +1,311 @@ +--- +title: 创建_XPCOM_组件/使用_XPCOM_组件 +slug: Mozilla/Tech/XPCOM/Guide/Creating_components/Using_XPCOM_Components +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Creating_components/Using_XPCOM_Components +--- +

+

« 上一页下一页 »

+

+ +

创建一个新的 XPCOM 组件, 特别是在我们设计一个供别人使用的组件接口的时候, 最好方式是参照已有的组件. 我们在编写 Starting WebLock 这个例子的时候, 也是这么做的.

+ +

Mozilla 浏览器应用是复杂的, 模块化的 XPCOM 客户程序. 实际上, 基本上所有与浏览器相关的功能都被定义成了组件的形式, 包括网页间的跳转, 窗口管理, cookie 管理, 书签, 安全, 搜索, 润色等等的其他功能, 这些功能都是由组件的接口提供的. Mozilla就是一堆 XPCOM 组件.

+ +

本章将讨论 Mozilla 是如何使用象 CookieManager 这样的 XPCOM 对象, 然后根据这些例子我们定义 WebLock 组件的访问接口.

+ +

组件的例子

+ +

可以在这里 XPCOM API Reference 找到下面要描述的组件. 我们要了解的是象本节中所给出的组件是如何被 Mozilla 浏览器获取和使用的.

+ + + +

Cookie 管理是以组件形式向 Mozilla 浏览器提供支持的众多组件之一, 这些组件可以被重用在需要类似功能的应用中. 当用户通过 Cookie 管理器对话框来观察, 组织, 或者删除 cookies 的时候, Cookie 管理器在背后默默的工作. Cookie 管理器对话框负责向用户提供 Cookie 管理器的 UI 界面[cookie-manager-ui].

+ +

Cookie 管理器对话框

+ +

Image:cookie_mgr_dlog.png

+ +

对话框是用 XUL (XML UI 语言) 和 JavaScript 语言编写, 使用称为XPConnect 的组件无缝连接到 Cookie 管理器组件(参看下面的 从接口连接到组件). XUL 只是一种暴露 Cookie 管理器功能的方式, 但是却是 Mozilla 环境下最有用的方式之一.

+ +

CookieManager 组件的功能通过 nsICookieManager 接口提供, 接口的方法如下:

+ +

nsICookieManager 接口

+ + + + + + + + + + + + + + + + +
removeAll删除 cookie 列表中所有的 cookies.
enumerator通过 cookie 列表枚举.
remove从列表中删除某个 cookie .
+ +

XPCOM 中所有的接口必须固定, 虽然组件对接口的实现会有所变化. 接口都是public 的, 相对的, 接口实现是 private 的[private-xpcom-interfaces]. 当用户选中 cookie 列表中的一个 cookie, 点击 Remove 按钮, nsICookieManager 接口的 Remove 方法被调用. CookieManager 组件执行该函数, 选中的组件就被删除了.

+ +

下面的从 JavaScript 中访问 CookieManager 组件代码, 展示了如何从 JavaScript 中调用 Remove() 方法:

+ +

从 JavaScript 中访问 CookieManager 组件

+ +
// xpconnect to cookiemanager
+// get the cookie manager component in JavaScript
+var cmgr = Components.classes["@mozilla.org/cookiemanager;1"]
+                     .getService();
+cmgr = cmgr.QueryInterface(Components.interfaces.nsICookieManager);
+
+// called as part of a largerDeleteAllCookies() function
+function FinalizeCookieDeletions() {
+  for (var c=0; c<deletedCookies.length; c++) {
+    cmgr.remove(deletedCookies[c].host,
+                deletedCookies[c].name,
+                deletedCookies[c].path);
+  }
+  deletedCookies.length = 0;
+}
+
+ +
+

从接口连接到组件

+ +

Mozilla 中使用的从 JavaScript 访问 XPCOM 组件的技术称为XPConnect, XPConnect 也是一个组件.

+ +

XPConnect 把应用程序代码与 Mozilla 浏览器, 基于 Gecko 的 XUL, 和象 xpcshell 这样的 JavaScript 环境绑定在一起.

+ +

xpcshsell 是 Mozilla 内嵌的 XPCOM 工具, 它是 JavaScript 的命令行解释器.

+ +

参看 http://www.mozilla.org/scriptable/, 获取更多关于 XPConnect 和 JavaScript 的信息.

+
+ +

上面展现的技术当然并不是 XPCOM 的全部, 但是却是一个重要的方面. XPCOM 强加的契约打开了一扇通往二进制互操作技术的大门. - 这是一种能够在运行时刻访问, 使用, 重用 XPCOM 组件的技术, 这种技术能够保证用某种语言编写的组件能够被其他的语言所访问.

+ +

在 Mozilla 浏览器中, 组件常常通过接口在 JavaScript 中访问, 搜索 Mozilla 的源代码, 会发现 CookieManager 组件只是在 JavaScript 中被调用. 在本教程中, 我们也使用这种方式来访问它[教程中使用的 coocki 管理器].

+ +
+

JavaScript 与 Mozilla

+ +

JavaScript 是 Mozilla 浏览器的喉舌, 它把自己与 XPCOM 紧紧地绑定在一起. XPCOM 的这种可扩展能力 - 从 XPConnect 绑定的语言中访问组件的能力, 是 XPCOM 的一个关键属性.

+
+ +

WebBrowserFind 组件

+ +

组件的应用是广泛的: 在浏览这样的高级应用中, 会有 nsWebBrowserFind 这样的接口, 它提供 find()findNext() 方法用于在网页上查找特定内容. 在一些低级应用中, 会提供数据管理这样的功能. 虽然 Mozilla 并不能将所有的 API 都写成 XPCOM 组件的形式, 但是绝大多数浏览器的典型功能都是用 XPCOM 的组件形式实现的, 因此可以被嵌入和扩展.

+ +

除了 CookieManager 组件, 这里还要介绍一个 WebBrowserFind 组件. 它实现的 nsIWebBrowserFind 接口见下表 nsIWebBrowserFind 接口.

+ +

nsIWebBrowserFind 接口

+ + + + + + + + + + + + + + + + + + + + + + + + +
findNext找到字符串出现的下一个位置.
findBackwards布尔类型属性值, 控制 findNext() 方法向前/向后搜索.
searchFrames布尔类型属性值, 标识是否搜索当前页面的子框(subframes).
matchCase布尔类型属性值, 标识是否按照大小写匹配搜索网页.
entireWord布尔类型属性值, 标识是否匹配整个词.
+ +

一旦我们使用接口来获的了某个组件, 我们就可以询问该组件是否支持其他的接口. 这种基本服务由 nsISupports 接口提供, 会由所有的 XPCOM 组件继承; 它允许我们查询组件的接口, 并在接口之间进行切换; 它展现了 XPCOM 的运行时刻确定类型的能力. 它由 QueryInterface 方法实现, 我们将在后面什么是 XPCOM?一章中介绍. XPCOM API Reference 中提供了完整的 XPCOM 组件的索引.

+ +

WebLock 组件

+ +

现在我们把 WebLock 组件看成另一个 XPCOM 组件的例子. 在面向对象编程中, 通常是先设计接口 - 首先定义要提供的功能, 而不是考虑如何实现这些功能. 因此我们把实现这个组件的细节问题放到下一章, 这一章先考虑从外部如何看待这个组件. - 即定义 WebLock 组件的接口.

+ +

IWebLock 接口

+ + + + + + + + + + + + + + + + + + + + + + + + +
lock锁定浏览器到当前站点, 或者是磁盘上保存的某个白名单上的站点.
unlock解开浏览器锁定, 开放访问所有站点.
addSite添加一个新的站点到白名单.
removeSite从白名单上删除某个站点.
sites枚举白名单上的站点.
+ +

WebLock 组件就是要实现上面接口定义的功能. 它在浏览器启动的时候, 注册自己. 当用户或者管理员点击浏览器上的 weblock 图标时, 类厂会创建对象实例.

+ +

Mozilla 中使用的组件

+ +

那么我们应该如何获得组件, 然后如何在 Mozilla 中使用它呢? 我们在前面已经看到了一小段 JavaScript 代码, 但是我们并没有解释一般情况下该如何获得 XPCOM 组件.

+ +

这一节讨论 Mozilla 中实际使用的组件例子. 本节分成三部分: 一部分是关于该如何在 Mozilla 上找到组件. 其他两个部分是关于该如何访问这些组件.

+ +

查找 Mozilla 组件

+ +

本书试图向读者提供关于 XPCOM 组件和当前冻结的接口的索引信息. Mozilla 嵌入工程跟踪了当前冻结的接口.

+ +

Mozilla 包含了 Gecko 提供的查找和显示组件信息的工具 -XPCOM 组件观察器LXR.

+ +

提供 XPCOM 组件信息的主要问题是, Mozilla 接口在不断的发展, 试图选择一个冻结的断面是困难的. 组件观察器的实现并没有考虑组件是否已被冻结, 在 LXR 中我们会发现, 被冻结的接口会在头部标记 @status frozen.

+ +
XPCOM 组件观察器
+ +

组件观察器 是一个可选安装的浏览器插件.

+ +

XPCOM 组件观察器

+ +

Image:using-component-viewer.png

+ +

在上面的图中, 左列显示的是以gtx 字符串搜索契约 ID 得到的组件子集, 右列是左列选中组件实现的接口.

+ +

XPCOM 观察器在获取组件的大致信息的时候非常有用, 但是要知道组件观察器显示的是所有的组件, 有些组件并不稳定, 组件的接口可能会在后续版本中变化, 所以要慎重选取我们自己工程中使用的组件.

+ +

XXX mediawiki is t3h suxx0r XXX give me my C++

+ +

在 Cpp 代码中使用 XPCOM 组件

+ +

XPConnect 把对 XPCOM 组件作为 JavaScript 对象, 使得对 XPCOM 组件的访问变得非常简单, 从 C++ 代码中访问 XPCOM 要复杂一些.

+ +

从 Cpp 代码管理 Cookies 以 C++ 代码重新实现了从 JavaScript 中访问 CookieManager 组件的功能.

+ +

从 Cpp 代码管理 Cookies

+ +
nsCOMPtr<nsIServiceManager> servMan;
+nsresult rv = NS_GetServiceManager(getter_AddRefs(servMan));
+if (NS_FAILED(rv))
+  return -1;
+
+nsCOMPtr<nsICookieManager> cookieManager;
+rv = servMan->GetServiceByContractID("@mozilla.org/cookiemanager",
+                                     NS_GET_IID(nsICookieManager),
+                                     getter_AddRefs(cookieManager));
+
+if (NS_FAILED(rv))
+  return -1;
+
+PRUint32 len;
+deletedCookies->GetLength(&len);
+
+for (int c=0; c<len; c++)
+    cookieManager->Remove(deletedCookies[c].host,
+                          deletedCookies[c].name,
+                          deletedCookies[c].path,
+                          PR_FALSE);
+
+ +

XXX: In the original document, there were only the first three parameters to the |Remove| call. I added |PR_TRUE| as a fourth parameter because the interface seems to require it: http://lxr.mozilla.org/mozilla/sourc...Manager.idl#64 This problem also appears in the JavaScript version below, and I've added |false| as a fourth parameter there as well.

+ +

如果我们的应用是用 C++ 编写, 从 Cpp 代码管理 Cookies 这段代码向我们提供了很好的模板.

+ +

XPConnect: 在脚本中使用 XPCOM 组件

+ +

在本章开始我们讨论了CookieManager组件,他提供了一个很好的例子来说明如何使用javascript访问组件.在下面的代码片断里你可以看到如何通过getService()方法创建一个CookieManager组件对象,并且通过它提供的功能来让我们从用户界面来读取和删除cookies.

+ +

Managing Cookies from JavaScript

+ +
var cmgr = Components.classes["@mozilla.org/cookiemanager;1"]
+                     .getService();
+cmgr = cmgr.QueryInterface(Components.interfaces.nsICookieManager);
+
+function loadCookies() {
+  // load cookies into a table
+  var enumerator = cmgr.enumerator;
+  var count = 0;
+  var showPolicyField = false;
+  while (enumerator.hasMoreElements()) {
+    var nextCookie = enumerator.getNext();
+    nextCookie = nextCookie.QueryInterface(Components.interfaces.nsICookie);
+    /* .... */
+}
+function FinalizeCookieDeletions() {
+  for (var c=0; c<deletedCookies.length; c++) {
+    cmgr.remove(deletedCookies[c].host,
+                deletedCookies[c].name,
+                deletedCookies[c].path,
+                false);
+  }
+  deletedCookies.length = 0;
+}
+
+ +

XXX: In the original document, there were only the first three parameters to the |remove| call. I added |false| as a fourth parameter because the interface seems to require it: http://lxr.mozilla.org/mozilla/sourc...Manager.idl#64 This problem also appears in the C++ version above, and I've added |PR_FALSE| as a fourth parameter there as well.

+ +

除了CookieManager被调用的方法以外(也就是cookiemanager.remove(他会映射到remove()The nsICookieManager Interface),请注意那些在Javascript中反映XPCOM组件的专门的XPConnect对象和方法。

+ +

Components 是用来控制到组件连接的JavaScript对象, 而classes 是一组所有你可以根据契约ID来查询的对象。为了在Javascript中实例化XPCOM组件,你创建一个新的Component对象同时传入你所需要查询的组件契约ID,返回的可能是一个singleton或者一个实例。

+ +
var cmgr = Components.classes["@mozilla.org/cookiemanager;1"]
+                     .getService();
+
+ +

cookiemanager 对象的结果提供组件的所有在IDL中编译好然后编译到类型库中的方法的入口。 使用CookieManager组件, 你可以写如下的代码来完成从系统中清除所有cookies的操作:

+ +
cmgr = Components.classes["@mozilla.org/cookiemanager;1"]
+                 .getService();
+cmgr = cmgr.QueryInterface(Components.interfaces.nsICookieManager);
+
+// delete all cookies
+function trashEm() {
+   cmgr.removeAll();
+}
+
+ +

这个例子所展示的另外一个关键的XPConnect特性的是可以在所有从XPCOM映射到javascript的对象上执行的QueryInterface方法。如同在C++中, 你可以使用这个方法询问给定对象的别的接口。

+ +
+

Services Versus Regular Instances

+ +

到底让客户把你的组件作为一个实例还是服务是一个设计问题,你应当在你的组件文挡中进行描述。实际上,例子中通过方法createInstance()调用getService()方法的方法实际上也可以是对组件对象调用并且缓存结果,并让他做为一个singlenton而不是实例。

+ +

用来建立服务的singleton设计模式在XPCOM Services进行描述。

+
+ +

请记住,QueryInterface让你查询一个对象所支持的接口。在The nsICookieManager Interface的代码片断中, QueryInterface方法被用来从eunumerator中获得nsICookie接口,从而, 比如说, JavaScript代码就可以获得每个cookie的valuename属性。

+ +
    +
  1. Note: cookie-manager-ui
    注意接口不是组件的一部分. XPCOM通过Mozilla's Cross Platform Front End (XPFE)和其他的用户接口使使用CookieManager这样的组件变得容易,但是组件本身并不提供自身的UI。
  2. +
+ +
    +
  1. Note: private-xpcom-interfaces
    这方面也有例外. 一些XPCOM接口也可以是private并且不是作为公用的. Private接口和在IDL中公开的接口要求有所不同。
  2. +
+ +
    +
  1. Note: cookie-manager-in-tutorial
    CookieManager组件用来支持本教程所描述的网页所定功能。
  2. +
+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_utilities_to_make_things_easier/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_utilities_to_make_things_easier/index.html new file mode 100644 index 0000000000..98bb510dd8 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/creating_components/using_xpcom_utilities_to_make_things_easier/index.html @@ -0,0 +1,388 @@ +--- +title: 创建XPCOM组件/使用XPCOM工具类让事情变得简单 +slug: >- + Mozilla/Tech/XPCOM/Guide/Creating_components/Using_XPCOM_Utilities_to_Make_Things_Easier +tags: + - XPCOM + - 所有分类 +translation_of: >- + Mozilla/Tech/XPCOM/Guide/Creating_components/Using_XPCOM_Utilities_to_Make_Things_Easier +--- +

+

« 上一页下一页 »

+

+ +

本章回顾你已经在教程第一部分建立的代码 (see webLock1.cpp in the previous chapter) 并且使用 XPCOM 工具类让代码更容易更有效. 同时,介绍一个在XPCOM和Gecko API中广泛使用基本的字符串类型.

+ +

作为起点,第一部分描述可以替代webLock1.cpp中的很多代码的C++ 宏 . 很多用来完成软件组织和组件注册的代码都可以缩减为精简的数据结构和宏代码.

+ +

XPCOM Macros

+ +

XPCOM 架构包含了一系列宏让C++开发变得简单. 尽管有某些重叠(例如,高层的宏可以用其他的宏来组织),他们通常可以组织成如下的类别.

+ +

Generic XPCOM Module Macros

+ +

The work in the previous chapter was useful in setting up the generic component code. But there are only a few places in that code that are unique to the WebLock component, and it was a lot of typing. To write a different component library, you could copy the listing at the end of the chapter, change very little, and paste it into a new project. To avoid these kinds of redundancies, to regulate the way generic code is written, and to save typing, XPCOM providesgeneric module macros that expand into the module code you've already seen.

+ +

Since these macros expand into "generic" implementations, they may not offer as much flexibility as you have when you are writing your own implementation. But they have the advantage of allowing much more rapid development. To get an idea about how much can be handled with the macros described in this section, compare the code listing in weblock2.cpp at the end of the chapter with webLock1.cpp in the previous chapter.

+ +

The module macros include one set of macros that define the exported NSGetModule entry point, the required nsIModule implementation code and another that creates a generic factory for your implementation class. Used together, these macros can take care of a lot of the component implementation code and leave you working on the actual logic for your component.

+ +
+

Note that all of the macros described in this section are similar but are used in slightly different situations. Some differ only in whether or not a method is called when the module is created and/or destroyed. XPCOM Module Macros lists the macros discussed in this section.

+
+ +

XPCOM Module Macros

+ + + + + + + + + + + + + + + + + + + + + + + + +
MacroDescription
NS_IMPL_NSGETMODULE(name, components)Implements the nsIModule interface with the module name of name and the component list in components.
NS_IMPL_NSGETMODULE_WITH_CTOR(name, components, ctor)Same as above but allows for a special function to be called when the module is created.
NS_IMPL_NSGETMODULE_WITH_DTOR(name, components, dtor)Same as the first macro but allows for a special function to be called when the module is destroyed.
NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(name, components, ctor, dtor)This combines the last two macros so that you can define functions to be called at the construction and destruction of the module object.
+ +
Module Implementation Macros
+ +

The general case is to use NS_IMPL_NSGETMODULE, which doesn't take any callbacks, but all the macros follow the same general pattern. All of these macros work on an array of structures represented by the components parameter. Each structure describes a CID that is to be registered with XPCOM.

+ +

The first parameter for each of these macros is an arbitrary string that names the module. In a debugging environment, this string will be printed to the screen when the component library is loaded or unloaded. You should pick a name that makes sense and helps you keep track of things. The four required parts[other-parts] of the structure contain the following information:

+ + + +
static const nsModuleComponentInfo components[] =
+{
+  { "Pretty Class Name",
+    CID,
+    CONTRACT_ID,
+    Constructor
+  },
+  // ...
+};
+
+ +

The important thing to note in the fictitious listing above is that it can support multiple components in a module. Modules such as the networking libraries in Gecko ("necko") have over 50 components declared in a single nsModuleComponentInfo array like this.

+ +

The first entry of the nsModuleComponentInfo above is the name of the component. Though it isn't used that much internally at the present time, this name should be something that meaningfully describes the module.

+ +

The second entry of the nsModuleComponentInfo is the CID. The usual practice is to put the class ID (CID) into a #define and use the define to declare the CID in the components list. Many CIDs take the following form:

+ +
#define NS_IOSERVICE_CID                             \
+{ /* 9ac9e770-18bc-11d3-9337-00104ba0fd40 */         \
+    0x9ac9e770,                                      \
+    0x18bc,                                          \
+    0x11d3,                                          \
+    {0x93, 0x37, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
+}
+
+ +

The next entry is the Contract ID string, which is also usually defined in a #define in a header file.

+ +

These three entries constitute the required parameters for the RegisterFactoryLocation method we looked at in the prior chapter. When you use these implementation macros, you must declare a constructor for the object, and this keeps you from having to write a factory object.

+ +
Factory Macros
+ +

The factory macro makes it easy to write factory implementations. Given the class name ConcreteClass, the factory macro declaration is:

+ +
NS_GENERIC_FACTORY_CONSTRUCTOR(ConcreteClass)
+
+ +

This results in a function called ConcreteClassConstructor that can be used in the nsModuleComponentInfo structure.

+ +
#include "nsIGenericFactory.h"
+
+static const nsModuleComponentInfo components[] =
+{
+  { "Pretty Class Name",
+    SAMPLE_CID,
+    "@company.com/sample",
+    SampleConstructor
+  }
+}
+
+NS_IMPL_NSGETMODULE(nsSampleModule, components)
+
+ +

Most of the components in the Mozilla browser client use this approach.

+ +

Common Implementation Macros

+ +

Every XPCOM object implements nsISupports, but writing this implementation over and over is tedious. Unless you have very special requirements for managing reference counting or handling interface discovery, theimplementation macros that XPCOM provides can be used. Instead of implementing the nsISupports yourself, NS_IMPL_ISUPPORTS1 can expand to the implementation of AddRef, Release, and QueryInterface for any object.

+ +
NS_IMPL_ISUPPORTS1(classname, interface1)
+
+ +

Also, if you implement more than one interface, you can simply change the 1 in the macro to the number of interfaces you support and list the interfaces, separated by commas. For example:

+ +
NS_IMPL_ISUPPORTS2(classname, interface1, interface2)
+NS_IMPL_ISUPPORTSn(classname, interface1, ..., interfacen)
+
+ +

These macros automatically add the nsISupports entry for you, so you don't need to do something like this:

+ +
NS_IMPL_ISUPPORTS2(classname, interface1, nsISupports)
+
+ +


+ Take a close look at the above example. Note that it uses the actual name of the interface and not an IID. Inside the macro, the interface name expands to NS_GET_IID(), which is another macro that extracts the IID from the generated header of the interface. When an interface is written in XPIDL, the headers include static declarations of their IIDs. On any interface that is generated by XPIDL, you can call NS_GET_IID() to obtain the IID which is associated with that interface.

+ +
// returns a reference to a shared nsIID object\
+static const nsIID iid1 = NS_GET_IID(nsISupports);
+
+// constructs a new nsIID object
+static const nsIID iid2 = NS_ISUPPORTS_IID;
+
+ +

In order to use NS_IMPL_ISUPPORTSn, you must be sure that a member variable of type nsrefcnt is defined and named mRefCnt in your class. But why even bother when you can use another macro?

+ +

Declaration Macros

+ +

NS_DECL_NSISUPPORTS declares AddRef, Release, and QueryInterface for you, and it also defines the mRefCnt required by NS_IMPL_ISUPPORTS. Furthermore, NS_DECL_ appended with any interface name in all caps will declare all of the methods of that interface for you. For example, NS_DECL_NSIFOO will declare all of the methods of nsIFoo provided that it exists and that nsIFoo.h was generated by the XPIDL compiler. Consider the following real class:

+ +
class myEnumerator : public nsISimpleEnumerator
+{
+  public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSISIMPLEENUMERATOR
+
+    myEnumerator();
+    virtual ~myEnumerator() {}
+};
+
+ +

The declaration of this nsISimpleEnumerator class doesn't include any methods other than the contructor and destructor. Instead, the class uses the NS_DECL_ macro[nsISupports-warning].

+ +

Using these declaration macros not only saves a tremendous amount of time when you're writing the code, it can also save time if you make changes to your IDL file, since the C++ header file will then automatically include the updated list of methods to be supported.

+ +
+

The NS_INIT_ISUPPORTS macro is also a bit of a special case. Historically, it gets called in the constructor for your class and sets mRefCnt to zero. However, a change in XPCOM that occurred before Mozilla 1.3 makes NS_INIT_ISUPPORTS no longer necessary: mRefCnt's type has been changed from an integer to a class that provides its own auto-initialization. If you are building with versions earlier than Mozilla 1.3, this macro is still required.

+
+ +

The following table summarizes the macro usage in this portion of the weblock.cpp source file:

+ +

Common XPCOM Macros

+ + + + + + + + + + + + + + + + + + + + +
NS_IMPL_ISUPPORTSnImplements nsISupports for a given class with n number of interfaces
NS_DECL_ISUPPORTSDeclares methods of nsISupports including mRefCnt
NS_INIT_ISUPPORTSInitializes mRefCnt to zero. Must be called in class's constructor
NS_GET_IIDReturns the IID given the name of an interface. Interface must be generated by XPIDL
+ +

Using the macros described here, the code for the WebLock component has gone from around 340 lines of code to just under 40. Clearly from a code maintenance point of view, this kind of reduction is outstanding. The entire source file with these macros included appears in weblock2.cpp.

+ +

weblock2.cpp

+ +

The listing below shows the generic module code from webLock1.cpp using the macros described in this chapter:

+ +

weblock2.cpp

+ +
#include "nsIGenericFactory.h"
+#include "nsISupportsUtils.h"
+
+#define SAMPLE_CID \
+{ 0x777f7150, 0x4a2b, 0x4301, \
+{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}}
+
+class Sample: public nsISupports
+{
+  public:
+    Sample();
+    virtual ~Sample();
+
+    NS_DECL_ISUPPORTS
+};
+
+Sample::Sample()
+{
+  // note: in newer versions of Gecko (1.3 or later)
+  // you don't have to do this:
+  NS_INIT_ISUPPORTS();
+}
+
+Sample::~Sample()
+{
+}
+
+NS_IMPL_ISUPPORTS1(Sample, nsISupports);
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(Sample);
+
+static const nsModuleComponentInfo components[] =
+{
+  { "Pretty Class Name",
+    SAMPLE_CID,
+    "@company.com/sample",
+    SampleConstructor
+  }
+};
+
+NS_IMPL_NSGETMODULE(nsSampleModule, components)
+
+ +

String Classes in XPCOM

+ +

Strings are usually thought of as linear sequences of characters. In C++, the string literal "XPCOM", for example, consists of 6 consecutive bytes, where `X' is at byte offset zero and a null character is at byte offset 5. Other kinds of strings like "wide" strings use two bytes to represent each character, and are often used to deal with Unicode strings.

+ +

The string classes in XPCOM are not just limited to representing a null terminated sequence of characters, however. They are fairly complex because they support the Gecko layout engine and other subsystems that manage large chunks of data. Additionally, in some versions of Mozilla the string classes support sequences of characters broken up into multiple fragments (fragments which may or may not be null terminated)[nulls-in-strings].

+ +

All string classes in XPCOM derive from one of two abstract classes[other-string-classes]: nsAString and nsACString. The former handles double byte characters, and the latter tends to be used in more general circumstances, but both of these classes define the functionality of a string. You can see these classes being passed as arguments in many of the XPCOM interfaces we'll look at in the following chapters.

+ +

Using Strings

+ +

Explaining how all the string classes work is outside the scope of this book, but we can show you how to use strings in the WebLock component. The first thing to note is that the string classes themselves are not frozen, which means that you should not link against them when you can avoid it.

+ +

Linking the full string library (.lib or .a) into a component may raise its footprint by more than 100k (on Windows), which in many cases is an unacceptable gain (see the XPCOM string guide). For WebLock, where the string classes need to be only wrappers around already existing string data, trading advanced functionality for a much smaller footprint is the right way to go. The WebLock string classes don't need to append, concatenate, search, or do any other real work on the string data; they just need to represent char* and other data and pass them to methods that expect an nsACString.

+ +

nsEmbedString and nsEmbedCString

+ +

The strings used in this tutorial are nsEmbedString and nsEmbedCString, which implement the nsAString abstract class and the nsACString abstract classes, respectively. This first example shows an nsEmbedCString being used to pass an nsACString to a method that's not expected to modify the string.

+ +
// in IDL: method(in ACString thing);
+
+char* str = "How now brown cow?";
+nsEmbedCString data(str);
+rv = object->Method(data);
+
+ +

In this next example, the method is going to set the value of the string - as it might need to do when it returns the name of the current user or the last viewed URL.

+ +
// in IDL:  attribute ACString data;
+
+nsEmbedCString data;
+method->GetData(data);
+
+// now to extract the data from the url class:
+
+const char* aStringURL = data.get();
+
+ +

Note that the memory pointed to by aStringURL after the call to url.get() is owned by the URL string object. If you need to keep this string data around past the lifetime of the string object, you must make a copy.

+ +
+

String Size

+ +

The examples above illustrate the use of the single byte string class, nsEmbedCString. The double byte version, nsEmbedString, has the same functionality but the constructor takes nsAString and the .get() method returns the type PRUnichar*. Note that PRUnichar is a two byte value. In the coming chapters, you'll see examples that use this version in the WebLock component.

+
+ +

Smart Pointers

+ +

All of the interfaces that you've seen so far are reference counted. Leaking a reference by not releasing an object, as the code below demonstrates, can be a major problem.

+ +
{
+  nsISupports* value = nsnull;
+  object->method(&value);
+  if (!value) return;
+
+  // ...
+
+  if (NS_FAILED(error))
+    return;   // <------------ leaks |value|
+  //...
+
+  NS_RELEASE(value);  // release our reference
+}
+
+ +

A method returns an nsISupports interface pointer that has been reference counted before it is returned (assuming it wasn't nsnull). If you handle an error condition by returning prematurely, whatever value points at will leak-it will never be deleted. This is a trivial fix in this example, but in real code, this can easily happen in goto constructs, or in deep nesting with early returns.

+ +

Having more than one interface pointer that needs to be released when a block goes out of scope begs for a tool that can aid the developer. In XPCOM, this tool is the nsCOMPtr, orsmart pointer class, which can save you countless hours and simplify your code when you're dealing with interface pointers. Using smart pointers, the code above can be simplified to:

+ +
{
+  nsCOMPtr<nsISupports> value;
+  object->method(getter_AddRefs(value));
+  if (!value) return;
+
+  // ...
+
+  if (NS_FAILED(error))
+    return;
+  // ...
+}
+
+ +

The style or syntax may be unfamilar, but smart pointers are worth learning and using because they simplify the task of managing references. nsCOMPtr is a C++ template class that acts almost exactly like raw pointers, that can be compared and tested, and so on. When you pass them to a getter, you must do something special, however: You must wrap the variable with the function getter_AddRefs, as in the example above.

+ +

You cannot call the nsISupports AddRef or Release methods on a nsCOMPtr. But this restriction is desirable, since the nsCOMPtr is handling reference counting for you. If for some reason you need to adjust the reference count, you must assign the nsCOMPtr to a new variable and AddRef that. This is a common pattern when you have a local nsCOMPtr in a function and you must pass back a reference to it, as in the following:

+ +
SomeClass::Get(nsISupports** aResult)
+{
+  if (!aResult)
+    return NS_ERROR_NULL_POINTER;
+
+  nsCOMPtr<nsISupports> value;
+  object->method(getter_AddRefs(value));
+
+  *aResult = value.get();
+  NS_IF_ADDREF(*aResult);
+  return NS_OK;
+}
+
+ +

The first thing that this method does is check to see that the caller passed a valid address. If not, it doesn't even try to continue. Next, it calls another method on an object that is presumed to exist in this context. You can call a .get() method on the nsCOMPtr and have it returned for use as a raw pointer. This raw pointer can then be assigned to a variable and have its reference updated by NS_IF_ADDREF. Be very careful with the result of .get(), however. You should never call Release on this result because it may result in a crash. Instead, to explicitly release the object being held by a nsCOMPtr, you can assign zero to that pointer.

+ +

Another nice feature of smart pointers - the part that makes them smart - is that you can QueryInterface them quite easily. For example, there are two interfaces for representing a file on a file system, the nsIFile and nsILocalFile, and they are both implemented by an object. Although we haven't formally introduced these two interfaces, the next code sample shows how simple it is to switch between these two interface:

+ +
SomeClass::DoSomething(nsIFile* aFile)
+{
+  if (!aFile)
+    return NS_ERROR_NULL_POINTER;
+
+  nsresult rv;
+  nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFile, &rv);
+  // ...
+}
+
+ +

If the QueryInterface is successful, localFile will be non-null, and rv will be set to NS_OK. If QueryInterface fails, localFile will be null, and rv will be set to a specific error code corresponding to the reason for the failure. In this construct, the result code rv is an optional parameter. If you don't care what the error code is, you can simply drop it from the function call.

+ +

From this point on, we'll be using nsCOMPtrs as much as possible in WebLock. For a complete listing of smart pointer functionality, see mozilla.org's nsCOMPtr documentationXXX this should be in devmo.

+ +
    +
  1. Note: other-parts
    This section discusses the main parameters of this structure. For a complete listing of all available options you can look at the complete reference in the XPCOM API Reference.
  2. +
  3. Note: nsISupports-warning
    Note that NS_DECL_ISUPPORTS doesn't obey the general rule in which every interface has a declaration macro of the form NS_DECL_INTERFACENAME, where INTERFACENAME is the name of the interface being compiled.
  4. +
  5. Note: nulls-in-strings
    The string classes may also support embedded nulls.
  6. +
  7. Note: other-string-classes
    There are other abstract string classes, but they are outside the scope of this book.
  8. +
+ +

+

« 上一页下一页 »

+

+

Copyright (c) 2003 by Doug Turner and Ian Oeschger. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.02 or later. Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder. Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/hashtables/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/hashtables/index.html new file mode 100644 index 0000000000..24740b535c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/hashtables/index.html @@ -0,0 +1,282 @@ +--- +title: Hashtables +slug: Mozilla/Tech/XPCOM/Guide/Hashtables +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Hashtables +--- +

 

+

What Is a Hashtable?

+

A hashtable is a data construct that stores a set of items. Each item has a key that identifies the item. Items are found, added, and removed from the hashtable by using the key. Hashtables may seem like arrays, but there are important differences:

+

哈希表是一个存储一系列元素的数据结构。每个元素都由一个关键字来标识。元素可以通过关键字来进行查找,添加,删除操作。哈希表非常类似arrays,但是也有一些很大的区别。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 数组哈希表
关键字: + + 整数: + arrays are always keyed on integers, and must be contiguous. 数组必须用整数作为关键字,而且每两个元素之间必须相邻接 + + 任意类型: + almost any datatype can be used as key, including strings, integers, XPCOM interface pointers, IIDs, and almost anything else. Keys can be disjunct (i.e. you can store entries with keys 1, 5, and 3000). 任意类型都可以作为关键字,包括字符串,整数,XPCOM接口指针,IIDs等等。关键字之间可以不在一起(例如,你可以用1,5,和3000来作为关键字。)
查询时间: + + O(1): + lookup time is a simple constant。查找时间是个简单的定值 + + O(1): + lookup time is mostly-constant, but the constant time can be larger than an array lookup。查找时间几乎是定值,但是比数组慢点。
排序: + + sorted: + stored sorted; enumerated in a sorted fashion. + + unsorted: + stored unsorted; cannot be enumerated in a sorted manner.
插入/删除: + + O(n): + adding and removing items from a large array can be time-consuming + + O(1): + adding and removing items from hashtables is a quick operation
浪费空间: + + none: + Arrays are packed structures, so there is no wasted space. + + some: + hashtables are not packed structures; depending on the implementation, there may be significant wasted memory.
+

In their implementation, hashtables take the key and apply a mathematical hash function to randomize the key and then use the hash to find the location in the hashtable. Good hashtable implementations will automatically resize the hashtable in memory if extra space is needed, or if too much space has been allocated.

+

When Should I Use a Hashtable?

+

Hashtables are useful for

+ +

Hashtables should + + not + be used for

+ +

In these situations, an array, a linked-list, or various tree data structures are more efficient.

+

Mozilla's Hashtable Implementations

+

Mozilla has several hashtable implementations, which have been tested and, tuned, and hide the inner complexities of hashtable implementations:

+ +

Which Hashtable Should I Use?

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Key Type:
integerString/CStringnsIDnsISupports*Complex
Data Type:None (Hash Set)nsInt32HashSetns(C)StringHashSetnsTHashtable<...>
Simple (PRUint32)nsDataHashtablensTHashtable<...>
<nsUint32HashKey,
+ PRUint32>
<ns(C)StringHashKey,
+ PRUint32>
<nsIDHashKey,
+ PRUint32>
<nsISupportsHashKey,
+ PRUint32>
Interface (nsISupports)nsInterfaceHashtable
<nsUint32HashKey,
+ nsISupports>
<ns(C)StringHashKey,
+ nsISupports>
<nsIDHashKey,
+ nsISupports>
<nsISupportsHashKey,
+ nsISupports>
Class (nsString*)nsClassHashtable
<nsUint32HashKey,
+ nsString>
<ns(C)StringHashKey,
+ nsString>
<nsIDHashKey,
+ nsString>
<nsISupportsHashKey,
+ nsString>
Complex
+ (structures, etc.)
nsTHashtable<...>
+

PLDHash (JSDHash)

+

PLDHash and JSDHash are the same thing; one is linked from the XPCOM libraries, the other from the JS libraries. JSDHash is used extensively in the SpiderMonkey JS engine.

+

The PLDHash implementation is a fairly low-level implementation, written in C. It is extremely flexible, but requires some time to understand and use. A basic guide is included here, but you should read most of xpcom/glue/pldhash.h if you intend to use PLDHash. The C++ wrappers for PLDHash (see below) are often much easier and safer to use in C++ code, as many potential casting errors are easily avoided.

+

You must declare an entry struct type, deriving from <code>PLDHashEntryHdr</code>. This entry struct should contain whatever data you wish to store in the hashtable (any pointer or fixed-length data type). Note: because of the double-hashing implementation, entries may move in memory when the hashtable is altered. If you need entry pointers to remain constant, you may want to consider using PLHashTable instead.

+

You must also initialize a <code>PLDHashTableOps</code> structure. This serves similarly to a vtable in C++, with pointers to appropriate user-defined functions that initialize, compare, and match entries. Because PLDHash does not know what datatype your key is, all functions that work with keys are declared using const void*, and your client code must cast these pointers to the appropriate type.

+

PLDHashTables can be allocated on the stack or the heap:

+ +

PLHashTable

+

PLHashTable is a part of NSPR. The header file can be found at nsprpub/lib/ds/plhash.h. In general, PLDHash is a better solution than PLHashTable, because PLHashTable makes many heap allocations.

+

There are two situations where PLHashTable may be preferable to PLDHash:

+ +

nsTHashtable

+

nsTHashtable is a C++ template that wraps PLDHash. It hides many of the complexities of PLDHash (callback functions, the ops structure, etc). You should read xpcom/glue/nsTHashtable.h.

+

To use nsTHashtable, you must declare an entry-class in a pre-defined format. This entry class contains the key and the data that you are hashing (just like PLDHash, above). It also declares functions that manipulate the key. In most cases, the functions of this entry class can be entirely inline. For examples of entry classes, see the declarations at xpcom/glue/nsHashKeys.h.

+

The template parameter is the entry class. You must use the Init() function to initalize the table properly. At this point, use the functions PutEntry/GetEntry/RemoveEntry to alter the hashtable. EnumerateEntries will do enumeration, but beware that the enumeration will occur in a seemingly-random order (no sorting).

+ +

Before using nsTHashtable, see if nsBaseHashtable and relatives will work for you. They are much easier to use, because you do not have to declare an entry class. If you are hashing a simple key type to a simple data type, they are generally a better choice.

+

nsBaseHashtable and friends: nsDataHashtable, nsInterfaceHashtable, and nsClassHashtable

+

These C++ templates provide a high-level interface for using hashtables that hides most of the complexities of PLDHash. They provide the following features:

+ +

nsBaseHashtable is not used directly; choose one of the three derivative classes based on the data type you want to store. The KeyClass is taken from nsHashKeys.h and is the same for all three classes:

+ +

The important files to read are xpcom/glue/nsBaseHashtable.h and xpcom/glue/nsHashKeys.h. These classes can be used on the stack, as a class member, or on the heap. Initialize using the Init() function; you can specify whether you need thread-safety at this time. Use the Put(), Get(), and Remove() methods to alter the table.

+

There are two enumeration functions:

+ +

Using nsTHashtable as a hash-set

+

A hash set only tracks the existence of keys: it does not associate data with the keys. This can be done using nsTHashtable<nsSomeHashKey>. The appropriate entries are GetEntry and PutEntry.

+

Future Plans

+

nsISimpleEnumerator support

+

The (obsolete) nsHashtable has a wrapper that exposes an nsISimpleEnumerator on its items. I will add this support to the various nsBaseHashtable classes as well, as needed.

+

Hash Functions

+

All of the above hashtables need a Hash Function. This function converts the key into a semi-unique integer. The mozilla codebase already contains hash functions for most key types, including narrow and wide strings, pointers, and most binary data:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
void*
+ (or nsISupports*)
cast using NS_PTR_TO_INT32
char* stringnsCRT::HashCode()
PRUnichar* string
nsAStringHashString()
nsACString
nsID&nsIDHashKey::HashKey()
+

Writing a good hash function is well beyond the scope of this document, and has been discussed extensively in computer-science circles for many years. There are many different types of hash functions. Mozilla has tuned a good general-purpose hash algorithm for strings and nsID.

+

Mozilla's Old/Obsolete/Deprecated/Decrepit Hashtables

+

nsHashtable

+

nsHashtable was a C++ wrapper around PLHashTable, and now wraps PLDHash. The design of the key classes is not optimal, however, and nsHashtable has been deprecated in favor of nsDataHashtable and friends.

+

nsObjectHashtable

+

nsObjectHashtable is a form of nsHashtable. It has been replaced by nsClassHashtable.

+

nsSupportsHashtable

+

nsSupportsHashtable is a form of nsHashtable. It has been replaced by nsInterfaceHashtable.

+

nsHashSets

+

nsHashSets has predefined hash sets for common keys, which are trivially easy to use. See xpcom/ds/nsHashSets.h. This functionality has been replaced by nsTHashtable<nsSomeHashKey>.

+

nsDoubleHashtable

+

nsDoubleHashtable is the (obsolete) precursor to nsTHashtable. It uses macros instead of C++ templates.

+
+

Original Document Information

+ +
+

 

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/index.html new file mode 100644 index 0000000000..385888d9fb --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/index.html @@ -0,0 +1,15 @@ +--- +title: XPCOM 指南 +slug: Mozilla/Tech/XPCOM/Guide +tags: + - Landing + - Mozilla + - XPCOM +translation_of: Mozilla/Tech/XPCOM/Guide +--- +

 

+

本文提供了关于 XPCOM 的说明和使用文档,包括如何在你的工程中使用,如何为你的 Firefox 扩展等构建 XPCOM 组件。

+

+ + +

diff --git a/files/zh-cn/mozilla/tech/xpcom/guide/internal_strings/index.html b/files/zh-cn/mozilla/tech/xpcom/guide/internal_strings/index.html new file mode 100644 index 0000000000..fe5806168f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/guide/internal_strings/index.html @@ -0,0 +1,809 @@ +--- +title: Strings +slug: Mozilla/Tech/XPCOM/Guide/Internal_strings +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM/Guide/Internal_strings +--- +

 

+

Preface

+
+

by Alec Flett
+ Thanks to David Baron for actual docs,
+ Peter Annema for lots of direction,
+ Myk Melez for some more docs, and
+ David Bradley for a diagram
+ Revised by Darin Fisher for Mozilla 1.7
+ Revised by Jungshik Shin to clarify character encoding issues

+
+

This guide will attempt to document the plethora of string classes, and hopefully provide an answer to the age old question, "what string class should I use here?"

+
+

If you are a Mozilla embedder or if you are writing an XPCOM component that will be distributed separately from the Mozilla code base, then this string guide is most likely not for you! Provided you are developing against Mozilla 1.7 or later, you should instead be using the new minimal Mozilla string API and in particular the nsEmbedString class.

+
+

In a hurry? Go check out the String Quick-Reference ().

+

Introduction

+

The string classes are a library of C++ classes which are used to manage buffers of unicode and single-byte character strings. They reside in the mozilla codebase in the xpcom/string directory.

+

Abstract (interface) classes begin with "nsA" and concrete classes simply begin with "ns". Classes with a "CString" in the name store 8-bit bytes (char's) which may refer to single byte ASCII strings, or multibyte Unicode strings encoded in UTF-8 or a (multibyte or single byte) legacy character encoding (e.g. ISO-8859-1, Shift_JIS, GB2312, KOI8-R). All other classes simply have "String" in their name and refer to 16-bit strings made up of PRUnichar's, For example: nsAString is an abstract class for storing Unicode characters in UTF-16 encoding, and nsDependentCString is a concrete class which stores a 8-bit string. Every 16-bit string class has an equivalent 8-bit string class. For example: nsCString is the 8-bit string class which corresponds to nsString.

+

8-bit and 16-bit string classes have completely separate base classes, but share the same APIs. As a result, you cannot assign a 8-bit string to a 16-bit string without some kind of conversion helper class or routine. For the purpose of this document, we will refer to the 16-bit string classes in class documentation. It is safe to assume that every 16-bit class has an equivalent 8-bit class.

+

String Guidelines

+

Follow these simple rules in your code to keep your fellow developers, reviewers, and users happy.

+ +

The Abstract Classes

+

Every string class derives from nsAString (or nsACString). This class provides the fundamental interface for access and manipulation of strings. While concrete classes derive from nsAString, nsAString itself cannot be instantiated.

+

This is very similar to the idea of an "interface" that mozilla uses to describe abstract object descriptions in the rest of the codebase. In the case of interfaces, class names begin with "nsI" where "I" refers to "Interface". In the case of strings, abstract classes begin with "nsA" and the "A" means "Abstract".

+

There are a number of abstract classes which derive from nsAString. These abstract subclasses also cannot be instantiated, but they describe a string in slightly more detail than nsAString. They guarantee that the underlying implementation behind the abstract class provides specific capabilities above and beyond nsAString.

+

The list below describes the main base classes. Once you are familiar with them, see the appendix describing What Class to Use When.

+ +

The remainder of the string classes inherit from either nsSubstring or nsString. Thus, every string class is compatible with nsAString.

+

It's important to note that nsSubstring and nsAString both represent a contiguous array of characters that are not necessarily null-terminated. One might ask then ask why two different yet similar string classes need to exist. Well, nsSubstring exists primarily as an optimization since nsAString must retain binary compatibility with the frozen nsAString class that shipped with Mozilla 1.0. Up until the release of Mozilla 1.7, nsAString was capable of representing a string broken into multiple fragments. The cost associated with supporting multi-fragment strings was high and offered limited benefits. It was decided to eliminate support for multi-fragment strings in an effort to reduce the complexity of the string classes and improve performance. See bug 231995 for more details.

+

Though nsSubstring provides a more efficient interface to its underlying buffer than nsAString, nsAString is still the most commonly used class for parameter passing. This is because it is the string class corresponding to AString in XPIDL. Therefore, this string guide will continue to discuss the string classes with an emphasis on nsAString.

+

Since every string derives from nsAString (or nsACString), they all share a simple API. Common read-only methods:

+ +

Common methods that modify the string:

+ +

Complete documentation can be found in the Appendix.

+

Read-only strings

+

The const attribute on a string determines if the string is writable. If a string is defined as a const nsAString then the data in the string cannot be manipulated. If one tries to call a non-const method on a const string the compiler will flag this as an error at build time.

+

For example:

+
void nsFoo::ReverseCharacters(nsAString& str) {
+      ...
+     str.Assign(reversedStr); // modifies the string
+}
+
+

This should not compile, because you're assigning to a const class:

+
void nsFoo::ReverseCharacters(const nsAString& str) {
+      ...
+     str.Assign(reversedStr);
+}
+
+

As function parameters

+

It is recommended that you use the most abstract interface possible as a function parameter, instead of using concrete classes. The convention is to use C++ references (the '&' character) instead of pointers (the '*' character) when passing string references around. For example:

+
// abstract reference
+nsFoo::PrintString(const nsAString& str) {..}
+
+// using a concrete class!
+nsFoo::PrintString(const nsString& str) {..}
+
+// using a pointer!
+nsFoo::PrintString(const nsAString* str) {..}
+
+

The abstract classes are also sometimes used to store temporary references to objects. You can see both of these uses in Common Patterns, below.

+

NOTE: While using abstract string classes increases the re-usability of your methods, it also incurs a codesize and performance penalty. Therefore, when writing methods that will only ever be used within the confines of your source file or module, it is better to use const nsSubstring& for input parameters and nsString& for output parameters. --Darin

+

The Concrete Classes - which classes to use when

+

The concrete classes are for use in code that actually needs to store string data. The most common uses of the concrete classes are as local variables, and members in classes or structs. Whereas the abstract classes differ in storage mechansim, for the most part the concrete classes differ in storage policy.

+

The following is a list of the most common concrete classes. Once you are familiar with them, see the appendix describing What Class to Use When.

+ +

There are also a number of concrete classes that are created as a side-effect of helper routines, etc. You should avoid direct use of these classes. Let the string library create the class for you.

+ +

Of course, there are times when it is necessary to reference these string classes in your code, but as a general rule they should be avoided.

+

Iterators

+

Iterators are objects that retain a reference to a position in a string. In some ways they are like a number which refers to an index in an array, or a character-pointer that refers to a position in a character string. They also provide a syntactic means to distinguish between reading and writing to a string.

+

Iterators are most often used to extract substrings of a string. They provide the capability to modify the contents of a string, but often helper routines, or the string's own methods are quicker at complex string transformations.

+

Iterators are declared from the string class which they are iterating:

+
nsAString::const_iterator start, end; // reading-only iterators for nsAString
+nsString::iterator substr_start, substr_end; // writing iterators for nsString
+
+

Iterators are initialized with one of 4 methods on the string you wish to reference:

+
// let's read from 'str'
+str.BeginReading(start); // initialize 'start' to the beginning of 'str'
+str.EndReading(end); // 'end' will be at the end of the string
+
+// say we also want to write to 'url'
+url.BeginWriting(substr_start);
+url.EndWriting(substr_end);
+
+

You can access the code unit that an iterator points to with the dereference operator *.

+
if (*start == '[')
+     printf("Starts with a bracket\n");
+
+

Note in the above examples, that 'end' and 'substr_end' will actually point to the code unit past the end of the string, so you should never dereference the direct result of .EndReading().

+

You can test if two iterators point to the same position with == or !=. You can advance iterators with ++. Putting the ++ before your iterator is preferred, and will prevent creation of a temporary iterator.

+
while (start != end) // iterate through the whole string
+     ++start;
+
+

You can effectively write to a string with writing iterators (as opposed to const-iterators):

+
// change all * to !
+while (substr_start != substr_end) {
+     if (*substr_start == '*')
+           *substr_start = '!';
+     ++substr_start;
+}
+
+

With the patch for bug 231995, this loop is now as efficient as iterating with raw character pointers.

+

Helper Classes and Functions

+

Searching strings - looking for substrings, characters, etc.

+

FindInReadable() is the replacement for the old string.Find(..). The syntax is:

+
PRBool FindInReadable(const nsAString& pattern,
+                      nsAString::const_iterator start, nsAString::const_iterator end,
+                      nsStringComparator& aComparator = nsDefaultStringComparator());
+
+

To use this, start and end should point to the beginning and end of a string that you would like to search. If the search string is found, start and end will be adjusted to point to the beginning and end of the found pattern. The return value is PR_TRUE or PR_FALSE, indicating whether or not the string was found.

+

An example:

+
const nsAString& str = GetSomeString();
+nsAString::const_iterator start, end;
+
+str.BeginReading(start);
+str.EndReading(end);
+
+NS_NAMED_LITERAL_STRING(valuePrefix, "value=");
+
+if (FindInReadable(valuePrefix, start, end)) {
+    // end now points to the character after the pattern
+    valueStart = end;
+
+}
+
+

Memory Allocation - how to avoid it, which methods to use

+

The preferred method to allocate a new character buffer (PRUnichar*/char*) from an existing string is with one of the following methods:

+ +

These methods return a buffer allocated using XPCOM's allocator (nsMemory::Alloc) instead of the traditional allocator (malloc, etc.). You should use nsMemory::Free to deallocate the result when you no longer need it.

+

Substrings (string fragments)

+

It is very simple to refer to a substring of an existing string without actually allocating new space and copying the characters into that substring. Substring() is the preferred method to create a reference to such a string.

+
void ProcessString(const nsAString& str) {
+    const nsAString& firstFive = Substring(str, 0, 5);
+    // firstFive is now a string representing the first 5 characters
+}
+
+

Unicode Conversion ns*CString vs. ns*String

+

Strings can be + + stored + in two basic formats: 8-bit code unit (byte/char) strings, or 16-bit code unit (PRUnichar) strings. Any string class with a capital "C" in the classname contains 8-bit bytes. These classes include nsCString, nsDependentCString, and so forth. Any string class + + without + the "C" contains 16-bit code units.

+

A 8-bit string can be in one of many character encodings while a 16-bit string is always in UTF-16. The most common encodings are:

+ +

In addition, there are literally hundreds of encodings that are provided by internationalization libraries. Access to these libraries may be part of the application (such as nsICharsetConversionManager in Mozilla) or built into the operating system (such as iconv() in UNIX operating systems and MultiByteToWideChar/WideCharToMultiByte on Windows).

+

When working with existing code, it is important to examine the current usage of the strings that you are manipulating, to determine the correct conversion mechanism.

+

When writing new code, it can be confusing to know which storage class and encoding is the most appropriate. There is no single answer to this question, but there are a few important guidelines:

+ +


+ To assist with ASCII, UTF-8, and UTF-16 conversions, there are some helper methods and classes. Some of these classes look like functions, because they are most often used as temporary objects on the stack.

+

UTF-8 / UTF-16 conversion

+

NS_ConvertUTF8toUTF16( + + const nsACString& + ) - a nsAutoString subclass that converts a UTF-8 encoded nsACString or const char* to a 16-bit UTF-16 string. If you need a const PRUnichar* buffer, you can use the .get() method. For example:

+
/* signature: void HandleUnicodeString(const nsAString& str); */
+object->HandleUnicodeString(NS_ConvertUTF8toUTF16(utf8String));
+
+/* signature: void HandleUnicodeBuffer(const PRUnichar* str); */
+object->HandleUnicodeBuffer(NS_ConvertUTF8toUTF16(utf8String).get());
+
+

NS_ConvertUTF16toUTF8( + + const nsAString& + ) - a nsCAutoString which converts a 16-bit UTF-16 string (nsAString) to a UTF-8 encoded string. As above, you can use .get() to access a const char* buffer.

+
/* signature: void HandleUTF8String(const nsACString& str); */
+object->HandleUTF8String(NS_ConvertUTF16toUTF8(utf16String));
+
+/* signature: void HandleUTF8Buffer(const char* str); */
+object->HandleUTF8Buffer(NS_ConvertUTF16toUTF8(utf16String).get());
+
+

CopyUTF8toUTF16( + + const nsACString&, nsAString& + ) - converts and copies:

+
// return a UTF-16 value
+void Foo::GetUnicodeValue(nsAString& result) {
+    CopyUTF8toUTF16(mLocalUTF8Value, result);
+ }
+
+

AppendUTF8toUTF16( + + const nsACString&, nsAString& + ) - converts and appends:

+
// return a UTF-16 value
+void Foo::GetUnicodeValue(nsAString& result) {
+    result.AssignLiteral("prefix:");
+    AppendUTF8toUTF16(mLocalUTF8Value, result);
+}
+
+


+ UTF8ToNewUnicode( + + const nsACString&, PRUint32* aUTF16Count = nsnull + ) - allocates and converts (the optional parameter will contain the number of 16-byte units upon return, if non-null):

+
void Foo::GetUTF16Value(PRUnichar** result) {
+    *result = UTF8ToNewUnicode(mLocalUTF8Value);
+}
+
+


+ CopyUTF16toUTF8( + + const nsAString&, nsACString& + ) - converts and copies:

+
// return a UTF-8 value
+void Foo::GetUTF8Value(nsACString& result) {
+    CopyUTF16toUTF8(mLocalUTF16Value, result);
+}
+
+

AppendUTF16toUTF8( + + const nsAString&, nsACString& + ) - converts and appends:

+
// return a UTF-8 value
+void Foo::GetUnicodeValue(nsACString& result) {
+    result.AssignLiteral("prefix:");
+    AppendUTF16toUTF8(mLocalUTF16Value, result);
+}
+
+

ToNewUTF8String( + + const nsAString& + ) - allocates and converts:

+
void Foo::GetUTF8Value(char** result) {
+    *result = ToNewUTF8String(mLocalUTF16Value);
+}
+
+

Lossy Conversion

+

The following should only be used when you can guarantee that the original string is ASCII. These helpers are very similar to the UTF-8 / UTF-16 conversion helpers above.

+

UTF-16 to ASCII converters

+

These converters are + + very dangerous + because they + + lose information + during the conversion process. You should + + avoid UTF-16 to ASCII conversions + unless your strings are guaranteed to be ASCII. Each 16-bit code unit in 16-bit string is simply cast to an 8-bit byte, which means all Unicode character values above 0xFF are converted to an arbitrary 8-bit byte.

+ +

ASCII to UTF-16 converters

+

These converters are + + very dangerous + because they will + + mangle any non-ASCII string + into a meaningless UTF-16 string. You should + + avoid ASCII to UTF-16 conversions + unless your strings are guaranteed to be ASCII. For instance, if you have an 8-bit string encoded in a multibyte character encoding, each byte of the string will be "inflated" to a 16-bit number by simple casting.

+

For example, imagine a UTF-8 string where the first Unicode character of the string is represented with a 3-byte UTF-8 sequence, the "inflated" UTF-16 string will contain the 3 PRUnichar's instead of the single PRUnichar that represents the first character. These PRUnichar's have nothing to do with the first Unicode character in the UTF-8 string.

+ +

Common Patterns

+

Callee-allocated Parameters

+

Many APIs result in a method allocating a buffer in order to return strings to its caller. This can be tricky because the caller has to remember to free the string when they have finished using it. Fortunately, the nsXPIDLString class makes this very easy.

+

A method may look like this:

+
void GetValue(PRUnichar** aValue)
+{
+    *aValue = ToNewUnicode(foo);
+}
+
+

Without the string classes, the caller would need to free the string:

+
{
+    PRUnichar* val;
+    GetValue(&val);
+
+    if (someCondition) {
+        // don't forget to free the value!
+        nsMemory::Free(val);
+        return NS_ERROR_FAILURE;
+    }
+
+    ...
+    // and later, still don't forget to free!
+    nsMemory::Free(val);
+}
+
+

With nsXPIDLString you never have to worry about this. You can just use getter_Copies() to wrap the string class, and the class will remember to free the buffer when it goes out of scope:

+
{
+    nsXPIDLString val;
+    GetValue(getter_Copies(val));
+
+    // val will free itself here
+    if (someCondition)
+        return NS_ERROR_FAILURE;
+    ...
+    // and later, still nothing to free
+}
+
+

The resulting code is much simpler, and easy to read.

+

Literal Strings

+

A + + literal string + is a raw string value that is written in some C++ code. For example, in the statement printf("Hello World\n"); the value "Hello World\n" is a literal string. It is often necessary to insert literal string values when an nsAString or nsACString is required. These four macros will provide you with the necessary conversion:

+ +

The purpose of the CSTRING versions of these macros may seem unnecessary, given that nsDependentCString will also wrap a string value in an nsCString. The advantage to these macros is that the length of these strings is calculated at compile time, so the string does not need to be scanned at runtime to determine its length.

+

The STRING versions of these macros provide a portable way of declaring UTF-16 versions of the given literal string, avoiding runtime conversion on platforms which support literal UTF-16 strings (e.g., MSVC++ and GCC with the -fshort-wchar option).

+
// call Init(const PRUnichar*)
+Init(L"start value"); // bad - L"..." is not portable!
+Init(NS_ConvertASCIItoUTF16("start value").get()); // bad - runtime ASCII->UTF-16 conversion!
+
+// call Init(const nsAString&)
+Init(nsDependentString(L"start value")); // bad - not portable!
+Init(NS_ConvertASCIItoUTF16("start value")); // bad - runtime ASCII->UTF-16 conversion!
+
+// call Init(const nsACString&)
+Init(nsDependentCString("start value")); // bad - length determined at runtime
+
+

Here are some examples of proper NS_LITERAL_[C]STRING usage.

+
// call Init(const PRUnichar*)
+Init(NS_LITERAL_STRING("start value").get());
+
+// call Init(const nsAString&)
+Init(NS_LITERAL_STRING("start value"));
+
+// call Init(const nsACString&)
+Init(NS_LITERAL_CSTRING("start value"));
+
+

There are a few details which can be useful in tracking down issues with these macros:

+

NS_LITERAL_STRING does compile-time conversion to UTF-16 on some platforms (e.g. Windows, Linux, and Mac) but does runtime conversion on other platforms. By using NS_LITERAL_STRING your code is guaranteed to use the best possible conversion for the platform in question.

+

Because some platforms do runtime conversion, the use of literal string concatenation inside a NS_LITERAL_STRING/NS_NAMED_LITERAL_STRING macro will compile on these platforms, but not on platforms which support compile-time conversion.

+

For example:

+
// call Init(nsAString&)
+Init(NS_LITERAL_STRING("start "
+     "value")); // only compiles on some platforms
+
+

The reason for this is that on some platforms, the L"..." syntax is used, but it is only applied to the first string in the concatenation ("start "). When the compiler attempts to concatenate this with the non-Unicode string "value" it gets confused.

+

Also, using preprocessor macros as the string literal is unsupported:

+
#define some_string "See Mozilla Run"
+...
+Init(NS_LITERAL_STRING( some_string )); // only compiles on some platforms/with some compilers.
+
+
+

String Concatenation

+

Strings can be concatenated together using the + operator. The resulting string is a const nsSubstringTuple object. The resulting object can be treated and referenced similarly to a nsAString object. Concatenation + + does not copy the substrings + . The strings are only copied when the concatenation is assigned into another string object. The nsSubstringTuple object holds pointers to the original strings. Therefore, the nsSubstringTuple object is dependent on all of its substrings, meaning that their lifetime must be at least as long as the nsSubstringTuple object.

+

For example, you can use the value of two strings and pass their concatenation on to another function which takes an const nsAString&:

+
void HandleTwoStrings(const nsAString& one, const nsAString& two) {
+    // call HandleString(const nsAString&)
+    HandleString(one + two);
+}
+
+

NOTE: The two strings are implicitly combined into a temporary nsString in this case, and the temporary string is passed into HandleString. If HandleString assigns its input into another nsString, then the string buffer will be shared in this case negating the cost of the intermediate temporary. You can concatenate N strings and store the result in a temporary variable:

+
NS_NAMED_LITERAL_STRING(start, "start ");
+NS_NAMED_LITERAL_STRING(middle, "middle ");
+NS_NAMED_LITERAL_STRING(end, "end");
+// create a string with 3 dependent fragments - no copying involved!
+nsString combinedString = start + middle + end;
+
+// call void HandleString(const nsAString&);
+HandleString(combinedString);
+
+

If you are using NS_LITERAL_STRING to create a temporary that is only used once, then it is safe to define it inside a concatenation because the string buffer will live as long as the temporary concatenation object (of type nsSubstringTuple).

+
// call HandlePage(const nsAString&);
+// safe because the concatenated-string will live as long as its substrings
+HandlePage(NS_LITERAL_STRING("start ") + NS_LITERAL_STRING("end"));
+
+

Local variables

+

Local variables within a function are usually stored on the stack. The nsAutoString/nsCAutoString classes are derivatives of the nsString/nsCString classes. They own a 64-character buffer allocated in the same storage space as the string itself. If the nsAutoString is allocated on the stack, then it has at its disposal a 64-character stack buffer. This allows the implementation to avoid allocating extra memory when dealing with small strings.

+
...
+nsAutoString value;
+GetValue(value); // if the result is less than 64 code units,
+                 // then this just saved us an allocation
+...
+
+

Member variables

+

In general, you should use the concrete classes nsString and nsCString for member variables.

+
class Foo {
+    ...
+    // these store UTF-8 and UTF-16 values respectively
+    nsCString mLocalName;
+    nsString mTitle;
+};
+
+

Note that the strings are declared directly in the class, not as pointers to strings. Don't do this:

+
class Foo {
+public:
+    Foo() {
+        mLocalName = new nsCString();
+        mTitle = new nsString();
+    }
+    ~Foo() { delete mLocalName; delete mTitle; }
+
+private:
+    // these store UTF-8 and UTF-16 values respectively
+    nsCString* mLocalName;
+    nsString*  mTitle;
+};
+
+

The above code may appear to save the cost of the string objects, but nsString/nsCString are small objects - the overhead of the allocation outweighs the few bytes you'd save by keeping a pointer.

+

Another common incorrect pattern is to use nsAutoString/nsCAutoString for member variables. As described in Local Variables, these classes have a built in buffer that make them very large. This means that if you include them in a class, they bloat the class by 64 bytes (nsCAutoString) or 128 bytes (nsAutoString).

+

An example:

+
class Foo {
+    ...
+
+    // bloats 'Foo' by 128 bytes!
+    nsAutoString mLocalName;
+};
+
+

Raw Character Pointers

+

PromiseFlatString() can be used to create a temporary buffer which holds a null-terminated buffer containing the same value as the source string. PromiseFlatString() will create a temporary buffer if necessary. This is most often used in order to pass an nsAString to an API which requires a null-terminated string.

+

In the following example, an nsAString is combined with a literal string, and the result is passed to an API which requires a simple character buffer.

+
// Modify the URL and pass to AddPage(const PRUnichar* url)
+void AddModifiedPage(const nsAString& url) {
+    NS_NAMED_LITERAL_STRING(httpPrefix, "http://");
+    const nsAString& modifiedURL = httpPrefix + url;
+
+    // creates a temporary buffer
+    AddPage(PromiseFlatString(modifiedURL).get());
+}
+
+

PromiseFlatString() is smart when handed a string that is already null-terminated. It avoids creating the temporary buffer in such cases.

+
// Modify the URL and pass to AddPage(const PRUnichar* url)
+void AddModifiedPage(const nsAString& url, PRBool addPrefix) {
+    if (addPrefix) {
+        // MUST create a temporary buffer - string is multi-fragmented
+        NS_NAMED_LITERAL_STRING(httpPrefix, "http://");
+        AddPage(PromiseFlatString(httpPrefix + modifiedURL));
+    } else {
+        // MIGHT create a temporary buffer, does a runtime check
+        AddPage(PromiseFlatString(url).get());
+    }
+}
+
+

printf and a UTF-16 string

+

For debugging, it's useful to printf a UTF-16 string (nsString, nsAutoString, nsXPIDLString, etc). To do this usually requires converting it to an 8-bit string, because that's what printf expects. However, on Windows, the following should work:

+
printf("%S\n", yourString.get());
+
+

(Note: I didn't test this. Also, I'm not sure what exactly this does to non-ASCII characters, especially when they are outside the system codepage). The reason that this doesn't work on Unix is because a wchar_t, which is what %S expects, is usually 4 bytes there (even when Mozilla is compiled with -fshort-wchar, because this would require libc to be compiled with -fshort-wchar).

+

If non-ASCII characters aren't important, use:

+
printf("%s\n", NS_LossyConvertUTF16toASCII(yourString).get());
+
+

On platforms that use UTF-8 for console output (most Linux distributions), this works:

+
printf("%s\n", NS_ConvertUTF16toUTF8(yourString).get());
+
+

IDL

+

The string library is also available through IDL. By declaring attributes and methods using the specially defined IDL types, string classes are used as parameters to the corresponding methods.

+

IDL String types

+

The C++ signatures follow the abstract-type convention described above, such that all method parameters are based on the abstract classes. The following table describes the purpose of each string type in IDL.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDL typeC++ TypePurpose
stringchar*Raw character pointer to ASCII (7-bit) string, no string classes used. High bit is not guaranteed across XPConnect boundaries
wstringPRUnichar*Raw character pointer to UTF-16 string, no string classes used
AStringnsAStringUTF-16 string
ACStringnsACString8-bit string, all bits are preserved across XPConnect boundaries
AUTF8StringnsACStringUTF-8 string - converted to UTF-16 as necessary when value is used across XPConnect boundaries
DOMStringnsAStringUTF-16 string used in the DOM. More or less the same as AString, but in JavaScript it has no distinction between whether the string is void or just empty. (not sure on this, looking for corrections.
+

C++ Signatures

+

In IDL, in parameters are read-only, and the C++ signatures for *String parameters follows the above guidelines by using const nsAString& for these parameters. out and inout parameters are defined simply as nsAString so that the callee can write to them.

+ + + + + + + + + + + +
IDLC++
+
+interface nsIFoo : nsISupports {
+
+    attribute AString utf16String;
+
+
+
+
+    AUTF8String getValue(in ACString key);
+
+};
+
+
+
+class nsIFoo : public nsISupports {
+
+     NS_IMETHOD GetUtf16String(nsAString&
+                               aResult) = 0;
+     NS_IMETHOD SetUtf16String(const nsAString&
+                              aValue) = 0;
+
+     NS_IMETHOD GetValue(const nsACString& aKey,
+                     nsACString& aResult) = 0;
+};
+
+
+

In the above example, utf16String is treated as a UTF-16 string. The implementation of GetUtf16String() will use aResult.Assign to "return" the value. In SetUtf16String() the value of the string can be used through a variety of methods including Iterators, PromiseFlatString, and assignment to other strings.

+

In GetValue(), the first parameter, aKey, is treated as a raw sequence of 8-bit values. Any non-ASCII characters in aKey will be preserved when crossing XPConnect boundaries. The implementation of GetValue() will assign a UTF-8 encoded 8-bit string into aResult. If the this method is called across XPConnect boundaries, such as from a script, then the result will be decoded from UTF-8 into UTF-16 and used as a Unicode value.

+

Choosing a string type

+

It can be difficult to determine the correct string type to use for IDL. The following points should help determine the appropriate string type.

+ +

Appendix A - What class to use when

+

This table provides a quick reference for what classes you should be using.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ContextclassNotes
Local VariablesnsAutoString
+ nsCAutoString
 
Class Member VariablesnsString
+ nsCString
 
Method Parameter typesnsAString
+ nsACString
Use abstract classes for parameters. Use const nsAString& for "in" parameters and nsAString& for "out" parameters.
Retrieving "out" string/wstringsnsXPIDLString
+ nsXPIDLCString
Use getter_Copies(). Similar to nsString / nsCString.
Wrapping character buffersnsDependentString
+ nsDependentCString
Wrap const char* / const PRUnichar* buffers.
Literal stringsNS_LITERAL_STRING
+ NS_LITERAL_CSTRING
Similar to nsDependent[C]String, but pre-calculates length at build time.
+

Appendix B - nsAString Reference

+

Read-only methods.

+ +

Methods that modify the string.

+ diff --git a/files/zh-cn/mozilla/tech/xpcom/index.html b/files/zh-cn/mozilla/tech/xpcom/index.html new file mode 100644 index 0000000000..98620642db --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/index.html @@ -0,0 +1,44 @@ +--- +title: XPCOM +slug: Mozilla/Tech/XPCOM +tags: + - XPCOM + - 所有分类 +translation_of: Mozilla/Tech/XPCOM +--- +

XPCOM(Cross Platform Component Object Model)是一种跨平台组件对象模型,其原理与微软的COM技术类似,它支持多种语言绑定(Language Bindings)。也就是说,我们可以使用C++、JAVA、JavaScript、Python、Ruby、Perl等语言来编写组件。而XPCOM的接口是用一种叫做XPIDL的IDL(Interface Description Language)来定义的。

+ +
+

XPCOM 本身提供了一套核心的组件和类,用于诸如内存管理,线程,基本数据结构(strings, arrays, variants)等 。但是大部分的XPCOM组件并不是这个核心库提供的,而是由很多第三方的平台(例如Gecko或者Necko)提供,或者由一个应用,甚至一个扩展提供。

+ +

 

+ +

+
Generic factory
Most XPCOM factories can be very simple. Rick Potts wrote a templated-based generic factory (nsFactory<t>) that simplifies the factory creation process that just requires writing a CreateInstance() method. The new nsIGenericFactory interface takes this a step further, by providing a single interface that can be reused anytime a simple implementation of nsIFactory is needed. Here is the interface, and a description of its use.</t>
Observer Notifications
The following are topics that you can observe during the course of an application. Unless otherwise noted you register for the topics using the nsIObserverService.
Setting HTTP request headers
HTTP 是网络背后的核心技术之一。除了实质内容之外,一些重要的信息通过HTTP 头传递给HTTP 请求和响应。
Storage
Storage 存储是一个 SQLite 数据库API。它可用于受信任的调用者,仅限于扩展和Firefox组件。
XPCOM Glue
The XPCOM Glue is a static library which component developers and embedders can link against. It allows developers to link only against the frozen XPCOM method symbols and maintain compatibility with multiple versions of XPCOM.
XPCOM reference
This reference describes the interfaces and functions provided by the XPCOM library. In addition, it details the various helper classes and functions, as well as the components, provided by the XPCOM glue library. The contents herein are oriented primarily toward extension developers and people embedding XPCOM in other projects.
+
XPCOM 指南
本文提供了关于 XPCOM 的说明和使用文档,包括如何在你的工程中使用,如何为你的 Firefox 扩展等构建 XPCOM 组件。
与XPCOM cycle collector交互
本文是对于在Firefox 3的XPCOM中引入的cycle collector的一个简要描述,描述了将一个已有的C++类修改为一个XPCOM cycle collection中的参与项的步骤。如果你认为你有关于类的循环引用导致的内存泄漏,那可以看看这个。
使用剪贴板
This section provides information about cutting, copying and pasting to and from the clipboard.
创建Python XPCOM组件
Creating Applications with Mozilla 已经包含了一个教程用于编写简单的基于JavaScript和C++(实现nsISimple接口)的组件,本文阐述如何通过Python语言使用PyXPCOM创建相同的组件。
收集 In-Memory 数据源
语言绑定
一款 XPCOM 的语言绑定是连接某种特定的程序设计语言与 XPCOM 之间的纽带,它用来提供从语言到 XPCOM 对象的访问, 并且将此种语言写成的模块作为其他进行 XPCOM 绑定的程序语言的 XPCOM 对象。
+

+ +

+ +
+

加入 XPCOM 社区

+
+
请选择你喜欢的方式加入我们:
+ +
+ +
+

+ +

+
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xpcom/interfacing_with_the_xpcom_cycle_collector/index.html b/files/zh-cn/mozilla/tech/xpcom/interfacing_with_the_xpcom_cycle_collector/index.html new file mode 100644 index 0000000000..a0b4472d02 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/interfacing_with_the_xpcom_cycle_collector/index.html @@ -0,0 +1,141 @@ +--- +title: 与XPCOM cycle collector交互 +slug: Mozilla/Tech/XPCOM/Interfacing_with_the_XPCOM_cycle_collector +translation_of: Mozilla/Tech/XPCOM/Interfacing_with_the_XPCOM_cycle_collector +--- +

本文是对于在Firefox 3的XPCOM中引入的cycle collector的一个简要描述,描述了将一个已有的C++类修改为一个XPCOM cycle collection中的参与项的步骤。如果你认为你有关于类的循环引用导致的内存泄漏,那可以看看这个。

+ +

本文面向Mozilla C++开发者。

+ +

cycle collector干了些什么

+ +

cycle collector大部分时间在记录可能导致循环引用的XPCOM对象指针。在collector的空闲阶段,nsAutoRefCnt的变体通过collector快速的修改自己的注册状态(注册/注销),会传递出一个“可疑”的引用计数事件(从N+1到N,N≠0)。

+ +

collector会阶段性的唤醒并验证缓冲区中记录过的可疑指针。这是collector的扫描阶段。在这个阶段,collector会请求每个候选项的cycle-collection helper类,如果存在,则需要helper来描述候选项拥有的子结构。collector可以以这种方式建立一个从可疑对象开始的拥有权关系图。

+ +

如果collector发现一组对象出现了彼此互相引用,并且确定组内对象的引用计数全由组内其他对象提供,则认定这组对象为循环引用,并尝试释放它们。这是collector的释放阶段。在这个阶段,collector遍历已找到的循环引用对象,再次请求它们的helper对象,释放其子结构和其他对象的引用。

+ +

collector也能遍历JS堆,并定位传入和传出的循环引用。

+ +

collector失效

+ +

cycle collector是一个保守的设备。有些情况下,它无法回收循环引用。

+ +
    +
  1. 它默认不怀疑任何指针;对象必须要标记它们自己为可疑对象,一般用nsCycleCollectingAutoRefCnt而不是nsAutoRefCnt。
  2. +
  3. 它只遍历那些在QI(QueryInterface)时返回helper对象的对象。如果在遍历图的过程中遇到了未知的边,那它会直接放弃这条边,因此每条边都需要被标记为可疑对象,否则找不到环。
  4. +
  5. helper对象中的TraverseUnlink方法不是魔法,是程序员编码的,如果代码写错了,那collector也还是会崩。
  6. +
  7. collector不知道怎么去搜索一个存在栈中的具有所有权的临时指针,所以将它放在程序的最顶层运行是有必要的。虽然有额外的所有权指针时不会崩,但是它会无法统计已记录的对象的引用计数,这也有可能导致回收失败。
  8. +
+ +

怎么标记一个类为候选项

+ +

cycle collector和你的类之间的接口使用xpcom/base/nsCycleCollector.h中的内容实现直接获取,但是在xpcom/glue/nsCycleCollectionParticipant.h中提供了很多方便的宏用来标记你的类。通常,如果你用nsCOMPtr的mBar和mBaz来修改类nsFoo,可以简化为几个简单的修改:

+ +
    +
  1. 在nsFoo.h和nsFoo.cpp中包含头文件nsCycleCollectionParticipant.h。 
  2. +
  3. 在nsFoo.cpp中加一行用于声明nsFoo类是cycle collection的候选项的语句: +
    NS_IMPL_CYCLE_COLLECTION_CLASS(nsFoo)
    +
  4. +
  5. 在nsFoo的定义里,将写有NS_DECL_ISUPPORTS的行修改为NS_DECL_CYCLE_COLLECTING_ISUPPORTS.
  6. +
  7. +

    在nsFoo的定义里public部分加一行NS_DECL_CYCLE_COLLECTION_CLASS(nsFoo)。如果nsFoo从多个接口继承而来的话,可以写成NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFoo, nsIBar),在你QueryInterface nsFoo为nsISSupports时,nsIBar作为接口返回。(我们把nsIBar称为nsFoo的典型ISupport类型。)

    +
  8. +
  9. 在nsFoo.cpp里接口map处加一行NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsFoo) : +
    NS_INTERFACE_TABLE_HEAD(nsFoo)
    +  NS_INTERFACE_TABLE2(nsFoo,
    +                      nsIBar,
    +                      nsIBaz)
    +  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsFoo)
    +NS_INTERFACE_MAP_END
    +
    +
  10. +
  11. 在nsFoo.cpp里把NS_IMPL_ADDREF(nsFoo)修改为NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFoo),同样的修改NS_IMPL_RELEASE(nsFoo)NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFoo)。
  12. +
  13. 可以在nsFoo.cpp中添加合适的NS_IMPL_CYCLE_COLLECTION_#宏, #是你类中的成员数量。如果nsFoo包含两个成员变量,mBar和mBaz,我们可以写成NS_IMPL_CYCLE_COLLECTION_2(nsFoo, mBar, mBaz)。
  14. +
+ +

你的类可能会比这张图的结构更复杂。例如,你的类可能有好几个nsISupport基类,需要使用一些执行消除歧义的* _AMBIGUOUS宏。或者说你的类拥有复杂的所有权结构,这样简单的NS_IMPL_CYCLE_COLLECTION_N宏就低效了;你可能需要手动的实现helper类的Traverse和Unlink方法。即使是这样的情况,也可以使用NS_IMPL_CYCLE_COLLECTION_TRAVERSE_ {BEGIN,END}和NS_IMPL_CYCLE_COLLECTION_UNLINK_ {BEGIN,END}。可以在一些复杂的类中看到实例,例如content/base/src/nsGenericElement.cpp。 If your class has tearoffs or is being aggregated by other classes it is important to make the tearoff classes or the outer classes participate in cycle collection too, not doing so could lead to the cycle collector trying to collect the objects too soon.

+ +

手动的实现Traverse和Unlink方法

+ +

每个可能包含循环回收对象的域都需要被传递给cycle collector,以检查通过这些域的循环。

+ +

用于Traverse的宏主要是是NS_IMPL_CYCLE_COLLECTION_TRAVERSE:

+ +

  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSomeMember)

+ +

Unlink同理:

+ +

  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSomeMember)

+ +

这些宏应当处理各种情况,像指向nsISupports对象的指针或者非nsISupports对象的指针,或者这些指针的数组,当然这些指针都是有引用计数的、被collector记录的指针。

+ +

处理JSObject

+ +

如果你的类需要保存一个指向JSObject的指针,你需要告知cycle collector。像这样操作:

+ +

首先,它必须被保存在JS::Heap<JSObject *>域,假如你的类nsFoo有一个域mSomeObj:

+ +
private:
+  ...
+  JS::Heap<JSObject*> mSomeObj;
+  ...
+ +

当你在JS对象指针中存了东西时,你需要用mozilla::HoldJSObjects来告诉GC遍历它并保持这个对象的存活:

+ +
...
+mSomeObj = ... ;
+mozilla::HoldJSObjects(this);
+...
+
+ +

在Unlink方法(或者析构函数)里,需要将对象指针置为空:

+ +
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFoo)
+  ...
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSomeMember)
+  ...
+  //如果你的类是wrapper cache:
+  //NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+
+  tmp->mSomeObj = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+ +

在析构函数里调用

+ +
mozilla::DropJSObjects(this);
+ +

你需要在Traverse方法列出cycle collector中记录的成员,也就是非JS对象:

+ +
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFoo)
+  ...
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSomeMember)
+  ...
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+ +

最后你需要把JS对象加入Trace方法:

+ +
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFoo)
+  //if your class is a wrapper cache:
+  //NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mSomeObj)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+ +

如果你的类是一个wrapper cache,可能生成的代码用了NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_#宏而不是NS_IMPL_CYCLE_COLLECTION_#. 这个宏不能定义Trace方法,因此不能列出JS对象;所以你需要向上面那样手动实现Trace和Unlink。

+ +

处理 JS::Value fields

+ +

 这里说过,一个JS::Value可能引用一个字符串或者对象并且被GC控制。于是我们需要告知cycle collector这种成员变量的存在。这与JSObject相似,但是使用的是NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK宏:

+ +
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFoo)
+  ...
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mSomeJSVal).
+  ...
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.cloneinto/index.html b/files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.cloneinto/index.html new file mode 100644 index 0000000000..0bc55dbf99 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.cloneinto/index.html @@ -0,0 +1,290 @@ +--- +title: Components.utils.cloneInto +slug: Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.cloneInto +translation_of: Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.cloneInto +--- +
+ +

该函数为定义在某一作用域中的对象提供了一个安全的、将其结构化克隆到其字作用域中的方法,并返回对克隆对象的引用:

+ +
var clonedObject = cloneInto(myObject, targetWindow);
+ +

可以将克隆后的对象作为可扩展对象的动态属性引入到特定作用域中,以便运行在该作用域的脚本进行访问:

+ +
targetWindow.foo = clonedObject;
+ +

通过这种方式,运行在某一作用域中的代码可以和运行在另一作用域中的代码共享对某一对象的访问。

+ +

语法

+ +
Components.utils.cloneInto(obj, targetScope[, options]);
+ +

参数列表

+ +
+
obj : object
+
被克隆对象。
+
targetScope : object
+
对象克隆后的容器。
+
options : object
+
该参数为一可选参数。该参数为一拥有以下可选属性的对象:
+
+ + + +

返回值

+ +

对克隆后的对象的引用。

+ +

范例

+ +

This add-on script creates an object, clones it into the content window and makes it a property of the content window global:

+ +
// add-on script
+
+var addonScriptObject = {"greeting" : "hello from add-on"};
+contentWindow.addonScriptObject = cloneInto(addonScriptObject, contentWindow);
+ +

Scripts running in the page can now access the object:

+ +
// page script
+
+button.addEventListener("click", function() {
+  console.log(window.addonScriptObject.greeting);     // "hello from add-on"
+}, false);
+ +

Of course, you don't have to assign the clone to the window itself: you can assign it to some other object in the target scope:

+ +
contentWindow.foo.addonScriptObject = cloneInto(addonScriptObject, contentWindow);
+ +

You can also pass it into a function defined in the page script. Suppose the page script defines a function like this:

+ +
// page script
+
+function foo(greeting) {
+  console.log("they said: " + greeting.message);
+}
+
+ +

The add-on script can define an object, clone it, and pass it into this function:

+ +
// add-on script
+
+var addonScriptObject = {"message" : "hello from add-on"};
+contentWindow.foo(cloneInto(addonScriptObject, contentWindow));  // "they said: hello from add-on"
+ +

Cloning objects that have functions

+ +

If the object to be cloned contains functions, you must pass the {cloneFunctions:true} flag or you'll get an error. If you do pass this flag, then functions in the object are cloned using the same mechanism as that used in Components.utils.exportFunction:

+ +
// add-on script
+
+var addonScriptObject = {
+  greetme: function() {
+    alert("hello from add-on");
+  }
+};
+
+contentWindow.addonScriptObject = cloneInto(addonScriptObject,
+                                           contentWindow,
+                                           {cloneFunctions: true});
+
+ +
// page script
+
+var test = document.getElementById("test");
+
+test.addEventListener("click", function() {
+  window.addonScriptObject.greetme();
+}, false);
+ +

Cloning objects that contain DOM elements

+ +

By default, if the object you clone contains objects that are reflected from C++, such as DOM elements, the cloning operation will fail with an error. If you pass the {wrapReflectors:true} flag, then the object you clone is allowed to contain these objects:

+ +
// add-on script
+
+var addonScriptObject = {
+  body: contentWindow.document.body
+};
+
+contentWindow.addonScriptObject = cloneInto(addonScriptObject,
+                                           contentWindow,
+                                           {wrapReflectors: true});
+ +
// page script
+
+var test = document.getElementById("test");
+
+test.addEventListener("click", function() {
+  console.log(window.addonScriptObject.body.innerHTML);
+}, false);
+ +

Access to these objects in the target scope is subject to the normal security checks.

diff --git a/files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.getglobalforobject/index.html b/files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.getglobalforobject/index.html new file mode 100644 index 0000000000..a22b49a2d5 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/language_bindings/components.utils.getglobalforobject/index.html @@ -0,0 +1,41 @@ +--- +title: Components.utils.getGlobalForObject +slug: Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.getGlobalForObject +translation_of: Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.getGlobalForObject +--- +

+ +

此方法是用于确定与对象关联的全局对象。用于获取创建对象时所处的全局对象, 即在执行创建对象的脚本时使用的全局对象。

+ +

语法

+ +
var global = Components.utils.getGlobalForObject(obj);
+
+ +

参数

+ +
+
obj
+
其对应的全局对象将被检索的对象; 非可选参数,必须是对象。
+
+ +

例子

+ +
var obj = {};
+function foo() { }
+var global = this;
+
+var g1 = Components.utils.getGlobalForObject(foo);
+var g2 = Components.utils.getGlobalForObject(obj);
+// g1 === global, g2 === global, g1 === g2
+
+// In a script in another window
+var global2 = this;
+function bar() { }
+var obj2 = {};
+
+// Then, assuming bar refers to the function defined in that other window:
+var o1 = Components.utils.getGlobalForObject(bar);
+var o2 = Components.utils.getGlobalForObject(obj2);
+// o1 === global2, o2 === global2
+
diff --git a/files/zh-cn/mozilla/tech/xpcom/language_bindings/index.html b/files/zh-cn/mozilla/tech/xpcom/language_bindings/index.html new file mode 100644 index 0000000000..cf8ced2678 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/language_bindings/index.html @@ -0,0 +1,20 @@ +--- +title: 语言绑定 +slug: Mozilla/Tech/XPCOM/Language_Bindings +tags: + - XPCOM + - 'XPCOM:Language Bindings' +translation_of: Mozilla/Tech/XPCOM/Language_Bindings +--- +

一款 XPCOM 的语言绑定是连接某种特定的程序设计语言与 XPCOM 之间的纽带,它用来提供从语言到 XPCOM 对象的访问, 并且将此种语言写成的模块作为其他进行 XPCOM 绑定的程序语言的 XPCOM 对象。 

+

更具体的说, 一个 XPCOM 语言绑定:

+ +

由于 XPCOM 层本身使用 C/C++ 编写,因此可以使用 C/C++ 直接访问其 API。而当其它的程序设计语言需要访问该 API 时,则需要通过额外的桥接层来实现。

+

当前有效的链接层如下:

+

+
Components
Components 对象是 XPConnect 功能被映射到 JavaScript 上的对象。Components 对象的 native 实现位置在   nsIXPCComponents , 这个接口会被映射成JavaScript 作为使用 XPConnect 的最高层级的对象。
Components.classes
Components.utils.cloneInto
该函数为定义在某一作用域中的对象提供了一个安全的、将其结构化克隆到其字作用域中的方法,
Components.utils.evalInSandbox
Components.utils.getGlobalForObject
此方法是用于确定与对象关联的全局对象。用于获取创建对象时所处的全局对象, 即在执行创建对象的脚本时使用的全局对象。
+
Components.utils.import
这个方法在 Firefox 3 中被引入,它使得在不同的作用域之间分享代码变得更加容易。例如:你可以直接导入 XPCOMUtils.jsm 而不必复制/粘贴冗长的XPCOM组件。
JavaXPCOM
PyXPCOM
XPConnect
[]
+

diff --git a/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/index.html b/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/index.html new file mode 100644 index 0000000000..6ce4c6a6ba --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/index.html @@ -0,0 +1,49 @@ +--- +title: JavaXPCOM +slug: Mozilla/Tech/XPCOM/Language_bindings/JavaXPCOM +tags: + - Java + - JavaXPCOM +translation_of: Mozilla/Tech/XPCOM/Language_bindings/JavaXPCOM +--- +

+

JavaXPCOM允许在Java和XPCOM间进行会话,这样一来,Java应用程序就可以访问XPCOM对象,并且XPCOM也可以访问任何实现了XPCOM接口的Java类。借助JavaXPCOM,开发者可以在Java应用程序中同XPCOM或嵌入的Gecko对话。JavaXPCOM和XPConnect(JavaScript-XPCOM桥)十分相似,并且使用XPIDL实现其功能。 +

JavaXPCOM默认地作为XULRunner的一部分被构建。下载最近的编译成品或XULRunner 1.8.0.4进行尝试。 +

+ + + + +
+

预览

+ +

文章精选

+ +

View All... +

+
+

其他页面

+ +

相关主题

+
XPCOM, 嵌入式Mozilla +
+

there's no javaxpcom category on webwatch <rss>http://developer.mozilla.org/webwatc...t=23&feed=rss2|short|max=5|charset=UTF-8</rss> <span class="alllinks">View All...</span> +

+
+
+

原始文档信息

+ +
+


+

diff --git "a/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\344\275\277\347\224\250javaxpcom\345\234\250java\345\272\224\347\224\250\347\250\213\345\272\217\344\270\255\345\265\214\345\205\245mozilla/index.html" "b/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\344\275\277\347\224\250javaxpcom\345\234\250java\345\272\224\347\224\250\347\250\213\345\272\217\344\270\255\345\265\214\345\205\245mozilla/index.html" new file mode 100644 index 0000000000..9a8e1805fa --- /dev/null +++ "b/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\344\275\277\347\224\250javaxpcom\345\234\250java\345\272\224\347\224\250\347\250\213\345\272\217\344\270\255\345\265\214\345\205\245mozilla/index.html" @@ -0,0 +1,65 @@ +--- +title: 使用JavaXPCOM在Java应用程序中嵌入Mozilla +slug: Mozilla/Tech/XPCOM/Language_bindings/JavaXPCOM/使用JavaXPCOM在Java应用程序中嵌入Mozilla +tags: + - 'JavaXPCOM:Articles' +translation_of: Archive/Mozilla/Embedding_Mozilla_in_a_Java_Application_using_JavaXPCOM +--- +

+


+XULRunner中包含了JavaXPCOM组件,允许Java代码与XPCOM对象交互。在这片文章中您将会看到,在Java中使用XPCOM对象,要比在C++中容易得多。 +

+

必要条件

+ +
+

2006-01-16:XULRunner目前还没有官方发布版本,因此,为了能XULRunner加上JavaXPCOM一起使用,您应该马上下载1.8.0版分支的一个每夜构建。(LinuxMac OS XWindows)。下面提到的MozillaInterfaces.jar文件可以在sdk顶层文件夹中找到。 +

+
+

嵌入

+

为了在Java应用程序中嵌入Mozilla,您需要将库文件MozillaInterfaces.jar加入您的classpath中。这个库(它是SDK的一部分)提供了启动Mozilla和调用XPCOM方法所必需的接口。 +

要开始嵌入,我们使用Mozilla单件类提供的方法。首先,Java应用程序必须找到一个合适的XULRunner安装: +

+
 Mozilla mozilla = Mozilla.getInstance();
+ GREVersionRange[] range = new GREVersionRange[1];
+ range[0] = new GREVersionRange("1.8.*", false, "1.9", false);
+   // work with trunk nightly version 1.9a1  ^^
+
+ try {
+   File grePath = Mozilla.getGREPathWithProperties(range, null);
+   LocationProvider locProvider = new LocationProvider(grePath);
+   mozilla.initEmbedding(grePath, grePath, locProvider);
+ } catch (FileNotFoundException e) {
+   // this exception is thrown if greGREPathWithProperties cannot find a GRE
+ } catch (XPCOMException e) {
+   // this exception is thrown if initEmbedding failed
+ }
+
+

LocationProvider是Java应用程序提供的一个类。它实现了IAppFileLocProvider接口,并且告诉XPCOM那里可以找到那些文件和目录。 +

initEmbedding方法启动嵌入进程,允许Java应用程序与XPCOM和Mozilla一起工作。一旦Java应用程序使用完Mozilla,就需要中止嵌入进程: +

+
 try {
+   mozilla.termEmbedding();
+ } catch (XPCOMException e) {
+   // this exception is thrown if termEmbedding failed
+ }
+
+

与XPCOM对象一起工作

+

现在,Mozilla已经嵌入了,Java应用程序可以和XPCOM对象工作了。Mozilla类提供了多种方法使工作更加容易,例如getServiceManagergetComponentManager,和newLocalFile。为了在XPCOM对象中增加查询和调用的方法,JavaXPCOM允许Java应用程序传递Java类对象给XPCOM方法。 +

例如: +

+
 Mozilla mozilla = Mozilla.getInstance();
+ WindowCreator creator = new WindowCreator();  // implements nsIWindowCreator
+
+ nsIServiceManager serviceManager = mozilla.getServiceManager();
+
+ nsIWindowWatcher windowWatcher = (nsIWindowWatcher) serviceManager
+   .getServiceManagerByContractID(NS_WINDOWWATCHER_CONTRACTID,
+     nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
+ windowWatcher.setWindowCreator(creator);
+
+

在这个例子中,我们有一个叫WindowCreator的类,它实现了nsIWindowCreator接口,我们想要在Mozilla中注册它。要做到这点,我们首先获取服务管理器(service manager),通过它,我们可以获取Mozilla窗口监视器的引用。 +

+
+
diff --git "a/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\345\274\200\345\217\221/index.html" "b/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\345\274\200\345\217\221/index.html" new file mode 100644 index 0000000000..d21deddbb6 --- /dev/null +++ "b/files/zh-cn/mozilla/tech/xpcom/language_bindings/javaxpcom/\345\274\200\345\217\221/index.html" @@ -0,0 +1,26 @@ +--- +title: 开发 +slug: Mozilla/Tech/XPCOM/Language_bindings/JavaXPCOM/开发 +tags: + - JavaXPCOM +translation_of: Mozilla/Tech/XPCOM/Language_bindings/JavaXPCOM/Development +--- +

+

+

简述

+

JavaXPCOM源于Mozilla的Java版firefox计划,后来演变为Mozilla的一项重要的扩展应用技术。目前JavaXPCOM是Mozilla最活跃的扩展应用技术之一。 +简单的说,JavaXPCOM就是通过Java运行环境启动GRE(Gecko Runtime Environment)环境,然后通过Java Interface与GRE typelib的映射关系,使得Java对象可以与XPCOM对象进行对象交互。当然,与XPCOM一样,JavaXPCOM也支持通过XPConnect映射同以xul/js为主体的Mozilla界面环境进行对象交互。 +

+

源代码

+

最新的源代码可以在Mozilla主干上找到,在extensions/java/xpcom目录中。 +

+

构建指令

+

构建指令可以在这里找到:构建JavaXPCOM。 +

+

Bugs

+

所有的JavaXPCOM的bugs都在Bugzilla中被跟踪, 使用"Core"产品和"Java to XPCOM Bridge"组件。 +

+ diff --git a/files/zh-cn/mozilla/tech/xpcom/language_bindings/pyxpcom/index.html b/files/zh-cn/mozilla/tech/xpcom/language_bindings/pyxpcom/index.html new file mode 100644 index 0000000000..397d95ff78 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/language_bindings/pyxpcom/index.html @@ -0,0 +1,67 @@ +--- +title: PyXPCOM +slug: Mozilla/Tech/XPCOM/Language_bindings/PyXPCOM +translation_of: Mozilla/Tech/XPCOM/Language_bindings/PyXPCOM +--- +

 

+
+

PyXPCOM允许在PythonXPCOM之间进行通信,例如Python应用能够访问XPCOM对象,XPCOM能够访问任何实现了XPCOM接口的Python类。使用PyXPCOM一个开发者可以与XPCOM交互或者从一个Python应用中嵌入Gecko。PyXPCOM就类似于JavaXPCOM(Java-XPCOM桥)或者是XPConnect(JavaScript-XPCOM桥)。

+

Python类和接口:Mozilla定义了许多外部接口并允许用于嵌入使用和组件开发。PyXPCOM提供了方法以像Python语言接口那样来访问这些接口。PyXPCOM同时也包含了几个用于提供从Python访问那些初始化及关闭XPCOM和Gecko功能的类,以及一些XPCOM的帮助函数。

+
+ + + + + + + +
+

文档

+
+
+ 构建 PyXPCOM
+
+ PyXPCOM构建指导。
+
+
+
+ 创建 Python XPCOM 组件
+
+ 如何使用Python创建简单的XPCOM组件的例子。
+
+
+
+ PyXPCOM 入门
+
+ PyXPCOM是XPCOM与Python之间的一种桥接技术。本节带给你的是PyXPCOM入门级的向导。
+
+

NOTE: The links to Part II and III of this series are broken and I cannot find them on the IBM site. Please update this page if/when the links can be found.

+

View All...

+

历史

+

PyXPCOM was initially developed by ActiveState Tool Corporation, and came out of their Komodo project. Current releases are now integrated with the Mozilla build system.

+

Other Resources
+ PythonExt - extension that provides PyXPCOM
+ Samples - demo applications using PyXPCOM

+
+

交流

+
+ +

源代码

+ + +
+
+ XPCOM
+
+ PyDOM: replace JavaScript with Python
+
+ Python-SpiderMonkey
+
+
+

 

diff --git a/files/zh-cn/mozilla/tech/xpcom/language_bindings/xpconnect/index.html b/files/zh-cn/mozilla/tech/xpcom/language_bindings/xpconnect/index.html new file mode 100644 index 0000000000..df0270b533 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/language_bindings/xpconnect/index.html @@ -0,0 +1,67 @@ +--- +title: XPConnect +slug: Mozilla/Tech/XPCOM/Language_bindings/XPConnect +translation_of: Mozilla/Tech/XPCOM/Language_bindings/XPConnect +--- +

XPConnect是JavaScriptXPCOM之间的桥梁。利用XPConnect,你可以通过JavaScript代码使用XPCOM组件,同时让XPCOM组件与JavaScript对象交互。XPConnect是Firefox的组成部分,同时也应用于XUL应用。

+ + + + + + + + +
+

文档

+ +
+
结构基础
+
XPConnect, JavaScript, XPCOM, XUL...
+
使用组件
+
如何与XPCOM组件通信。
+
XPConnect 和 XPIDL 的常见问题解答
+
关于使用XPConnect和XPIDL的常见问题解答。该页面尚未迁移至MDN。
+
XPConnect Wrappers
+
XPConnect的wrappers的生成和使用
+
+ +

XPConnect 脚本安全

+
+

工具

+ + +
+ +
+
+

加入XPCOM社区

+ +
+
选择你喜欢的方式来加入讨论:
+ + +
+ + +
+
+ + diff --git a/files/zh-cn/mozilla/tech/xpcom/observer_notifications/index.html b/files/zh-cn/mozilla/tech/xpcom/observer_notifications/index.html new file mode 100644 index 0000000000..86fdd81a37 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/observer_notifications/index.html @@ -0,0 +1,880 @@ +--- +title: Observer Notifications +slug: Mozilla/Tech/XPCOM/Observer_Notifications +translation_of: Mozilla/Tech/XPCOM/Observer_Notifications +--- +

Observer topics

+ +

The following are topics that you can observe during the course of an application. Unless otherwise noted you register for the topics using the nsIObserverService.

+ +

Application startup

+ +

These are the topics that you can observe on startup, in order of appearance.

+ +

If your component requires access to the user profile, or any services which require access to the profile (preferences, bookmarks, and so on) then a common pattern is to register with the nsICategoryManager for the app-startup topic which can be done in the component's registration code, and then in that notification register with the observer service for the profile-after-change notification. See Receiving startup notifications for more information about how this works.

+ +

Starting in Firefox 3.5 components can simply register for the profile-after-change notification in nsICategoryManager.

+ + + + + + + + + + + + +
TopicDescription
* +

Everything.  [nsObserverService.cpp]

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDescription
xpcom-startup +

Note: An extension can no longer be registered to receive this notification in Firefox 4 and later. See XPCOM changes in Gecko 2.0 for details.

+ +

Called when xpcom is initialized. Many things are not available for use at this point. To receive this notification you have to register with nsICategoryManager. The registered component is always retrieved as a singleton (That is getService() will be used to instantiate it).

+
app-startup +

Note: An extension can no longer be registered to receive this notification in Firefox 4 and later. See XPCOM changes in Gecko 2.0 for details.

+ +

General event for application startup. To receive this notification you have to register with nsICategoryManager. Prepend "service," to the contract ID in the category registration to be invoked via getService() instead of createInstance().

+
profile-do-changeThis is fired after the profile has been selected. You will not be able to access user preferences, bookmarks, or anything that uses the profile folder until this event occurs. This occurs after any profile migration.
profile-after-change +

This is fired after all the observers for profile-do-change have been notified.

+ +

You can register with nsICategoryManager to receive this notification. Prior to Firefox 3.5, this was available to observers observing the app-startup/xpcom-startup notification.

+
final-ui-startup +

Triggered just before the first window for the application is displayed.

+
sessionstore-windows-restored +

Sent by the session restore process to indicate that all initial browser windows have opened. Note that while the window are open and the chrome loaded the tabs in the windows may still be being restored after this notification.

+ +

Note: This notification is specific to Firefox and SeaMonkey 2.0 applications

+
+ +

Application shutdown

+ +

These are the topics that you can observe on shutdown, in order of appearance.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDescription
quit-application-requestedSomething has requested that the application be shutdown. You can cancel the shutdown from here by setting aSubject.data to true (aSubject is the first parameter to your observer, the data value is an nsISupportsPRBool).
quit-application-grantedAll observers have agreed to the shutdown.
quit-applicationThe application is about to quit. This can be in response to a normal shutdown, or a restart.
Note: The data value for this notification is either 'shutdown' or 'restart'.
profile-change-net-teardownThe network connection is going offline at this point.
Note: The data value for this notification is either 'shutdown-persist' or 'shutdown-cleanse'.
profile-change-teardownPart of the shutdown, profile data is still available at this point.
Note: The data value for this notification is either 'shutdown-persist' or 'shutdown-cleanse'.
profile-before-changeCalled just before the profile is lost.
Note: The data value for this notification is either 'shutdown-persist' or 'shutdown-cleanse'.
xpcom-will-shutdown Called just before xpcom-shutdown. Observer must not spin event loop.
xpcom-shutdownThis is the end. Many things will not be available here.
+ +

Browser

+ +

These topics indicate interesting things that happen that the browser alerts you to.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDescription
browser:purge-session-historySent when the sanitizer runs to purge all history and other information.
browser:purge-domain-dataSent after domain-specific history and other information have been purged. The data value is a string form of the domain.
browser-lastwindow-close-requestedSent when the browser wishes to close the last open browser window. When this is sent, it is possible that other windows may still be open, such as the download manager or preferences. The data value is an nsISupportsPRBool. Recipients may set this to true to abort the close.
browser-lastwindow-close-grantedSent when all interested parties have responded to the browser-lastwindow-close-requested notification and none of them requested that the close be aborted. After this is sent and handled, the browser window will close.
browser-delayed-startup-finishedSent when the browser window and all its components have been loaded and initialized.
+ +

Documents

+ +

These topics indicate notifications you can monitor related to DOM documents.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicSubjectDataDescription
chrome-document-global-created nsIDOMWindownullSent immediately after a chrome document window has been set up, but before any script code has been executed. This lets extensions inject API into chrome windows as needed (see nsIDOMGlobalPropertyInitializer for an alternative method of doing this, which uses significantly less memory).
+ data is intentionally left blank.
content-document-global-created nsIDOMWindoworiginSent immediately after a web content document window has been set up, but before any script code has been executed. This lets extensions inject API into content windows as needed (see nsIDOMGlobalPropertyInitializer for an alternative method of doing this).
+ data is a string form of the origin (for use in security checks), eg "http://developer.mozilla.org".
document-element-inserted DocumentnullSent immediately after the root element of a document has been created, but before executing any script on it.
user-interaction-active nsIDOMWindownull +

Sent once every 5000ms while this chrome document sees some kind of user activity (for example, keyboard or mouse events), and at the exact moment of the state transition from idle to active.

+
user-interaction-inactive nsIDOMWindownull +

Sent when the chrome document has seen no user activity for a while. The notification is not repeated during a continuous inactivity period.

+
+ +

Windows

+ +

These topics indicate points of interest during the lifetime of a window.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
dom-window-destroyed  Called just before a DOM window is destroyed.
inner-window-destroyed  nullCalled when an inner window is removed from the backward/forward cache. See Working With BFCache for information about the bfcache, and Inner and outer windows for details about how the window hierarchy works. Extensions that cache information about windows may wish to observe this so they can release information when the window is destroyed.  The window id can be obtained from subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data
outer-window-destroyed nullCalled when an outer window is disconnected from its docshell.  See Inner and outer windows for details about how the window hierarchy works. Extensions that cache information about windows may wish to observe this so they can release information when the window is destroyed.  The window id can be obtained from subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data
toplevel-window-ready Called just after a new top level window has been opened and is ready, but has not yet loaded a document.
xul-window-destroyed Called just before a XUL window is destroyed.
xul-window-registered Called just after a top level XUL window is registered with the window mediator service.
xul-window-visible Called just after a XUL window is made visible.
+ +

Spelling checker

+ +

These topics indicate activities that have occurred related to the spelling checker.

+ + + + + + + + + + + + + + +
TopicDataDescription
spellcheck-dictionary-update Sent by a spell checker implemented by the mozISpellingChecker interface when something has happened that causes a change that may interest the editor; these are received primarily by nsIEditor.
+ +

IO Notifications

+ +

These topics can be used to watch the IO service for useful information.

+ + + + + + + + + + + + + + + + + + + + +
TopicDescription
offline-requestedCalled to query whether the application can go offline. The attempt to go offline can be canceled. +

Note: If your code chooses to cancel the attempt to go offline, it must notify the user.

+
network:offline-about-to-go-offlineCalled just before all network IO is taken offline.
network:offline-status-changedCalled when the offline state has changed.
Note: The data value for this notification 'offline' or 'online' to indicate the new state.
+ +

HTTP requests

+ +

These are the topics that you can observe during a HTTP request (see Setting HTTP request headers and Creating Sandboxed HTTP Connections). Both are passed an nsIHttpChannel as the subject parameter.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDescription
http-on-modify-requestCalled as a http request is made. The channel is available to allow you to modify headers and such. See this code snippet to learn how to get the tab that issued the request.
http-on-opening-request Similar to http-on-modify-request, but called earlier (synchronously during the channel's asyncOpen() call), and some channel atttributes (proxyInfo) may be missing.  Use only if your observer must be called before asyncOpen returns.
http-on-examine-responseCalled after a response has been received from the web server. Headers are available on the channel. The response can be accessed and modified via nsITraceableChannel.
http-on-examine-cached-response Called instead of http-on-examine-response when a response will be read completely from the cache. Headers are available on the channel.
http-on-examine-merged-responseCalled instead of http-on-examine-response when a response will be read partially from cache, and partially from the network (HTTP 206 or 304 response). Headers are available on the channel.
+ +

Cookies

+ +

These topics indicate whenever a cookie has been changed (added, changed, cleared, or deleted) or its setting rejected by the browser. See nsICookieService for details.

+ + + + + + + + + + + + + + + + +
TopicDescription
cookie-changedCalled upon a cookie change (added, changed, cleared, or deleted)
cookie-rejectedCalled when the setting of a cookie was rejected by the browser (per the user's preferences)
+ +

Download Manager

+ +

These topics indicate that events related to the Download Manager have occurred.

+ + + + + + + + + + + + + + + + +
TopicDescription
download-manager-ui-doneCalled when the list of downloads in the Download Manager windows finishes updating.  This can happen multiple times, such as when the window first opens, when multiple items are removed, and when entering private browsing mode.
download-manager-remove-download Called when a download of the list is removed or all the list is cleared. The subject will be the download id wrapped in nsISupportsPRUint32, for one download removed, or null for multi download remove, for example when the download list is cleared.
+ +

Extension Manager

+ +
+

Note: These notifications are no longer available starting with Gecko 2.0, instead use AddonManager.addAddonListener() to receive similar events.

+
+ +

This topic indicates when the extension manager performs some action. Note that any action will be taken the next time the application starts. See nsIExtensionManager for details.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
em-action-requesteditem-installedA new extension has been installed.
em-action-requesteditem-upgradedA different version of an existing extension has been installed.
em-action-requesteditem-uninstalledAn addon has been marked to be uninstalled.
em-action-requesteditem-enabledAn addon has been enabled.
em-action-requesteditem-disabledAn addon has been disabled.
em-action-requesteditem-cancel-actionA previous action has been cancelled.
+ +

Idle Service

+ +

This topic indicates when actions related to the Idle Service, provided by the nsIIdleService interface. Unlike the user-interaction-active and user-interaction-inactive topics listed above, the Idle Service monitors user activity in general, whether related to the Mozilla application or not (acting somewhat like the user activity/inactivity events a screen saver would be interested in).

+ + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
idleThe length of time the user has been idle, in milliseconds.Sent when the user becomes idle.
idle-dailyThe length of time the user has been idle, in milliseconds.Sent once a day while the user is idle.
backThe length of time the user has been idle, in milliseconds.Sent when the user returns from being idle.
+ +

Computer sleep and wake

+ +

This topic indicates when actions related to the computer going to sleep or waking up occur.  (Note: these notifications are not currently available on Linux.  See bug 758848.)

+ + + + + + + + + + + + + + + + + + + +
TopicDataDescription
sleep_notificationnullSent when the computer is going to sleep.
wake_notificationnullSent when the computer is waking up.
+ +

Login Manager

+ +

This topic indicates when actions related to the Login Manager occur.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
passwordmgr-found-formnoAutofillFormsA login is available for this form, but autofill of forms is disabled, so the form was not automatically filled out. 
passwordmgr-found-formautocompleteOffA login is available for this form, but autocomplete is disabled.
passwordmgr-storage-changedaddLoginA login has been added to the Login Manager's database. The notification's subject is the login that was added to the database.
passwordmgr-storage-changedremoveLoginA login was removed from the Login Manager's database. The notification's subject is the login that was removed from the database.
passwordmgr-storage-changedmodifyLoginA login in the Login Manager's database was modified. The notification's subject is an array whose first entry is the old login and whose second entry is the new one.
passwordmgr-storage-changedremoveAllLoginsAll logins have been removed from the Login Manager's database.
passwordmgr-storage-changedhostSavingEnabledHost saving has been enabled.
passwordmgr-storage-changedhostSavingDisabledHost saving has been disabled.
+ +

Places

+ +

This topic indicates when actions related to Places (the history and bookmarks database) occur.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
places-autocomplete-feedback-updated Sent when Places updates the location bar's autocompletion display.
places-connection-closed Sent after Places has closed its database connection. Once this has been sent, no Places features will work.
places-connection-closing  +

Sent as the last notification before the Places service closes its database connection.

+ +
Warning: This is for internal use only.
+
places-database-locked The Places database is currently locked by a third-party process and cannot be opened.
places-favicons-expired Sent when all favicons have been expired.
places-init-complete The Places database has been successfully initialized. You should wait until this notification occurs before querying the places database.
places-maintenance-finished Sent when maintenance of the Places database is complete; this is done periodically in the background to keep the Places database tidy.
places-shutdown Sent when Places shuts down. If you are referencing instances of mozIStorageStatement referencing Places databases when this notification occurs, you should call their mozIStorageStatement.finalize() method
places-sync-finished Sent when the Places database has been successfully flushed to disk.
places-will-close-connection  +

Sent when the Places service is about to close its database connection. Only necessary cleanup tasks should run at this point, and nothing should be added to the database. In addition, after this has been sent, no Places APIs should be called.

+ +
Warning: This is for internal use only.
+
+ +

Session Store

+ +

These topics are used when actions related to Session Store occur.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
sessionstore-state-read Sent immediately after session store data is read and before it's used.
sessionstore-state-finalized Sent immediately after the session is restored.
sessionstore-state-write Sent immediately before the session store data is written to disk.
sessionstore-state-write-complete Sent immediately after the session store data is written to disk.
sessionstore-state-purge-complete  
+ +

Private browsing

+ +

These topics indicate when actions related to private browsing occur.

+ + + + + + + + + + + + + + + + + + + +
TopicDataDescription
private-browsingenterSent when private browsing mode is activated.
private-browsingexitSent when private browsing mode is deactivated.
+ +

Bookmarks

+ +

These topics indicate when actions related to bookmarks occur.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
bookmarks-restore-beginjsonSent just before bookmarks are restored from JSON.
bookmarks-restore-beginhtmlSent just before bookmarks are restored from HTML. If bookmarks will be restored into a specific folder, observers will be passed an nsISupportsPRInt64 through their subject parameters indicating the ID of the folder. The subject is null otherwise.
bookmarks-restore-beginhtml-initialSent just before bookmarks are restored from HTML on initial import. If bookmarks are restored into a specific folder, observers will be passed an nsISupportsPRInt64 through their subject parameters indicating the ID of the folder. The subject is null otherwise.
bookmarks-restore-successjsonSent just after bookmarks are restored from JSON.
bookmarks-restore-successhtmlSent just after bookmarks are restored from HTML. If bookmarks were restored into a specific folder, observers will be passed an nsISupportsPRInt64 through their subject parameters indicating the ID of the folder. The subject is null otherwise.
bookmarks-restore-successhtml-initialSent just after bookmarks are restored from HTML on initial import. If bookmarks were restored into a specific folder, observers will be passed an nsISupportsPRInt64 through their subject parameters indicating the ID of the folder. The subject is null otherwise.
bookmarks-restore-failedjsonSent when bookmarks could not be sucessfully restored from JSON.
bookmarks-restore-failedhtmlSent when bookmarks could not be successfully restored from HTML. If bookmarks were to have been restored into a specific folder, observers will be passed an nsISupportsPRInt64 through their subject parameters indicating the ID of the folder. The subject is null otherwise.
bookmarks-restore-failedhtml-initialSent when bookmarks could not be successfully restored from HTML on intial import. If bookmarks were to have been restored into a specific folder, observers will be passed an nsISupportsPRInt64 through their subject parameters indicating the ID of the folder. The subject is null otherwise.
+ +

Themes

+ +

These topics indicate when actions related to themes occur.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
lightweight-theme-preview-requested jsonSent when the user requests to preview a lightweight theme, but before existing windows are styled with the new theme.
lightweight-theme-change-requested jsonSent to indicate that the user has chosen a new theme in the add-ons manager, but before the change takes effect.
lightweight-theme-changed -Sent after the current theme is changed.
lightweight-theme-styling-update jsonSent when the current theme being used is changed; this is sent even when the user is previewing a theme, not just when the theme is actually selected.
lightweight-theme-list-changed -The list of available lightweight themes has changed.
+ +

Developer tools

+ +

These topics let you know about things that have happened related to Firefox's built-in developer tools.

+ +

 

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicDataDescription
highlighter-ready - +

Sent when the highlighter component is initialized.

+ +
Note: This is used by the Inspector to detect when it should begin its initialization process.
+
inspector-closed -Sent when the Inspector tool is closed.
inspector-editor-closed -Sent after the attribute-value editor has been closed.
inspector-editor-opened -Sent after the attribute-value editor has been opened and initialized.
inspector-editor-saved -Sent when changes have been saved in the attribute-value editor.
inspector-highlighting -Sent every time a different node in the page gets highlighted.
inspector-opened -Sent after the Inspector tool has finished its initialization.
inspector-ruleview-ready -Sent when the inspector's CSS Rule View is opened and initialized.
inspector-state-restored -Sent when the Inspector is re-opened after a tab switch.
inspector-treepanel-ready -Sent when the Inspector's Tree Panel is opened and initialized.
inspector-unhighlighting -Sent every time the highlighter stops highlighting a node.
+ +

Telemetry

+ + + + + + + + + + + + + + +
TopicDataDescription
gather-telemetry -Sent by the telemetry service when it's time to start gathering telemetry data, since the telemetry ping is coming soon.
+ +

Plugins

+ + + + + + + + + + + + + + +
TopicDataDescription
plugin-crashed-Sent when a plugin has crashed.
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/index.html new file mode 100644 index 0000000000..92f0a47369 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/index.html @@ -0,0 +1,16 @@ +--- +title: XPCOM glue classes +slug: Mozilla/Tech/XPCOM/Reference/Glue_classes +tags: + - Classes + - Landing + - NeedsTranslation + - TopicStub + - XPCOM +translation_of: Mozilla/Tech/XPCOM/Reference/Glue_classes +--- +

These "glue" classes are provided to make it easier to use XPCOM from C++ code. When these classes are used by a component, you may need to link the component against the XPCOM glue library.

+

+
+
使用nsCOMPtr
这篇文档是对nsCOMPtr的一个总述。如果您所遇到的问题,无法在该文档中找到答案,可能就没有其他文档可以回答它了。您需要求助于XPCOM新闻组或者有nsCOMPtr使用经验的人来求解,或者根据自己的试验获取答案。
+

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/getting_started_guide/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/getting_started_guide/index.html new file mode 100644 index 0000000000..32dedcf102 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/getting_started_guide/index.html @@ -0,0 +1,478 @@ +--- +title: 入门指南 +slug: Mozilla/Tech/XPCOM/Reference/Glue_classes/nsCOMPtr/Getting_Started_Guide +translation_of: Mozilla/Tech/XPCOM/Using_nsCOMPtr/Getting_Started_Guide +--- +

下面开始探讨智能指针问题。

+

介绍

+

什么是 nsCOMPtr?

+

nsCOMPtr 是防止内存泄漏的一种工具。

+

nsCOMPtr 是一种智能指针。 它是一个模板类,在使用上类似C/C++中的普通指针。如:可使用*或者->得到其所指定的内容。nsCOMPtr之所以智能,是因为它不像一般指向XPCOM对象的指针,nsCOMPtr还管理AddRef, Release, 和QueryInterface方法。 nsCOMPtr是在以下源文件中定义的:

+ +

...though you probably don't want to look in there, just yet.

+

利用nsCOMPtr,比使用原始的XPCOM接口指针,能够把代码写的更简短,更清晰,更明白,更安全。

+

[XP]COM Basics: Ownership and Reference Counting

+

这段是对XPCOM的一些基本问题的一个复习。对nsCOMPtrs的理解,需要对XPCOM有一个基本的认识。您可通过以下方式对XPCOM进行学习。Don BoxEssential COM 介绍了COM的基本规则和使用。 Don Box 在 Effective COM.一书中更详尽的说明了COM的细节,缺陷和易犯的错误。您还需要对C++有基本的了解。这里列举三本比较有用的书:Bjarne Stroustrup 的 The C++ Programming Language,Scott Meyers 的 Effective C++More Effective C++

+

All XPCOM objects are allocated on the heap. Clients don't get to know much about the implementation of any such object. They reference it only through a pointer to an `interface', i.e., the static type of the pointer is a pointer to an abstract base class, the actual object pointed to is a class derived from that abstract base class. The XPCOM object is said to `implement that interface'. The client's reference to the object is typically called `an interface pointer'.

+

An object may implement many interfaces. Each interface is (at least conceptually) separately `reference counted'. That is, the interface keeps a count of the number of clients holding references to it. When that count goes to zero, the interface may delete itself. Clients are expected to keep this reference count accurate by incrementing it when they acquire a reference to the interface, and decrementing it before they let go. To facilitate this, all interfaces inherit from an abstract base class that provides the member functions AddRef, and Release.

+

A rule of XPCOM is that any function that creates or returns an interface pointer will have already AddRefed it. The caller can then hold onto the reference indefinitely, calling Release when it no longer needs it. When the last pointer to an interface is Released, the interface (and consequently, typically the underlying object) will delete itself. As long as there is an outstanding AddRef against the interface, it continues to exist. If you forget to call Release, the object will leak, i.e., the storage for that object will never be reclaimed. Leaks are bad :-).

+

A reference through which you will call AddRef and Release is called an owning reference. It holds a stake in the underlying object. That object cannot go away until the owning reference has relinquished its claim. Not all references need to be owning references. In fact, if two objects somehow end up owning each other (even transitively) it becomes difficult for either of those object to be reclaimed without adding some `out-of-band' mechanism for breaking the ownership cycle. The document Some COM Ownership Guidelines provides some hints on when ownership is needed. The following lists are good starting point, but by no means complete.

+

You use an owning reference when

+ +

You don't need an owning reference when

+ +

It turns out that reference counting by hand is hard for programmers to get right. It may sound simple, but in practice it's very easy to forget to Release at the appropriate moment. Or to AddRef too many or too few times.

+

How does nsCOMPtr help?

+

nsCOMPtr manages AddRef, Release, and other red-tape for you. An nsCOMPtr looks and acts as much like a raw XPCOM interface pointer as C allows, but it knows it owns the object it points to. This takes a little getting used to on your part, but ends up with less typing, clearer, safer code, and less leaks.

+

For instance, here is a typical snippet of code (at its most compact) where you assign a XPCOM interface pointer into a member variable, i.e., the body of a `setter' function, side-by-side using raw XPCOM interface pointers and nsCOMPtrs. 

+

对照1.设置成员变量。

+

 

+ + + + + + + + +
+  
+
+// raw [XP]COM interface pointers...
+// given: |nsIFoo* mFooPtr;|
+
+/*
+   |AddRef| the new value if it's not
+   |NULL|; assign it in; and |Release|
+   the old value, if any (so we don't
+   leak it).
+
+   This order of assignment is special
+   and must be used to avoid particular
+   ownership bugs.
+ */
+
+NS_IF_ADDREF(aFooPtr);
+nsIFoo* temp = mFooPtr;
+mFooPtr = aFooPtr;
+NS_IF_RELEASE(temp);
+
+
+
+// |nsCOMPtr|...
+// given: |nsCOMPtr<nsIFoo> mFooPtr;|
+
+/*
+   This assignment automatically
+   |Release|s the old value in
+   |mFooPtr|, if any, and |AddRef|s the
+   new one, in the appropriate sequence
+   to avoid the ownership bug mentioned
+   earlier.
+ */
+
+
+
+
+
+mFooPtr = aFooPtr;
+
+
+
+

Additionally, the class using raw XPCOM interface pointers will need a destructor to Release mFooPtr; and a constructor to ensure that mFooPtr is initially set to NULL (or some other reasonable value).

+

nsCOMPtr helps you write code that is leak-proof, exception safe, and significantly less verbose than you would with raw XPCOM interface pointers. With nsCOMPtr, you may never have to call AddRef, Release, or QueryInterface by hand.

+

You still have to understand XPCOM. You still have to know which functions return interface pointers that have already been AddRefed and which don't. You still have to ensure your program logic doesn't produce circularly referencing garbage. nsCOMPtr is not a panacea. It is, however, helpful, easy to use, well-tested, and polite. It doesn't require that a function author cooperate with you, nor does your use force others to use it.

+

使用nsCOMPtr

+

The Basics

+

多数情况下,使用nsCOMPtr和一个一般的XPCOM接口指针是类似的。注意在声明中的细微区别。

+ + + + + + + + +
+ 对照 2. 相似点: nsCOMPtr类似于 XPCOM接口指针
+
+// raw [XP]COM interface pointers...
+
+nsIFoo* fooPtr = 0;
+ // ...
+fooPtr->SomeFunction(x, y, z);
+AnotherFunction(fooPtr);
+
+if ( fooPtr )
+  // ...
+
+if ( fooPtr == foo2Ptr )
+  // ...
+
+
+
+// |nsCOMPtr|...
+
+nsCOMPtr<nsIFoo> fooPtr;
+// ...
+fooPtr->SomeFunction(x, y, z);
+AnotherFunction(fooPtr);
+
+if ( fooPtr )
+  // ...
+
+if ( fooPtr == foo2Ptr )
+  // ...
+
+
+

 

+

有两点主要区别。第一:不需要也不再允许调用AddRefRelease方法。 

+ + + + + + + + +
+ 对照 3. 不同点: AddRef Release 对于 nsCOMPtrs 来说是非法的。
+
+// raw [XP]COM interface pointers...
+// given: |nsIFoo* mFooPtr;|
+
+  /*
+    Note: this sequence is not the
+    correct order to do assign
+    raw pointers anyway (see
+    {{ Anch("Comparison 1") }}) but I need it
+    for this comparison.
+  */
+
+NS_IF_RELEASE(mFooPtr);
+
+mFooPtr = aFooPtr;
+NS_IF_ADDREF(mFooPtr);
+
+
+
+
+// |nsCOMPtr|...
+// given: |nsCOMPtr<nsIFoo> mFooPtr;|
+
+  /*
+    You no longer need, nor will the
+    compiler let you, call |AddRef|,
+    or |Release|.
+  */
+
+
+
+NS_IF_RELEASE(mFooPtr);
+  // Error: |Release| is private
+mFooPtr = aFooPtr;
+NS_IF_ADDREF(mFooPtr);
+  // Error: |AddRef| is private
+
+
+

 

+

第二:使用 getter_AddRefs 标识nsCOMPtr,作为获取指针返回值的函数的参数,而不能只使用nsCOMPtr的地址作为参数。

+ + + + + + + + +
+ 对照 4. 不同点: nsCOMPtr 作为输出参数时,使用 getter_AddRefs。
+
+// raw [XP]COM interface pointers...
+
+nsIFoo* foo;
+
+GetFoo(&foo);
+
+
+
+// |nsCOMPtr|s...
+
+nsCOMPtr<nsIFoo> foo;
+
+GetFoo(getter_AddRefs(foo));
+
+
+

 

+

以上是对nsCOMPtrS的一些说明,基本涵盖了平日使用的90%。以下是在一些复杂情况下,对其的细节说明。

+

 

+

一些细节

+

 

+

以下是更多细节让您更了解 nsCOMPtr

+

通常,通过调用 QueryInterface 获取接口指针 QueryInterface 是一个 getter 函数,由以上方法,可通过 getter_AddRefs 方法来获取。

+ + + + + + + +
+ The hard way to QueryInterface into an nsCOMPtr.
+
+// A way (though not the best way) to |QueryInterface| into an |nsCOMPtr|...
+
+nsCOMPtr<nsIFoo> foo;
+
+nsresult rv = bar->QueryInterface(NS_GET_IID(nsIFoo), getter_AddRefs(foo));
+
+  // Or, if you're a savvy [XP]COM programmer,
+  //  you use the type-safe version...
+nsresult rv = CallQueryInterface(bar, getter_AddRefs(foo));
+
+
+

因为 QueryInterface 使用频繁,nsCOMPtr 提供了一种特殊方式对其调用。这种方式是类型安全的,QueryInterface的返回值能直接构造nsCOMPtr。这种构造方式比通过赋值进行构造效率更高。这种方式是 do_QueryInterface 。通过使用这种方式,以上例子可写为:

+ + + + + + + +
+ How to QueryInterface into an nsCOMPtr.
+
+// The best way to |QueryInterface| into an |nsCOMPtr|...
+
+nsresult rv;
+nsCOMPtr<nsIFoo> foo( do_QueryInterface(bar, &rv) );
+
+  // Or, if you don't care about the |nsresult|
+nsCOMPtr<nsIFoo> foo( do_QueryInterface(bar) );
+
+
+

nsCOMPtr happily calls AddRef and Release implicitly. This same favor is not extended to QueryInterface. nsCOMPtr does not QueryInterface on assignment without your explicit permission in the form of the do_QueryInterface directive. You need never worry about hidden queries. However, be aware that if you should have queried but didn't, e.g., when assigning in a raw pointer where C allows the assignment, but XPCOM wouldn't, nsCOMPtr will assert at runtime. Use do_QueryInterface whenever you assign in a pointer to a XPCOM interface of a different type, even if that type happens to derive from the base type of the nsCOMPtr

+

 

+ + + + + + + + +
+ 对照6. do_QueryInterface 避免了XPCOM 中的类型错误。
+
+class nsIBar
+  : public nsIFoo ... { ... };
+
+nsIBar* p = ...;
+
+  // C   thinks every |nsIBar*| is an
+  //  |nsIFoo*|, therefore, C   allows
+  //  this...
+nsCOMPtr<nsIFoo> foo = p;
+  //  ...even though it is an [XP]COM
+  //  type error
+
+
+
+class nsIBar
+  : public nsIFoo ... { ... };
+
+nsIBar* p = ...;
+
+
+
+  // No type error here...
+nsCOMPtr<nsIFoo> foo( do_QueryInterface(p) );
+
+
+
+
+

Remember, the C type system and the XPCOM type system are really two independent things. Because XPCOM interfaces are expressed as abstract C base classes, you may be tempted to let C handle the differences, or to use C casts to navigate between interface types. This is wrong. The only sanctioned way to get between XPCOM types is with QueryInterface. In the example above, there is no reason to assume that the nsIFoo* C pulls out of p would be the same one that p->QueryInterface() would return.

+

dont_AddRef is a similar directive that helps you when you assign in a pointer that has already been AddRefed, e.g., because you called a getter that returned the pointer as its function result.

+ + + + + + + +
+ Using dont_AddRef.
+
+nsCOMPtr<nsIFoo> foo( dont_AddRef(CreateFoo()) );
+  // |CreateFoo| |AddRef|s its result, as all good getters do
+
+
+

Something nsCOMPtr Doesn't Do

+

An nsCOMPtr does all that is necessary to behave as an owning reference. A given nsCOMPtr does not, however, cooperate in making other owning pointers. After learning how nsCOMPtr automatically AddRefs a pointer as it is being assigned in, the natural assumption is that it does the same thing when assigning out. Here is a snippet of code that demonstrates this misconception.

+ + + + + + +
+
+// Incorrect assumptions about |nsCOMPtr|...
+
+nsresult
+nsCacheRecord::GetFileSpec( nsIFileSpec** aFileSpecResult )
+    /*
+      ...fills in the callers |nsFileSpec*| (which the caller supplied
+      the address of) with a copy of my member variable |mFileSpec|,
+      an |nsCOMPtr|.  I.e., this function is a `getter'.
+
+      Remember: good [XP]COM getters always |AddRef| their result.
+    */
+  {
+    // ...
+    *aFileSpec = mFileSpec;
+      // the |nsCOMPtr| should take care of the refcount here, right?
+    return NS_OK;
+  }
+
+
+

Plainly, the author believed (though perhaps with some question) that the nsCOMPtr, mFileSpec, would AddRef automatically as it was assigned into *aFileSpec. This is not the case. An nsCOMPtr automatically calls AddRef and Release (only) on its own behalf. In all other situations, it is designed to be a drop in replacement for a raw XPCOM pointer. Where ever an nsCOMPtr is used in a situation where a raw pointer is needed, the nsCOMPtr automatically provides one.

+ + + + + + +
+
+// |nsCOMPtr| produces a raw pointer when needed...
+
+nsCOMPtr<nsIFoo> foo = ...;
+
+  // 1.  Assigning into a raw pointer
+nsIFoo* raw_foo = foo;
+
+  // 2.  Assigning into another |nsCOMPtr|
+nsCOMPtr<nsIFoo> foo2 = foo;
+
+  // 3.  As a parameter
+SetFoo(foo);
+
+  // 4.  Testing the value in an |if| expression
+  // 5.  Calling a member function
+if ( foo )
+  foo->DoSomething();
+
+
+

In all of these cases, pretty much the exact same code is executed (case 2 is slightly different, but the intent is the same). In each case, you are essentially extracting the raw pointer value for your own purpose. If the nsCOMPtr AddRefed the value each time you did that, cases 4 and 5 would obviously always generate leaks. SetFoo, from case 3, would have to be written two different ways when given an nsCOMPtr, it would know the value was already AddRefed, and when given a raw pointer it would assume the value was not AddRefed. Actually the contradictions run deeper than that. All these cases show that automatically AddRefing on `output' makes nsCOMPtrs and raw-pointers act differently from the point of view of the clients. The goal is to make them act the same so that nsCOMPtrs can be a drop in replacement (modulo managing its own `ownership').

+

Given what you now know, the rule is predictable. As described above, and unless you tell it otherwise, an nsCOMPtr AddRefs when you assign in to it. It does nothing when you assign out of it.

+

Where should I use nsCOMPtrs?

+

You should use an nsCOMPtr any place you use an interface pointer as an owning reference, i.e., where you call AddRef and Release on it. You should use nsCOMPtr as a member variable, where it will simplify setters, and eliminate constructors, destructors, and assignment operators. You should use nsCOMPtr on the stack, where it makes calling QueryInterface almost pleasant, and eliminates the complex logic that falls out of error handling.

+

Where shouldn't I use nsCOMPtrs?

+

Don't use nsCOMPtrs where you don't need an owning reference. See Some COM Ownership Guidelines. nsCOMPtr is designed to be used with XPCOM interfaces, so don't use it with non-interfaces with specific exceptions described below. Don't use nsCOMPtrs in XPCOM interfaces. Don't use them in plain old C code; nsCOMPtrs are, of course, a C only construct. Never cast an nsCOMPtr, it's almost guaranteed to leak.

+

nsCOMPtrs for non-interface classes

+

Appropriately formatted answer to come, in the meanwhile, the full details are available in this news posting (via Google Groups).

+

nsCOMPtrs in function signatures

+

In general, you won't want to use nsCOMPtr in the signature of XPCOM (i.e., `scriptable') functions. nsCOMPtr is not currently directly supported by IDL. However, you may sometime be tempted to use an nsCOMPtr in a non-scriptable function.

+
nsCOMPtr<T> f() 不返回 nsCOMPtr
+

This practice is dangerous. Returning an AddRefed pointer in almost any form as a function result leads to several potential errors, some of which are leaks, some of which are dangling pointers. Returning an nsCOMPtr may seem like a good idea (since it tells clients you are giving them ownership), however it can be the cause of an dangling pointer. Consider:

+ + + + + + +
+
+// Don't return |nsCOMPtr|s...
+nsCOMPtr<nsIFoo> CreateFoo();
+// ...
+
+nsIFoo* myFoo = CreateFoo(); // Oops: |myFoo| now dangles!
+  // |CreateFoo| returns an |nsCOMPtr|, which
+  //  automatically |Release|s right after this
+  //  assignment.  Now |myFoo| refers to a
+  //  deleted object.
+
+
+

You can tell callers you are giving them ownership in a way that doesn't pose this hazard by returning a already_AddRefed<T> (see bug #59212). An nsCOMPtr knows not to AddRef a value that is already_AddRefed.

+ + + + + + +
+
+// Preferred form: if you must return a pointer, use |already_AddRefed|...
+already_AddRefed<nsIFoo> CreateFoo();
+// ...
+
+nsIFoo* myFoo1 = CreateFoo(); // doesn't dangle
+nsCOMPtr<nsIFoo> myFoo2( CreateFoo() ); // doesn't leak
+nsCOMPtr<nsIFoo> myFoo3( dont_AddRef(CreateFoo()) ); // redundant, but legal and correct
+
+
+

Compare this to the most frequent leaks caused by returning a raw pointer you have already AddRefed:

+ + + + + + +
+
+// Don't return raw pointers; that incites leaks...
+nsIFoo* CreateFoo(); // returns an |AddRef|ed pointer
+// ...
+
+nsCOMPtr<nsIFoo> myFoo = CreateFoo(); // Oops: leak;
+nsCOMPtr<nsIFoo> myFoo( dont_AddRef(CreateFoo()) );
+  // Since |CreateFoo| already |AddRef|s its result, we must remind
+  //  our |nsCOMPtr| not to.  It's easy to forget.  Prevent it in advance
+  //  by not returning pointers as function results, or else by returning
+  //  an |already_AddRefed<T>| as above.
+
+
+
void f( nsCOMPtr<T> ) don't pass an nsCOMPtr by value
+

This practice is wasteful, but not otherwise harmful. There is no need to AddRef parameters, as they are guaranteed to live as long as the function call. You only need to AddRef them as you store them in a structure that will live longer than the function call. Which means the appropriate member of that structure should be an nsCOMPtr, not the function parameter. Additionally, this signature may confuse callers into thinking they need an nsCOMPtr just to call the function.

+
void f( const nsCOMPtr<T>& ) don't pass an nsCOMPtr by const reference
+

Exactly as the signature above, this practice is wasteful, but not otherwise harmful, and has the same impact as passing an nsCOMPtr by value if the caller only supplied a raw pointer.

+
void f( nsCOMPtr<T>* ) avoid passing an nsCOMPtr by address, if possible
+

This practice requires callers to have an nsCOMPtr, and requires them to do a little extra work, as operator& for nsCOMPtrs is private (to help prevent leaks caused by casting; also see {{ Bug(59414) }}). This is an acceptable way to declare `in/out' parameters, but prefer passing nsCOMPtrs by reference, as below.

+ + + + + + +
+
+// Passing an |nsCOMPtr| by pointer requires extra work...
+void f( nsCOMPtr<nsIFoo>* );
+// ...
+
+nsCOMPtr<nsIFoo> myFoo = ...;
+
+f( address_of(myFoo) );
+
+
+
void f( nsCOMPtr<T>& ) do pass an nsCOMPtr by reference for `in/out' parameters
+

This is the prefered scheme for providing `in/out' parameters. If you were to use a raw pointer instead, your function couldn't know what ownership relationship the caller had to the input value, and hence, couldn't know whether to Release it or not before assigning in the new value. By declaring the parameter as an nsCOMPtr&, the relationship is explicit.

+

Summary

+

An nsCOMPtr is an owning reference. Whatever it points to has been AddRefed, counting the nsCOMPtr as one of its `owners'. An nsCOMPtr always calls Release before letting go, whether the nsCOMPtr is letting go so that it can point to a different object, or because the nsCOMPtr is going out of scope. Any time a new value is assigned into an nsCOMPtr, the nsCOMPtr automatically always Releases its old referent, if any, and (unless you tell it you already have) AddRefs the new.

+

You use an nsCOMPtr exactly as you would a raw XPCOM interface pointer in almost all cases. You won't have to explictly call AddRef or Release through it, nor will the compiler allow it. The only place you can't use an nsCOMPtr without change is where a raw XPCOM interface pointer is an `out' parameter. In this case, you wrap the nsCOMPtr with getter_AddRefs (see {{ web.link("#Comparison_4", "Comparison 4") }}).

+

When assigning into an nsCOMPtr, you will usually just supply another pointer (either a raw XPCOM interface pointer or an nsCOMPtr), with no additional directives { web.link("#Comparison_1", "Comparison 1") }}). As stated above, with no directives, the nsCOMPtr will Release its old referent, if any, and AddRef the new. This is appropriate when the thing you're assigning in hasn't yet been AddRefed to account for the new reference. This is typically the case when you are assigning in a pointer that you didn't call a function to get, e.g., one that was passed in as a parameter, or that you pulled out of a structure.

+

You can tell nsCOMPtr it doesn't need to AddRef the new value on assignment by wrapping the new value in dont_AddRef. Do this, for example, when you got the new value from a function which, like all good XPCOM getters, already called AddRef on your behalf.

+

You may not assign in a pointer to a different interface type; you must first query it to the right type (see, e.g., {{ web.link("#Comparison_6", "Comparison 6") }} and the surrounding discussion). nsCOMPtr never calls QueryInterface implicitly, i.e., you must call it yourself, or explictly ask nsCOMPtr to call it with do_QueryInterface. The do_QueryInterface directive allows you to do the query as part of the assignment. This better facilitates constructing an nsCOMPtr directly from the right value, rather than constructing it and assigning in the correct value later. Construction alone is more efficient than construction followed by assignment. Prefer construction over assignment whereever reasonable. Be careful not to apply do_QueryInterface to a function returning an AddRefed pointer [see this short section for an explanation]

+

For more details, continue on to the Reference Manual.

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/index.html new file mode 100644 index 0000000000..d9c427784a --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/glue_classes/nscomptr/index.html @@ -0,0 +1,56 @@ +--- +title: 使用nsCOMPtr +slug: Mozilla/Tech/XPCOM/Reference/Glue_classes/nsCOMPtr +translation_of: Mozilla/Tech/XPCOM/Reference/Glue_classes/nsCOMPtr +--- +

这篇文档是对nsCOMPtr的一个总述。如果您所遇到的问题,无法在该文档中找到答案,可能就没有其他文档可以回答它了。您需要求助于XPCOM新闻组或者有nsCOMPtr使用经验的人来求解,或者根据自己的试验获取答案。

+ +

如果您尚未使用过nsCOMPtr,您正好可从这里开始。当您使用了一段时间后,或者遇到了不熟悉的领域,或者出现编译错误,您可返回该文档,在参考手册或者FAQ中求助。

+ +

内容

+ +
    +
  1. 状态,最新修改和计划 + +
      +
    1. nsCOMPtr的最新修改
    2. +
    +
  2. +
  3. 入门指南 +
      +
    1. 介绍
    2. +
    3. 使用 nsCOMPtr
    4. +
    5. 小结
    6. +
    +
  4. +
  5. 参考手册 +
      +
    1. 基本原理
    2. +
    3. 初始化和赋值
    4. +
    5. Using an nsCOMPtr<T> as a T*
    6. +
    7. Efficiency and Correctness
    8. +
    9. Compiler Annoyances
    10. +
    +
  6. +
  7. FAQ +
      +
    1. 编译时错误
    2. +
    3. 运行时错误
    4. +
    5. How do I...
    6. +
    7. General
    8. +
    9. Bibliography
    10. +
    +
  8. +
+ +
+

Original Document Information

+ + +
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/index.html new file mode 100644 index 0000000000..188a822ae6 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/index.html @@ -0,0 +1,14 @@ +--- +title: XPCOM reference +slug: Mozilla/Tech/XPCOM/Reference +translation_of: Mozilla/Tech/XPCOM/Reference +--- +

This reference describes the interfaces and functions provided by the XPCOM library. In addition, it details the various helper classes and functions, as well as the components, provided by the XPCOM glue library. The contents herein are oriented primarily toward extension developers and people embedding XPCOM in other projects.

+
+

Note: If you're working on a module in the Mozilla codebase that's compiled with the MOZILLA_INTERNAL_API flag set, some of these APIs -- the string functions and classes in particular -- are not the ones you should be using. See the XPCOM internal string guide for documentation of the internal string API used within the Mozilla codebase.

+
+

+
XPCOM glue classes
These "glue" classes are provided to make it easier to use XPCOM from C++ code.
XPCOM Interface Reference
这是一个Mozilla平台提供XPCOM接口参考.
+
+

+

Many XPCOM pages return an nsresult. Prior to Gecko 19 (Firefox 19 / Thunderbird 19 / SeaMonkey 2.16), this was an integer that simply returned an error code. It is now a strongly typed enum when XPCOM is built using a C++11 compiler. This causes compile-time errors to occur when improper values are returned as nsresult values, thereby making it easier to catch many bugs.

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/index.html new file mode 100644 index 0000000000..da50238f6f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/index.html @@ -0,0 +1,11 @@ +--- +title: XPCOM Interface Reference +slug: Mozilla/Tech/XPCOM/Reference/Interface +translation_of: Mozilla/Tech/XPCOM/Reference/Interface +--- +

这是一个Mozilla平台提供XPCOM接口参考.

+
+

相关链接

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiaccessibleprovider/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiaccessibleprovider/index.html new file mode 100644 index 0000000000..488e504556 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiaccessibleprovider/index.html @@ -0,0 +1,45 @@ +--- +title: nsIAccessibleProvider +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIAccessibleProvider +tags: + - Accessibility + - Interfaces +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIAccessibleProvider +--- +

 

+


+

+
accessible/public/nsIAccessibleProvider.idl脚本化
+ + +Please add a summary to this article. + + +
+  +最后修改于Gecko 1.9 (Firefox 3)
+

+

Inherits from: nsISupports

+

Attributes

+ + + + + + + + + + + + + +
AttributeTypeDescription
accessiblensIAccessibleReturns an accessible. + + Read only +
+

See also

+ diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboard/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboard/index.html new file mode 100644 index 0000000000..a1778f2cbb --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboard/index.html @@ -0,0 +1,91 @@ +--- +title: nsIClipboard +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIClipboard +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIClipboard +--- +

+
widget/public/nsIClipboard.idl脚本化
+ + +This interface supports basic clipboard operations such as: setting, retrieving, emptying, matching and supporting clipboard data. + + +
+继承于: nsISupports +最后修改于Gecko 1.8 (Firefox 1.5 / Thunderbird 1.5 / SeaMonkey 1.0)
+

+

方法概述

+ +
void emptyClipboard(in long aWhichClipboard);
void forceDataToClipboard(in long aWhichClipboard); 已废弃 Gecko 1.8
void getData(in nsITransferable aTransferable, in long aWhichClipboard);
boolean hasDataMatchingFlavors([array, size_is(aLength)] in string aFlavorList, in unsigned long aLength, in long aWhichClipboard);
void setData(in nsITransferable aTransferable, in nsIClipboardOwner anOwner, in long aWhichClipboard);
boolean supportsSelectionClipboard();
+

常量

+

Most users will expect clipboard operations to use the global clipboard. In fact, the kSelectionClipboard is peculiar to the X Windows System, and not used much even under X.

+ +
常量名称 描述
kSelectionClipboard 0 Clipboard for selection.
kGlobalClipboard 1 Clipboard for global use.
+

方法

+

emptyClipboard()

+

This method empties the clipboard and notifies the clipboard owner. It empties the "logical" clipboard. It does not clear the native clipboard.

+
void emptyClipboard(
+  in long aWhichClipboard
+);
+
+
参数
+
aWhichClipboard
Specifies the clipboard to which this operation applies.
+
+

+

forceDataToClipboard()

+ 已废弃 Gecko 1.8 (Firefox 1.5 / Thunderbird 1.5 / SeaMonkey 1.0) +

+

Some platforms support deferred notification for putting data on the clipboard This method forces the data onto the clipboard in its various formats This may be used if the application going away.

+
void forceDataToClipboard(
+  in long aWhichClipboard
+);
+
+
参数
+
aWhichClipboard
Specifies the clipboard to which this operation applies.
+
+

getData()

+

This method retrieves data from the clipboard into a transferable.

+
void getData(
+  in nsITransferable aTransferable,
+  in long aWhichClipboard
+);
+
+
参数
+
aTransferable
The transferable to receive data from the clipboard.
aWhichClipboard
Specifies the clipboard to which this operation applies.
+
+

hasDataMatchingFlavors()

+

This method provides a way to give correct UI feedback about, for instance, whether a paste should be allowed. It does not actually retrieve the data and should be a very inexpensive call. All it does is check if there is data on the clipboard matching any of the flavors in the given list.

+
boolean hasDataMatchingFlavors(
+  [array, size_is(aLength)] in string aFlavorList,
+  in unsigned long aLength,
+  in long aWhichClipboard
+);
+
+
参数
+
aFlavorList
An array of ASCII strings.
aLength
The length of the aFlavorList.
aWhichClipboard
Specifies the clipboard to which this operation applies.
+
+
返回值
+

Returns true, if data is present and it matches the specified flavor. Otherwise it returns false.

+

setData()

+

This method sets the data from a transferable on the native clipboard.

+
void setData(
+  in nsITransferable aTransferable,
+  in nsIClipboardOwner anOwner,
+  in long aWhichClipboard
+);
+
+
参数
+
aTransferable
The transferable containing the data to put on the clipboard.
anOwner
The owner of the transferable.
aWhichClipboard
Specifies the clipboard to which this operation applies.
+
+

supportsSelectionClipboard()

+

This method allows clients to determine if the implementation supports the concept of a separate clipboard for selection.

+
boolean supportsSelectionClipboard();
+
+
参数
+

None.

+
返回值
+

Returns true if kSelectionClipboard is available. Otherwise it returns false.

+

相关链接

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboardhelper/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboardhelper/index.html new file mode 100644 index 0000000000..b4c7881597 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiclipboardhelper/index.html @@ -0,0 +1,65 @@ +--- +title: nsIClipboardHelper +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIClipboardHelper +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIClipboardHelper +--- +
+
widget/public/nsIClipboardHelper.idl脚本化
+ + +nsIClipboardHelper接口是能够快速方便的使用 nsIClipboard 接口中常用方法的辅助接口. + + +
+继承于: nsISupports +最后修改于Gecko 1.7
+
+

方法概述

+ + + + + + + + + +
void copyString(in AString aString);
void copyStringToClipboard(in AString aString, in long aClipboardID);
+

方法

+

copyString()

+

该方法将字符串复制到默认剪切板.

+
void copyString(
+  in AString aString
+);
+
+
参数
+
+
+ aString
+
+ 将要复制到剪切板的字符串.
+
+

copyStringToClipboard()

+

该方法将字符串复制到指定剪切板.

+
void copyStringToClipboard(
+  in AString aString,
+  in long aClipboardID
+);
+
+
参数
+
+
+ aString
+
+ 将要复制到指定剪切板的字符串.
+
+ aClipboardID
+
+ 指定剪切板的ID(例如kSelectionClipboard).
+
+

相关连接

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiconsoleservice/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiconsoleservice/index.html new file mode 100644 index 0000000000..b373505057 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiconsoleservice/index.html @@ -0,0 +1,215 @@ +--- +title: nsIConsoleService +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIConsoleService +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIConsoleService +--- +
+

Error Console在Firefox中已经过期,只有将devtools.errorconsole.enabled + + 设为 + true才能使用. 对于web应用使用 Web Console 代替, 对于浏览器中的chrome应用,使用 Browser Console 代替 .

+
+

+
xpcom/base/nsIConsoleService.idl脚本化
+ + +console service是Error Console 后端的一部分, 与每一个Mozilla应用绑定在一起. 它用来记录各种消息、警告以及错误,同时可获取所有已经记录的消息 + + +
+继承于: nsISupports +最后修改于Gecko 1.9 (Firefox 3)
+

+

实现方式: @mozilla.org/consoleservice;1 as a service:

+
var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
+                     .getService(Components.interfaces.nsIConsoleService);
+
+

Method overview

+ + + + + + + + + + + + + + + + + + + + + +
void getMessageArray([array, size_is(count)] out nsIConsoleMessage messages, out uint32_t count);已废弃 Gecko 19
+ void getMessageArray([optional] out uint32_t count, [retval, array, size_is(count)] out nsIConsoleMessage messages);
void logMessage(in nsIConsoleMessage message);
void logStringMessage(in wstring message);
void registerListener(in nsIConsoleListener listener);
void reset();
void unregisterListener(in nsIConsoleListener listener);
+

Methods

+

getMessageArray()

+

获取有关目前所有控制台记录的信息的数组

+

已废弃 Gecko 19 (Firefox 19 / Thunderbird 19 / SeaMonkey 2.16)
This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.

+
void getMessageArray(
+  [array, size_is(count)] out nsIConsoleMessage messages,
+  out PRUint32 count
+);
+
+
Parameters
+
+
+ messages
+
+ 已经记录的消息数组
+
+ count
+
+ 数组中消息的数。如果没有消息被记录,函数会返回0,但同时仍会为message分配一个标记,在从脚本调用时,表示返回的一个长度为0的消息。
+
+

+
void getMessageArray(
+  [optional] out PRUint32 count,
+  [retval, array, size_is(count)] out nsIConsoleMessage messages
+);
+
+
Parameters
+
+
+ count
+
+ The number of messages in the array. If no messages are logged, this function will return a count of 0 but still will allocate one word for messages, so as to show up as a 0-length array when called from script.
+
+

Note: See the code samples below for how to call getMessageArray.

+

logMessage()

+
void logMessage(
+  in nsIConsoleMessage message
+);
+
+
Parameters
+
+
+ message
+
+ An nsIConsoleMessage to log.
+
+

logStringMessage()

+

Convenience method for logging simple messages.

+
void logStringMessage(
+  in wstring message
+);
+
+
Parameters
+
+
+ message
+
+ The string to log.
+
+

registerListener()

+

Registers a listener for notification when an error is logged.

+

Note: To guard against stack overflows from listeners that could log messages (it is easy to do this inadvertently from listeners implemented in JavaScript), we do not call any listeners when another error is already being logged.

+
void registerListener(
+  in nsIConsoleListener listener
+);
+
+
Parameters
+
+
+ listener
+
+ The nsIConsoleListener to add.
+
+

reset()

+

Clear the message buffer (For example, for privacy reasons).

+
void reset();
+
+
Parameters
+

None.

+

Note: Console listeners expect you to log an empty string message before calling reset so that they can clear their message buffers too. (This works before Gecko 1.9 too of course.)

+

unregisterListener()

+

Unregisters a listener.

+
void unregisterListener(
+  in nsIConsoleListener listener
+);
+
+
Parameters
+
+
+ listener
+
+ The nsIConsoleListener to remove.
+
+

Examples

+

Retrieving the message array

+

To retrieve the message array in Gecko prior to version 19:

+
function getConsoleMessageArray() {
+  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
+                                 .getService(Components.interfaces.nsIConsoleService);
+  var array = {};
+  consoleService.getMessageArray(array, {});
+  return array.value;
+}
+
+

To retrieve the message array in Gecko 19 or later:

+
function getConsoleMessageArray() {
+  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
+                                 .getService(Components.interfaces.nsIConsoleService);
+  return consoleService.getMessageArray();
+}
+
+

To retrieve the message array in a compatible way:

+
function getConsoleMessageArray() {
+  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
+                                 .getService(Components.interfaces.nsIConsoleService);
+  var array = {};
+  return consoleService.getMessageArray(array, {}) || array.value;
+}
+
+

Logging a simple message

+

A common usage is to log a string message to console:

+
function LOG(msg) {
+  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
+                                 .getService(Components.interfaces.nsIConsoleService);
+  consoleService.logStringMessage(msg);
+}
+
+

Alternative logging methods include Components.utils.reportError and dump().

+

Logging a message with additional information

+

To include other information an nsIConsoleMessage object must be used. In this example nsIScriptError, which implements nsIConsoleMessage, is used to include information about the source file and line number of the error.

+
function myLogToConsole(aMessage, aSourceName, aSourceLine, aLineNumber,
+                        aColumnNumber, aFlags, aCategory)
+{
+  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
+                                 .getService(Components.interfaces.nsIConsoleService);
+  var scriptError = Components.classes["@mozilla.org/scripterror;1"]
+                              .createInstance(Components.interfaces.nsIScriptError);
+  scriptError.init(aMessage, aSourceName, aSourceLine, aLineNumber,
+                   aColumnNumber, aFlags, aCategory);
+  consoleService.logMessage(scriptError);
+}
+
+ +

See also

+ +

+
+  
diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidirectoryserviceprovider/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidirectoryserviceprovider/index.html new file mode 100644 index 0000000000..20d094eaf3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidirectoryserviceprovider/index.html @@ -0,0 +1,65 @@ +--- +title: nsIDirectoryServiceProvider +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIDirectoryServiceProvider +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIDirectoryServiceProvider +--- +

+
xpcom/io/nsIDirectoryService.idl脚本化
+ + +本接口是目录服务用于得到文件位置的函数。 + + +
+继承于: nsISupports +最后修改于Gecko 1.7
+

+

nsIDirectoryServiceProvider.

+

方法概览

+ + + + + + +
nsIFile getFile(in string prop, out PRBool persistent);
+

方法

+

getFile()

+

The Directory Service calls this method when it gets the first request for a prop or on every request if the prop is not persistent.

+
nsIFile getFile(
+  in string prop,
+  out PRBool persistent
+);
+
+
Parameters
+
+
+ prop
+
+ The symbolic name of the file.
+
+ persistent
+
+ true if the returned file will be cached by Directory Service. Subsequent requests for this prop will bypass the provider and use the cache. false if the provider will be asked for this prop each time it is requested.
+
+
Return value
+

The nsIFile represented by the property.

+

示例

+

This code creates a global, read-only string called currDir with the value of the current working directory.

+
 __defineGetter__("currDir",
+                  function getCurrDir() {
+                    return Components.classes["@mozilla.org/file/directory_service;1"]
+                                     .getService(Components.interfaces.nsIDirectoryServiceProvider)
+                                     .getFile("CurWorkD",{}).path;
+                   });
+
+

Test it with to see the magic happen.

+
 alert(currDir);
+
+

参见

+ +

Additionally, see section 16.5.2 of the Rapid Application Development with Mozilla book for instructions on how to get the current working directory and the process binary directory, among other things.

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidomclientrect/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidomclientrect/index.html new file mode 100644 index 0000000000..20a00c9e26 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsidomclientrect/index.html @@ -0,0 +1,92 @@ +--- +title: nsIDOMClientRect +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMClientRect +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIDOMClientRect +--- +

+
dom/interfaces/base/nsIDOMClientRect.idl脚本化
+代表一个矩形盒子。盒子类型由返回这种盒子对象的方法指定的。它是由像element.getBoundingClientRect的函数返回的。. + +
+ +
1.0
+ +
66
+ +
+ +
+ +
Introduced
+
Gecko 1.9
+ +
+ +
+ +
+继承于: nsISupports +最后修改于Gecko 1.9.1 (Firefox 3.5 / Thunderbird 3.0 / SeaMonkey 2.0)
+

+ +

属性

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDescription
bottomfloatY 轴,相对于视口原点(viewport origin)矩形盒子的底部。只读。 
heightfloat矩形盒子的高度(等同于 bottom 减 top)。只读。
leftfloatX 轴,相对于视口原点(viewport origin)矩形盒子的左侧。只读。 
rightfloatX 轴,相对于视口原点(viewport origin)矩形盒子的右侧。只读。 
topfloatY 轴,相对于视口原点(viewport origin)矩形盒子的顶部。只读。
widthfloat矩形盒子的宽度(等同于 right 减 left)。只读。 
xfloatX 轴,相对于视口原点(viewport origin)矩形盒子的左侧。只读。 
yfloatY 轴,相对于视口原点(viewport origin)矩形盒子的顶部。只读。
+ +

参考资料

+ + + +

这个对象几次易名:最初叫做 TextRectangle,然后叫做 ClientRect,后来叫做 DOMRect。

+ +

该对象最初只有 top、left、right、bottom 属性,后来添加了 width、height、x、y 属性。

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifile/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifile/index.html new file mode 100644 index 0000000000..d966771e83 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifile/index.html @@ -0,0 +1,828 @@ +--- +title: nsIFile +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIFile +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIFile +--- +

+
xpcom/io/nsIFile.idl脚本化
+ + +An instance of this interface is a cross-platform representation of a location in the filesystem. + + +
+继承于: nsISupports +最后修改于Gecko 1.0
+

+

nsIFile is the correct platform-agnostic way to specify a file; you should always use this instead of a string to ensure compatibility.

+

With an nsIFile you can navigate to ancestors or descendants without having to deal with the different path separators used on different platforms, query the state of any file or directory at the position represented by the nsIFile and create, move or copy items in the filesystem.

+

An nsIFile can be retrieved by either instantiating an nsILocalFile using a platform specific path string or by using cross-platform locations retrieved from the directory service.

+

All methods with string parameters have two forms. The preferred form operates on UTF-16 encoded characters strings. An alternate form operates on characters strings encoded in the "native" charset. A string containing characters encoded in the native charset cannot be safely passed to javascript via xpconnect. Therefore, the UTF-16 forms are scriptable, but the "native methods" are not. In addition, the native form cannot deal with files whose name contains characters outside the default system code page on Windows. Using the native form limits the ability of your code to deal with the full Unicode support on Windows 2000 or later where the OS itself does not have such a limitation. Therefore, you must not use the native form unless it is guaranteed that the path passed to a native form function is always ASCII.

+
+ Note: nsILocalFile was merged with this interface in Gecko 14. Much of the documentation has not been updated to reflect this change.
+

Method overview

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void append(in AString node);
void appendNative(in ACString node); Native code only!
void appendRelativeNativePath(in ACString relativeFilePath); Native code only!
void appendRelativePath(in AString relativeFilePath);
nsIFile clone();
boolean contains(in nsIFile inFile, in boolean recur);
void copyTo(in nsIFile newParentDir, in AString newName);
void copyToFollowingLinks(in nsIFile newParentDir, in AString newName);
void copyToFollowingLinksNative(in nsIFile newParentDir, in ACString newName); Native code only!
void CopyToNative(in nsIFile newParentDir, in ACString newName); Native code only!
void create(in unsigned long type, in unsigned long permissions);
void createUnique(in unsigned long type, in unsigned long permissions);
boolean equals(in nsIFile inFile);
boolean exists();
ACString getRelativeDescriptor(in nsIFile fromFile);
void initWithFile(in nsIFile aFile);
void initWithNativePath(in ACString filePath); Native code only!
void initWithPath(in AString filePath);
boolean isDirectory();
boolean isExecutable();
boolean isFile();
boolean isHidden();
boolean isReadable();
boolean isSpecial();
boolean isSymlink();
boolean isWritable();
void launch();
PRLibraryStar load(); Native code only!
void moveTo(in nsIFile newParentDir, in AString newName);
void moveToNative(in nsIFile newParentDir, in ACString newName); Native code only!
void normalize();
FILE openANSIFileDesc(in string mode); Native code only!
PRFileDescStar openNSPRFileDesc(in long flags, in long mode); Native code only!
void remove(in boolean recursive);
void reveal();
void setRelativeDescriptor(in nsIFile fromFile, in ACString relativeDesc);
+

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDescription
directoryEntriesnsISimpleEnumeratorReturns an enumeration of the elements in a directory. Each element in the enumeration is an nsIFile. Read only. +
Exceptions thrown
+
+
+ NS_ERROR_FILE_NOT_DIRECTORY
+
+ Indicates that this nsIFile does not reference a directory.
+
+
diskSpaceAvailable PRInt64The number of bytes available to non-superuser on the disk volume containing the nsIFile. Read only.
fileSizePRInt64 +

The value of this attribute is the number of bytes corresponding to the data represented by the file.

+

On the Mac, getting/setting the file size with nsIFile only deals with the size of the data fork. If you need to know the size of the combined data and resource forks use nsILocalFileMac.GetFileSizeWithResFork().

+ Changing the size of a nsIFile operates on the underlying filesystem, possibly truncating the existing file to specified size.
fileSizeOfLinkPRInt64 +

This attribute exposes the size of the symbolic link referenced by this nsIFile.

+

Unlike fileSize, this attribute corresponds to the size of the symbolic link referenced by this nsIFile. If this nsIFile does not reference a symbolic link, then the value of this attribute is undefined.

+ The value of this attribute is the number of bytes corresponding to the data represented by the symbolic link. Any meta data, such as a resource fork on the Mac, is not included in the measurement of the file size. Read only.
followLinks PRBool +

Determines whether or not the nsIFile will automatically resolve symbolic links.

+ By default, this value is false on all non-UNIX systems. As of Mozilla 1.7, this attribute is ignored on UNIX systems.
lastModifiedTimePRInt64 +

This attribute exposes the time when the file referenced by this nsIFile was last modified.

+

The value of this attribute is milliseconds since midnight (00:00:00), January 1, 1970 Greenwich Mean Time (GMT).

+ Changing the last modified time of a nsIFile operates on the underlying filesystem. As of Gecko 1.7, changing the last modified time of a non-existent file has undefined behavior.
lastModifiedTimeOfLinkPRInt64 +

This attribute exposes the time when the symbolic link referenced by this nsIFile was last modified.

+

Unlike lastModifiedTime, this attribute corresponds to the last modified time of the symbolic link referenced by this nsIFile. If this nsIFile does not reference a symbolic link, then the value of this attribute is undefined.

+

The value of this attribute is milliseconds since midnight (00:00:00), January 1, 1970 Greenwich Mean Time (GMT).

+ Changing the last modified time of a nsIFile operates on the underlying filesystem. As of Gecko 1.7, changing the last modified time of a non-existent file has undefined behavior.
leafNameAString +

This attribute exposes the name of the nsIFile without any directory components.

+ Changing the leaf name of a nsIFile does not affect the underlying filesystem. It only changes what this nsIFile references.
nativeLeafNameACString +

This attribute exposes the name of the nsIFile without any directory components. [native character encoding variant]

+ Changing the leaf name of a nsIFile does not affect the underlying filesystem. It only changes what this nsIFile references. Native code only!
nativePathACString +

This attribute exposes the full path of the nsIFile. [native character encoding variant]

+ The value of this attribute is a platform-specific file path. Read only. Native code only!
nativeTargetACString +

This attribute exposes the full target of the nsIFile - the full path with any symbolic links dereferenced. [native character encoding variant]

+ The value of this attribute is a platform-specific file path. Read only. Native code only!
parentnsIFile +

This attribute returns the parent nsIFile for this nsIFile.

+ The parent will be null when this nsIFile references the top of the volume. For example, C:\ does not have a parent. Read only.
pathAString +

This attribute exposes the full platform-specific path of the nsIFile (including the leafName). Read only.

+ Example, this could return "/home/user/foo.txt" or "C:\Images\my.jpeg"
permissionsunsigned long +

The value of this attribute is a UNIX-style file permission mask for this nsIFile.

+ Changing the permissions of a nsIFile operates on the underlying filesystem. As of Gecko 1.7, changing the permissions of a non-existent file has undefined behavior.
permissionsOfLinkunsigned long +

The value of this attribute is a UNIX-style file permission mask for this nsIFile.

+

Unlike permissions, this attribute corresponds to the permissions of the symbolic link referenced by this nsIFile. If this nsIFile does not reference a symbolic link, then the value of this attribute is undefined.

+ Changing the permissions of a nsIFile operates on the underlying filesystem. As of Gecko 1.7, changing the permissions of a non-existent file has undefined behavior.
persistentDescriptor ACString +

On some platforms, the value of nsIFile.path may be insufficient to uniquely identify the file on the local file system. The persistent descriptor is intended to be used whenever a nsIFile needs to be serialized to disk and later recovered. This string is not intended for display to users.

+
Note: The value of the followLinks attribute is not encoded in the persistent descriptor.
targetAString +

This attribute exposes the full target of the nsIFile - the full path with any symbolic links dereferenced.

+

Accessor to the string path. The native version of these strings are not guaranteed to be a usable path to pass to NSPR or the C stdlib. There are problems that affect platforms on which a path does not fully specify a file because two volumes can have the same name (For example Mac). This is solved by holding "private", native data in the nsIFile implementation. This native data is lost when you convert to a string. DO NOT PASS TO USE WITH NSPR OR STDLIB! Read only.

+
Exceptions thrown
+
+
+ NS_ERROR_FILE_INVALID_PATH
+
+ Indicates that this nsIFile does not reference a symbolic links.
+
+
+

Constants

+ + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
NORMAL_FILE_TYPE0A normal file.
DIRECTORY_TYPE1A directory/folder.
DELETE_ON_CLOSE 0x80000000Optional parameter used by openNSPRFileDesc
+

Methods

+

append()

+

This function is used for constructing a descendant of the current nsIFile.

+
+

Note: This method does not return a new nsIFile; it modifies the object it was called on. If the old nsIFile should be retained, use clone().

+
+
void append(
+  in AString node
+);
+
+
Parameters
+
+
+ node
+
+ A string which is intended to be a child node of the nsIFile. This string must not contain a path separator character.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_UNRECOGNIZED_PATH
+
+ Indicates that aNode incorrectly contains a path separator character.
+
+

Native code only!

appendNative

+

This method is used for constructing a descendant of the current nsIFile. [native character encoding variant]

+
void appendNative(
+  in ACString node
+);
+
+
Parameters
+
+
+ node
+
+ A string that is intended to be a child node of the current nsIFile. This string must not contain a path separator character. This string must be encoded using the native character encoding.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_UNRECOGNIZED_PATH
+
+ Indicates that aNode incorrectly contains a path separator character.
+
+

clone()

+

This method creates a clone of the nsIFile. (It does NOT clone the file itself; see the copy methods.)

+
nsIFile clone();
+
+
Parameters
+

None.

+
Return value
+

A new nsIFile instance that corresponds to the same file or directory as this nsIFile.

+

contains()

+

This method tests whether or not a nsIFile instance is a descendant of the this nsIFile.

+
boolean contains(
+  in nsIFile inFile,
+  in boolean recur
+);
+
+
Parameters
+
+
+ inFile
+
+ The nsIFile to test.
+
+ recur
+
+ This parameter specifies whether or not subdirectories should be inspected. As of Gecko 1.7, this parameter is ignored and always treated as false by the canonical Local File implementation.
+
+
Return value
+

true if inFile is a descendant of this nsIFile.

+

copyTo()

+

This method copies a source file to a new location if it does not already exist.

+

This method will NOT resolve aliases/shortcuts during the copy.

+
void copyTo(
+  in nsIFile newParentDir,
+  in AString newName
+);
+
+
Parameters
+
+
+ newParentDir
+
+ This parameter specifies the parent directory to copy the file into. If this parameter is null, then the parent directory of the file will be used.
+
+ newName
+
+ This parameter allows you to specify a new leaf name for the file to be copied. This parameter may be empty, in which case the current leaf name will be used.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_DESTINATION_NOT_DIR
+
+ If the "newParentDir" is not a directory.
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the current file path does not exist. It is not possible to copy a file that does not exist.
+
+ NS_ERROR_FILE_ALREADY_EXISTS
+
+ Indicates that there is already a file named "newName" in the destination directory.
+
+

copyToFollowingLinks()

+

This method copies a source file to a new location if it does not already exist.

+

This method is identical to copyTo() except that any symbolic links will be followed as the name suggests.

+
void copyToFollowingLinks(
+  in nsIFile newParentDir,
+  in AString newName
+);
+
+
Parameters
+
+
+ newParentDir
+
+ This parameter specifies the parent directory to copy the file into. If this parameter is null, then the parent directory of the file will be used.
+
+ newName
+
+ This parameter allows you to specify a new leaf name for the file to be copied. This parameter may be empty, in which case the current leaf name will be used.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_DESTINATION_NOT_DIR
+
+ If the "newParentDir" is not a directory.
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the current file path does not exist. It is not possible to copy a file that does not exist.
+
+ NS_ERROR_FILE_ALREADY_EXISTS
+
+ Indicates that there is already a file named "newName" in the destination directory.
+
+

Native code only!

copyToFollowingLinksNative

+

This method copies this file to a new location. [native character encoding variant]

+

This method is identical to copyToNative() except that any symbolic links will be followed as the name suggests.

+
void copyToFollowingLinksNative(
+  in nsIFile newParentDir,
+  in ACString newName
+);
+
+
Parameters
+
+
+ newParentDir
+
+ This parameter specifies the parent directory to copy the file into. If this parameter is null, then the parent directory of the file will be used.
+
+ newName
+
+ This parameter allows you to specify a new leaf name for the file to be copied. This parameter may be empty, in which case the current leaf name will be used. This string must be encoded using the native character encoding.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_DESTINATION_NOT_DIR
+
+ If the "newParentDir" is not a directory.
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the current file path does not exist. It is not possible to copy a file that does not exist.
+
+ NS_ERROR_FILE_ALREADY_EXISTS
+
+ Indicates that there is already a file named "newName" in the destination directory.
+
+

Native code only!

CopyToNative

+

This method copies this file to a new location. [native character encoding variant]

+
void CopyToNative(
+  in nsIFile newParentDir,
+  in ACString newName
+);
+
+
Parameters
+
+
+ newParentDir
+
+ This parameter specifies the parent directory to copy the file into. If this parameter is null, then the parent directory of the file will be used.
+
+ newName
+
+ This parameter allows you to specify a new leaf name for the file to be copied. This parameter may be empty, in which case the current leaf name will be used. This string must be encoded using the native character encoding.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_DESTINATION_NOT_DIR
+
+ If the "newParentDir" is not a directory.
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the current file path does not exist. It is not possible to copy a file that does not exist.
+
+ NS_ERROR_FILE_ALREADY_EXISTS
+
+ Indicates that there is already a file named "newName" in the destination directory.
+
+

create()

+

This method creates a new file or directory in the file system corresponding to the file path represented by this nsIFile. This method will create any path segments that do not already exist.

+
void create(
+  in unsigned long type,
+  in unsigned long permissions
+);
+
+
Parameters
+
+
+ type
+
+ This specifies the type of file system object to be made. The only two types at this time are file and directory which are defined above.
+
+ permissions
+
+ A UNIX-style file permissions value. For example, the octal value 0600 may be used to limit read and write access to the current user of the system. This parameter may be ignored on systems that do not support file permissions.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_ALREADY_EXISTS
+
+ Indicates that the file or directory already exists.
+
+ NS_ERROR_FILE_UNKNOWN_TYPE
+
+ Indicates that the value of "type" does not correspond to a known type.
+
+

createUnique()

+

This function will create a new file or directory in the file system. Any nodes that have not been created or resolved, will be. If this file already exists, we try variations on the leaf name "suggestedName" until we find one that did not already exist. This method will create any path segments that do not already exist.

+
void createUnique(
+  in unsigned long type,
+  in unsigned long permissions
+);
+
+
Parameters
+
+
+ type
+
+ This specifies the type of file system object to be made. The only two types at this time are file and directory which are defined above.
+
+ permissions
+
+ A UNIX-style file permissions value. For example, the octal value 0600 may be used to limit read and write access to the current user of the system. This parameter may be ignored on systems that do not support file permissions.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_UNKNOWN_TYPE
+
+ Indicates that the value of "type" does not correspond to a known type.
+
+ NS_ERROR_FILE_TOO_BIG
+
+ Indicates that the search for nonexistent files was unsuccessful because all of the attempted leaf name variants already exist.
+
+

equals()

+

This method tests whether or not two nsIFile instances correspond to the same file or directory.

+
boolean equals(
+  in nsIFile inFile
+);
+
+
Parameters
+
+
+ inFile
+
+ The nsIFile to compare this nsIFile against.
+
+
Return value
+

true if "inFile" is equivalent to this nsIFile.

+

exists()

+

This method tests whether or not this nsIFile exists.

+
boolean exists()
+
+
Parameters
+

None.

+
Return value
+

true if the file or directory exists. Otherwise it returns false.

+

isDirectory()

+

This method tests whether or not this nsIFile corresponds to a directory.

+
boolean isDirectory();
+
+
Parameters
+

None.

+
Return value
+

true if this nsIFile corresponds to a directory. Otherwise it returns false.

+

isExecutable()

+

This method tests whether or not this nsIFile corresponds to a file that may be executed.

+
+

Note: This method does not work on all platforms due to bug 322865.

+
+
boolean isExecutable();
+
+
+

Note: Use nsIProcess to then execute/run this file.

+
+
Parameters
+

None.

+
Return value
+

true if the nsIFile may be executed by the user. Otherwise it returns false.

+

isFile()

+

This method tests whether or not this nsIFile corresponds to a normal file.

+
boolean isFile();
+
+
Parameters
+

None.

+
Return value
+

true if this nsIFile corresponds to a normal file. Otherwise it returns false.

+

isHidden()

+

This method tests whether or not this nsIFile corresponds to a file or directory that is hidden. In Unix, hidden files start with a period. On Mac and Windows, they have an attribute bit set.

+
boolean isHidden();
+
+
Parameters
+

None.

+
Return value
+

true if the file or directory is hidden. Otherwise it returns false.

+

isReadable()

+

This method tests whether or not this nsIFile corresponds to a file or directory that may be read by the user.

+
boolean isReadable();
+
+
Parameters
+

None.

+
Return value
+

true if the file or directory may be read by the user. Otherwise it returns false.

+

isSpecial()

+

This method tests whether or not this nsIFile corresponds to a special system file.

+

Note: The definition of a special system file is platform dependent. For example, under UNIX platforms this might correspond to a device file, socket, or fifo.

+
boolean isSpecial();
+
+
Parameters
+

None.

+
Return value
+

true if this nsIFile corresponds to a special system file. Otherwise it returns false.

+

isSymlink()

+

This method tests whether or not this nsIFile corresponds to a symbolic link, shortcut, or alias.

+
boolean isSymlink();
+
+
Parameters
+

None.

+
Return value
+

true if this nsIFile corresponds to a symbolic link. Otherwise it returns false.

+

isWritable()

+

This method tests whether or not this nsIFile corresponds to a file or directory that may be modified by the user.  As of Gecko 9, files on read only shares will return false.  Files that are exclusively opened on Win32 will return true if they are normally writable, and files that don't have write permissions will return false. For specific handling before Gecko 9 (Firefox 9.0 / Thunderbird 9.0 / SeaMonkey 2.6), please see bug 682571.

+
boolean isWritable();
+
+
Parameters
+

None.

+
Return value
+

true if the file or directory may be modified by the user. Otherwise it returns false.

+

moveTo()

+

This method moves this file to a new location.

+
+ Note: If this method succeeds, this instance will be updated to point to the new file.
+

If the current file path corresponds to a regular file (for storage of bytes), and if the new leaf name identifies a regular file that already exists, then this method will overwrite the destination file.

+

Usually, "move" means to relocate the file to a different directory without changing the file's contents or properties, or in fact the file's serial number (inode). That is a very fast operation because it just changes directory information. The actual data doesn't move.

+

Unfortunately, an actual "move" is impossible between different volumes (disks or partitions). This method attempts to do the "right thing" when moving files across volumes. That is, it will copy the old file to the new location, try to assign the file attributes as the old file had them, and then delete the old file. You should be aware of these possible problems:

+ +
void moveTo(
+  in nsIFile newParentDir,
+  in AString newName
+);
+
+
Parameters
+
+
+ newParentDir
+
+ This parameter specifies the parent directory to move the file into. If this parameter is null, then the parent directory of the file will be used.
+
+ newName
+
+ This parameter allows you to specify a new leaf name for the file to be moved. This parameter may be empty, in which case the current leaf name will be used.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the current file path does not exist. It is not possible to move a file that does not exist.
+
+ NS_ERROR_FILE_DIR_NOT_EMPTY
+
+ Indicates that an attempt was made to move a directory to the location of an existing directory that is not empty.
+
+ NS_ERROR_FILE_ACCESS_DENIED
+
+ Indicates that an attempt was made to move a directory to the location of an existing directory that is not writable.
+
+ NS_ERROR_FILE_DESTINATION_NOT_DIR
+
+ Indicates that "newParentDir" exists and is not a directory.
+
+

Native code only!

moveToNative

+

This method moves this file to a new location. [native character encoding variant]

+
+ Note: If this method succeeds, this instance will be updated to point to the new file.
+

If the current file path corresponds to a regular file (for storage of bytes), and if the new leaf name identifies a regular file that already exists, then this method will overwrite the destination file.

+

Usually, "move" means to relocate the file to a different directory without changing the file's contents or properties, or in fact the file's serial number (inode). That is a very fast operation because it just changes directory information. The actual data doesn't move.

+

Unfortunately, an actual "move" is impossible between different volumes (disks or partitions). This method attempts to do the "right thing" when moving files across volumes. That is, it will copy the old file to the new location, try to assign the file attributes as the old file had them, and then delete the old file. You should be aware of these possible problems:

+ +
void moveToNative(
+  in nsIFile newParentDir,
+  in ACString newName
+);
+
+
Parameters
+

 

+
+
+ newParentDir
+
+ This parameter specifies the parent directory to copy the file into. If this parameter is null, then the parent directory of the file will be used.
+
+ newName
+
+ This parameter allows you to specify a new leaf name for the file to be copied. This parameter may be empty, in which case the current leaf name will be used. This string must be encoded using the native character encoding.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the current file path does not exist. It is not possible to move a file that does not exist.
+
+ NS_ERROR_FILE_DIR_NOT_EMPTY
+
+ Indicates that an attempt was made to move a directory to the location of an existing directory that is not empty.
+
+ NS_ERROR_FILE_ACCESS_DENIED
+
+ Indicates that an attempt was made to move a directory to the location of an existing directory that is not writable.
+
+ NS_ERROR_FILE_DESTINATION_NOT_DIR
+
+ Indicates that "newParentDir" exists and is not a directory.
+
+

normalize()

+

This method is used to canonicalize the path represented by this nsIFile. (for example removing .. and . components on Unix).

+

As of Gecko 1.7, this method is only implemented under UNIX builds (except for Mac OSX). This method will fail if the path does not exist.

+
void normalize();
+
+
Parameters
+

None.

+
Exceptions thrown
+
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the file path does not exist.
+
+ NS_ERROR_FILE_DESTINATION_NOT_DIR
+
+ Indicates that a component of the path prefix is not a directory.
+
+ NS_ERROR_FILE_ACCESS_DENIED
+
+ Read or search permission was denied for a component of the path prefix.
+
+

remove()

+

This method removes the file or directory corresponding to the file path represented by this nsIFile.

+

This method will not resolve any symlinks.

+
void remove(
+  in boolean recursive
+);
+
+
Parameters
+
+
+ recursive
+
+ If this nsIFile corresponds to a directory that is not empty, then this parameter must be true in order for the directory to be deleted. Otherwise, this parameter is ignored.
+
+
Exceptions thrown
+
+
+ NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+
+ Indicates that the current file path does not exist. It is not possible to remove a file that does not exist.
+
+ NS_ERROR_FILE_DIR_NOT_EMPTY
+
+ Indicates that an attempt was made to remove a directory that is not empty.
+
+ NS_ERROR_FILE_ACCESS_DENIED
+
+ Indicates that an attempt was made to remove a file in a way that exceeded your permissions. Details depend on your file system and how its permissions work.
+
+

Remarks

+

All string-valued methods and attributes have two forms. The preferred form operates on UTF-16 (Unicode) encoded character strings. The alternate form operates on character strings encoded in the "native" multibyte character set. The native character encoding is defined as the single-byte character encoding used with the standard fopen function on the host system.

+

The native character encoding is determined using platform specific methods. As of Gecko 1.7, it is UTF-8 on Mac OS X. On Linux and other UNIX platforms, it is the value returned from nl_langinfo (CODESET), which usually corresponds to the value of the LC_ALL, LC_CTYPE and LANG environment variables (with the precedence the same as the order they're enumerated). On Win32 platforms, it is the currently selected ANSI codepage (specified by CP_ACP).

+

The word "Native" appears in the name of methods that operate on or return strings encoded in the native character set.

+

A string containing characters encoded in the native character set cannot be safely passed to JavaScript via XPConnect. Therefore, the "native" methods and attributes are not scriptable.

+

XPCOM provides the string conversion functions NS_CStringToUTF16 and NS_UTF16ToCString, which can be used to convert a string between UTF-16 and the native character encoding.

+

This interface was frozen for Gecko 1.0. See bug 129279 for details. From Gecko 2.0 interfaces are no longer frozen.

+

See also

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifilepicker/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifilepicker/index.html new file mode 100644 index 0000000000..7122dcd1ef --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsifilepicker/index.html @@ -0,0 +1,376 @@ +--- +title: nsIFilePicker +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIFilePicker +tags: + - Filepicker + - 文件选取器 +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIFilePicker +--- +

+
widget/nsIFilePicker.idl脚本化
+ + +文件选择器组件是通过显示标准的用户界面来让用户来选择文件和目录,以及选择目的地来命名和新建文件。 + + +
+继承于: nsISupports +最后修改于Gecko 17.0 (Firefox 17.0 / Thunderbird 17.0 / SeaMonkey 2.14)
+

+ +

实现自: @mozilla.org/filepicker;1。要创建一个实例,使用以下代码:

+ +
var filePicker = Components.classes["@mozilla.org/filepicker;1"]
+                 .createInstance(Components.interfaces.nsIFilePicker);
+
+ +

方法概述

+ + + + + + + + + + + + + + + + + + + +
void appendFilter(in AString title, in AString filter);
void appendFilters(in long filterMask);
void init(in nsIDOMWindow parent, in AString title, in short mode);
void open(in nsIFilePickerShownCallback aFilePickerShownCallback);
short show(); 已废弃 Gecko 17.0
+ +

属性

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性类型说明
addToRecentDocs booleanIf true, the file is added to the operating system's "recent documents" list (if the operating system has one; nothing happens if there is no such concept on the user's platform). This attribute has no effect if private browsing mode is in effect.
defaultExtensionAStringThe extension for the type of files you want to work with. On some platforms, this is automatically appended to filenames the user enters, if required.  Specify it without a leading dot, for example "jpg".
defaultStringAStringThe filename, including extension, that should be suggested to the user as a default. This should be set this before calling open() or show(). +
Exceptions thrown
+ +
+
NS_ERROR_FAILURE
+
If you try to read this attribute.
+
+
displayDirectorynsILocalFileThe directory that the file picker dialog should initially display. This should be set this before calling open() or show() to specify a starting point.
filensILocalFileThe currently selected file or directory. Read only.
filesnsISimpleEnumerator +

An enumerator of the currently selected files. Read only.

+
Note: Only works with modeOpenMultiple mode.
fileURLnsIURIThe URI of the currently selected file or directory. Read only.
filterIndexlongThe (0-based) index of the filter which is currently selected in the file picker dialog. Set this to choose a particular filter to be selected by default.
+ +

常量

+ +

模式常量

+ +

These constants are used to specify the type of file picker to create when calling init().

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
常量说明
modeOpen0Load a file or directory.
modeSave1Save a file or directory.
modeGetFolder2Select a folder/directory.
modeOpenMultiple3Load multiple files.
+ +

返回值常量

+ +

These values are returned by show(), indicating the result of the file picker activity.

+ + + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
returnOK0The file picker dialog was closed by the user hitting 'Ok'
returnCancel1The file picker dialog was closed by the user hitting 'Cancel'
returnReplace2The user chose an existing file and acknowledged that they want to overwrite the file
+ +

筛选器常量

+ +

These constants are used to create filters for commonly-used file types. For the most up to date list see filepicker.properties.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
filterAll0x001Corresponds to the *.* filter for file extensions. All files will pass through the filter.
filterHTML0x002Corresponds to the *.html, *.htm, *.shtml and *.xhtml filters for file extensions.
filterText0x004Corresponds to the *.txt and *.text filter for file extensions.
filterImages0x008Corresponds to the *.jpe, *.jpg, *.jpeg, *.gif, *.png, *.bmp, *.ico, *.svg, *.svgz, *.tif, *.tiff, *.ai, *.drw, *.pct, *.psp, *.xcf, *.psd and *.raw filters for file extensions.
filterXML0x010Corresponds to the *.xml filter for file extensions.
filterXUL0x020Corresponds to the *.xul filter for file extensions.
filterApps0x040Corresponds to the platform specific application filter for file extensions. Application files for the user's platform will pass through the filter.
filterAllowURLs0x80Allow URLs.
filterAudio0x100Corresponds to the *.aac, *.aif, *.flac, *.iff, *.m4a, *.m4b, *.mid, *.midi, *.mp3, *.mpa, *.mpc, *.oga, *.ogg, *.ra, *.ram, *.snd, *.wav and *.wma filters for file extensions.
filterVideo0x200Corresponds to the *.avi, *.divx, *.flv, *.m4v, *.mkv, *.mov, *.mp4, *.mpeg, *.mpg, *.ogm, *.ogv, *.ogx, *.rm, *.rmvb, *.smil, *.webm, *.wmv and *.xvid filters for file extensions.
+ +

方法

+ +

appendFilter()

+ +

Appends a custom file extension filter to the dialog. The filter appended first will be used to display the nsIFilePicker dialog, the user may then select another from the list.

+ +
void appendFilter(
+  in AString title,
+  in AString filter
+);
+
+ +
Parameters
+ +
+
title
+
The title of the filter.
+
filter
+
The filter string. Multiple extensions may be included, separated by a semicolon and a space.
+
+ +
Example
+ +

Some example filter strings:

+ + + +

appendFilters()

+ +

Appends a list of file extension filters, from the predefined list, to the dialog.

+ +
void appendFilters(
+  in long filterMask
+);
+
+ +
Parameters
+ +
Note: If appendFilters is the first (or only) call to set the file filters the filter with the smallest code will be used as default filter when displaying the nsIFilePicker dialog. If you would like to use another you must append it separately before the others you want to go into the drop down list.
+ +
+
filterMask
+
A combination of the filters you wish to use. You may OR multiple filters together; for example filterAll | filterHTML.
+
+ +

init()

+ +

Initialize the file picker widget. The file picker is not valid until this method is called.

+ +
void init(
+  in nsIDOMWindow parent,
+  in AString title,
+  in short mode
+);
+
+ +
Parameters
+ +
+
parent
+
The nsIDOMWindow parent. This dialog will be dependent on this parent. Must be non-null.
+
title
+
The file picker dialog title. If this is null, the dialog will have the default title.
+
mode
+
One of the mode constants, indicating the type of picker to create.
+
+ +

open

+ +

Opens the file dialog asynchrounously. The passed in object's done method will be called upon completion.

+ +
void open(
+  in nsIFilePickerShownCallback aFilePickerShownCallback
+);
+
+ +
Parameters
+ +
+
aFilePickerShownCallback
+
The nsIFilePickerShownCallback to be called on completion.
+
+ +

show

+ +

Displays the file picker dialog. The dialog is displayed modally.

+ +
short show();
+
+ +
Parameters
+ +

None.

+ +
Return value
+ +

One of the return constants.

+ +

示例

+ +

Here's an example:

+ +
const nsIFilePicker = Components.interfaces.nsIFilePicker;
+
+var fp = Components.classes["@mozilla.org/filepicker;1"]
+	           .createInstance(nsIFilePicker);
+fp.init(window, "Dialog Title", nsIFilePicker.modeOpen);
+fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText);
+
+var rv = fp.show();
+if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
+  var file = fp.file;
+  // Get the path as string. Note that you usually won't
+  // need to work with the string paths.
+  var path = fp.file.path;
+  // work with returned nsILocalFile...
+}
+
+ +

If your code is a component and window is not defined, you can get one using nsIWindowMediator.

+ +

When selecting multiple files:

+ +
    ....
+    fp.init(window, "Dialog Title", nsIFilePicker.modeOpenMultiple);
+    ....
+
+    var files = fp.files;
+    var paths = [];
+    while (files.hasMoreElements())
+    {
+        var arg = files.getNext().QueryInterface(Components.interfaces.nsILocalFile).path;
+        paths.push(arg);
+    }
+
diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsihttpchannel/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsihttpchannel/index.html new file mode 100644 index 0000000000..b469773f43 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsihttpchannel/index.html @@ -0,0 +1,365 @@ +--- +title: nsIHttpChannel +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIHttpChannel +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIHttpChannel +--- +

+
netwerk/protocol/http/nsIHttpChannel.idl脚本化
+ + +This interface allows for the modification of HTTP request parameters and the inspection of the resulting HTTP response status and headers when they become available. + + +
+继承于: nsIChannel +最后修改于Gecko 1.3
+

+ +

To create an HTTP channel, use nsIIOService with a HTTP URI, for example:

+ +
var ios = Components.classes["@mozilla.org/network/io-service;1"]
+                    .getService(Components.interfaces.nsIIOService);
+var ch = ios.newChannel("http://www.example.com/", null, null);
+
+ +

方法概述

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ACString getRequestHeader(in ACString aHeader);
ACString getResponseHeader(in ACString header);
boolean isNoCacheResponse();
boolean isNoStoreResponse();
void setRequestHeader(in ACString aHeader, in ACString aValue, in boolean aMerge);
void setResponseHeader(in ACString header, in ACString value, in boolean merge);
void visitRequestHeaders(in nsIHttpHeaderVisitor aVisitor);
void visitResponseHeaders(in nsIHttpHeaderVisitor aVisitor);
+ +

属性

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性名类型描述
allowPipeliningboolean +

This attribute is a hint to the channel to indicate whether or not the underlying HTTP transaction should be allowed to be pipelined with other transactions. This should be set to false, for example, if the application knows that the corresponding document is likely to be very large.

+ +

This attribute is true by default, though other factors may prevent pipelining.

+ This attribute may only be set before the channel is opened. + +
可能抛出的异常
+ +
+
NS_ERROR_FAILURE
+
If set after the channel has been opened.
+
+
redirectionLimitunsigned long +

This attribute specifies the number of redirects this channel is allowed to make. If zero, the channel will fail to redirect and will generate a NS_ERROR_REDIRECT_LOOP failure status.

+
Note: An HTTP redirect results in a new channel being created. If the new channel supports nsIHttpChannel, then it will be assigned a value to its redirectionLimit attribute one less than the value of the redirected channel's redirectionLimit attribute. The initial value for this attribute may be a configurable preference (depending on the implementation).
referrernsIURI +

Get or set the URI of the HTTP Referer: header. This is the address (URI) of the resource from which this channel's URI was obtained (see RFC2616 section 14.36).

+ +

This attribute may only be set before the channel is opened.

+
Note: The channel may silently refuse to set the Referer: header if the URI does not pass certain security checks (e.g., a "https://" URL will never be sent as the referrer for a plaintext HTTP request). The implementation is not required to throw an exception when the referrer URI is rejected.
+ +
可能抛出的异常
+ +
+
NS_ERROR_IN_PROGRESS
+
If set after the channel has been opened.
+
+
requestMethodACString +

获取或设置HTTP请求方法(默认为"GET").设置时不区分大小写,获取时返回的都是大写字母组成的字符串.

+ +

该属性的值只能在通道打开之前进行设置.

+ +

Note:  The data for a "POST" or "PUT" request can be configured via nsIUploadChannel. However, after setting the upload data, it may be necessary to set the request method explicitly. The documentation for nsIUploadChannel has further details.

+ +
可能抛出的异常
+ +
+
NS_ERROR_IN_PROGRESS
+
If set after the channel has been opened.
+
+
requestSucceededboolean +

Returns true if the HTTP response code indicates success. The value of nsIRequest.status() will be NS_OK even when processing a 404 File Not Found response because such a response may include a message body that (in some cases) should be shown to the user. Use this attribute to distinguish server error pages from normal pages, instead of comparing the response status manually against the set of valid response codes, if that is required by your application. Read only.

+ +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
If called before the response has been received (before onStartRequest()).
+
+
responseStatusunsigned long获取HTTP响应状态码(比如200). 只读. +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
If called before the response has been received (before onStartRequest()).
+
+
responseStatusTextACString +

获取HTTP响应状态信息(比如"OK").

+
Note: This returns the raw (possibly 8-bit) text from the server. There are no assumptions made about the charset of the returned text. You have been warned!
Read only. + +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
If called before the response has been received (before onStartRequest()).
+
+
+ +

方法

+ +

getRequestHeader()

+ +

Get the value of a particular request header.

+ +
ACString getRequestHeader(
+  in ACString aHeader
+);
+
+ +
参数
+ +
+
aHeader
+
需要查询的请求头名称,不区分大小写(比如"Cache-Control").
+
+ +
返回值
+ +

指定请求头的值.

+ +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
如果没有这个请求头
+
+ +

getResponseHeader()

+ +

获取指定响应头的值.

+ +
ACString getResponseHeader(
+  in ACString header
+);
+
+ +
参数
+ +
+
header
+
需要查询的响应头名称,不区分大小写(比如"Set-Cookie").
+
+ +
返回值
+ +

指定响应头的值.

+ +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
在响应头还未完全返回的时候调用了该方法(before onStartRequest()),或者响应中没有包含此响应头的情况下.
+
+ +

isNoCacheResponse()

+ +

Returns true if the server sent the equivalent of a "Cache-Control: no-cache" response header. Equivalent response headers include: "Pragma: no-cache", "Expires: 0", and "Expires" with a date value in the past relative to the value of the "Date" header.

+ +
boolean isNoCacheResponse();
+
+ +
参数
+ +

+ +
返回值
+ +

如果服务器返回了"Cache-control: no-cache"或者其他能够禁止缓存的响应头,则该方法返回true,否则返回false.

+ +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
在响应头还未完全返回的时候调用了该方法(before onStartRequest()).
+
+ +

isNoStoreResponse()

+ +
boolean isNoStoreResponse();
+
+ +
参数
+ +

+ +
返回值
+ +

如果服务器返回了"Cache-Control: no-store"这样的响应头,则该方法返回true,否则返回false.

+ +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
在响应头还未完全返回的时候调用了该方法(before onStartRequest()).
+
+ +

setRequestHeader()

+ +

This method is called to set the value of a particular request header. This method allows, for example, the cookies module to add "Cookie" headers to the outgoing HTTP request. This method may only be called before the channel is opened. If aValue is empty and aMerge is false, the header will be cleared.

+ +
void setRequestHeader(
+  in ACString aHeader,
+  in ACString aValue,
+  in boolean aMerge
+);
+
+ +
参数
+ +
+
aHeader
+
指定请求头的名称,不区分大小写(例如"Cookie").
+
aValue
+
指定请求头的值(例如"X=1").
+
aMerge
+
如果该参数为true,则新指定的请求头的值会合并到该请求头已有的值的后面.如果指定的请求头不支持(或者说不适合)新旧值的合并操作,则这个参数会被忽略(比如"Connection"头就只能有一个值).具体那些请求头会忽略掉这个参数,本文档不会给出.如果该参数的值为false,则新指定的请求头的值会覆盖掉该请求头已有的值.
+
+ +
可能抛出的异常
+ +
+
NS_ERROR_IN_PROGRESS
+
在通道已经打开之后才调用了该方法
+
+ +

setResponseHeader()

+ +

设置指定响应头的值.This method allows, for example, the HTML content sink to inform the HTTP channel about HTTP-EQUIV headers found in HTML <META> tags. If value is empty and merge is false, the header will be cleared.

+ +
void setResponseHeader(
+  in ACString header,
+  in ACString value,
+  in boolean merge
+);
+
+ +
参数
+ +
+
header
+
指定响应头的名称,不区分大小写(例如"Cache-Control").
+
value
+
指定响应头的值(例如"no-cache").
+
merge
+
如果该参数为true,则新指定的响应头的值会合并到该响应头已有的值的后面.如果指定的响应头不支持(或者说不适合)新旧值的合并操作,则这个参数会被忽略(比如"Content-Type"头就只能有一个值).具体那些响应头会忽略掉这个参数,本文档不会给出.如果该参数的值为false,则新指定的响应头的值会覆盖掉该响应头已有的值.
+
+ +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
在响应头还未完全返回的时候调用了该方法(before onStartRequest()).
+
NS_ERROR_ILLEGAL_VALUE
+
If changing the value of this response header is not allowed.
+
+ +

visitRequestHeaders()

+ +

Call this method to visit all request headers. Calling setRequestHeader() while visiting request headers has undefined behavior. Don't do it!

+ +
void visitRequestHeaders(
+  in nsIHttpHeaderVisitor aVisitor
+);
+
+ +
参数
+ +
+
aVisitor
+
The header visitor instance.
+
+ +

visitResponseHeaders()

+ +

Call this method to visit all response headers.

+ +

{

Calling setResponseHeader() while visiting response headers has undefined behavior. Don't do it!

+ +
void visitResponseHeaders(
+  in nsIHttpHeaderVisitor aVisitor
+);
+
+ +
参数
+ +
+
aVisitor
+
The header visitor instance.
+
+ +
可能抛出的异常
+ +
+
NS_ERROR_NOT_AVAILABLE
+
If called before the response has been received (before onStartRequest()).
+
diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiidleservice/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiidleservice/index.html new file mode 100644 index 0000000000..a0dec4ad73 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiidleservice/index.html @@ -0,0 +1,119 @@ +--- +title: nsIIdleService +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIIdleService +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIIdleService +--- +

nsIIdleService 的定义文档是:widget/public/nsIIdleService.idl 。 It is scriptable and unfrozen (hasn't changed since Mozilla 1.9a) .

+

概要

+

该服务可使您监测到空闲时间,例如,用户没有进行鼠标或者键盘等操作。您可直接捕获到空闲的时间,但一般,需要注册一个监听。

+

目前 nsIIdleService 服务在 Windows, Mac OS X, and Linux (via XScreenSaver) 等系统上都已实现。

+

实现: @mozilla.org/widget/idleservice;1。创建实例如:

+
var idleService = Components.classes["@mozilla.org/widget/idleservice;1"]
+                            .getService(Components.interfaces.nsIIdleService)
+
+

方法预览

+ + + + + + + + + +
void addIdleObserver(in nsIObserver observer, in unsigned long time)
void removeIdleObserver(in nsIObserver observer, in unsigned long time)
+

属性

+ + + + + + + + + + + + + +
属性类型描述
idleTimelongThe amount of time in milliseconds that has passed since the last user activity. Read only.
+

方法

+

addIdleObserver()

+

添加一个observer,用于侦听使用者何时离开,及何时归来。

+
void addIdleObserver(
+  in nsIObserver observer,
+  in unsigned long time
+)
+
+
参数 
+
+
+ observer
+
+ The observer to be notified.
+
+
+
+ time
+
+    使用者离开多少秒钟后,开始侦听。
+
+
备注
+ + + +

+
Gecko 1.9.2 note
+
从版本 Gecko 1.9.2 开始,增加一个新的侦听消息:‘idle-daily’ 。
+

+

removeIdleObserver()

+

删除observer。

+
void removeIdleObserver(
+  in nsIObserver observer,
+  in unsigned long time
+)
+
+
参数
+
+
+ observer
+
+ the observer to be removed
+
+
+
+ time
+
+ 消息侦听的时间(一段时间)。
+
+

备注

+

删除 observer 时,根据指定的 idle 时间来删除。如果已经添加了多个 observer ,则需要删除多次。

+

示例:

+

例一:

+
var idleService = Components.classes["@mozilla.org/widget/idleservice;1"]
+                            .getService(Components.interfaces.nsIIdleService)
+setTimeout(function() { alert(idleService.idleTime) }, 1000)
+// if you don't use the mouse or the keyboard after running this snippet,
+// you'll see a number around 1000 alerted.
+
+

例二:

+
var idleService = Components.classes["@mozilla.org/widget/idleservice;1"]
+                            .getService(Components.interfaces.nsIIdleService)
+var idleObserver = {
+  observe: function(subject, topic, data) {
+    alert("topic: " + topic + "\ndata: " + data);
+  }
+};
+idleService.addIdleObserver(idleObserver, 60); // one minute
+// ...
+// Don't forget to remove the observer using removeIdleObserver!
+idleService.removeIdleObserver(idleObserver, 60);
+
+

Interwiki Language Links

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsilocalfile/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsilocalfile/index.html new file mode 100644 index 0000000000..882450bf87 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsilocalfile/index.html @@ -0,0 +1,478 @@ +--- +title: nsILocalFile +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsILocalFile +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsILocalFile +--- +

 

+ +
+

In Gecko 14 this Interface was merged into the nsIFile interface.

+
+ +

 

+ +

+
xpcom/io/nsILocalFile.idl脚本化
+ + +This interface adds methods to nsIFile that are particular to a file that is accessible via the local file system. + + +
+ +
66
+ +
+ +
Introduced
+
Gecko 1.0
+ +
+ +
Deprecated
+
Gecko 14
+ +
+ +
+继承于: nsIFile +最后修改于Gecko 1.0
+

+ +

Implemented by: @mozilla.org/file/local;1. To create an instance, use:

+ +
var localFile = Components.classes["@mozilla.org/file/local;1"]
+                .createInstance(Components.interfaces.nsILocalFile);
+
+ +

Method overview

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void appendRelativeNativePath(in ACString relativeFilePath); Native code only!
void appendRelativePath(in AString relativeFilePath);
ACString getRelativeDescriptor(in nsILocalFile fromFile);
void initWithFile(in nsILocalFile aFile);
void initWithNativePath(in ACString filePath); Native code only!
void initWithPath(in AString filePath);
void launch();
PRLibraryStar load(); Native code only!
FILE openANSIFileDesc(in string mode); Native code only!
PRFileDescStar openNSPRFileDesc(in long flags, in long mode); Native code only!
void reveal();
void setRelativeDescriptor(in nsILocalFile fromFile, in ACString relativeDesc);
+ +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDescription
diskSpaceAvailablePRInt64The number of bytes available to non-superuser on the disk volume containing the nsILocalFile. Read only.
followLinksPRBool +

Determines whether or not the nsILocalFile will automatically resolve symbolic links.

+ By default, this value is false on all non-UNIX systems. As of Mozilla 1.7, this attribute is ignored on UNIX systems.
persistentDescriptorACString +

On some platforms, the value of nsIFile.path may be insufficient to uniquely identify the file on the local file system. The persistent descriptor is intended to be used whenever a nsILocalFile needs to be serialized to disk and later recovered. This string is not intended for display to users.

+
Note: The value of the followLinks attribute is not encoded in the persistent descriptor.
+ +

Constants

+ + + + + + + + + + + + + + +
ConstantValueDescription
DELETE_ON_CLOSE0x80000000Optional parameter used by openNSPRFileDesc().
+ +

Methods

+ +

Native code only!

appendRelativeNativePath

+ +

Appends a relative, native character encoding, path to the current path of the nsILocalFile object.

+ +
void appendRelativeNativePath(
+  in ACString relativeFilePath
+);
+
+ +
Parameters
+ +
+
relativeFilePath
+
A native relative path. For security reasons, this cannot contain '..' or cannot start with a directory separator '.'. Must be in the native file system character set.
+
+ +
Exceptions thrown
+ +
+
NS_ERROR_FILE_UNRECOGNIZED_PATH
+
Indicates that relativeFilePath incorrectly begins with a path separator character or otherwise contains invalid characters.
+
+ +

appendRelativePath()

+ +

Appends a relative native path to the current path of the nsILocalFile object.

+ +
void appendRelativePath(
+  in AString relativeFilePath
+);
+
+ +
Parameters
+ +
+
relativeFilePath
+
A native relative path. For security reasons, this cannot contain '..' or cannot start with a directory separator '.' .
+
+ +
Exceptions thrown
+ +
+
NS_ERROR_FILE_UNRECOGNIZED_PATH
+
Indicates that relativeFilePath incorrectly begins with a path separator character or otherwise contains invalid characters.
+
+ +

getRelativeDescriptor()

+ +

Returns a relative file path in an opaque, cross platform format. It is therefore not a native path.

+ +
ACString getRelativeDescriptor(
+  in nsILocalFile fromFile
+);
+
+ +
Parameters
+ +
+
fromFile
+
The file from which the descriptor is relative. There is no defined result if this parameter is null.
+
+ +
Return value
+ +

An opaque string value with undefined character encoding. This string is not intended for display to users.

+ +

The result returned from this method may be used with setRelativeDescriptor() to initialize a nsILocalFile instance.

+ +

initWithFile()

+ +

Initializes this object with another file.

+ +
void initWithFile(
+  in nsILocalFile aFile
+);
+
+ +
Parameters
+ +
+
aFile
+
The file this becomes equivalent to.
+
+ +

Native code only!

initWithNativePath

+ +

Used to set the full path that this nsILocalFile references. All current settings will be reset.

+ +
void initWithNativePath(
+  in ACString filePath
+);
+
+ +
Parameters
+ +
+
filePath
+
A string that specifies a platform-specific, full path to a file or directory. Must be in the native file system character set.
+
+ +
Exceptions thrown
+ +
+
NS_ERROR_FILE_UNRECOGNIZED_PATH
+
Indicates that FilePath is not an absolute file path.
+
+ +

initWithPath()

+ +

Used to set the full path that this nsILocalFile references. All current settings will be reset.

+ +
void initWithPath(
+  in AString filePath
+);
+
+ +
Parameters
+ +
+
filePath
+
A string that specifies a platform-specific, full path to a file or directory.
+
+ +
Exceptions thrown
+ +
+
NS_ERROR_FILE_UNRECOGNIZED_PATH
+
Indicates that FilePath is not an absolute file path.
+
+ +

launch()

+ +

Requests that the operating system attempt to open this file.

+ +
void launch();
+
+ +
Parameters
+ +

None.

+ +

Native code only!

load

+ +

Returns the result of PR_LoadLibrary() on the file. The caller is responsible for calling PR_UnloadLibrary() on the result.

+ +
PRLibraryStar load();
+
+ +
Parameters
+ +

None.

+ +
Return value
+ +

A pointer to a PRLibrary.

+ +
Example
+ +
#include "prlink.h"
+#include "nsError.h"
+#include "nsILocalFile.h"
+
+// Load the DLL corresponding to the given nsILocalFile...
+
+nsresult LoadDLL(nsILocalFile *aLocalFile)
+{
+  PRLibrary *dll;
+  nsresult rv = aLocalFile->Load(&dll);
+  if (NS_FAILED(rv))
+    return rv;
+
+  // Do something with the library now that it is open...
+
+  PR_FreeLibrary(dll);
+  return NS_OK;
+}
+
+ +

Native code only!

openANSIFileDesc

+ +

Returns the result of fopen() on the file. The caller is responsible for calling fclose() on the result.

+ +
FILE openANSIFileDesc(
+  in string mode
+);
+
+ +
Parameters
+ +
+
mode
+
An ANSI file open mode string, which will be passed to fopen().
+
+ +
Return value
+ +

A pointer to an ANSI FILE type.

+ +
Example
+ +
#include <stdio.h>
+#include "nsError.h"
+#include "nsILocalFile.h"
+
+// Read the contents of a nsILocalFile...
+
+nsresult ReadLocalFile(nsILocalFile *aLocalFile)
+{
+  FILE *fp;
+  nsresult rv = aLocalFile->OpenANSIFileDesc("r", &fp);
+  if (NS_FAILED(rv))
+    return rv;
+
+  char buf[512];
+  size_t n;
+
+  while ((n = fread(buf, sizeof(buf), 1, fp)) > 0)
+  {
+    // Do something with n-byte block of data from file...
+  }
+
+  if (ferror(fp) != 0)
+    rv = NS_ERROR_UNEXPECTED;
+
+  fclose(fp);
+  return rv;
+}
+
+ +

Native code only!

openNSPRFileDesc

+ +

Returns the result of PR_Open() on the file. The caller is responsible for calling PR_Close() on the result.

+ +
PRFileDescStar openNSPRFileDesc(
+  in long flags,
+  in long mode
+);
+
+ +
Parameters
+ +
+
flags
+
+

The PR_Open() flags from nsprpub/pr/include/prio.h, plus optionally DELETE_ON_CLOSE. DELETE_ON_CLOSE may be implemented by removing the file (by path name) immediately after opening it, so beware of possible races; the file should be exclusively owned by this process.

+ +

A bitwise combination of the following open flags:

+ +
    +
  • PR_RDONLY Open for reading only.
  • +
  • PR_WRONLY Open for writing only.
  • +
  • PR_RDWR Open for reading and writing.
  • +
  • PR_CREATE_FILE If the file does not exist, the file is created. If the file exists, this flag has no effect.
  • +
  • PR_APPEND The file pointer is set to the end of the file prior to each write.
  • +
  • PR_TRUNCATE If the file exists, its length is truncated to 0.
  • +
  • PR_SYNC If set, each write will wait for both the file data and file status to be physically updated.
  • +
  • PR_EXCL With PR_CREATE_FILE, if the file does not exist, the file is created. If the file already exists, no action and null is returned.
  • +
  • DELETE_ON_CLOSE File will be deleted when closed.
  • +
+
+
mode
+
A UNIX-style file permissions value. For example, the octal value 0600 may be used to limit read and write access to the current user of the system. This parameter may be ignored on systems that do not support file permissions.
+
+ +
Return value
+ +

If the file is successfully opened, returns a pointer to the PRFileDesc created for the newly opened file. Returns a null pointer if the open failed.

+ +
Example
+ +
#include "prio.h"
+#include "nsError.h"
+#include "nsILocalFile.h"
+
+// Read the contents of a nsILocalFile...
+
+nsresult ReadLocalFile(nsILocalFile *aLocalFile)
+{
+  PRFileDesc *fd;
+  nsresult rv = aLocalFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
+  if (NS_FAILED(rv))
+    return rv;
+
+  char buf[512];
+  PRInt32 n;
+
+  while ((n = PR_Read(fd, buf, sizeof(buf))) > 0)
+  {
+    // Do something with n-byte block of data from file...
+  }
+
+  if (n < 0)
+    rv = NS_ERROR_UNEXPECTED;
+
+  PR_Close(fd);
+  return rv;
+}
+
+ +

reveal()

+ +

Ask the operating system to open the folder which contains this file or folder. This routine only works on platforms which support the ability to open a folder. See the note in the remarks below.

+ +
void reveal();
+
+ +
Parameters
+ +

None.

+ +

setRelativeDescriptor()

+ +

Initializes the file to the location relative to fromFile using a string returned by getRelativeDescriptor().

+ +
void setRelativeDescriptor(
+  in nsILocalFile fromFile,
+  in ACString relativeDesc
+);
+
+ +
Parameters
+ +
+
fromFile
+
The file to which the descriptor is relative.
+
relativeDesc
+
The relative descriptor obtained from getRelativeDescriptor().
+
+ +

Remarks

+ +

The methods initWithNativePath() and appendRelativeNativePath() take string valued parameters that are encoded using the native character encoding. That means, you cannot deal with files whose name contain characters outside the default code page on Windows even though Windows 2000 or later has no problem with them. Therefore, never use these functions unless you are absolutely sure that the path passed to them is always ASCII-only. See nsIFile for more information on the native character encoding.

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprocess/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprocess/index.html new file mode 100644 index 0000000000..1abc109440 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprocess/index.html @@ -0,0 +1,283 @@ +--- +title: nsIProcess +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIProcess +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIProcess +--- +

+
xpcom/threads/nsIProcess.idl脚本化
+ + +This interface represents an executable process. + + +
+继承于: nsISupports +最后修改于Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)
+

+

Implemented by: @mozilla.org/process/util;1. To create an instance, use:

+
var process = Components.classes["@mozilla.org/process/util;1"]
+              .createInstance(Components.interfaces.nsIProcess);
+
+

Method overview

+ + + + + + + + + + + + + + + + + + + + + + + + +
void init(in nsIFile executable);
void initWithPid(in unsigned long pid); 已废弃 Gecko 1.9.2
void kill();
void run(in boolean blocking, [array, size_is(count)] in string args, in unsigned long count);
void runAsync([array, size_is(count)] in string args, in unsigned long count, [optional] in nsIObserver observer, [optional] in boolean holdWeak);
void runw(in boolean blocking, [array, size_is(count)] in wstring args, in unsigned long count);
void runwAsync([array, size_is(count)] in wstring args, in unsigned long count, [optional] in nsIObserver observer, [optional] in boolean holdWeak);
+

属性

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性名称属性类型属性描述
exitValuelongThe value returned by the process upon exit. This is only valid after the process has exited. Read only.
isRunningbooleantrue if the process is running, otherwise false. Only accurate if the process was run with blocking disabled. Read only.
locationnsIFile +

The location of the executable file on disk. Read only.

+

+
Gecko 1.9.1 note
+
This attribute is no longer implemented as of Gecko 1.9.1, and is removed entirely in Gecko 1.9.2.
+

+
pidunsigned longThe process ID of the process. This value is only available after the process has started; in addition, some platforms may not offer this value at all. Read only.
processNamestring +

The name of the process. Read only.

+

+
Gecko 1.9.1 note
+
This attribute is no longer implemented as of Gecko 1.9.1, and is removed entirely in Gecko 1.9.2.
+

+
processSignatureunsigned long +

The process signature. Read only.

+

+
Gecko 1.9.1 note
+
This attribute is no longer implemented as of Gecko 1.9.1, and is removed entirely in Gecko 1.9.2.
+

+
+

方法

+

init()

+

Initializes the nsIProcess with the specified executable file. Once initialized, you can start the process executing by calling run().

+

Note: This function does not work with application bundles on Mac OS X, see bug 307463 for details.

+
void init(
+  in nsIFile executable
+);
+
+
参数
+
+
+ executable
+
+ The nsIFile executable file to be represented by the nsIProcess object.
+
+

+

initWithPid()

+ 已废弃 Gecko 1.9.2 (Firefox 3.6 / Thunderbird 3.1 / Fennec 1.0) +

+

Initializes the nsIProcess to represent an existing process, given that process's ID.

+

+
Gecko 1.9.1 note
+
This method is no longer implemented as of Gecko 1.9.1, and is removed entirely in Gecko 1.9.2.
+

+
void initWithPid(
+  in unsigned long pid
+);
+
+
参数
+
+
+ pid
+
+ The process ID to begin to represent.
+
+

kill()

+

立即终止该nsIProcess对象所代表的进程,只在该进程是非阻塞方式启动的情况下才有效.

+

+
Gecko 1.9.1 note
+
在Gecko 1.9.1 (Firefox 3.5)之前版本中, 该方法在Windows和Mac OS X下无效.目前此bug已经修复.
+

+
void kill();
+
+
参数
+

无.

+

run()

+

开始执行进程.

+

+
Gecko 1.9.1 note
+
在Gecko 1.9.1 (Firefox 3.5)之前版本中,该方法会返回一个新执行进程的进程ID,目前已经不会返回任何值.
+

+
void run(
+  in boolean blocking,
+  [array, size_is(count)] in string args,
+  in unsigned long count
+);
+
+
参数
+
+
+ blocking
+
+ 如果为true,则该方法会阻塞,直到所打开的进程关闭为止,如果为false,则该方法会立即返回.
+
+ args
+
+ An array of count arguments, using the native character set, to be passed to the executable on its command line.
+
+ count
+
+ 参数args中的参数个数.
+
+

runAsync()

+

Asynchronously runs the process with which the object was initialized, optionally calling an observer when the process finishes running.

+
void runAsync(
+  [array, size_is(count)] in string args,
+  in unsigned long count,
+  in nsIObserver observer, 可选
+  in boolean holdWeak 可选
+);
+
+
Parameters
+
+
+ args
+
+ An array of arguments to pass into the process, using the native character set. This array must have count entries.
+
+ count
+
+ The number of arguments passed in the args array.
+
+ observer 可选
+
+ An observer that will be notified when the process exits. The observer will receive this nsIProcess instance as the subject and "process-finished" or "process-failed" as the topic. The observer will be notified on the main thread.
+
+ holdWeak 可选
+
+ If true, a weak reference is used to hold the observer.
+
+  
+
+

runw()

+

Executes the file this object was initialized with.

+
void runw(
+  in boolean blocking,
+  [array, size_is(count)] in wstring args,
+  in unsigned long count
+);
+
+
Parameters
+
+
+ blocking
+
+ If true, this method will block until the process terminates; if false, the method returns immediately.
+
+ args
+
+ An array of count arguments, using UTF-16, to be passed to the executable on its command line.
+
+ count
+
+ The number of arguments in the args array.
+
+

runwAsync()

+

Asynchronously runs the process with which the object was initialized, optionally calling an observer when the process finishes running.

+
void runwAsync(
+  [array, size_is(count)] in wstring args,
+  in unsigned long count,
+  in nsIObserver observer, 可选
+  in boolean holdWeak 可选
+);
+
+
Parameters
+
+
+ args
+
+ An array of arguments to pass into the process, using UTF-16. This array must have count entries.
+
+ count
+
+ The number of arguments passed in the args array.
+
+ observer 可选
+
+ An observer that will be notified when the process exits. The observer will receive this nsIProcess instance as the subject and "process-finished" or "process-failed" as the topic. The observer will be notified on the main thread.
+
+ holdWeak 可选
+
+ If true, a weak reference is used to hold the observer.
+
+

Example

+
// create an nsILocalFile for the executable
+var file = Components.classes["@mozilla.org/file/local;1"]
+                     .createInstance(Components.interfaces.nsILocalFile);
+file.initWithPath("c:\\myapp.exe");
+
+// create an nsIProcess
+var process = Components.classes["@mozilla.org/process/util;1"]
+                        .createInstance(Components.interfaces.nsIProcess);
+process.init(file);
+
+// Run the process.
+// If first param is true, calling thread will be blocked until
+// called process terminates.
+// Second and third params are used to pass command-line arguments
+// to the process.
+var args = ["argument1", "argument2"];
+process.run(false, args, args.length);
+
+

See also

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprompt/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprompt/index.html new file mode 100644 index 0000000000..9bd2106964 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiprompt/index.html @@ -0,0 +1,55 @@ +--- +title: nsIPrompt +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIPrompt +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIPrompt +--- +

+
netwerk/base/public/nsIPrompt.idl脚本化
+ + +This is the prompt interface which can be used without knowledge of a parent window. The parentage is hidden by the GetInterface though which it is obtained. + + +
+继承于: nsISupports +最后修改于Gecko 1.8 (Firefox 1.5 / Thunderbird 1.5 / SeaMonkey 1.0)
+

+
+ 注: 本接口基本等价于nsIPromptService,只是没有parent nsIDOMWindow这个参数.为了避免重复的文档,下面的所有方法都链接到了nsIPromptService.如果你准备使用这个接口,一定要删除那些方法中的nsIDOMWindow参数.
+

Normally you would use the prompt service as it is more flexible, but sometimes a callback will request an nsIPrompt via nsIInterfaceRequestor.getInterface(). To get an instance, call the nsIWindowWatcher.getNewPrompter().

+

方法概述

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void alert(in wstring dialogTitle, in wstring text);
void alertCheck(in wstring dialogTitle, in wstring text, in wstring checkMsg, inout boolean checkValue);
boolean confirm(in wstring dialogTitle, in wstring text);
boolean confirmCheck(in wstring dialogTitle, in wstring text, in wstring checkMsg, inout boolean checkValue);
PRInt32 confirmEx(in wstring dialogTitle, in wstring text, in unsigned long buttonFlags, in wstring button0Title, in wstring button1Title, in wstring button2Title, in wstring checkMsg, inout boolean checkValue);
boolean prompt(in wstring dialogTitle, in wstring text, inout wstring value, in wstring checkMsg, inout boolean checkValue);
boolean promptPassword(in wstring dialogTitle, in wstring text, inout wstring password, in wstring checkMsg, inout boolean checkValue);
boolean promptUsernameAndPassword(in wstring dialogTitle, in wstring text, inout wstring username, inout wstring password, in wstring checkMsg, inout boolean checkValue);
boolean select(in wstring dialogTitle, in wstring text, in PRUint32 count, [array, size_is(count)] in wstring selectList, out long outSelection);
+

常量

+

nsIPrompt中的按钮标识同样等同于nsIPromptService.Constants中定义的那些.示例代码可以在这里找到: 使用按钮标识

+

相关链接

+

nsIPromptService

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsipromptservice/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsipromptservice/index.html new file mode 100644 index 0000000000..b194faca6b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsipromptservice/index.html @@ -0,0 +1,696 @@ +--- +title: nsIPromptService +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIPromptService +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIPromptService +--- +

+
embedding/components/windowwatcher/public/nsIPromptService.idl脚本化
+该接口用来显示一些简单的对话框.在chrome上下文,你应该使用该接口的所属方法来替代常规的DOM方法,例如 window.alert, window.confirm, 等. + +
+继承于: nsISupports +最后修改于Gecko 1.7.5
+

+

You can define access keys (or keyboard shortcuts) for buttons by including an ampersand ("&") in front of the character that should be the access key for that button. If you need to include an ampersand in the button's text, use two of them, like this: "&&".

+
+ Note: Some of these interface methods use out and inout parameters. In C++, out parameters are pointers. For JavaScript, they are extra work, as you can't use an out parameter directly. You need to wrap them in a temporary object, which can be either empty or have a value property set to the out parameter type. For more information on out parameters and JavaScript refer to Working with out parameters.
+

该接口由: @mozilla.org/embedcomp/prompt-service;1 组件实现,下面的代码可以得到一个promptService对象实例:

+
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                              .getService(Components.interfaces.nsIPromptService);
+
+

方法概述

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void alert(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText);
void alertCheck(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in wstring aCheckMsg, inout boolean aCheckState);
boolean confirm(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText);
boolean confirmCheck(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in wstring aCheckMsg, inout boolean aCheckState);
PRInt32 confirmEx(in nsIDOMWindow aParent,in wstring aDialogTitle,in wstring aText, in unsigned long aButtonFlags,in wstring aButton0Title, in wstring aButton1Title,in wstring aButton2Title,in wstring aCheckMsg, inout boolean aCheckState);
boolean prompt(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aValue, in wstring aCheckMsg, inout boolean aCheckState);
boolean promptUsernameAndPassword(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aUsername, inout wstring aPassword, in wstring aCheckMsg, inout boolean aCheckState);
boolean promptPassword(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, inout wstring aPassword, in wstring aCheckMsg, inout boolean aCheckState);
boolean select(in nsIDOMWindow aParent, in wstring aDialogTitle, in wstring aText, in PRUint32 aCount, [array, size_is(aCount)] in wstring aSelectList, out long aOutSelection);
+

常量

+

The following flags are combined to form the aButtonFlags parameter passed to confirmEx. All flags are defined as unsigned long constants and can be accessed as Components.interfaces.nsIPromptService.flagname from JavaScript and as nsIPromptService::flagname from C++.

+

Button position flags

+

On Linux and Mac, button 2 is on the left of the prompt, while buttons 1 and 0 are on the right. On Windows and OS/2, the buttons are centred in the order 0, 2, 1.

+ + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
BUTTON_POS_01This is usually the button used to confirm the prompt. It typically has the label "OK", "Yes" or "Save".
BUTTON_POS_1256This is the button used to cancel the prompt. It typically has the label "Cancel" or "No". It is equivalent to pressing the Escape key (or Cmd+. on the Mac), or closing the window through the OS controls.
BUTTON_POS_265536This button can be used to give the user a choice of options, but still allowing the user to cancel the prompt. For instance, it might have the label "Don't Save".
+

Button title flags

+

These flags are used along with Button position flags to set the labels of buttons in the prompt.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
BUTTON_TITLE_OK1 These flags are used to select standard labels from the user's current locale.
BUTTON_TITLE_CANCEL2
BUTTON_TITLE_YES3
BUTTON_TITLE_NO4
BUTTON_TITLE_SAVE5
BUTTON_TITLE_DONT_SAVE6
BUTTON_TITLE_REVERT7
BUTTON_TITLE_IS_STRING127This flag indicates that the label is passed as a separate string. Use this for labels that don't match one of the constants above.
+

Button default flags

+

These flags are used to select which button is the default.

+ + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
BUTTON_POS_0_DEFAULT0 
BUTTON_POS_1_DEFAULT16777216 
BUTTON_POS_2_DEFAULT33554432 
+

BUTTON_DELAY_ENABLE

+

BUTTON_DELAY_ENABLE causes the buttons to be initially disabled. They are enabled after a timeout expires. The implementation may interpret this loosely, as the intent is to ensure that the user does not click through a security dialog too quickly. Strictly speaking, the implementation could choose to ignore this flag. A delay can be useful not only to give the user more time to think before acting, but also as a countermeasure against malicious web sites that intentionally create a race condition whereby the user intends to click or type a key responding, for example, to the web site's prompt but the security dialog pops up unexpectedly and its button is unintentionally activated.

+ + + + + + + + + + + + + +
ConstantValueDescription
BUTTON_DELAY_ENABLE67108864 
+

Standard Buttons flags

+ + + + + + + + + + + + + + + + + + +
ConstantValueDescription
STD_OK_CANCEL_BUTTONS513 +

selects the standard set of OK/Cancel buttons.

+ (BUTTON_TITLE_OK *BUTTON_POS_0) +(BUTTON_TITLE_CANCEL * BUTTON_POS_1)
STD_YES_NO_BUTTONS1027 +

selects the standard set of Yes/No buttons.

+ (BUTTON_TITLE_YES *BUTTON_POS_0) +(BUTTON_TITLE_NO * BUTTON_POS_1)
+

方法

+

alert()

+

alert 方法显示一个警告对话框,包含一个确认按钮. 除了可以设置对话框的标题以外,效果和window.alert全都相同 . 在chrome上下文,你应该使用该xpcom方法来替代window.alert.

+
void alert(
+  in nsIDOMWindow aParent,
+  in wstring aDialogTitle,
+  in wstring aText
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+

代码示例:alert_example.

+

alertCheck()

+

显示一个警告对话框,包含一个确认按钮和一个复选框.

+
void alertCheck(
+  in nsIDOMWindow aParent,
+  in wstring aDialogTitle,
+  in wstring aText,
+  in wstring aCheckMsg,
+  inout boolean aCheckState
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow..
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+ aCheckMsg
+
+ 复选框的说明文字.
+
+ aCheckState
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性控制了复选框的初始选择状态.当对话框关闭时,变量的value属性会存储下复选框的最后选择状态.该变量初始化时可以包含一个类型为布尔值的value属性或者是空对象.
+
+

代码示例:alertCheck_example.

+

confirm()

+

显示一个确认对话框,包含一个确认按钮和一个取消按钮.

+
boolean confirm(
+  in nsIDOMWindow aParent,
+  in wstring aDialogTitle,
+  in wstring aText
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+
返回值
+
+
+ 点确定按钮返回 true , 点取消按钮返回 false
+
+

代码示例:confirm_example.

+

confirmCheck()

+

显示一个对话框,包含一个确认按钮,一个取消按钮和一个复选框.

+

代码示例:confirm_example.

+
boolean confirmCheck(
+  in nsIDOMWindow aParent,
+  in wstring aDialogTitle,
+  in wstring aText,
+  in wstring aCheckMsg,
+  inout boolean aCheckState
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+ aCheckMsg
+
+ 复选框的说明文字.
+
+ aCheckState
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性控制了复选框的初始选择状态.当对话框关闭时,变量的value属性会存储下复选框的最后选择状态.该变量初始化时可以包含一个类型为布尔值的value属性或者是空对象.
+
+
返回值
+
+
+ 点确定按钮返回 true , 点取消按钮返回 false
+
+

confirmEx()

+

Puts up a dialog with up to 3 buttons and an optional, labeled checkbox.

+

The Buttons are numbered 0 - 2. The implementation can decide what order the buttons appear in, and it may not be simply right-to-left (2, 1, 0) or left-to-right (0, 1, 2). See bug 624043 for more on this. Button 0 is the default button unless one of the Button Default Flags is specified (see Button default flags).

+

A button may use a predefined title, specified by one of the Button Title Flags values. Each title value can be multiplied by a position value to assign the title to a particular button. If BUTTON_TITLE_IS_STRING is used for a button, the string parameter for that button will be used. If the value for a button position is zero, the button will not be shown.

+

The following Example creates a Dialog with an OK button an an custom button description.

+

aButtonFlags = (BUTTON_POS_0) * (BUTTON_TITLE_OK) +
+ (BUTTON_POS_1) * (BUTTON_TITLE_IS_STRING) +
+ BUTTON_POS_1_DEFAULT;

+
+ confirmEx always returns 1 if the user closes the window using the close button in the titlebar! bug 345067
+
PRInt32 confirmEx(
+  in nsIDOMWindow  aParent,
+  in wstring aDialogTitle,
+  in wstring aText,
+  in unsigned long aButtonFlags,
+  in wstring aButton0Title,
+  in wstring aButton1Title,
+  in wstring aButton2Title,
+  in wstring aCheckMsg,
+  inout boolean aCheckState
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+ aButtonFlags
+
+ aButtonFlags is a combination of Button flags as described in Using the button flags below.
+
+ aButton0Title
+
+ caption displayed for button 0 if(BUTTON_TITLE_IS_STRING*BUTTON_TITLE_POS_0) flags are set in aButtonFlags
+
+ aButton1Title
+
+ caption displayed for button 1 if(BUTTON_TITLE_IS_STRING*BUTTON_TITLE_POS_1) flags are set in aButtonFlags
+
+ aButton2Title
+
+ caption displayed for button 2 if(BUTTON_TITLE_IS_STRING*BUTTON_TITLE_POS_2) flags are set in aButtonFlags
+
+ aCheckMsg
+
+  复选框的说明文字. 如果值设为Null,则复选框不会显示.
+
+ aCheckState
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性控制了复选框的初始选择状态.当对话框关闭时,变量的value属性会存储下复选框的最后选择状态.该变量初始化时可以包含一个类型为布尔值的value属性或者是空对象.
+
+
返回值
+
+
+ 按下按钮的索引.
+
+

prompt()

+

显示一个对话框,包含一个文本框,一个可选的复选框.

+

代码示例:prompt_example.

+
boolean prompt(
+  in nsIDOMWindow aParent,
+  in wstring aDialogTitle,
+  in wstring aText,
+  inout wstring aValue,
+  in wstring aCheckMsg,
+  inout boolean aCheckState
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+ aValue
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性值就是文本输入框的的初始值.当用户点击确认按钮关闭对话框时,变量的value属性会存储下文本输入框的最后确定值.其他方法关闭对话框时,变量的value属性值不会改变.该变量初始化时可以包含一个类型为字符串值的value属性或者是空对象.
+
+ aCheckMsg
+
+ 复选框的说明文字. 如果值设为Null,则复选框不会显示.
+
+ aCheckState
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性控制了复选框的初始选择状态.当对话框关闭时,变量的value属性会存储下复选框的最后选择状态.该变量初始化时可以包含一个类型为布尔值的value属性或者是空对象.
+
+
返回值
+
+
+ 点确定按钮返回 true , 点取消按钮返回 false
+
+

promptUsernameAndPassword()

+

显示一个对话框,内部包含一个文本输入框,一个密码输入框,和一个可选的复选框.

+

代码示例:promptUsernameAndPassword_example.

+
boolean promptUsernameAndPassword(
+  in nsIDOMWindow aParent,
+  in wstring aDialogTitle,
+  in wstring aText,
+  inout wstring aUsername,
+  inout wstring aPassword,
+  in wstring aCheckMsg,
+  inout boolean aCheckState
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+ aUsername
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性值就是用户名输入框的的初始值.当用户点击确认按钮关闭对话框时,变量的value属性会存储下用户名输入框的最后确定值.其他方法关闭对话框时,变量的value属性值不会改变.该变量初始化时可以包含一个类型为字符串值的value属性或者是空对象.
+
+ aPassword
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性值就是密码输入框的的初始值.当用户点击确认按钮关闭对话框时,变量的value属性会存储下密码输入框的最后确定值.其他方法关闭对话框时,变量的value属性值不会改变.该变量初始化时可以包含一个类型为字符串值的value属性或者是空对象.
+
+ aCheckMsg
+
+ 复选框的说明文字. 如果值设为Null,则复选框不会显示.
+
+ aCheckState
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性控制了复选框的初始选择状态.当对话框关闭时,变量的value属性会存储下复选框的最后选择状态.该变量初始化时可以包含一个类型为布尔值的value属性或者是空对象.
+
+
返回值
+
+
+ 点确定按钮返回 true , 点取消按钮返回 false
+
+

promptPassword()

+

显示一个对话框,包含一个密码框,一个可选的复选框.

+

代码示例:promptPassword_example.

+
boolean promptPassword(
+  in nsIDOMWindow aParent,
+  in wstring aDialogTitle,
+  in wstring aText,
+  inout wstring aPassword,
+  in wstring aCheckMsg,
+  inout boolean aCheckState
+);
+
+
参数
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+ aPassword
+
+ 该变量是一个对象引用,当对话框打开时,变量的value属性值就是密码输入框的的初始值.当用户点击确认按钮关闭对话框时,变量的value属性会存储下密码输入框的最后确定值.其他方法关闭对话框时,变量的value属性值不会改变.该变量初始化时可以包含一个类型为字符串值的value属性或者是空对象.
+
+ aCheckMsg
+
+ 复选框的说明文字. 如果值设为Null,则复选框不会显示.
+
+ aCheckState
+
+     该变量是一个对象引用,当对话框打开时,变量的value属性控制了复选框的初始选择状态.当对话框关闭时,变量的value属性会存储下复选框的最后选择状态.该变量初始化时可以包含一个类型为布尔值的value属性或者是空对象.
+
+
返回值
+
+
+ 点确定按钮返回 true , 点取消按钮返回 false
+
+

select()

+

显示一个对话框,包含一个单项选择的字符串列表.

+

代码示例:select_example.

+
boolean select(
+  in  nsIDOMWindow aParent,
+  in  wstring       aDialogTitle,
+  in  wstring       aText,
+  in  PRUint32     aCount,
+  [array, size_is(aCount)] in wstring aSelectList,
+  out long         aOutSelection
+);
+
+
+
+ aParent
+
+ 对话框的父窗口,如果该值设为 null,则父窗口为当前激活的窗口 nsIWindowWatcher.activeWindow.
+
+ aDialogTitle
+
+ 对话框的标题文字.
+
+ aText
+
+ 对话框的内容文字.
+
+ aCount
+
+ 参数aSelectList的数组长度.
+
+ aSelectList
+
+ 构成字符串列表的字符串数组.
+
+ aOutSelection
+
+ 该变量是一个对象引用,当用户选择某个项目后,变量的value属性值存储了用户所选列表项目的索引值.
+
+
返回值
+
+
+ 点确定按钮返回 true , 点取消按钮返回 false
+
+

代码示例

+

 

+

alert example

+

alert() 显示一个简单的对话框.

+

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+prompts.alert(null, "Title of this Dialog", "Hello! You have now been alerted.");
+
+

alertCheck example

+

alertCheck() 显示一个包含复选框的对话框

+

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var check = {value: false};                      // default the checkbox to false
+
+prompts.alertCheck(null, "Title of this Dialog", "Hello! You have now been alerted.",
+                   "And this is a checkbox", check);
+
+// check.value is now true if the box was checked and false if the box was cleared
+
+

confirm example

+

confirm() 显示一个提示框,内部包含一个确认按钮和一个取消按钮.

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var result = prompts.confirm(null, "Title of this Dialog", "Are you sure?");
+
+// result is now true if OK was clicked, and false if cancel was clicked
+
+

confirmCheck example

+

confirmCheck 显示一个提示框,内部包含一个确认按钮,一个取消按钮,一个复选框.

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var check = {value: true};                   // default the checkbox to true
+
+var result = prompts.confirmCheck(null, "Title of this Dialog", "Are you sure?",
+                                  "Don't ask again", check);
+
+// check.value is now true if the box was checked AND OK was pressed, false if
+// the box was cleared AND OK was pressed, and is the default of true if Cancel was pressed.
+
+

confirmEx example

+

confirmEx()  显示一个对话框,内部包含三个或三个以下的按纽,和一个可选的复选框.

+

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var check = {value: false};                  // default the checkbox to false
+
+var flags = prompts.BUTTON_POS_0 * prompts.BUTTON_TITLE_SAVE +
+            prompts.BUTTON_POS_1 * prompts.BUTTON_TITLE_IS_STRING  +
+            prompts.BUTTON_POS_2 * prompts.BUTTON_TITLE_CANCEL;
+// This value of flags will create 3 buttons. The first will be "Save", the
+// second will be the value of aButtonTitle1, and the third will be "Cancel"
+
+var button = prompts.confirmEx(null, "Title of this Dialog", "What do you want to do?",
+                               flags, "", "Button 1", "", null, check);
+
+// The checkbox will be hidden, and button will contain the index of the button pressed,
+// 0, 1, or 2.
+
+

prompt example

+

prompt() 显示一个对话框,内部包含一个文本输入框.

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var check = {value: false};                  // default the checkbox to false
+
+var input = {value: "Bob"};                  // default the edit field to Bob
+
+var result = prompts.prompt(null, "Title", "What is your name?", input, null, check);
+
+// result is true if OK is pressed, false if Cancel. input.value holds the value of the edit field if "OK" was pressed.
+
+

promptUsernameAndPassword example

+

promptUsernameAndPassword() 显示一个对话框,内部包含一个文本输入框,一个密码输入框和一个可选的复选框.

+

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var username = {value: "user"};              // default the username to user
+
+var password = {value: "pass"};              // default the password to pass
+
+var check = {value: true};                   // default the checkbox to true
+
+var result = prompts.promptUsernameAndPassword(null, "Title", "Enter username and password:",
+                                               username, password, "Save", check);
+
+// result is true if OK was pressed, false if cancel was pressed. username.value,
+// password.value, and check.value are set if OK was pressed.
+
+

promptPassword example

+

promptPassword() 显示一个对话框,内部包含一个密码输入框和一个可选的复选框.

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var password = {value: "pass"};              // default the password to pass
+
+var check = {value: true};                   // default the checkbox to true
+
+var result = prompts.promptPassword(null, "Title", "Enter password:", password, null, check);
+
+// result is true if OK was pressed, false if cancel was pressed. password.value is
+// set if OK was pressed. The checkbox is not displayed.
+
+

select example

+

select() 显示一个对话框,内部是一个包含多个选项的列表框.

+

+
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+                        .getService(Components.interfaces.nsIPromptService);
+
+var items = ["Hello", "Welcome", "Howdy", "Hi", ":)"]; // list items
+
+var selected = {};
+
+var result = prompts.select(null, "Title", "What greeting do you want?", items.length,
+                            items, selected);
+
+// result is true if OK was pressed, false if cancel. selected is the index of the item array
+// that was selected. Get the item using items[selected.value].
+
+

相关链接

+ +

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiscriptableunicodeconverter/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiscriptableunicodeconverter/index.html new file mode 100644 index 0000000000..fe406f1bba --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiscriptableunicodeconverter/index.html @@ -0,0 +1,609 @@ +--- +title: nsIScriptableUnicodeConverter +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIScriptableUnicodeConverter +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIScriptableUnicodeConverter +--- +

+
intl/uconv/idl/nsIScriptableUConv.idl脚本化
+ + +This interface is a Unicode encoder for use by scripts. + + +
+继承于: nsISupports +最后修改于Gecko 1.8 (Firefox 1.5 / Thunderbird 1.5 / SeaMonkey 1.0)
+

+

Implemented by: @mozilla.org/intl/scriptableunicodeconverter. To create an instance, use:

+
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
+                .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+
+

Method overview

+ + + + + + + + + + + + + + + + + + + + + +
ACString ConvertFromUnicode(in AString aSrc);
ACString Finish();
AString ConvertToUnicode(in ACString aSrc);
AString convertFromByteArray([const,array,size_is(aCount)] in octet aData, in unsigned long aCount);
void convertToByteArray(in AString aString,[optional] out unsigned long aLen,[array, size_is(aLen),retval] out octet aData);
nsIInputStream convertToInputStream(in AString aString);
+

Attributes

+ + + + + + + + + + + + + +
AttributeTypeDescription
charsetstringCurrent character set. Throws NS_ERROR_UCONV_NOCONV if the requested charset is not supported.
+

Methods

+

ConvertFromUnicode()

+

Converts the data from Unicode to one Charset. Returns the converted string. After converting, Finish should be called and its return value appended to this return value.

+
ACString ConvertFromUnicode(
+  in AString aSrc
+);
+
+

Finish()

+

Returns the terminator string. Should be called after ConvertFromUnicode() and appended to that function's return value.

+
ACString Finish();
+
+

ConvertToUnicode()

+

Converts the data from one Charset to Unicode.

+
AString ConvertToUnicode(
+  in ACString aSrc
+);
+
+

convertFromByteArray()

+

Converts an array of bytes to a unicode string.

+
AString convertFromByteArray(
+  [const,array,size_is(aCount)] in octet aData,
+  in unsigned long aCount
+);
+
+

convertToByteArray()

+

Convert a unicode string to an array of bytes. Finish does not need to be called.

+
void convertToByteArray(in AString aString,
+  out unsigned long aLen, 可选
+  [array, size_is(aLen),retval] out octet aData
+);
+
+

convertToInputStream()

+

Converts a Unicode string to an input stream. The bytes in the stream are encoded according to the charset attribute. The returned stream is non-blocking.

+
nsIInputStream convertToInputStream(
+  in AString aString
+ );
+
+
Parameters
+
Return value
+

An nsIInputStream that will present the text specified in aString as its data.

+ +
+
+

Examples

+

See Reading textual data and Writing textual data for examples.

+

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsisyncmessagesender/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsisyncmessagesender/index.html new file mode 100644 index 0000000000..1af1e116c3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsisyncmessagesender/index.html @@ -0,0 +1,65 @@ +--- +title: nsISyncMessageSender +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsISyncMessageSender +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsISyncMessageSender +--- +

+
content/base/public/nsIMessageManager.idl脚本化
+ + +Handles sending messages synchronously to a destination frame. + + +
+ +
1.0
+ +
66
+ +
+ +
+ +
Introduced
+
Gecko 2.0
+ +
+ +
+继承于: nsIFrameMessageManager +最后修改于Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)
+

+

方法概述

+ + + + + + +
void sendSyncMessage(in messageName, in JSON, in [array] jsObjects);
+

sendSyncMessage()

+

同步发送一条短消息.

+
void sendSyncMessage(
+  in DOMString messageName,
+  in DOMString json,
+);
+
+
Parameters
+
+
+ messageName
+
+ 消息的名称.
+
+ json
+
+ 一个JSON格式的字符串,代表了要发送的数据.
+
+

相关链接

+ diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitimer/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitimer/index.html new file mode 100644 index 0000000000..24cfb2eb4f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitimer/index.html @@ -0,0 +1,285 @@ +--- +title: nsITimer +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsITimer +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsITimer +--- +
+
+

nsITimer 接口的功能是:在指定延迟后唤醒一个程序。

+

nsITimer 的定义文档: xpcom/threads/nsITimer.idl 。It is scriptable and unfrozen (hasn't changed since 1.9.1) .

+

继承自: nsISupports

+

实现: @mozilla.org/timer;1。创建实例如:

+
var timer = Components.classes["@mozilla.org/timer;1"]
+                    .createInstance(Components.interfaces.nsITimer);
+
+
+

方法预览

+
+ Edit section
+ + + + + + + + + + + + + + + +
void initWithCallback(in nsITimerCallback aCallback, in unsigned long aDelay, in unsigned long aType);
[noscript] void initWithFuncCallback(in nsITimerCallbackFunc aCallback, in voidPtr aClosure, in unsigned long aDelay, in unsigned long aType);
void init(in nsIObserver aObserver, in unsigned long aDelay, in unsigned long aType);
void cancel();
+
+
+

属性

+
+ Edit section
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDescription
delayunsigned longThe timeout delay in millisecond.
typeunsigned longDefines the timer type: one shot, repeating slack or repeating precise. Must be one of the constants defined under Constants on this page
callbackreadonly nsITimerCallback The nsITimerCallback object passed to initWithCallback().
closure[noscript] readonly voidPtr +

The opaque pointer pass to initWithFuncCallback().

+
targetnsIEventTarget The nsIEventTarget to which the callback is dispatched.  This target must be set before calling any of the initialization methods.
+
+
+

常量

+
+ Edit section
+ + + + + + + + + + + + + + + + + + + + + + + +
ConstantValueDescription
TYPE_ONE_SHOT0Type of a timer that fires once only.
TYPE_REPEATING_SLACK1After firing, the timer is stopped and not restarted until its callback completes. Specified timer period will be at least the time between when processing for last firing the callback completes and when the next firing occurs.
TYPE_REPEATING_PRECISE2This repeating timer aims to have constant period between firings. The processing time for each timer callback should not influence the timer period. However, if the processing for the last timer firing could not be completed until just before the next firing occurs, then you could have two timer notification routines being executed in quick succession.
+
+
+

方法

+
+ Edit section
+
+

initWithCallback()

+
+ Edit section
+

Initialize a timer to fire after the given millisecond interval. This version takes a function to call and a closure to pass to that function.

+
 void initWithCallback (
+   in nsITimerCallback aCallback,
+   in unsigned long aDelay,
+   in unsigned long aType
+ );
+
+
+
Parameters
+
+ Edit section
+
+
+ aFunc
+
+ nsITimerCallback interface to call when timer expires.
+
+
+
+ aDelay
+
+ timeout delay in milliseconds.
+
+
+
+ aType
+
+ Defines the timer type: one shot, repeating slack or repeating precise. Must be one of the constants defined under Constants on this page.
+
+
+
+
+

initWithFuncCallback()

+
+ Edit section
+

Initialize a timer to fire after the given millisecond interval. This version takes a function to call and a closure to pass to that function.

+
 [noscript] void initWithFuncCallback(
+   in nsTimerCallbackFunc aCallback,
+   in voidPtr aClosure,
+   in unsigned long aDelay,
+   in unsigned long aType
+ );
+
+
+
Parameters
+
+ Edit section
+
+
+ aFunc
+
+ a nsITimerCallbackFunc interface compatible function to call when timer fires.
+
+
+
+ aClosure
+
+ An opaque pointer to pass to that function.
+
+
+
+ aDelay
+
+ timeout delay in milliseconds.
+
+
+
+ aType
+
+ Defines the timer type: one shot, repeating slack or repeating precise. Must be one of the constants defined under Constants on this page.
+
+
+
+
+

init()

+
+ Edit section
+

Initialize a timer that will fire after the specified delay. A user must keep a reference to this timer till it is no longer needed or has been canceled.

+
 void init(
+   in nsIObserver aObserver,
+   in unsigned long aDelay,
+   in unsigned long aType
+ );
+
+
+
Parameters
+
+ Edit section
+
+
+ aObserver
+
+ A callback Object, that is capable listening to timer events. If the timer fires, the observer will be notified via the nsIObserver Interface. The subject is set to the nsITimer Object which fired, the topic is equal to "timer-callback" and data is always set to null.
+
+
+
+ aDelay
+
+ timeout delay in milliseconds.
+
+
+
+ aType
+
+ Defines the timer type: one shot, repeating slack or repeating precise. Must be one of the constants defined under Constants on this page.
+
+
+
+
+

cancel()

+
+ Edit section
+

Cancels the timer. This method works on all types, not just on repeating timers -- you might want to cancel a TYPE_ONE_SHOT timer, and even reuse it by re-initializing it (to avoid object destruction and creation costs by conserving one timer instance).

+
 void cancel();
+
+
+
Parameters
+
+ Edit section
+

None.

+
+
+
+
+

备注

+
+ Edit section
+

TYPE_REPEATING_SLACK timer is the preferable repeating timer type for most situations

+
+
+

 

+
+ 实例
+
+ Edit section
+
 // we need a nsITimerCallback
+ compatible...
+ // ... interface for the callbacks.
+ var event
+   = { notify: function(timer) { alert("Fire!"); } }
+
+ // Now it is time to create the timer...
+ var timer
+   = Components.classes["@mozilla.org/timer;1"]
+       .createInstance(Components.interfaces.nsITimer);
+
+ // ... and to initialize it, we want to call event.notify() ...
+ // ... one time after exactly ten second.
+ timer.initWithCallback(
+   event,
+   10000,
+   Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+
+

 

+
+
+

请参阅

+
+ Edit section
+

nsITimerCallbackFunc , nsITimerCallback

+
+
+
+ +

标记:

+
+ +
+

 

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitraceablechannel/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitraceablechannel/index.html new file mode 100644 index 0000000000..ce7c6deb2f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsitraceablechannel/index.html @@ -0,0 +1,71 @@ +--- +title: nsITraceableChannel +slug: Mozilla/Tech/XPCOM/Reference/Interface/NsITraceableChannel +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/NsITraceableChannel +--- +

+
netwerk/base/public/nsITraceableChannel.idl脚本化
+这个接口用于允许拦截 HTTP 流量。It is implemented by nsIHttpChannel. + +
+ +
1.0
+ +
66
+ +
+ +
+ +
Introduced
+
Gecko 1.9.0.4
+ +
+ +
+继承于: nsISupports +最后修改于Gecko 1.9.0.4
+

+

使用这个接口的典型方式如下:

+ +

之后,你的 nsIStreamListener 实现将会获取到响应数据(response data),并且能够传递数据到原始的 nsIStreamListener(可能会修改它)。

+

See nsITraceableChannel, Intercept HTTP Traffic for a more detailed description with code samples.

+

See Modify URL before loading page in firefox for an overview of how to modify a request before it is made.

+

Method overview

+ + + + + + +
nsIStreamListener setNewListener(in nsIStreamListener aListener);
+

Methods

+

setNewListener()

+

用一个新的来替换该通道的当前监听器,返回先前分配给该通道的监听器。

+
nsIStreamListener setNewListener(
+  in nsIStreamListener aListener
+);
+
+
参数
+
+
+ aListener
+
+ An nsIStreamListener to be notified of events on the HTTP channel.
+
+
返回值
+

该通道的前一个监听器。Each listener call through to the previous listener for every call, in order to establish a call chain to allow all interested parties a chance to act on each event.

+

实现 nsIStreamListener

+

一个 nsIStreamListener 接口传递给 setNewListener() 需要实现下列的方法,这是通过调用(这些方法)来通知它在 HTTP stream 上发生的事件:

+ +
+ Note: It is critical that you pass along requests to the previous listener as soon as possible -- especially for onStartRequest.
+

Channels may restrict when you may replace the listener. In particular, listeners typically should not be replaced after onStartRequest has been called.

diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiuri/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiuri/index.html new file mode 100644 index 0000000000..d133861ac3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsiuri/index.html @@ -0,0 +1,407 @@ +--- +title: nsIURI +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIURI +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIURI +--- +

+
netwerk/base/public/nsIURI.idl脚本化
+ + +这是具有国际化支持的统一资源标识符的接口,提供允许设置和查询URI基本组件的属性以及用于在URI上执行基本操作的方法。 + + +
+继承于: nsISupports +最后修改于Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)
+

+ +

细节请查看下列 RFCs:

+ + + +

nsIURI的子类,  例如 nsIURL, 加强了URI未来的结构化.

+ +

为了创建一个 nsIURI 对象, 你应该如此使用 nsIIOService.newURI():

+ +
function makeURI(aURL, aOriginCharset, aBaseURI) {
+  var ioService = Components.classes["@mozilla.org/network/io-service;1"]
+                  .getService(Components.interfaces.nsIIOService);
+  return ioService.newURI(aURL, aOriginCharset, aBaseURI);
+}
+
+ +

一个 URI 的组件

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
prePathpath
scheme userPass host port ref
ftp://username@password@hostname:portnumber/pathname?query=value#ref
+ +

函数预览

+ + + + + + + + + + + + + + + + + + + + + + +
nsIURI clone();
nsIURI cloneIgnoringRef();
boolean equals(in nsIURI other);
boolean equalsExceptRef(in nsIURI other);
AUTF8String resolve(in AUTF8String relativePath);
boolean schemeIs(in string scheme);
+ +

属性

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性类别描述
asciiHostACString +

The URI host with an ASCII compatible encoding. Follows the IDNA draft specification for converting internationalized domain names (UTF-8) to ASCII for compatibility with existing Internet infrastructure. Read only.

+ +
+

Note: IPv6 addresses are not enclosed in square brackets.

+
+
asciiSpecACString (US-ASCII)The URI spec with an ASCII compatible encoding. The host portion follows the IDNA draft spec. Other parts are URL-escaped per the rules of RFC3986. The result is strictly ASCII. Read only.
hasRefbooleanReturns if there is a reference portion (the part after the "#") of the URI.
+
+
hostAUTF8String +

The host is the Internet domain name to which this URI refers. It could be an IPv4 (or IPv6) address literal. If supported, it could be a non-ASCII internationalized domain name.

+ +
Exceptions thrown
+ +
+
NS_ERROR_FAILURE
+
If host is not applicable to the URI scheme (e.g. about:blank)
+
+ +
Note: Characters are not escaped. IPv6 addresses are not enclosed in square brackets.
+
hostPortAUTF8String +

The "host:port" part of the URI (or simply the host, if port is -1).

+ +
Exceptions thrown
+ +
+
NS_ERROR_FAILURE
+
If hostPort is not applicable to the URI scheme (e.g. about:blank)
+
+ +
Note: Characters are not escaped.
+
originCharsetACString +

The charset of the document from which this URI originated. An empty value implies UTF-8.

+ If this value is something other than UTF-8 then the URI components (for example spec, prePath, username, and so on) are all fully URL-escaped. Otherwise, the URI components may contain unescaped multibyte UTF-8 characters. Read only.
passwordAUTF8String +

The optional password, assuming the preHost consists of "username:password".

+ +
Exceptions thrown
+ +
+
NS_ERROR_FAILURE
+
If password is not applicable to the URI scheme (e.g. about:blank)
+
+ +

Note: Some characters may be escaped.

+
pathAUTF8String +

The path, typically including at least a leading '/' (but may also be empty, depending on the protocol).

+
Note: Some characters may be escaped.
portlong +

The URI's port. A port value of -1 corresponds to the protocol's default port (for example -1 implies port 80 for HTTP URIs).

+ +
Exceptions thrown
+ +
+
NS_ERROR_FAILURE
+
If port is not applicable to the URI scheme (e.g. about:blank)
+
+
prePathAUTF8String +

The prePath returns the string before the path (such as "scheme://user:password@host:port").

+ +

This is related to the Web Origin Concept of RFC6454.

+ +

This is useful for authentication, managing sessions, or for checking the origin of an URI to prevent cross-site scripting attacks while using methods such as window.postMessage().

+
Note: Some characters may be escaped.
Read only.
refAUTF8String +

Returns the reference portion (the part after the "#") of the URI. If there is not one, an empty string is returned.

+
Note: Some characters may be escaped.
schemeACString (US-ASCII) +

The scheme is the protocol to which this URI refers. The scheme is restricted to the US-ASCII charset per RFC3986.

+ +
Warning: Setting this is highly discouraged outside of a protocol handler implementation, since doing so will generally lead to unpredictable results.
+
specAUTF8String +

Returns a string representation of the URI. Setting the spec causes the new spec to be parsed using the rules for the scheme the URI currently has. If the string cannot be parsed as a URI, NS_ERROR_MALFORMED_URI thrown.

+ +
Warning: Because parsing the string is done using the current URI's scheme, setting the spec to a URI with a different scheme will produce incorrect results. Therefore, only protocol handler implementations should do this.
+ +

If the URI stores information from the nsIIOService interface's nsIIOService.newURI() call that created it, other than just the parsed string, the behavior of this information when setting the spec attribute is undefined.

+
Note: Some characters may be escaped.
specIgnoringRefAUTF8StringReturns a string representation of the URI without the ref (part after the #) portion.
+
+
Note: Some characters may be escaped.
usernameAUTF8String +

The optional username, assuming the preHost consists of "username:password".

+ +
Exceptions thrown
+ +
+
NS_ERROR_FAILURE
+
If username is not applicable to the URI scheme (e.g. about:blank)
+
+
Note: Some characters may be escaped.
userPassAUTF8String +

The "username:password" (or username only if the value doesn't contain a ':').

+ +
Exceptions thrown
+ +
+
NS_ERROR_FAILURE
+
If userPass is not applicable to the URI scheme (e.g. about:blank)
+
+
Note: Some characters may be escaped.
+ +

Methods

+ +

clone()

+ +

Clones the URI, returning a new nsIURI object.

+ +
Note: For some protocols, this is more than just an optimization. For example, under Mac OS X, the spec of a file URI doesn't necessarily uniquely identify a file, since two volumes can have the same name.
+ +
nsIURI clone();
+
+ +
Parameters
+ +

None.

+ +
Return value
+ +

An nsIURI object that represents the same URI as the current nsIURI.

+ +

cloneIgnoringRef()

+ +

Clones the current URI, clearing the 'ref' attribute in the clone.

+ +
nsIURI cloneIgnoringRef();
+
+ +
Parameters
+ +

None.

+ +
Return value
+ +

An nsIURI object that represents the same URI as the current nsIURI without the 'ref' attribute.

+ +

equals()

+ +

Compares the current URI with another URI.

+ +
Note: This is more than a string comparison, as two different URI strings can represent the same location. For example, comparing "http://foo.com:80/" and "http://foo.com/" will return true.
+ +
boolean equals(
+  in nsIURI other
+);
+
+ +
Parameters
+ +
+
other
+
Another nsIURI to compare to.
+
+ +
Return value
+ +

true if the two URIs represent the same location; otherwise false.

+ +

equalsExceptRef()

+ +

Compares the current URI with another URI, ignoring the value of the .ref member.

+ +
Note: This is more than a string comparison, as two different URI strings can represent the same location. For example, comparing "http://foo.com/#" and "http://foo.com/" or "http://foo.com/#aaa" and "http://foo.com/#bbb" will return true.
+ +
boolean equalsExceptRef(
+  in nsIURI other
+);
+
+ +
Parameters
+ +
+
other
+
Another nsIURI to compare to.
+
+ +
Return value
+ +

true if the two URIs represent the same location; otherwise false.

+ +

resolve()

+ +

Resolves a relative URI string, using this URI as the base.

+ +

Note: Some implementations may have no concept of a relative URI.

+ +
AUTF8String resolve(
+  in AUTF8String relativePath
+);
+
+ +
Parameters
+ +
+
relativePath
+
The relative path to resolve.
+
+ +
Return value
+ +

The resolved absolute URI string.

+ +

schemeIs()

+ +

Quickly reports whether the nsIURI represents a URI with the specified scheme. This comparison is case-insensitive.

+ +

Note: This is an optimization, allowing you to check the scheme of the URI without having to get the scheme and do the comparison yourself; this saves memory allocations.

+ +
boolean schemeIs(
+  in string scheme
+);
+
+ +
Parameters
+ +
+
scheme
+
A string representing the scheme to compare to.
+
+ +
Return value
+ +

true if the URI is for the specified scheme; otherwise false.

+ +

See also

+ + diff --git a/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsixmlhttprequest/index.html b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsixmlhttprequest/index.html new file mode 100644 index 0000000000..f12f52cb12 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/reference/interface/nsixmlhttprequest/index.html @@ -0,0 +1,90 @@ +--- +title: nsIXMLHttpRequest +slug: Mozilla/Tech/XPCOM/Reference/Interface/nsIXMLHttpRequest +tags: + - XMLHttpRequest + - XPCOM API 参考 + - XPCOM 接口参考 + - 指南 + - 接口 +translation_of: Mozilla/Tech/XPCOM/Reference/Interface/nsIXMLHttpRequest +--- +

Obsolete since Gecko 60 (Firefox 60 / Thunderbird 60 / SeaMonkey 2.57)
This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.

+ +

nsIXMLHttpRequest along with nsIJSXMLHttpRequest and nsIXMLHttpRequestEventTarget are Mozilla's implementation details of the DOM XMLHttpRequest object.

+ +
注意: 如果你是 Web 开发者或者 Mozilla add-on 开发者,请参考 XMLHttpRequest
+ +

This page contains documentation, specific to Mozilla application and add-on developers.

+ +

The interface definition: https://dxr.mozilla.org/mozilla-central/source/dom/xhr/nsIXMLHttpRequest.idl

+ +

Elevated Privileges

+ +

As mentioned in the "Non-Standard Properties" the property of channel was read-only. When using the XPCOM interface, as seen below in Example 2, we can get access to this. The most obvious benefit is that we can set nsiRequest - Constants in the xhr.channel.loadFlags. For instance, as done in Example 2, the flag of LOAD_ANONYMOUS is added, this strips all user data (cookies, tokens, etc).

+ +

Using event handlers from native code

+ +

(Not sure if it's up-to-date)

+ +

From native code, the way to set up onload and onerror handlers is a bit different. Here is a comment from Johnny Stenback <jst@netscape.com>:

+ +
The mozilla implementation of nsIXMLHttpRequest implements the interface nsIDOMEventTarget and that's how you're supported to add event listeners. Try something like this: nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(myxmlhttpreq)); target->AddEventListener(NS_LITERAL_STRING("load"), mylistener, PR_FALSE) where mylistener is your event listener object that implements the interface nsIDOMEventListener. The 'onload', 'onerror', and 'onreadystatechange' attributes moved to nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using those.
+ +

Though actually, if you use addEventListener from C++ weird things will happen too, since the result will depend on what JS happens to be on the stack when you do it....

+ +

Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless you're aware of all the security implications. And then think twice about it.

+ +

Example code

+ +

This is a simple example code for opening a simple HTTP request from a xul application (like a Mozilla extension) without using observers:

+ +
 var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
+ req.open('POST', "http://www.foo.bar:8080/nietzsche.do", true);
+ req.send('your=data&and=more&stuff=here');
+
+ +

Example 2

+ +
var {Cu: utils, Cc: classes, Ci: instances} = Components;
+Cu.import('resource://gre/modules/Services.jsm');
+function xhr(url, cb) {
+    let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
+
+    let handler = ev => {
+        evf(m => xhr.removeEventListener(m, handler, !1));
+        switch (ev.type) {
+            case 'load':
+                if (xhr.status == 200) {
+                    cb(xhr.response);
+                    break;
+                }
+            default:
+                Services.prompt.alert(null, 'XHR Error', 'Error Fetching Package: ' + xhr.statusText + ' [' + ev.type + ':' + xhr.status + ']');
+                break;
+        }
+    };
+
+    let evf = f => ['load', 'error', 'abort'].forEach(f);
+    evf(m => xhr.addEventListener(m, handler, false));
+
+    xhr.mozBackgroundRequest = true;
+    xhr.open('GET', url, true);
+    xhr.channel.loadFlags |= Ci.nsIRequest.LOAD_ANONYMOUS | Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_PERSISTENT_CACHING;
+    xhr.responseType = "arraybuffer"; //dont set it, so it returns string, you dont want arraybuffer. you only want this if your url is to a zip file or some file you want to download and make a nsIArrayBufferInputStream out of it or something
+    xhr.send(null);
+}
+
+xhr('https://www.gravatar.com/avatar/eb9895ade1bd6627e054429d1e18b576?s=24&d=identicon&r=PG&f=1', data => {
+    Services.prompt.alert(null, 'XHR Success', data);
+    var file = OS.Path.join(OS.Constants.Path.desktopDir, "test.png");
+    var promised = OS.File.writeAtomic(file, new UInt8Array(data));
+    promised.then(
+        function() {
+            alert('succesfully saved image to desktop')
+        },
+        function(ex) {
+             alert('FAILED in saving image to desktop')
+        }
+    );
+});
diff --git a/files/zh-cn/mozilla/tech/xpcom/setting_http_request_headers/index.html b/files/zh-cn/mozilla/tech/xpcom/setting_http_request_headers/index.html new file mode 100644 index 0000000000..b91030b424 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpcom/setting_http_request_headers/index.html @@ -0,0 +1,261 @@ +--- +title: Setting HTTP request headers +slug: Mozilla/Tech/XPCOM/Setting_HTTP_request_headers +translation_of: Mozilla/Tech/XPCOM/Setting_HTTP_request_headers +--- +

HTTP 是网络背后的核心技术之一。除了实质内容之外,一些重要的信息通过HTTP 头传递给HTTP 请求和响应。

+ +

你可以添加你自己的HTTP头到应用程序所做的任何请求中,不论你的代码是否启动了显式打开了基于 XMLHttpRequest 活动、<img>元素或者甚至是从css中的 HTTP Channel的请求。

+ +

HTTP Channels

+ +

当你处理HTTP请求和响应时,通常情况下你是通过 nsIHttpChannel来做的。 nsIHttpChannel接口有一些属性和方法,但是这下方法中我们只对setRequestHeader感兴趣。这个方法允许我们设置一个 HTTP request header.

+ +

下面是设置一个HTTP header 的简单代码

+ +
// adds "X-Hello: World" header to the request
+httpChannel.setRequestHeader("X-Hello", "World", false);
+
+ +

在这个示例代码中我们有一个变量名为httpChannel,它是一个nsIHttpChannel的实例。

+ +

setRequestHeader有三个参数,第一个参数是HTTP请求头的名字,第二个参数是HTTP请求头的值,第三个参数我们暂时忽略它,总设置其为false。

+ +

在我们的示例代码中,我们为HTTP reques header中增加了被我们命名为X-Hello的HTTP请求头,其值为World

+ +
+

NOTE: If you are making up your own HTTP header, you MUST put a X- in front of the name. (In our example, our made up HTTP header is X-Hello and NOT Hello because we correctly added the X- in front of our name.)

+ +


+ No longer the case: http://tools.ietf.org/html/draft-ietf-appsawg-xdash-02

+
+ +

Notifications

+ +

The question that may be coming to your mind right now is, how do you get the nsIHttpChannel when an HTTP request is made.

+ +

In the case your code initiates the request, you probably already have one. Trapping other requests is done with notifications, which are a lot like events or signals found in other languages and frameworks.

+ +

In particular, to get the nsIHttpChannel just before the HTTP request is made we need to observe the "http-on-modify-request" topic. (And yes, "http-on-modify-request" is a string.)

+ +
+

NOTE: There are many topics, besides just "http-on-modify-request", that you can get notifications about, for example "http-on-examine-response" and "xpcom-shutdown". You can also make up your own topics and send out your own notifications.

+ +

For more information about notifications framework and a list of common notification topics, see Observer Notifications.

+
+ +

Observers

+ +

To get notified about some topic (like "http-on-modify-request") we need to create an observer. An observer is a component implementing nsIObserver interface. And once the observer is registered for a topic, it will get notified about the topic by having its observe method called.

+ +

Below is an example observer that adds a custom header "X-Hello" to the channel passed in for http-on-modify-request notification:

+ +
var httpRequestObserver =
+{
+  observe: function(subject, topic, data)
+  {
+    if (topic == "http-on-modify-request") {
+      var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
+      httpChannel.setRequestHeader("X-Hello", "World", false);
+    }
+  }
+};
+
+ +

div class="note"> Doesn't seem very suitable for this article; readers should are typically assumed to be familiar with JS. Nickolay '''NOTE''': Often people expect JavaScript to be just like Java. And while superficially, they look very similar, there are some important differences between the two. For example, while Java is an <em>object-oriented programming language</em>, JavaScript is not. JavaScript is <em>prototype-based programming language</em> and as such while it has <em>objects</em> it does not have <em>classes</em>. (Which is why, if you are not well versed with JavaScript, the object creation in the sample code above may look strange.) </div

+ +

Note that the number of parameter that the observe method takes is important. It takes 3 parameters (as we've shown in the example code above). For the "http-on-modify-request" topic, the first parameter (named subject in the code above) will be the nsIHttpChannel. However, it is passed to us as an nsISupports. So we need to change the nsISupports into a nsIHttpChannel which is what the QueryInterface call does. And yes, converting objects from one kind to another is very ugly, and lacks (what is usually called) syntactic sugar.

+ +

The second line of code in the if block should already be familiar to you. It is the same code we used before, earlier in this article, to add the HTTP request header.

+ +

The name of this object -- httpRequestObserver -- isn't important. We could have named it anything we liked.

+ +

Registering

+ +

After we've created the observer, we need to register it. In our case, we want to register it for the "http-on-modify-request" topic. We can do this with the code below.

+ +
var observerService = Components.classes["@mozilla.org/observer-service;1"]
+                                .getService(Components.interfaces.nsIObserverService);
+observerService.addObserver(httpRequestObserver, "http-on-modify-request", false);
+
+ +

The first statement gets the object that will let us register with topics that we want to get notified about.

+ +

The second statement does the actual registering. We are saying we want httpRequestObserver to be notified (by calling its observe method) when a "http-on-modify-request" topic takes place (which we know happens just before each HTTP request).

+ +

Unregistering

+ +

You should unregister the observer on shutdown. Failing to do that may cause memory leaks. To unregister the observer use nsIObserverService.removeObserver as follows:

+ +
observerService.removeObserver(httpRequestObserver, "http-on-modify-request");
+ +

All-in-one example

+ +

Here is a slightly different version of our httpRequestObserver object. While the previous version we showed before was good for learning, in an actual real-world application, you'd probably want to code it more like the following.

+ +
var httpRequestObserver =
+{
+  observe: function(subject, topic, data)
+  {
+    if (topic == "http-on-modify-request") {
+      var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
+      httpChannel.setRequestHeader("X-Hello", "World", false);
+    }
+  },
+
+  get observerService() {
+    return Components.classes["@mozilla.org/observer-service;1"]
+                     .getService(Components.interfaces.nsIObserverService);
+  },
+
+  register: function()
+  {
+    this.observerService.addObserver(this, "http-on-modify-request", false);
+  },
+
+  unregister: function()
+  {
+    this.observerService.removeObserver(this, "http-on-modify-request");
+  }
+};
+
+ +

This object has a convenience register() and unregister() methods, so in order to activate it you just need to call:

+ +
httpRequestObserver.register();
+
+ +

You should also remember to unregister the observer at shutdown:

+ +
httpRequestObserver.unregister();
+
+ +

And that's it.

+ +

XPCOM components

+ +

You need to register a single http-on-modify-request observer per application (and not one per window). This means that you should put the observer's implementation in an XPCOM component instead of an overlay. If you want to support Gecko2 (Firefox4) you need to register your javascript component as described here: https://developer.mozilla.org/zh-cn/XPCOM/XPCOM_changes_in_Gecko_2.0#JavaScript_components.

+ +
var headerName  = "X-hello";
+var headerValue = "world";
+
+function LOG(text)
+{
+    //    var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
+    //    consoleService.logStringMessage(text);
+}
+
+function myHTTPListener() { }
+
+myHTTPListener.prototype = {
+
+  observe: function(subject, topic, data)
+  {
+      if (topic == "http-on-modify-request") {
+
+          LOG("----------------------------> (" + subject + ") mod request");
+
+          var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
+          httpChannel.setRequestHeader(headerName, headerValue, false);
+          return;
+      }
+
+
+      if (topic == "profile-after-change") {
+
+          LOG("----------------------------> profile-after-change");
+
+          var os = Components.classes["@mozilla.org/observer-service;1"]
+                             .getService(Components.interfaces.nsIObserverService);
+
+          os.addObserver(this, "http-on-modify-request", false);
+          return;
+      }
+  },
+
+  QueryInterface: function (iid) {
+        if (iid.equals(Components.interfaces.nsIObserver) ||
+            iid.equals(Components.interfaces.nsISupports))
+            return this;
+
+        Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+        return null;
+    },
+};
+
+var myModule = {
+    registerSelf: function (compMgr, fileSpec, location, type) {
+
+        var compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
+        compMgr.registerFactoryLocation(this.myCID,
+                                        this.myName,
+                                        this.myProgID,
+                                        fileSpec,
+                                        location,
+                                        type);
+
+
+          LOG("----------------------------> registerSelf");
+
+        var catMgr = Components.classes["@mozilla.org/categorymanager;1"].getService(Components.interfaces.nsICategoryManager);
+        catMgr.addCategoryEntry("app-startup", this.myName, this.myProgID, true, true);
+    },
+
+
+    getClassObject: function (compMgr, cid, iid) {
+
+          LOG("----------------------------> getClassObject");
+
+        return this.myFactory;
+    },
+
+    myCID: Components.ID("{9cf5f3df-2505-42dd-9094-c1631bd1be1c}"),
+
+    myProgID: "@dougt/myHTTPListener;1",
+
+    myName:   "Simple HTTP Listener",
+
+    myFactory: {
+        QueryInterface: function (aIID) {
+            if (!aIID.equals(Components.interfaces.nsISupports) &&
+                !aIID.equals(Components.interfaces.nsIFactory))
+                throw Components.results.NS_ERROR_NO_INTERFACE;
+            return this;
+        },
+
+        createInstance: function (outer, iid) {
+
+          LOG("----------------------------> createInstance");
+
+          return new myHTTPListener();
+        }
+    },
+
+    canUnload: function(compMgr) {
+        return true;
+    }
+};
+
+function NSGetModule(compMgr, fileSpec) {
+    return myModule;
+}
+
+ +

Privacy and security good practice

+ +

A use case for setting specific a HTTP request header is to have a specific web site be able to check if a specific plugin / addon / extension is installed.

+ +

The good practice is not to have this specific HTTP header (for example "X-site.net-extension") sent all the time but only when doing requests with this specific web sites. By not advertising to all sites what extensions are installed this improves both privacy (this makes it harder to track a user known by his set of plugins, addons and extensions) and security (some plugins, addons and extensions may be known to have flaws by attackers).

+ +

With this privacy and security addition the code to use becomes:

+ +
 observe: function(subject, topic, data)
+  {
+    if (topic == "http-on-modify-request") {
+      var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
+      if (/site.net/.test(httpChannel.originalURI.host)) {
+        httpChannel.setRequestHeader("X-Hello", "World", false);
+      }
+    }
+  },
+
diff --git a/files/zh-cn/mozilla/tech/xpidl/index.html b/files/zh-cn/mozilla/tech/xpidl/index.html new file mode 100644 index 0000000000..c976d0bae9 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpidl/index.html @@ -0,0 +1,502 @@ +--- +title: XPIDL +slug: Mozilla/Tech/XPIDL +tags: + - XPCOM + - xpidl +translation_of: Mozilla/Tech/XPIDL +--- +

 

+

XPIDL 是一个用于指定 XPCOM 接口类的接口描述语言

+

Interface Description Languages (IDL) are used to describe interfaces in a language- and machine-independent way. IDLs make it possible to define interfaces which can then be processed by tools to autogenerate language-dependent interface specifications. XPIDL is expected to converge towards WebIDL in the future.

+
+

Note: Starting in {{Gecko("9.0")}}, the older xpidl utility, which was previously used to generate C++ header files, typelib information, and so forth has been replaced withpyxpidl in the Gecko SDKpyxpidl has been used for some time now, but now the older tool has been fully retired.

+
+

Writing XPIDL interface files

+

XPIDL closely resembles OMG IDL, with extended syntax to handle IIDs and additional types. Some examples are in the {{Source("xpcom/base")}} and {{Source("xpcom/ds")}} directories of the Mozilla tree.

+ +

Explanation of IDL semantics

+

A full guide to the syntax can be found at XPIDL:Syntax, which is written in an ABNF form.

+

An xpidl file is essentially just a series of declarations. At the top level, we can define typedefs, native types, or interfaces. Interfaces may furthermore contain typedefs, natives, methods, constants, or attributes. Most declarations can have properties applied to them.

+

Types

+

There are three ways to make types: a typedef, a native, or an interface. In addition, there are a few built-in native types. The built-in native types are those listed under the type_spec production above. The following is the correspondence table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Table 1: Standard IDL types
IDLC++ in parameterC++ out parameterJS typeNotes
booleanboolbool *boolean 
charcharchar *stringOnly chars in range \u0000-\u00ff permitted
doubledoubledouble *number 
floatfloatfloat *number 
longint32_tint32_t *number 
long longint64_tint64_t *number 
octetuint8_tuint8_t *number 
shortint16_tint16_t *number 
stringconst char *char **stringOnly chars in range \u0000-\u00ff permitted
unsigned longuint32_tuint32_t *number 
unsigned long longuint64_tuint64_t *number 
unsigned shortuint16_tuint16_t *number 
wcharPRUnicharPRUnichar *stringFull Unicode set permitted
wstringconst PRUnichar *PRUnichar **stringFull Unicode set permitted
+

In addition to this list, nearly every IDL file includes nsrootidl.idl in some fashion, which also defines the following types:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Table 2: Types provided by nsrootidl.idl
IDL typedefC++ in parameterC++ out parameterJS typeNotes
PRTime(XPIDL unsigned long long typedef, 64 bits)numberPRTime is in microseconds, while JS date assumes time in milliseconds
nsresult(XPIDL unsigned longtypedef, 32 bits)number 
nsrefcnt(XPIDL unsigned longtypedef, 32 bits)number 
size_t(XPIDL unsigned longtypedef, 32 bits)number 
voidPtrvoid *void *not allowed 
charPtrchar *char **not allowed 
unicharPtrPRUnichar *PRUnichar **not allowed 
nsIDRefconst nsID &nsID *? 
nsIIDRefconst nsIID &nsIID *? 
nsCIDRefconst nsCID &nsCID *? 
nsIDPtrconst nsID *nsID **? 
nsIIDPtrconst nsIID *nsIID **? 
nsCIDPtrconst nsCID *nsCID **? 
nsIIDconst nsIIDnsIID *? 
nsIDconst nsIDnsID *? 
nsCIDconst nsCIDnsCID *? 
nsQIResultvoid *void **objectShould only be used with methods that act like QueryInterface
DOMStringconst nsAString &nsAString &stringFull Unicode set permitted
AUTF8Stringconst nsACString &nsACString &stringFull Unicode set permitted (translated to UTF-8)
ACStringconst nsACString &nsACString &stringOnly chars in range \u0000-\u00ff permitted
AStringconst nsAString &nsAString &stringFull Unicode set permitted
jsvalconst jsval &jsval *anything 
jsidjsidjsid *not allowed 
+

Typedefs in IDL are basically as they are in C or C++: you define first the type that you want to refer to and then the name of the type. Types can of course be one of the fundamental types, or any other type declared via a typedef, interface, or a native type.

+

Native types are types which correspond to a given C++ type. Most native types are not scriptable: if it is not present in the list above, then it is certainly not scriptable (some of the above, particularly jsid, are not scriptable).

+

The contents of the parentheses of a native type declaration (although native declarations without parentheses are parsable, I do not trust that they are properly handled by the xpidl handlers) is a string equivalent to the C++ type. XPIDL itself does not interpret this string, it just literally pastes it anywhere the native type is used. The interpretation of the type can be modified by having properties on the native declaration:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Table 3: Native type definitions
astringThis is an nsAString declaration. Overrides native string.
cstringThis is an nsACString declaration. Overrides native string.
domstringThis is an nsAString declaration. Overrides native string.
jsvalThis type gets const when an in type. Special in typelib.
nsidThis type gets const when an in type. Special in typelib.
ptrThe type is really (native str)*
refThe type is really (native str)&
utf8stringThis is an nsACString declaration whose text is UTF-8.
+

As far as I can tell, these properties also apply to typedefs. Need to verify.

+

Constants

+

Constants are technically legal at the top level, but xpidl I forbids them from being placed there; instead, they must be in an interface. The only constants supported are those which become integer types when compiled to source code; string constants and floating point constants, though parseable, cannot be made into a header or xpt file.

+

Constants are emitted in header files using anonymous enums, although there is an outstanding patch that combines adjacent constants into the same anonymous enums to quiet enum mismatch warnings.

+

Interfaces

+

Specifying interfaces is the primary purpose of using xpidl. Interfaces are basically a collection of constants, methods, and attributes; in Mozilla, these are the primary ways in which JavaScript code can interact with native C++ code. Furthermore, interfaces can also inherit from another interface. Every interface should inherit nsISupports in some fashion. However, it is generally not recommended to have a chain of interfaces inheriting from each other if you intend to have a chain of implementations for each interface, as it can cause problems in C++ code.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Table 4: Basic interface attributes
AttributeInterpretation
uuid(12345678-fedc-ba98-7654-0123456789ab)This is the internal way this interface is accessed; it must be unique, and the uuid must be changed anytime any part of the interface or its ancestors are changed. For instructions on how to generate an UUID see Generating GUIDs.
builtinclassJavaScript classes are forbidden from implementing this interface. All children must also be marked with this property.
functionThe JavaScript implementation of this interface may be a function that is invoked on property calls instead of an object with the given property
scriptableThis interface is usable by JavaScript classes. Must inherit from ascriptable interface.
deprecatedThis interface should no longer be used. The compiler will emit warnings if you attempt to use this.
+

Methods and attributes

+

Interfaces declare a series of attributes and methods. Attributes in IDL are akin to JavaScript properties, in that they are a getter and (optionally) a setter pair. In JavaScript contexts, attributes are exposed as a regular property access, while native code sees attributes as a Get and possibly a Set method.

+

Attributes can be declared readonly, in which case setting causes an error to be thrown in script contexts and native contexts lack the Set method, by using the "readonly" keyword.

+

To native code, on attribute declared 'attribute type foo;' is syntactic sugar for the declaration of two methods 'type getFoo();' and 'void setFoo(in type foo);'. If foo were declared readonly, the latter method would not be present. Attributes support all of the properties of methods with the exception of optional_argc, as this does not make sense for attributes.

+

There are some special rules for attribute naming. As a result of vtable munging by the MSVC++ compiler, an attribute with the name `IID' is forbidden. In addition, any attribute whose name matches the regex /^[a-z]{2,3}I[A-Z][a-z]/ is emitted with a warning, as its name looks like an nsIInterface or a mozIInterface declaration. Also like methods, if the first character of an attribute is lowercase in IDL, it is made uppercase in native code only.

+

Methods define a return type and a series of in and out parameters. When called from a JavaScript context, they invocation looks as it is declared for the most part; some parameter properties can adjust what the code looks like. The calls are more mangled in native contexts.

+

An important attribute for methods and attributes is scriptability. A method or attribute is scriptable if it is declared in a scriptable interface and it lacks anoscript or notxpcom property. Any method that is not scriptable can only be accessed by native code. However, scriptable methods must contain parameters and a return type that can be translated to script: any native type, save those declared with an nsiddomstringutf8stringcstringastring, or jsval property, may not be used in a scriptable method or attribute. An exception to the above rule is if the parameter has the iid_is property (a special case for some QueryInterface-like operations). In general, this means that the only usable native types are those declared in nsrootidl.idl (see above).

+

Methods and attributes are mangled on conversion to native code. If a method is declared notxpcom, the mangling of the return type is prevented, so it is called mostly as it looks. Otherwise, the return type of the native method is nsresult, and the return type acts as a final outparameter if it is not void. The name is translated so that the first character is unconditionally uppercase; subsequent characters are unaffected. However, the presence of the binaryname property allows the user to select another name to use in native code (to avoid conflicts with other functions). For example, the method '[binaryname(foo)] void bar();' becomes 'nsresult Foo()' in native code (note that capitalization is still applied). However, the capitalization is not applied when using binaryname with attributes; i.e., [binaryname(foo)] readonly attribute Quux bar; becomes Getfoo(Quux**) in native code. Attributes named 'IID' and methods named 'GetIID' are forbidden, although this is checked before binaryname conversion.

+

The implicit_jscontext and optional_argc parameters are properties which help native code implementations determine how the call was made from script. Ifimplicit_jscontext is present on a method, then an additional JSContext *cx parameter is added just after the regular list which receives the context of the caller. If optional_argc is present, then an additional uint8_t _argc method is added at the end which receives the number of optional arguments that were actually used (obviously, you need to have an optional argument in the first place). Note that if both properties are set, the JSContext *cx is added first, followed by the uint8_t _argc, and then ending with return value parameter. Finally, as an exception to everything already mentioned, for attribute getters and setters the JSContext *cx comes before any other arguments.

+

In addition, methods and attributes can be both marked as deprecated with thedeprecated property, which causes compilers to emit deprecation usage warnings. Note that this is only verified in native code and not script code.

+

The final native-only property is nostdcall. Normally, declarations are made in the stdcall ABI on Windows to be ABI-compatible with COM interfaces. Any non-scriptable method or attribute with nostdcall instead uses the thiscall ABI convention. Methods without this property generally use NS_IMETHOD in their declarations and NS_IMETHODIMP in their definitions to automatically add in the stdcall declaration specifier on requisite compilers; those that use this method may use a plain `nsresult' instead.

+

Source and Binary Compatibility

+

Some consumers of IDL interfaces create binary plugins that expect the interfaces to be stored in a specific way in memory. In other words, some changes made to IDL interfaces require the author to modify the unique identifier (IID) in order to make it clear to plugins that utilize these interfaces that they have changed, and thus their plugin must be recompiled.

+

Common changes to an interface, such as changes to a method signature, number of arguments, and number or type of attributes, automatically require an IID change. In addition, some changes to interface attributes require that an IID be changed, as well. When a change to an interface made by an XPIDL developer requires that third-party binary addons be recompiled, we say that it affects binary compatibility. When a change to an interface made by an XPIDL developer requires that third-party binary addons change their source code, we say that it affects source compatibility. In table 5, the columns on the far right indicate whether changes to a specific attribute affect source compatibility, binary compatibility, or both.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Table 5: Optional interface attributes
AttributeValid for methodsValid for attributesEffectChanges Source Compatibility?Changes Binary Compatibility?
binaryname(foo)YYResults in the C++ method being called "Foo"YN
deprecatedYYEmits a compiler warning if used in C++ codeNN
implicit_jscontextYYAdds an additionalJSContext *cx parameter to the C++ implementationYY
noscriptYYProhibits the method/attribute from being accessible in JS codeNN
nostdcallYYThe C++ implementation uses virtual nsresultinstead ofNS_IMETHOD/NS_IMETHODIMPYY
notxpcomYYThe C++ implementation does not return nsresult(implies noscript)YY
optional_argcYNAdds an additional uint8_t _argc parameter to the C++ implementationYY
+

Method parameters

+

Each method parameter can be specified in one of three modes: inout, or inout. An out parameter is essentially an auxiliary return value, although these are moderately cumbersome to use from script contexts and should therefore be avoided if reasonable. An inout parameter is an in parameter whose value may be changed as a result of the method; these parameters are rather annoying to use and should generally be avoided if at all possible.

+

Out and inout parameters are reflected as objects having the .value property which contains the real value of the parameter; it is not initialized in the case of out parameters and is initialized to the passed-in-value for inout parameters. The script code would need to set this property to assign a value to the parameter. Regular in parameters are reflected more or less normally, with numeric types all representing numbers, booleans as true or false, the various strings (including AString et al) as a JavaScript string, and nsid types as a Components.ID instance. In addition, the jsval type is translated as the appropriate JavaScript value (since a jsval is the internal representation of all JavaScript values), and objects that are marked nsIVariant have their
+ types automatically boxed and unboxed as appropriate.

+

The equivalent representations of all IDL types in native code is given in the earlier tables; parameters of type inout follow their out form. Native code should pay particular attention to not passing in null values for out parameters (although some parts of the codebase are known to violate this, it is strictly enforced at the JS<->native barrier), and also ensuring that boolean types only receive values of 0 (false) or 1 (true).

+

Representations of types additionally depend on some of the many types of properties they may have. The array property turns the parameter into an array; the parameter must also have a corresponding size_is property whose argument is the parameter that has the size of the array. In native code, the type gains another pointer indirection, and JavaScript arrays are used in script code. Script code callers can ignore the value of array parameter, but implementors must still set the values appropriately.

+

The const and shared properties are special to native code. As its name implies, the const property makes its corresponding argument const. The shared property is only meaningful for out or inout parameters and it means that the pointer value should not be freed by the caller. Only the string, wstring, and native types having the nsid, domstring, utf8string, cstirng, astring, or jsval properties may be declared shared, and, even then, only if the parameter is not an array parameter. The shared property also makes its corresponding argument const.
+
+ The retval property indicates that the parameter is actually acting as the return value, and it is only the need to assign properties to the parameter that is causing it to be specified as a parameter. It has no effect on native code, but script code uses it like a regular return value. Naturally, a method which contains a retval parameter must be declared void, and the parameter itself must be an out parameter and the last parameter.

+

Other properties are the optional and iid_is property. The optional property indicates that script code may omit the property without problems; all subsequent parameters must either by optional themselves or the retval parameter. Note that optional out parameters still pass in a variable for the parameter, but its value will be ignored. The iid_is parameter indicates that the real IID of an nsQIResult parameter may be found in the corresponding parameter, to allow script code to automatically unbox the type.

+

Not all type combinations are possible. Native types with the various string properties are all forbidden from being used as an inout parameter or as an array parameter. In addition, native types with the nsid property but lacking either a ptr or ref property are forbidden unless the method is notxpcom and it is used as an inparameter.

+

For types that reference heap-allocated data (strings, arrays, interface pointers, etc), you must follow the XPIDL data ownership conventions in order to avoid memory corruption and security vulnerabilities:

+ +

Resources (mostly outdated)

+ diff --git a/files/zh-cn/mozilla/tech/xpidl/syntax/index.html b/files/zh-cn/mozilla/tech/xpidl/syntax/index.html new file mode 100644 index 0000000000..daca23f49f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpidl/syntax/index.html @@ -0,0 +1,127 @@ +--- +title: Syntax +slug: Mozilla/Tech/XPIDL/Syntax +tags: + - xpidl +translation_of: Mozilla/Tech/XPIDL/Syntax +--- +

Status of this document

+ +

This is a partial reverse-engineering of the libIDL source code's parser, limited mostly to the subset of functionality that is supported by the Mozilla xpidl binary.

+ +

Purpose of this document

+ +

This document is not an introduction to XPIDL or IDL in general. It is more focused on XPIDL syntax and grammar. See XPIDL Main Page for more links and introductory content.

+ +

Simplifications, conventions and notation

+ +

The syntax is specified according to ABNF as defined by RFC 5234, although a few productions use prose for clarity of understanding.

+ +

Lexically, tokens are delimited by whitespace (defined here as spaces, tabs, vertical tabs, form feeds, line feeds, and carriage returns, or [ \t\v\f\r\n] in regular expression form). LibIDL only considers a single line feed as a newline, and not carriage returns (although xpidl begs to differ). Additionally, the use of both C-style (/* ... */) and C++-style (// ... end-of-line) comments are permitted between any two tokens.

+ +

Some productions can only occur at the beginning of lines; to simplify the grammar, I will not mention them in the grammar, especially since they are handled as a preprocessing step before the IDL source code is actually parsed.

+ +
    +
  1. A `%{' that appears at the beginning of a line is the start of a raw code fragment, which extends until the end of a line that begins with `%}'. Text inside raw code fragments are not otherwise parsed by xpidl directly. This may be followed by the language, as in `%{C++', to output the raw fragment only in the specified language.
  2. +
  3. A `#include "file"' line instructs the xpidl processor to include that file in the same sense that the C preprocessor includes a file. Note that includes within comments or raw code fragments are not processed by xpidl. Unlike the C preprocessor, when a file is included multiple times, it acts as if the subsequent includes did not happen; this prevents the need for include guards.
  4. +
+ +

XPIDL Syntax (ABNF)

+ +

The root production here is idl_file.

+ +

idl_file = 1*definition
+ definition = [type_decl / const_decl / interface] ";"
+ interface = [prop_list] "interface" ident [[inheritance] "{" *(ifacebody) "}"]
+ inheritance = ":" *(scoped_name ",") scoped_name]
+ ifacebody = [type_decl / op_decl /attr_decl / const_decl] ";" / codefrag
+
+ type_decl = [prop_list] "typedef" type_spec *(ident ",") ident
+ type_decl /= [prop_list] "native" ident [parens]
+ const_decl = "const" type_spec ident "=" expr
+ op_decl = [prop_list] (type_spec / "void") parameter_decls raise_list
+ parameter_decls = "(" [*(param_decl ",") param_decl] ")"
+ param_decl = [prop_list] ("in" / "out" / "inout") type_spec ident
+ attr_decl = [prop_list] ["readonly"] "attribute" type_spec *(ident ",") ident
+
+ ; Descending order of precedence
+ expr /= expr ("|" / "^" / "&") expr ; Unequal precedence "|" is lowest
+ expr /= expr ("<<" / ">>") expr
+ expr /= expr ("+" / "-") expr
+ expr /= expr ("*" / "/" / "%") expr
+ expr /= ["-" / "+" / "~"] (scoped_name / literal / "(" expr ")" )
+
+ ; Numeric literals: quite frankly, I'm sure you know how these kinds of
+ ; literals work, and these are annoying to specify in ABNF.
+ literal = octal_literal / decimal_literal / hex_literal / floating_literal
+ literal /= string_literal / char_literal
+ literal /= "TRUE" / "FALSE"
+
+ ; In regex: /"[^"\n]*["\n]/. Yes, newline terminates.
+ string_literal = 1*(%x22 *(any char except %x22 or %x0a) (%x22 / %x0a))
+ ; Same as above, but s/"/'/g
+ char_literal = 1*(%x27 *(any char except %x27 or %x0a) (%x27 / %x0a))
+
+ type_spec = "float" / "double" / "string" / "wstring"
+ type_spec /= ["unsigned"] ("short" / "long" / "long" "long")
+ type_spec /= "char" / "wchar" / "boolean" / "octet"
+ type_spec /= scoped_name
+
+ prop_list = "[" *(property ",") property "]"
+ property = ident [parens]
+ raise_list = "raises" "(" *(scoped_name) ",") scoped_name ")"
+
+ scoped_name = *(ident "::") ident / "::" ident

+ ; In regex: [A-Za-z_][A-Za-z0-9_]*; identifiers beginning with _ cause warnings
+ ident = (%x41-5a / %x61-7a / "_") *(%x41-5a / %x61-7a / %x30-39 / "_")
+ parens = "(" 1*(any char except ")") ")"

+ +

Functionality not used in xpidl

+ +

The libIDL parser we use is more powerful than xpidl itself can understand. The following is a list of potential features which are parseable but may not result in expected code:

+ + + +

Pyxpidl syntax

+ +

idlfile = *(CDATA / INCLUDE / interface / typedef / native)
+
+ typedef = "typedef" IDENTIFER IDENTIFIER ";"
+ native = [attributes] "native" IDENTIFIER "(" NATIVEID ")"
+ interface = [attributes] "interface" IDENTIFIER" [ifacebase] [ifacebody] ";"
+ ifacebase = ":" IDENTIFIER
+ ifacebody = "{" *(member) "}"
+
+ member = CDATA / "const" IDENTIFIER IDENTIFIER "=" number ";"
+ member /= [attributes] ["readonly"] "attribute" IDENTIFIER IDENTIFER ";"
+ member /= [attributes] IDENTIFIER IDENTIFIER "(" paramlist ")" raises ";"
+ paramlist = [param *("," param)]
+ raises = ["raises" "(" IDENTIFIER *("," identifier) ")"]
+ attributes = "[" attribute *("," attribute) "]"
+ attribute = (IDENTIFIER / CONST) ["(" (IDENTIFIER / IID) ")"]
+ param = [attributes] ("in" / "out" / "inout") IDENTIFIER IDENTIFIER
+
+ number = NUMBER / IDENTIFIER
+ number /= "(" number ")"
+ number /= "-" number
+ number /= number ("+" / "-" / "*") number
+ number /= number ("<<" / >>") number
+ number /= number "|" number
+
+ ; Lexical tokens, I'm going to specify these in regex form
+ NUMBER = /-?\d+|0x[0-9A-Fa-f]+/
+ CDATA = /%\{[ ]*C\+\+[ ]*\n(.*?\n?)%\}[ ]*(C\+\+)?/s
+ INCLUDE = /\#include[ \t]+"[^"\n]+"/
+ NATIVEID = /[^()\n]+(?=\))/
+ IID = /[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}/
+ IDENTIFIER = /unsigned long long|unsigned short|unsigned long|long long|[A-Za-z][A-Za-z_0-9]*/

diff --git a/files/zh-cn/mozilla/tech/xpidl/xpidl/index.html b/files/zh-cn/mozilla/tech/xpidl/xpidl/index.html new file mode 100644 index 0000000000..57838ceae4 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xpidl/xpidl/index.html @@ -0,0 +1,58 @@ +--- +title: xpidl +slug: Mozilla/Tech/XPIDL/xpidl +tags: + - 'Developing_Mozilla:Tools' + - Tools + - xpidl + - 开发Mozilla + - 所有分类 +translation_of: Mozilla/Tech/XPIDL/xpidl +--- +

 

+

xpidl 是一个基于 XPIDL 接口描述文件, 用于生成 XPCOM 接口信息的工具. 它会自动生成:

+ +

编译 xpidl

+

xpidl 的实现是基于 Gnome 工程中的 libIDL idl 编译器. libIDL 编译器依赖的 glib 库也来自于 gnome 工程. xpidl 编译器现在是 Mozilla 整个编译过程中必须包含的一分子, 我们用它来生成 XPCOM 组件的头文件. 如何得到 libIDL 和 glib 请看 Build Documentation.

+

Unix: 如果你仅仅想编译 xpidl 本身, 你只需要编译很少一部分目录. 在获取 mozilla 源码后, 执行 'configure', 然后以下面的命令就可以在 dist/bin 目录下编译出 xpidl:

+
make -C config
+make -C nsprpub
+make -C xpcom/typelib
+
+

使用 xpidl

+

xpidl build page 有关于如何添加一个 XPIDL 文件到 Mozilla 的编译过程的说明. xpidl 也可以在 Unix 和 Windows 下以命令行的形式执行:

+
Usage: ./xpidl -m mode [-w] [-v] [-t version number]
+          [-I path] [-o basename | -e filename.ext] filename.idl
+       -a emit annotations to typelib
+       -w turn on warnings (recommended)
+       -v verbose mode (NYI)
+       -t create a typelib of a specific version number
+       -I add entry to start of include path for ``#include "nsIThing.idl"
+       -o use basename (e.g. ``/tmp/nsIThing) for output
+       -e use explicit output filename
+       -m specify output mode:
+          header        Generate C++ header            (.h)
+          typelib       Generate XPConnect typelib     (.xpt)
+          doc           Generate HTML documentation    (.html)
+          java          Generate Java interface        (.java)
+
+

资源

+ +

Flames to docs mike+mozilla@meer.net & mang@subcarrier.org

+

 

+
+

原始文档信息

+ +
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/acceltext/index.html b/files/zh-cn/mozilla/tech/xul/attribute/acceltext/index.html new file mode 100644 index 0000000000..77bc1dccbe --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/acceltext/index.html @@ -0,0 +1,23 @@ +--- +title: acceltext +slug: Mozilla/Tech/XUL/Attribute/acceltext +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/acceltext +--- +
+ « XUL Reference home
+
+
+ acceltext
+
+ Type: + + string +
+
+ Text that appears beside beside the menu label to indicate the shortcut key (accelerator key) to use to invoke the command. If this value is set, it overrides an assigned key set in the key attribute. This attribute does not apply to menus directly on the menubar.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/accesskey/index.html b/files/zh-cn/mozilla/tech/xul/attribute/accesskey/index.html new file mode 100644 index 0000000000..e6697bda0d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/accesskey/index.html @@ -0,0 +1,43 @@ +--- +title: accesskey +slug: Mozilla/Tech/XUL/Attribute/accesskey +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/accesskey +--- +
« XUL Reference home
+ +
+
+
Attribute of: button, checkbox, caption, description, label, listitem, menu, menuitem, menulist, tab, radio, toolbarbutton, textbox (Firefox autocomplete)
+
+
+ +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/activetitlebarcolor/index.html b/files/zh-cn/mozilla/tech/xul/attribute/activetitlebarcolor/index.html new file mode 100644 index 0000000000..5352f49114 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/activetitlebarcolor/index.html @@ -0,0 +1,19 @@ +--- +title: activetitlebarcolor +slug: Mozilla/Tech/XUL/Attribute/activetitlebarcolor +translation_of: Archive/Mozilla/XUL/Attribute/activetitlebarcolor +--- +
+ « XUL Reference home
+
+
+ activetitlebarcolor
+
+ Type: color string
+
+ Specify background color of the window's titlebar when it is active (foreground). Moreover this hides separator between titlebar and window contents. This only affects Mac OS X.
+
+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/align/index.html b/files/zh-cn/mozilla/tech/xul/attribute/align/index.html new file mode 100644 index 0000000000..f940cbdbb3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/align/index.html @@ -0,0 +1,54 @@ +--- +title: align +slug: Mozilla/Tech/XUL/Attribute/align +tags: + - Reference + - XUL +translation_of: Archive/Mozilla/XUL/Attribute/align +--- +
« XUL Reference home
+ +
+
align
+
Type: one of the values below
+
The align attribute specifies how child elements of the box are aligned, when the size of the box is larger than the total size of the children.
+ 当box的尺寸大于全部子元素的尺寸时,align属性指定box元素的对齐方式。 +
    +
  • For boxes that have horizontal orientation, it specifies how its children will be aligned vertically.
  • +
  • 当box设置水平排列,它指定子元素如何垂直对齐。
  • +
  • For boxes that have vertical orientation, it specifies how its children will be aligned horizontally.
  • +
  • 当box设置垂直排列,它指定子元素如何水平对齐
  • +
+
+
+
+
start
+
Child elements are aligned starting from the left or top edge of the box. If the box is larger than the total size of the children, the extra space is placed on the right or bottom side.
+ 子元素从box的左边或顶部开始排列。如果box大于全部子元素的总和,多出的空间在右边或底部。
+
center
+
Extra space is split equally along each side of the child elements, resulting in the children being placed in the center of the box.
+ 多出的空间在子元素的周围,使子元素放置在box的中间。
+
end
+
Child elements are placed on the right or bottom edge of the box. If the box is larger than the total size of the children, the extra space is placed on the left or top side.
+ 子元素从box的右边或底部开始排列。如果box大于全部子元素的总和,多出的空间在左边或顶部部。
+
baseline
+
This value applies to horizontally oriented boxes only. It causes the child elements to be aligned so that their text labels are lined up.
+ 这个值只适用于水平方向的box元素。它让子元素的文本标签成一条直线。
+
stretch
+
This is the default value. The child elements are stretched to fit the size of the box. For a horizontal box, the children are stretched to be the height of the box. For a vertical box, the children are stretched to be the width of the box. If the size of the box changes, the children stretch to fit. Use the flex attribute to create elements that stretch in the opposite direction.
+ 这是默认值。拉伸子元素来填充box。在水平的box元素中,子元素在高度上被拉伸。在垂直的box元素中,子元素在宽度上被拉伸。如果box元素尺寸改变,子元素也随之改变。使用flex属性创建的元素在相反方向被拉伸。
+
left
+
The elements are aligned on their left edges.
+ 元素左边缘对齐。
+
center
+
The elements are centered horizontally.
+ 元素水平居中。
+
right
+
The elements are aligned on their right edges.
+ 元素右边缘对齐。
+
+
+
The pack attribute is related to the alignment but is used to specify the position in the opposite direction. You can also specify the value of align using the style property -moz-box-align.
+ pack也是有关对齐的属性,但是指定相反方向的位置。你也可以在style中使用对齐的方式-moz-box-align
+
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/allowevents/index.html b/files/zh-cn/mozilla/tech/xul/attribute/allowevents/index.html new file mode 100644 index 0000000000..5d17570f74 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/allowevents/index.html @@ -0,0 +1,30 @@ +--- +title: allowevents +slug: Mozilla/Tech/XUL/Attribute/allowevents +tags: + - XUL Attributes + - XUL Reference +translation_of: Archive/Mozilla/XUL/Attribute/allowevents +--- +
« XUL Reference home
+ +
+
allowevents
+
Type: + boolean
+
+ 类型:boolean
+
If true, events are passed to children of the element. Otherwise, events are passed to the element only.
+ 如果为真,事件向子元素传递。否则,事件只传递到当前元素。
+
+ +
+

On listitem and titlebar elements, mouse events normally do not get sent to their children; instead they are retargeted to the listitem and titlebar element itself. This means that elements placed inside a listitem do not respond to events, and instead clicking the mouse simply selects that item within the list. By setting the allowevents attribute to true, this special behavior is disabled, and the events are targeted the same as other elements.
+ 在 listitemtitlebar 元素中,鼠标事件通常不发送给子元素;相反它们重定向到 listitemtitlebar 元素本身。这意味着,放置在listitem内部的元素并不响应事件,而点击鼠标仅仅是选择在列表中的元素。当设置allowevents属性为真时,这种特殊的响应被禁止,事件则被定向到其他相同的元素。

+ +

For menu, menuseparator, menuitem and treecol elements, as well as menu buttons, and the popup datepicker, mouse events are also retargeted to the element itself. However, the allowevents attribute is handled in a different way. Instead, the allowevents may be set to true on a descendant instead. This does the same thing in that it allows events to be targeted normally, but allows this to be different for each descendant.

+ +

This behavior is used for menus, for instance, to allow a menu button to behave as a menu when clicking on it, yet have part of the menu behave as a button. For the latter, the allowevents attribute is set to true to have a click on the child button receive events instead of targeting all events at the menu.

+
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/allownegativeassertions/index.html b/files/zh-cn/mozilla/tech/xul/attribute/allownegativeassertions/index.html new file mode 100644 index 0000000000..51c8c4e222 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/allownegativeassertions/index.html @@ -0,0 +1,18 @@ +--- +title: allownegativeassertions +slug: Mozilla/Tech/XUL/Attribute/allownegativeassertions +translation_of: Archive/Mozilla/XUL/Attribute/allownegativeassertions +--- +
« XUL Reference home
+ +
+
allownegativeassertions
+
Type: boolean
+ 类型:布尔类型
+
Valid on any element that has a datasources attribute. When multiple datasources are used, one may override an assertion from another. This attribute, if true, which is the default, allows a datasource to negate an earlier assertion.
+ 适用于任何有 datasources 属性的元素。当使用多个数据源,一个数据源可以指定覆盖另一个。这个属性,如果为真,这是默认值,允许一个数据源覆盖之前的数据源。
+
+ +
+

+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/autocheck/index.html b/files/zh-cn/mozilla/tech/xul/attribute/autocheck/index.html new file mode 100644 index 0000000000..edd3c5e9ed --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/autocheck/index.html @@ -0,0 +1,24 @@ +--- +title: autocheck +slug: Mozilla/Tech/XUL/Attribute/autocheck +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/autoCheck +--- +
« XUL Reference home
+ +
+
autocheck
+
类型: + boolean +
+
如果此属性为 true,或空白, 每次点击按钮时,此按钮的状态检查都会被执行一次。如果此属性为false, 检查会手动的被拒绝。当autocheck值为true的时候,按钮将会变为多选框或者单选框。
+
+ +
+

See also

+ +

autoCheck

+
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/autoscroll/index.html b/files/zh-cn/mozilla/tech/xul/attribute/autoscroll/index.html new file mode 100644 index 0000000000..9bc1366f88 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/autoscroll/index.html @@ -0,0 +1,12 @@ +--- +title: autoscroll +slug: Mozilla/Tech/XUL/Attribute/autoscroll +translation_of: Archive/Mozilla/XUL/Attribute/autoscroll +--- +
« XUL Reference home
+ +
+
autoscroll
+
Type: boolean
+
Set to false to disable autoscroll for this browser. If this attribute is set to true or omitted, autoscroll will be enabled or depending on the user preference general.autoScroll.
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/buttonaccesskeyaccept/index.html b/files/zh-cn/mozilla/tech/xul/attribute/buttonaccesskeyaccept/index.html new file mode 100644 index 0000000000..4e42f14bad --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/buttonaccesskeyaccept/index.html @@ -0,0 +1,20 @@ +--- +title: buttonaccesskeyaccept +slug: Mozilla/Tech/XUL/Attribute/buttonaccesskeyaccept +translation_of: Archive/Mozilla/XUL/Attribute/buttonaccesskeyaccept +--- +
+ « XUL Reference home
+
+
+ buttonaccesskeyaccept
+
+ Type: string
+
+ The access key to use for the "accept" button.
+
+

 

+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra1/index.html b/files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra1/index.html new file mode 100644 index 0000000000..1de5913a9b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra1/index.html @@ -0,0 +1,19 @@ +--- +title: buttonlabelextra1 +slug: Mozilla/Tech/XUL/Attribute/buttonlabelextra1 +translation_of: Archive/Mozilla/XUL/Attribute/buttonlabelextra1 +--- +
+ « XUL Reference home
+
+
+ buttonlabelextra1
+
+ Type: string
+
+ The label to appear on the first extra button.
+
+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra2/index.html b/files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra2/index.html new file mode 100644 index 0000000000..1a7f700eac --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/buttonlabelextra2/index.html @@ -0,0 +1,19 @@ +--- +title: buttonlabelextra2 +slug: Mozilla/Tech/XUL/Attribute/buttonlabelextra2 +translation_of: Archive/Mozilla/XUL/Attribute/buttonlabelextra2 +--- +
+ « XUL Reference home
+
+
+ buttonlabelextra2
+
+ Type: string
+
+ The label to appear on the second extra button.
+
+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/buttons/index.html b/files/zh-cn/mozilla/tech/xul/attribute/buttons/index.html new file mode 100644 index 0000000000..5759eabd90 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/buttons/index.html @@ -0,0 +1,28 @@ +--- +title: buttons +slug: Mozilla/Tech/XUL/Attribute/buttons +translation_of: Archive/Mozilla/XUL/Attribute/buttons +--- +
+ « XUL Reference
+
+
+ buttons
+
+ 类型: 列表,下面的值用逗号分隔
+
+ 需要显示在对话框上的按钮的一个列表,使用逗号分隔。将按钮放置在合适的位置,将根据用户平台自动执行基本的事件处理。在列表中可以使用以下值: +
    +
  • accept:“确定”按钮,按下按钮时将接受更改。此按钮为默认按钮。
  • +
  • cancel:“取消”按钮,将取消操作。
  • +
  • help:“帮助”按钮,在对话框显示一个“帮助”按钮。
  • +
  • disclosure:“更多信息”按钮,显示一个“more info”按钮。该按钮可能是一个按钮或一个三角形。
  • +
  • extra1:一个可选的额外的按钮。你可以通过buttonlabelextra1 属性设置它的label。
  • +
  • extra2:第二个可选的额外的按钮。你可以通过 buttonlabelextra2 属性设置它的label。
  • +
+
+
+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/checked/index.html b/files/zh-cn/mozilla/tech/xul/attribute/checked/index.html new file mode 100644 index 0000000000..249a1f1ee1 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/checked/index.html @@ -0,0 +1,24 @@ +--- +title: checked +slug: Mozilla/Tech/XUL/Attribute/checked +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/checked +--- +
+ « XUL Reference home
+
+
+ checked
+
+ Type: + + boolean +
+
+ Indicates whether the element is checked or not.
+
+ Use hasAttribute() to determine whether this attribute is set instead of getAttribute().
+
+ For buttons, the type attribute must be set to checkbox or radio for this attribute to have any effect.<magic name="\"PAGENAME\"/"></magic>
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/class/index.html b/files/zh-cn/mozilla/tech/xul/attribute/class/index.html new file mode 100644 index 0000000000..45eb8dbc87 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/class/index.html @@ -0,0 +1,23 @@ +--- +title: class +slug: Mozilla/Tech/XUL/Attribute/class +tags: + - XUL Attributes + - XUL Reference +translation_of: Archive/Mozilla/XUL/Attribute/class +--- +
« XUL Reference home
+ +
+
class
+
Type: + string
+
+ 类型:字符串(string)
+
The style class of the element. Multiple classes may be specified by separating them with spaces.
+ 元素样式类型。多个类可以使用空格分开。
+
+ +
 
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/coalesceduplicatearcs/index.html b/files/zh-cn/mozilla/tech/xul/attribute/coalesceduplicatearcs/index.html new file mode 100644 index 0000000000..01e6ddd51f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/coalesceduplicatearcs/index.html @@ -0,0 +1,17 @@ +--- +title: coalesceduplicatearcs +slug: Mozilla/Tech/XUL/Attribute/coalesceduplicatearcs +tags: + - XUL Attributes + - XUL Reference +translation_of: Archive/Mozilla/XUL/Attribute/coalesceduplicatearcs +--- +
« XUL Reference home
+ +
+
coalesceduplicatearcs
+
Type: boolean
+ 类型:布尔类型(boolean)
+
Valid on any element that has a datasources attribute. When multiple datasources are used, one may override an assertion from another. This attribute, if true, which is the default, allows a datasource to negate an earlier assertion.
+ 任何有 datasources 属性的元素有效。当有多个数据源时使用,可以覆盖另一个声明。这个属性,如果是真,这是默认属性,允许一个数据源取消更早的声明。 
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/collapsed/index.html b/files/zh-cn/mozilla/tech/xul/attribute/collapsed/index.html new file mode 100644 index 0000000000..50d54b771f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/collapsed/index.html @@ -0,0 +1,27 @@ +--- +title: collapsed +slug: Mozilla/Tech/XUL/Attribute/collapsed +translation_of: Archive/Mozilla/XUL/Attribute/collapsed +--- +
« XUL Reference home
+ +
+
collapsed
+
Type: boolean
+ 类型:布尔类型(boolean)
+
If true, then the element is collapsed and does not appear. It is equivalent to setting the CSS visibility property to collapse.
+ 如果是真,那么这个元素可以折叠并且隐藏。相当于设置CSS的 visibility 属性为 collapse。
+
+ +
+

See also
+ 相关参考

+ + + +

+
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/command/index.html b/files/zh-cn/mozilla/tech/xul/attribute/command/index.html new file mode 100644 index 0000000000..75c4957f0e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/command/index.html @@ -0,0 +1,30 @@ +--- +title: command +slug: Mozilla/Tech/XUL/Attribute/command +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/command +--- +
+ « XUL Reference home
+
+
+ command
+
+ Type: + + element id +
+
+ Set to the id of a command element that is being observed by the element.
+
+
+

Example

+
<command id="cmd_openhelp" oncommand="alert('Help');"/>
+<button label="Help" command="cmd_openhelp"/>
+<button label="More Help" command="cmd_openhelp"/>
+
+

See also

+

command element, oncommand and commandset

+
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/container/index.html b/files/zh-cn/mozilla/tech/xul/attribute/container/index.html new file mode 100644 index 0000000000..4b1429ae43 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/container/index.html @@ -0,0 +1,18 @@ +--- +title: container +slug: Mozilla/Tech/XUL/Attribute/container +translation_of: Archive/Mozilla/XUL/Attribute/container +--- +
« XUL Reference home
+ +
+
container
+
Type: boolean
+ 类型:布尔类型(boolean)
+
Set to true if the element is to act as a container which can have child elements. This would be used for folders. This will be set by the template builder as needed.
+ 如果该元素是作为一个容器可以有子元素,设置为真。
+
+ +
+

+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/control/index.html b/files/zh-cn/mozilla/tech/xul/attribute/control/index.html new file mode 100644 index 0000000000..74a0edec5a --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/control/index.html @@ -0,0 +1,23 @@ +--- +title: control +slug: Mozilla/Tech/XUL/Attribute/control +tags: + - XUL Attributes + - XUL Reference +translation_of: Archive/Mozilla/XUL/Attribute/control +--- +
+ « XUL Reference home
+
+
+ control
+
+ Type: element id
+
+ This attribute specifies the id of the element with which the label is associated. When the user clicks on the label, the associated element is given focus.
+ 这个属性定义了元素的id,它与label相关联。当用户点击 label 的时候,相关联的元素将获得焦点。
+
+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/crop/index.html b/files/zh-cn/mozilla/tech/xul/attribute/crop/index.html new file mode 100644 index 0000000000..1ab3f59210 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/crop/index.html @@ -0,0 +1,37 @@ +--- +title: crop +slug: Mozilla/Tech/XUL/Attribute/crop +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/crop +--- +
+ « XUL Reference home
+
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ +
+
+
+ Depending on the platform and theme being used, some elements will have a set maximum width so they will be always appear cropped. If you wish to use the value none and the displayed text is larger than this maximum width, you may be able to use the max-width CSS property (or the maxwidth attribute) to override this size. For example, for a menuitem in a menu you can add the following CSS rule when you want to use the value none:
+
+
menupopup > menuitem, menupopup > menu { max-width: none; }
+
+
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/description/index.html b/files/zh-cn/mozilla/tech/xul/attribute/description/index.html new file mode 100644 index 0000000000..008aa1281c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/description/index.html @@ -0,0 +1,23 @@ +--- +title: description +slug: Mozilla/Tech/XUL/Attribute/description +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/description +--- +
+ « XUL Reference home
+
+
+ description
+
+ Type: + + string +
+
+ Descriptive text to appear in addition to the dialog title.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/dir/index.html b/files/zh-cn/mozilla/tech/xul/attribute/dir/index.html new file mode 100644 index 0000000000..0b4c5c36a4 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/dir/index.html @@ -0,0 +1,39 @@ +--- +title: dir +slug: Mozilla/Tech/XUL/Attribute/dir +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/dir +--- +
+ « XUL Reference home
+
+
+ dir
+
+ Type: + + one of the values below +
+
+ The direction in which the child elements of the element are placed.
+
+
+
+ normal
+
+ For scales, the scale's values are ordered from left to right (for horizontal scales) or from top to bottom (for vertical scales)  For other elements, the elements are placed left to right or top to bottom in the order they appear in the XUL code
+
+ reverse
+
+ For scales, the scale's values are ordered from right to left (for horizontal scales) or from bottom to top (for vertical scales). For other elements, they are placed right to left or bottom to top. This is reverse of the order in which they appear in the XUL code.
+
+ +
+

See also

+ +
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/disabled/index.html b/files/zh-cn/mozilla/tech/xul/attribute/disabled/index.html new file mode 100644 index 0000000000..057bca261d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/disabled/index.html @@ -0,0 +1,38 @@ +--- +title: disabled +slug: Mozilla/Tech/XUL/Attribute/disabled +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/disabled +--- +
« XUL Reference home
+ +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/flex/index.html b/files/zh-cn/mozilla/tech/xul/attribute/flex/index.html new file mode 100644 index 0000000000..7d9954d30a --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/flex/index.html @@ -0,0 +1,23 @@ +--- +title: flex +slug: Mozilla/Tech/XUL/Attribute/flex +tags: + - XUL Attributes + - XUL Reference +translation_of: Archive/Mozilla/XUL/Attribute/flex +--- +
« XUL Reference home
+ +
+
flex
+
Type: string (representing an integer)
+ 类型:字符串 (string) 表示一个整数
+
Indicates the flexibility of the element, which indicates how an element's container distributes remaining empty space among its children. Flexible elements grow and shrink to fit their given space. Elements with larger flex values will be made larger than elements with lower flex values, at the ratio determined by the two elements. The actual value is not relevant unless there are other flexible elements within the same container. Once the default sizes of elements in a box are calculated, the remaining space in the box is divided among the flexible elements, according to their flex ratios. Specifying a flex value of 0 has the same effect as leaving the flex attribute out entirely.
+ 指示一个元素的伸缩性,
+
+ +
+

+
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/href/index.html b/files/zh-cn/mozilla/tech/xul/attribute/href/index.html new file mode 100644 index 0000000000..50013e44b3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/href/index.html @@ -0,0 +1,24 @@ +--- +title: href +slug: Mozilla/Tech/XUL/Attribute/href +tags: + - XUL 参考 + - XUL 属性 +translation_of: Archive/Mozilla/XUL/Attribute/href +--- +
« XUL Reference home
+ +
+
href
+
类型: 文本
+
定义一个当元素被点击时将会打开的 URL 。需要引用类 text-link
+
+ +
+
<label href="http://example.com" class="text-link" value="点击这里前往 example.com"/>
+
+
+ +
+

+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/id/index.html b/files/zh-cn/mozilla/tech/xul/attribute/id/index.html new file mode 100644 index 0000000000..50e8e7b188 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/id/index.html @@ -0,0 +1,41 @@ +--- +title: id +slug: Mozilla/Tech/XUL/Attribute/id +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/id +--- +
+ « XUL Reference home
+
+
+ id
+
+ 类型: 元素的ID,在主窗口中必须唯一
+
+ 一个唯一的标识一边开发者能够定义. 你可以使用方法 getElementById() 或者其他 DOM 的函数并在样式表中添加对元素的引用。
+
+
+

示例

+
<button id="foo" label="Click Me" oncommand="doSomething()"/>
+
+<script>
+function doSomething(){
+    var myButton = document.getElementById('foo');
+    myButton.setAttribute('label','The button was pressed');
+}
+</script>
+
+

一个更加抽象的版本

+
<button id="foo" label="Click Me" oncommand="setWidgetLabel(this, 'I was pressed')"/>
+<script>
+function setWidgetLabel(idName, newCaption){
+   document.getElementById( idName.id ).setAttribute('label',newCaption)
+}
+
+</script>
+
+

同样,这里还有一些资料

+

name

+
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/image.onload/index.html b/files/zh-cn/mozilla/tech/xul/attribute/image.onload/index.html new file mode 100644 index 0000000000..846d404d89 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/image.onload/index.html @@ -0,0 +1,12 @@ +--- +title: image.onload +slug: Mozilla/Tech/XUL/Attribute/image.onload +translation_of: Archive/Mozilla/XUL/Attribute/image.onload +--- +
« XUL Reference home
+ +
+
image.onload
+
类型: 脚本代码
+
该事件的处理函数将会在 image 元素指示的图片加载完毕之后触发。此事件触发适用于用 src 元素属性或用 list-style-image css属性声明元素样式。如果图片的加载源发生变化,该事件会在图片加载完毕之后再次触发。该事件不会在文档树上向上冒泡。
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/image/index.html b/files/zh-cn/mozilla/tech/xul/attribute/image/index.html new file mode 100644 index 0000000000..dd82594964 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/image/index.html @@ -0,0 +1,25 @@ +--- +title: image +slug: Mozilla/Tech/XUL/Attribute/image +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/image +--- +
+ « XUL Reference home
+
+
+ image
+
+ Type: + + image URL +
+
+ The URL of the image to appear on the element. If this attribute is empty or left out, no image appears. The position of the image is determined by the dir and orient attributes.
+
+
+

See also

+

image element

+
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/increment/index.html b/files/zh-cn/mozilla/tech/xul/attribute/increment/index.html new file mode 100644 index 0000000000..782156bb47 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/increment/index.html @@ -0,0 +1,15 @@ +--- +title: increment +slug: Mozilla/Tech/XUL/Attribute/increment +translation_of: Archive/Mozilla/XUL/Attribute/increment +--- +
+ « XUL Reference home
+
+
+ increment
+
+ 类型:整数
+
+ 拖动刻度条控件(scale元素)中的拉杆,点击滚动条控件(scrollbar元素)中的箭头(拖动拉杆也可以),点击数字输入框(type属性为numbertextbox元素)中的箭头时,其curpos属性或者value属性每次改变的数字值,默认值为1.
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/index.html b/files/zh-cn/mozilla/tech/xul/attribute/index.html new file mode 100644 index 0000000000..097a3d6678 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/index.html @@ -0,0 +1,304 @@ +--- +title: Attributes +slug: Mozilla/Tech/XUL/Attribute +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute +--- +

« XUL Reference home +

+ +
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/label/index.html b/files/zh-cn/mozilla/tech/xul/attribute/label/index.html new file mode 100644 index 0000000000..1846c63a8e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/label/index.html @@ -0,0 +1,41 @@ +--- +title: label +slug: Mozilla/Tech/XUL/Attribute/label +tags: + - XUL Attributes + - XUL Reference +translation_of: Archive/Mozilla/XUL/Attribute/label +--- +
+ « XUL Reference home
+
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+
+

See also

+ +

Examples in JavaScript

+
<label value="Whaw" id="the-big-label" command="the-big-button"/>
+<button id="the-big-button" label="Click me"
+	oncommand="alert(document.getElementById('the-big-label').value)"/>
+
+<label id="myLabel" value="My label"/>
+<button label="Click me"
+	oncommand="document.getElementById('myLabel').setAttribute('value','Value changed');" />
+
+<checkbox label="my Checkbox" id="myCheckboX"/>
+<button label="Another click"
+	oncommand="document.getElementById('myCheckboX').setAttribute('label','Still not checked');"/>
+<button label="Show label of checkbox"
+	oncommand="alert( document.getElementById('myCheckboX').getAttribute('label') )"/>
+
+
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/max/index.html b/files/zh-cn/mozilla/tech/xul/attribute/max/index.html new file mode 100644 index 0000000000..93eb88d4f7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/max/index.html @@ -0,0 +1,20 @@ +--- +title: max +slug: Mozilla/Tech/XUL/Attribute/max +translation_of: Archive/Mozilla/XUL/Attribute/max +--- +
+ « XUL Reference home
+
+
+ 类型:整数
+
+ 设置刻度条控件(scale元素)或者数字输入框控件(type属性为number的textbox元素)中能输入的最大数字.刻度条控件中,该属性的默认值为100,数字输入框中,该属性的默认值为无穷大.
+
+
+

相关链接

+ +
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/menuitem.key/index.html b/files/zh-cn/mozilla/tech/xul/attribute/menuitem.key/index.html new file mode 100644 index 0000000000..b4239b866d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/menuitem.key/index.html @@ -0,0 +1,23 @@ +--- +title: menuitem.key +slug: Mozilla/Tech/XUL/Attribute/menuitem.key +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/menuitem.key +--- +
+ « XUL Reference home
+
+
+ key
+
+ Type: + + element id +
+
+ Set to the id of a key element whose key shortcut is displayed in the menuitem.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/menuitem.name/index.html b/files/zh-cn/mozilla/tech/xul/attribute/menuitem.name/index.html new file mode 100644 index 0000000000..a485138846 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/menuitem.name/index.html @@ -0,0 +1,38 @@ +--- +title: menuitem.name +slug: Mozilla/Tech/XUL/Attribute/menuitem.name +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/menuitem.name +--- +
+ « XUL Reference home
+
+
+ name
+
+ Type: + + string name +
+
+ Radio menuitems with the same name as put into a group. Only one menuitem in each radio group can be checked at a time.
+
+
+

Example

+
<toolbox>
+  <menubar id="planets-menubar">
+    <menu id="planet-menu" label="Planet">
+      <menupopup>
+        <menuitem id="jupiter" label="Jupiter" type="radio" name="planet"/>
+        <menuitem id="saturn" label="Saturn" type="radio" name="planet" checked="true"/>
+        <menuitem id="uranus" label="Uranus" type="radio" name="planet"/>
+      </menupopup>
+    </menu>
+  </menubar>
+</toolbox>
+
+

See also

+

name and menus in the XUL Tutorial

+
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/menuitem.type/index.html b/files/zh-cn/mozilla/tech/xul/attribute/menuitem.type/index.html new file mode 100644 index 0000000000..872c50331b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/menuitem.type/index.html @@ -0,0 +1,28 @@ +--- +title: menuitem.type +slug: Mozilla/Tech/XUL/Attribute/menuitem.type +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/menuitem.type +--- +
+ « XUL Reference home
+
+
+ type
+
+ Type: + + one of the values below +
+
+ Can be used to create checkable menuitems or for radio button menuitems.
+
+ +

More information on adding checkmarks to menus in the XUL tutorial

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/min/index.html b/files/zh-cn/mozilla/tech/xul/attribute/min/index.html new file mode 100644 index 0000000000..9646b1da96 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/min/index.html @@ -0,0 +1,16 @@ +--- +title: min +slug: Mozilla/Tech/XUL/Attribute/min +translation_of: Archive/Mozilla/XUL/Attribute/min +--- +
+ « XUL Reference home
+
+
+ min
+
+ 类型:整数
+
+ 该控件可以有的最小的整数值,默认值为0.
+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/name/index.html b/files/zh-cn/mozilla/tech/xul/attribute/name/index.html new file mode 100644 index 0000000000..cd1695a84c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/name/index.html @@ -0,0 +1,16 @@ +--- +title: name +slug: Mozilla/Tech/XUL/Attribute/name +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/name +--- +
+ « XUL Reference home +

See also

+ +
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/onpopupshowing/index.html b/files/zh-cn/mozilla/tech/xul/attribute/onpopupshowing/index.html new file mode 100644 index 0000000000..ec821daefe --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/onpopupshowing/index.html @@ -0,0 +1,21 @@ +--- +title: onpopupshowing +slug: Mozilla/Tech/XUL/Attribute/onpopupshowing +translation_of: Archive/Mozilla/XUL/Attribute/onpopupshowing +--- +
+ « XUL Reference home
+
+
+ onpopupshowing
+
+ Type: script code
+
+ This event is sent to a popup just before it is opened. This handler is usually used to dynamically set the contents when the user requests to display it. Returning false from this event handler prevents the popup from appearing.
+
+ 该事件在 popup 打开之前传给它。它用于动态生成菜单项。如果返回 false 值,则 popup 将不会显示菜单项。
+
+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/onpopupshown/index.html b/files/zh-cn/mozilla/tech/xul/attribute/onpopupshown/index.html new file mode 100644 index 0000000000..a94af052a2 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/onpopupshown/index.html @@ -0,0 +1,21 @@ +--- +title: onpopupshown +slug: Mozilla/Tech/XUL/Attribute/onpopupshown +translation_of: Archive/Mozilla/XUL/Attribute/onpopupshown +--- +
+ « XUL Reference home
+
+
+ onpopupshown
+
+ Type: script code
+
+ This event is sent to a popup after it has been opened, much like the onload event is sent to a window when it is opened.
+
+ 该事件在 popup 打开之后触发,与 window 的 onload 事件比较类似。
+
+
+

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/orient/index.html b/files/zh-cn/mozilla/tech/xul/attribute/orient/index.html new file mode 100644 index 0000000000..aa1c735a6c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/orient/index.html @@ -0,0 +1,16 @@ +--- +title: orient +slug: Mozilla/Tech/XUL/Attribute/orient +translation_of: Archive/Mozilla/XUL/Attribute/orient +--- +

布局(orient)

+
+
+ 值类型:可以是下面值中的一种。
+ 指定了子控件的布局(orient)为水平分布的(horizontally)或者是垂直分布的(vertically)。默认值依赖于控件本身。你也可以使用-moz-box-orient中的样式属性。 +
    +
  • horizontally: 子控件会被按照在xul源文件中出现的位置依次布置在一行中。
  • +
  • vertically: 子控件会被按照在xul源文件中出现的位置依次布置在一列中。
  • +
+
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/pending/index.html b/files/zh-cn/mozilla/tech/xul/attribute/pending/index.html new file mode 100644 index 0000000000..0ab9643c8f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/pending/index.html @@ -0,0 +1,15 @@ +--- +title: pending +slug: Mozilla/Tech/XUL/Attribute/pending +translation_of: Archive/Mozilla/XUL/Attribute/pending +--- +
+ « XUL Reference home
+
+
+ pending
+
+ Type: boolean
+
+ This attribute is set to true if the tab is currently in the process of being restored by the session store service. Once the tab is restored, this attribute is removed. You can determine if a tab is being restored by checking to see if hasAttribute("pending") is true. If the user has turned on the "Don't load tabs until selected" preference, the pending attribute is set on tabs until they get loaded.
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/persist/index.html b/files/zh-cn/mozilla/tech/xul/attribute/persist/index.html new file mode 100644 index 0000000000..b1d30d5a59 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/persist/index.html @@ -0,0 +1,24 @@ +--- +title: persist +slug: Mozilla/Tech/XUL/Attribute/persist +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/persist +--- +
+ « XUL Reference home
+
+
+ persist
+
+ Type: + + space-separated list of attribute names +
+
+ A space-separated list of attributes that are maintained when the window is closed. When the window is re-opened, the values of persistent attributes are restored. In Mozilla, persistent attributes are stored in the per-profile file localstore.rdf. Persistence can also be stored using the document.persist function. In order for persistence to work, the element must also have an id.
+
+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/selected/index.html b/files/zh-cn/mozilla/tech/xul/attribute/selected/index.html new file mode 100644 index 0000000000..47971cd8c8 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/selected/index.html @@ -0,0 +1,28 @@ +--- +title: selected +slug: Mozilla/Tech/XUL/Attribute/selected +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/selected +--- +
+ « XUL Reference home
+
+
+ selected
+
+ Type: + + boolean +
+
+ Indicates whether the element is selected or not. This value is read-only. To change the selection, set either the selectedIndex or selectedItem property of the containing element.
+
+
+

See also

+ +
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/selectedindex/index.html b/files/zh-cn/mozilla/tech/xul/attribute/selectedindex/index.html new file mode 100644 index 0000000000..72dd679801 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/selectedindex/index.html @@ -0,0 +1,15 @@ +--- +title: selectedIndex +slug: Mozilla/Tech/XUL/Attribute/selectedIndex +translation_of: Archive/Mozilla/XUL/Attribute/selectedIndex +--- +
+ « XUL Reference home
+
+
+ selectedIndex
+
+ 类型: 整数
+
+ 获取或设置当前所选面板的索引号,索引号从0开始.
+
diff --git a/files/zh-cn/mozilla/tech/xul/attribute/tabindex/index.html b/files/zh-cn/mozilla/tech/xul/attribute/tabindex/index.html new file mode 100644 index 0000000000..c5e54fdd1c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/tabindex/index.html @@ -0,0 +1,18 @@ +--- +title: tabindex +slug: Mozilla/Tech/XUL/Attribute/tabindex +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/tabindex +--- +
« XUL Reference home
+ +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ +
 
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/validate/index.html b/files/zh-cn/mozilla/tech/xul/attribute/validate/index.html new file mode 100644 index 0000000000..a56181d8b7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/validate/index.html @@ -0,0 +1,27 @@ +--- +title: validate +slug: Mozilla/Tech/XUL/Attribute/validate +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/validate +--- +
+ « XUL Reference home
+
+
+ validate
+
+ Type: + + one of the values below +
+
+ This attribute indicates whether to load the image from the cache or not. This would be useful if the images are stored remotely or you plan on swapping the image frequently. The following values are accepted, or leave out the attribute entirely for default handling:
+
+ +
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/attribute/value/index.html b/files/zh-cn/mozilla/tech/xul/attribute/value/index.html new file mode 100644 index 0000000000..f436308d89 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/attribute/value/index.html @@ -0,0 +1,30 @@ +--- +title: value +slug: Mozilla/Tech/XUL/Attribute/value +tags: + - XUL Attributes +translation_of: Archive/Mozilla/XUL/Attribute/value +--- +
+ « XUL Reference home
+
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+
+

See also

+ +
+

diff --git a/files/zh-cn/mozilla/tech/xul/broadcaster/index.html b/files/zh-cn/mozilla/tech/xul/broadcaster/index.html new file mode 100644 index 0000000000..be97efef42 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/broadcaster/index.html @@ -0,0 +1,91 @@ +--- +title: broadcaster +slug: Mozilla/Tech/XUL/broadcaster +translation_of: Archive/Mozilla/XUL/broadcaster +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+
+
+ 当您希望若干个元素共享一个或多个属性值时,或者当您想要多个元素对某一个状态改变做出响应是,可以使用 broadcaster。任何监视 broadcaster 的元素都会共享到 broadcaster 中的属性。比如说,假设我们有一个 broadcaster,它拥有一个 label 属性,而它的观察者们正在监视这个 label。这时如果 label 发生了改变,label 的观察者们将立刻被唤醒(update)。改变发生时,每个观察者都会收到一个 onbroadcast 事件。
+
+ 对于 menuitem 或者 button 来说,如果只是为了根据功能是否可用,即时更新菜单项目的 disabled 状态,那么您应该优先考虑 command
+

更多内容请参考 Broadcasters and Observers XUL Tutorial.

+

Examples

+

(example needed)

+

Attributes

+

+ + + + + +

Inherited from XUL element
+align, +allowevents, +allownegativeassertions, +class, +coalesceduplicatearcs, +collapsed, +container, +containment, +context, +contextmenu, +datasources, +dir, +empty, +equalsize, +flags, +flex, +height, +hidden, +id, +insertafter, +insertbefore, +left, +maxheight, +maxwidth, +menu, +minheight, +minwidth, +mousethrough, +observes, +ordinal, +orient, +pack, +persist, +popup, +position, +preference-editable, +querytype, +ref, +removeelement, +sortDirection, +sortResource, +sortResource2, +statustext, +style, +template, +tooltip, +tooltiptext, +top, +uri, +wait-cursor, +width

+

+

Properties

+

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +

TBD

+

diff --git a/files/zh-cn/mozilla/tech/xul/browser/index.html b/files/zh-cn/mozilla/tech/xul/browser/index.html new file mode 100644 index 0000000000..4f9a039f3a --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/browser/index.html @@ -0,0 +1,409 @@ +--- +title: browser +slug: Mozilla/Tech/XUL/browser +translation_of: Archive/Mozilla/XUL/browser +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

A frame which is expected to contain a view of a Web document. It is similar to an iframe except that it holds a page history and contains additional methods to manipulate the currently displayed page.

+

Most of the properties and methods of the browser will rarely be used and can only be called from chrome URLs. Other URLs will need to use the document and history objects to change the displayed document.

+
+
+ Attributes
+
+ autocompleteenabled, autocompletepopup, autoscroll, disablehistory, disablesecurity, homepage, showcaret, src, type
+
+
+
+ Properties
+
+ accessibleType, canGoBack, canGoForward, contentDocument, contentPrincipal, contentTitle, contentViewerEdit, contentViewerFile, contentWindow, currentURI, docShell, documentCharsetInfo, homePage, markupDocumentViewer, messageManager, preferences, securityUI, sessionHistory, webBrowserFind, webNavigation, webProgress
+
+
+
+ Methods
+
+ addProgressListener, goBack, goForward, goHome, gotoIndex, loadURI, loadURIWithFlags, reload, reloadWithFlags, removeProgressListener, stop, swapDocShells
+
+

Examples

+
+ Image:XUL_ref_browser.png
+
<!-- shows Mozilla homepage inside a groupbox -->
+<groupbox flex="1">
+  <caption label="Mozilla homepage"/>
+  <browser type="content" src="http://www.mozilla.org" flex="1"/>
+</groupbox>
+
+

Attributes

+

+

+ + +
+
autocompleteenabled
+
Type: boolean
+
Set to true to enable autocomplete of fields.
+
+
+ +
+
+ autocompletepopup
+
+ Type: id
+
+ The id of a popup element used to hold autocomplete results for the element.
+
+ +
+ + +
+
autoscroll
+
Type: boolean
+
Set to false to disable autoscroll for this browser. If this attribute is set to true or omitted, autoscroll will be enabled or depending on the user preference general.autoScroll.
+
+
+ +
disablehistory
Type: boolean
Disables both session and global history for the docshell attached to the browser.
+
+
+ + +
+
disablesecurity
+
Type: boolean
+
Set this attribute to true to disable the security UI for this browser. Omit this attribute off to enable it.
+
+
+ + +
+
homepage
+
Type: URL
+
This attribute allows you to set a homepage for the browser element. It does not have any correlation with the user's browser homepage; instead it is a convenient property to hold a home page. You can switch to this home page using the goHome method.
+
+
+ + +
+
showcaret
+
Type: boolean
+
Whether or not to cause a typing caret to be visible in the content area. Default is false.
+
+ + +
+ +
+
+ src
+
+ Type: URI
+
+ The URI of the content to appear in the element.
+
+ + +
+ + +
+
type
+
Type: one of the values below.
+
The type of browser, which can be used to set access of the document loaded inside the browser. If this is not set, the loaded document has the same access as the window containing the browser. More precisely: The document loaded into a chrome window is always of chrome type. Subdocuments of chrome documents are of chrome type, unless the container element (one of iframe, browser or editor) has one of the special type attribute values (the common ones are content, content-targetable and content-primary) indicating that the subdocument is of content type. This boundary has a number of special effects, such as making window.top == window (unless the browser is added to a chrome document), and preventing documents from inheriting the principal of the parent document. The type attribute on all frames in content documents is ignored; subdocuments of content documents are always content documents.
+
+
Warning: The type attribute must be set before the element is inserted into the document.
+
+
+
+
content
+
A browser for content. The content that is loaded inside the browser is not allowed to access the chrome above it.
+
content-primary
+
The primary browser for content. The content that is loaded inside the browser is not allowed to access the chrome above it. For instance, in a web browser, this would be the element that displays the web page. The window for the primary content can be retrieved more conveniently using window.content.
+
content-targetable
+
One browser among many for content. The content that is loaded inside the browser is not allowed to access the chrome above it. This is the preferred value for any browser element in an application, which will use multiple browsers of equal privileges, and is unselected at the moment.
+
chrome
+
(default behaviour): A browser, intended to be used for loading privileged content using a chrome:// URI. Don't use for content from web, as this may cause serious security problems!
+
+
+
+ + +

+

Properties

+

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ canGoBack
+
+ Type: boolean
+
+ This read-only property is true if there is a page to go back to in the session history and the Back button should be enabled.
+
+ +
+
canGoForward
+
Type: boolean
+
This read-only property is true if there is a page to go forward to in the session history and the Forward button should be enabled.
+
+
+
+ contentDocument
+
+ Type: document
+
+ This read-only property contains the document object in the element.
+
+ +
+
contentPrincipal
+
Type: nsIPrincipal
+
This read-only property contains the principal for the content loaded in the browser, which provides security context information.
+
+
+
+ contentTitle
+
+ Type: string
+
+ This read-only property contains the title of the document object in the browser.
+
+
+
+ contentViewerEdit
+
+ Type: nsIContentViewerEdit
+
+ This read-only property contains the nsIContentViewerEdit which handles clipboard operations on the document.
+
+
+
+ contentViewerFile
+
+ Type: nsIContentViewerFile
+
+ Reference to the nsIContentViewerFile interface for the document.
+
+
contentWindow
Type: TODO
Use the contentWindow.wrappedJSObject to obtain a DOM(html) window object
+
+
+
+ currentURI
+
+ Type: nsIURI
+
+ This read-only property contains the currently loaded URL. To change the URL, use the loadURI method.
+
+
+
+ docShell
+
+ Type: nsIDocShell
+
+ This read-only property contains the nsIDocShell object for the document.
+
+
+
+ documentCharsetInfo Obsolete since Gecko 12.0
+
+ Type: nsIDocumentCharsetInfo
+
+ This read-only property contains the nsIDocumentCharsetInfo object for the document which is used to handle which character set should be used to display the document. The properties of the nsIDocumentCharsetInfo object were merged into the docshell in Gecko 12.0 (Firefox 12.0 / Thunderbird 12.0 / SeaMonkey 2.9).
+
+
+
+ homePage
+
+ Type: string home page URL
+
+ This property holds the value of the user's home page setting.
+
+
+
+ markupDocumentViewer
+
+ 类型: nsIMarkupDocumentViewer
+
+ 这个只读的属性包含 nsIMarkupDocumentViewer 接口,负责document文档的绘制。
+
+
+
+ messageManager
+
+ Type: message manager object
+
+ This read-only property returns the message manager object for the browser element.
+
+
+
+ preferences
+
+ 类型: nsIPrefService
+
+ 这是一个只读属性,其值为一个nsIPref对象,可以用来读取或设置用户的首选项.
+
+
+
+ securityUI
+
+ Type: nsISecureBrowserUI
+
+ The read-only property holds an object which may be used to determine the security level of the loaded document.
+
+
+
+ sessionHistory
+
+ Type: nsISHistory
+
+ This read-only property contains the nsISHistory object which holds the session history.
+
+
+
+ webBrowserFind
+
+ Type: nsIWebBrowserFind
+
+ This read-only property contains an nsIWebBrowserFind object which can be used to search for text in the document.
+
+
+
+ webNavigation
+
+ Type: nsIWebNavigation
+
+ This read-only property contains the nsIWebNavigation object for the document. Most of its methods are callable directly on the element itself, such as goBack and goForward. It also contains the load constants used by reloadWithFlags and loadURIWithFlags.
+
+
+
+ webProgress
+
+ Type: nsIWebProgress
+
+ This read-only property contains an nsIWebProgress object which is used to monitor the progress of a document loading.
+

+

Methods

+

+ + + + + +
+

Inherited Methods
+addEventListener(), appendChild(), blur, click, cloneNode(), compareDocumentPosition, dispatchEvent(), doCommand, focus, getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getBoundingClientRect(), getClientRects(), getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName(), getElementsByTagName(), getElementsByTagNameNS(), getFeature(), getUserData, hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isDefaultNamespace(), isEqualNode, isSameNode, isSupported(), lookupNamespaceURI, lookupPrefix, normalize(), querySelector(), querySelectorAll(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS(), setUserData

+ +

+

+
+ addProgressListener( listener )
+
+ Return type: no return value
+
+ Add a progress listener to the browser which will monitor loaded documents. The progress listener should implement the nsIWebProgressListener interface.
+
+
goBack()
+
Return type: no return value
+
Go back one page in the history.
+
+
goForward()
+
Return type: no return value
+
Go forward one page in the history.
+
+
goHome()
+
Return type: no return value
+
Load the user's home page into the browser.
+
+
gotoIndex( index )
+
Return type: no return value
+
Navigate to the page in the history with the given index. Use a positive number to go forward and a negative number to go back.
+

NOTE: This is the XUL method on <browser> / <tabbrowser>, not the global function in chrome://browser/content/browser.js. Please check which one you're documenting! (This one has no post data parameter, see loadURIWithFlags for a version that does)

+
+
+ loadURI( uri, referrer, charset )
+
+ Return type: no return value
+
+ Load a URL into the document, with the given referrer and character set.
+
+ The first argument should be a string, not a nsIURI object. To get a string from an nsIURI, use nsIURI.spec or nsIURI.asciiSpec
+
+
loadURIWithFlags( uri, flags, referrer, charset, postData )
+
Return type: no return value
+
Load a URL into the document, with the specified load flags, the given referrer, character set, and POST data. In addition to the flags allowed for the reloadWithFlags method, the following flags are also valid: +
    +
  • LOAD_FLAGS_IS_REFRESH: This flag is used when the URL is loaded because of a meta tag refresh or redirect.
  • +
  • LOAD_FLAGS_IS_LINK: This flag is used when the URL is loaded because a user clicked on a link. The HTTP Referer header is set accordingly.
  • +
  • LOAD_FLAGS_BYPASS_HISTORY: Do not add the URL to the session history.
  • +
  • LOAD_FLAGS_REPLACE_HISTORY: Replace the current URL in the session history with a new one. This flag might be used for a redirect.
  • +
+
+
+ +

(See nsIWebNavigation.loadURI() for details on the referrer and postData parameters.)

+
reload()
+
Return type: no return value
+
Reloads the document in the browser element on which you call this method.
+
+
reloadWithFlags( flags )
+
Return type: no return value
+
Reloads the document in the browser with the given load flags. The flags listed below may be used, which are all constants of the webNavigation property (or the nsIWebNavigation interface). You may combine flags using a or symbol ( | ). +
    +
  • LOAD_FLAGS_NONE: No special flags. The document is loaded normally.
  • +
  • LOAD_FLAGS_BYPASS_CACHE: Reload the page, ignoring if it is already in the cache. This is the flag used when the reload button is pressed while the Shift key is held down.
  • +
  • LOAD_FLAGS_BYPASS_PROXY: Reload the page, ignoring the proxy server.
  • +
  • LOAD_FLAGS_CHARSET_CHANGE: This flag is used if the document needs to be reloaded because the character set changed.
  • +
+
+
+
removeProgressListener( listener )
+
Return type: no return value
+
Remove a nsIWebProgressListener from the browser.
+
+
+ stop()
+
+ 返回值: 无返回值
+
+ 效果等同于按下了停止按钮,停止当前页面中文档的加载.
+
+
+ swapDocShells( otherBrowser )
+
+ Return type: no return value
+
+ Swaps the content, history and current state of this browser with another browser. During the swap, pagehide and pageshow events are fired on both browsers. This method can be used to move browser between windows or tear off a browser into a new window.
+
+ +
+

Note: Both browsers must be either standalone browsers or embedded in a tabbrowser. You can't mix them.

+ +
+
+ Interfaces
+
+ nsIAccessibleProvider
+
+

diff --git a/files/zh-cn/mozilla/tech/xul/button/index.html b/files/zh-cn/mozilla/tech/xul/button/index.html new file mode 100644 index 0000000000..a3bcf45284 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/button/index.html @@ -0,0 +1,528 @@ +--- +title: button +slug: Mozilla/Tech/XUL/button +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/button +--- +
+ « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+ +

按钮就是可以点击的东西。事件处理程序可以用来捕获鼠标、键盘和其他事件。它通常呈现为一个灰色开始长方形。您可以指定按钮的label 属性来将按钮的文字设置好,或者直接写在标签中间也行。

+ +

更多信息请参阅 XUL tutorial.

+ +
+
Attributes
+
accesskey, autocheck, checkState, checked, command, crop, dir, disabled, dlgtype, group, icon, image, label, open, orient, tabindex, type
+
+ +
+
Properties
+
accessKey, accessibleType, autoCheck, checkState, checked, command, crop, dir, disabled, dlgType, group, image, label, open, orient, tabIndex, type
+
+ +

Examples

+ +
Image:XUL_ref_button.png
+ +
<button label="Press Me"
+        oncommand="alert('You pressed me!');"/>
+
+ +

Attributes

+ +

+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ + +
+
autocheck
+
类型: + boolean +
+
如果此属性为 true,或空白, 每次点击按钮时,此按钮的状态检查都会被执行一次。如果此属性为false, 检查会手动的被拒绝。当autocheck值为true的时候,按钮将会变为多选框或者单选框。
+
+ + + +

+
+ + +
+
checkState
+
Type: integer, values 0, 1, or 2
+
This attribute may be used to create three state buttons, numbered 0, 1 and 2. When in state 0 or 1, pressing the button will switch to the opposite state. When in state 2, pressing the button will switch to state 0. This means that the button acts like a checkbox except that there is a third state which must be set manually by adjusting the check state. If you wish to have different behavior for how the states are adjusted, set the autoCheck attribute to false and adjust the state with a script. The type attribute must be set to checkbox for buttons with a check state. Constants for the possible values for this attribute are in the nsIDOMXULButtonElement interface.
+
+
+ +
+
+ checked
+
+ Type: + + boolean +
+
+ Indicates whether the element is checked or not.
+
+ Use hasAttribute() to determine whether this attribute is set instead of getAttribute().
+
+ For buttons, the type attribute must be set to checkbox or radio for this attribute to have any effect.<magic name="\"PAGENAME\"/"></magic>
+
+
+ +
+
+ command
+
+ Type: + + element id +
+
+ Set to the id of a command element that is being observed by the element.
+
+ +

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ +
+
+ dir
+
+ Type: + + one of the values below +
+
+ The direction in which the child elements of the element are placed.
+
+
+
+ normal
+
+ For scales, the scale's values are ordered from left to right (for horizontal scales) or from top to bottom (for vertical scales)  For other elements, the elements are placed left to right or top to bottom in the order they appear in the XUL code
+
+ reverse
+
+ For scales, the scale's values are ordered from right to left (for horizontal scales) or from bottom to top (for vertical scales). For other elements, they are placed right to left or bottom to top. This is reverse of the order in which they appear in the XUL code.
+
+ + +

 

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
dlgtype
+
Type: one of the values below
+
The dialog type of the button, used only when the button is in a dialog box. You can use this feature to replace the standard dialog box buttons with custom buttons, yet the dialog event methods will still function. For example, if the dlgType is set to accept, the button will replace the dialog box's accept button, which is usually labeled OK. Using this attribute on a button that is not in a dialog box has no effect. The following values can be used as the dialog type:
+
+
+
accept
+
The OK button, which will accept the changes when pressed.
+
cancel
+
The cancel button which will cancel the operation.
+
help
+
A help button for displaying help about the dialog.
+
disclosure
+
A button to show more information. This might be a button or a disclosure triangle.
+
extra1
+
An optional additional button.
+
extra2
+
A second optional additional button.
+
+
+
+
+ + +
+
group
+
Type: string group name
+
Buttons with type="radio" and the same value for their group attribute are put into the same group. Only one button from each group can be checked at a time. If the user selects one the buttons, the others in the group are unchecked.
+
+
+ + +
+
icon
+
Mozilla 1.8
+
Type: string
+
This attribute should be used to set the usage for common buttons. Some platforms display these buttons with a small icon indicating their usage. This should be used in place of the image attribute. Possible values include: accept, cancel, help, open, save, find, clear, yes, no, apply, close, print, add, remove, refresh, go-forward, go-back, properties, select-font, select-color, network. If you are using a button that matches one of these common usages, use the icon attribute to indicate this. See the appearance of the different icons on some available platforms.
+
+
+ +
+
+ image
+
+ Type: + + image URL +
+
+ The URL of the image to appear on the element. If this attribute is empty or left out, no image appears. The position of the image is determined by the dir and orient attributes.
+
+ +

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ + +
+
open
+
Type: boolean
+
For the menu type buttons, the open attribute is set to true when the menu is open. The open attribute is not present if the menu is closed.
+
+
+

布局(orient)

+
+
+ 值类型:可以是下面值中的一种。
+ 指定了子控件的布局(orient)为水平分布的(horizontally)或者是垂直分布的(vertically)。默认值依赖于控件本身。你也可以使用-moz-box-orient中的样式属性。 +
    +
  • horizontally: 子控件会被按照在xul源文件中出现的位置依次布置在一行中。
  • +
  • vertically: 子控件会被按照在xul源文件中出现的位置依次布置在一列中。
  • +
+
+
+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ + +
+
type
+
Type: one of the values below
+
The type of button. If this attribute is not present, a normal button is created. Leave the attribute out for a normal button.
+
+
+
checkbox
+
This type of button can be in two states. The user can click the button to switch between the states. This is not the same as a checkbox because it looks like a button.
+
menu
+
Set the type attribute to the value menu to create a button with a menu popup. Place a menupopup element inside the button in this case. The user may click anywhere on the button to open and close the menu.
+
menu-button
+
You can also use the value menu-button to create a button with a menu. Unlike the menu type, this type requires the user to press the arrow to open the menu, but a different command may be invoked when the main part of the button is pressed.
+
panel
+
Similar to the menu type, this opens a popup. Place a panel element inside the button. panel elements are popups that support any type of content.
+
radio
+
The button acts like a radio button. Only one button in the group can be on a once.
+
repeat
+
This button will fire its command event repeatedly while the mouse button is held down.
+
+
+
+

+ +

Properties

+ +

+
+
+ accessKey
+
+ Type: + + character +
+
+ Gets and sets the value of the accesskey attribute.
+
+ +

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+ +
+
autoCheck
+
Type: boolean
+
Gets and sets the value of the autoCheck attribute.
+
+
+
+ checkState
+
+ Type: integer, values 0, 1, or 2
+
+ Gets and sets the value of the checkState attribute.
+
+
+
+ checked
+
+ Type: boolean
+
+ Gets and sets the value of the checked attribute.
+
+
+
+ command
+
+ Type: + + element id +
+
+ Gets and sets the value of the command attribute.
+
+ +

+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+ +

+
+
+ dir
+
+ Type: string
+
+ Gets and sets the value of the dir attribute.
+
+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+ +
+
dlgType
+
Type: string
+
Gets and sets the value of the dlgType attribute.
+
+ +
+
group
+
Type: string group name
+
Gets and sets the value of the group attribute.
+
+
+
+ image
+
+ Type: + + image URL +
+
+ Gets and sets the value of the image attribute.
+
+ +

+
+
+ label
+
+ Type: + + string +
+
+ Gets and sets the value of the label attribute.
+
+ +

+
+
+ open
+
+ Type: boolean
+
+ Gets and sets the value of the open attribute.
+
+
+
+
+ orient
+
+ Type: string
+
+ Gets and sets the value of the orient attribute.
+
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+
+
+ type
+
+ Type: string
+
+ Gets and sets the value of the type attribute.
+
+

+ +

Methods

+ +

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ + + +
+
Interfaces
+
nsIAccessibleProvider, nsIDOMXULButtonElement
+
+ +
 
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/checkbox/index.html b/files/zh-cn/mozilla/tech/xul/checkbox/index.html new file mode 100644 index 0000000000..ea2eef19ba --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/checkbox/index.html @@ -0,0 +1,329 @@ +--- +title: checkbox +slug: Mozilla/Tech/XUL/checkbox +tags: + - 中文 +translation_of: Archive/Mozilla/XUL/checkbox +--- +
+ « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+ +

An element that can be turned on and off. This is most commonly rendered as a box when the element is off and a box with a check when the element is on. The user can switch the state of the check box by selecting it with the mouse. A label, specified with the label attribute, may be added beside the check box.

+ +

More information is available in the XUL tutorial.

+ +
+
Attributes
+
accesskey, checked, command, crop, disabled, src, label, preference, tabindex
+
+ +
+
Properties
+
accessKey, accessibleType, checked, command, crop, disabled, src, label, tabIndex
+
+ +

Examples

+ +
Image:XUL_ref_checkbox.png
+ +
<checkbox label="Enable JavaScript" checked="true"/>
+<checkbox label="Enable Java" checked="false"/>
+
+ +

Attributes

+ +

+ +

+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ +
+
+ checked
+
+ Type: + + boolean +
+
+ Indicates whether the element is checked or not.
+
+ Use hasAttribute() to determine whether this attribute is set instead of getAttribute().
+
+ For buttons, the type attribute must be set to checkbox or radio for this attribute to have any effect.<magic name="\"PAGENAME\"/"></magic>
+
+
+ +
+
+ command
+
+ Type: + + element id +
+
+ Set to the id of a command element that is being observed by the element.
+
+ +

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
src
+
Type: URI
+
Set this to an URI pointing to an image to appear in the checkbox. If this attribute is left out, no image appears. You can have both an image and a label.
+
+ + +
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ + +
+
preference
+
Type: id
+
Connects the element to a corresponding preference. This attribute only has any effect when used inside a prefwindow. More information is available in the Preferences System article.
+
+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+

+ +

Properties

+ +

+ +

+
+
+ accessKey
+
+ Type: + + character +
+
+ Gets and sets the value of the accesskey attribute.
+
+ +

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ checked
+
+ Type: boolean
+
+ Gets and sets the value of the checked attribute.
+
+
+
+ command
+
+ Type: + + element id +
+
+ Gets and sets the value of the command attribute.
+
+ +

+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+ +

+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+ +
+
src
+
Type: URL
+
Gets and sets the value of the src attribute.
+
+
+
+ label
+
+ Type: + + string +
+
+ Gets and sets the value of the label attribute.
+
+ +

+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+ +

Methods

+ +

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ + + +
+
Interfaces
+
nsIAccessibleProvider, nsIDOMXULCheckboxElement
+
diff --git a/files/zh-cn/mozilla/tech/xul/command/index.html b/files/zh-cn/mozilla/tech/xul/command/index.html new file mode 100644 index 0000000000..7a9a8916f9 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/command/index.html @@ -0,0 +1,105 @@ +--- +title: command +slug: Mozilla/Tech/XUL/command +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/command +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+ command 元素响应不同来源的、对于同一操作的操作请求。比如,剪贴板的粘贴操作,可以来自 “编辑”菜单,可以来自鼠标右键的上下文菜单,也可以来自键盘快捷键。你可以通过 command 的 oncommand 属性调用代码。对于用户来说,从什么地方触发了这个操作并不重要。另外,关闭 command 将自动关闭菜单中的项目和对键盘快捷键的响应。
+

Commands are identified by their id. If you include the script chrome://global/content/globalOverlay.js in your window, you can use the function goDoCommand function to invoke the command. Using this function has the advantage that the command will be sent to the part of the UI which will respond to it. Typically, this will be the currently focused element.

+

Like a broadcaster, commands forward attributes to other elements.

+

More information is available in the XUL tutorial. See also: command attribute, commandset element

+
+
+ Attributes
+
+ disabled, label, oncommand
+
+

Examples

+

The following code will send a paste command (cmd_paste) to the currently focused element:

+
 // First include chrome://global/content/globalOverlay.js
+ goDoCommand("cmd_paste");
+
+

Example with two buttons

+
<command id="cmd_openhelp" oncommand="alert('Help');"/>
+<button label="Help" command="cmd_openhelp"/>
+<button label="More Help" command="cmd_openhelp"/>
+
+

Attributes

+

+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ + +
+
oncommand
+
Type: script code
+
This event handler is called when the command is activated. This occurs when a user selects a menu item or presses a keyboard shortcut attached to the command.
+
+ + +

+

Properties

+

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ + +

diff --git a/files/zh-cn/mozilla/tech/xul/deprecated_defunct_markup/index.html b/files/zh-cn/mozilla/tech/xul/deprecated_defunct_markup/index.html new file mode 100644 index 0000000000..6ae3102b4f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/deprecated_defunct_markup/index.html @@ -0,0 +1,50 @@ +--- +title: Deprecated/Defunct Markup +slug: Mozilla/Tech/XUL/Deprecated_Defunct_Markup +translation_of: Archive/Mozilla/XUL/Deprecated_and_defunct_markup +--- +

The following XUL tags and attribute should be considered deprecated, if not defunct.

+

The list below may include a few elements which are actually in use, but at a deeper level in the code. Even some of the information on the tags below may be out of date, but is provided here for historical reference and to help anyone who comes across them in old code or documentation.

+

Elements

+ +

Attributes

+ +

References

+ diff --git a/files/zh-cn/mozilla/tech/xul/dialog/index.html b/files/zh-cn/mozilla/tech/xul/dialog/index.html new file mode 100644 index 0000000000..b4e3680bf3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/dialog/index.html @@ -0,0 +1,364 @@ +--- +title: dialog +slug: Mozilla/Tech/XUL/dialog +translation_of: Archive/Mozilla/XUL/dialog +--- +
+ « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

window 元素调用对话框时应使用此元素。buttons 属性可以用于设置哪些按钮应该出现在对话框中。这些按钮将被放置在用户平台指定的位置。

+

更多有用信息可以查看 XUL tutorialDialogs and prompts (代码片段)。

+
属性
buttonaccesskeyaccept, buttonaccesskeycancel, buttonaccesskeydisclosure, buttonaccesskeyextra1, buttonaccesskeyextra2, buttonaccesskeyhelp, buttonalign, buttondir, buttondisabledaccept, buttonlabelaccept, buttonlabelcancel, buttonlabeldisclosure, buttonlabelextra1, buttonlabelextra2, buttonlabelhelp, buttonorient, buttonpack, buttons, defaultButton, ondialogaccept, ondialogcancel, ondialogdisclosure, ondialogextra1, ondialogextra2, ondialoghelp, title
+
+
特性
buttons, defaultButton
+
+
方法
acceptDialog, cancelDialog, centerWindowOnScreen, getButton, moveToAlertPosition
+
+

示例

+
Image:XUL_ref_dialog.png
+
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+<dialog id="donothing" title="Dialog example"
+   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+   buttons="accept,cancel"
+   buttonlabelcancel="Cancel"
+   buttonlabelaccept="Save"
+   ondialogaccept="return doOK();"
+   ondialogcancel="return doCancel();">
+
+    <dialogheader title="Options" description="My preferences"/>
+    <groupbox>
+      <caption label="Colour"/>
+      <radiogroup>
+        <radio label="Red"/>
+        <radio label="Green" selected="true"/>
+        <radio label="Blue"/>
+      </radiogroup>
+      <label value="Nickname"/>
+      <textbox />
+   </groupbox>
+</dialog>
+
+

属性

+

+ +
+
+ activetitlebarcolor
+
+ Type: color string
+
+ Specify background color of the window's titlebar when it is active (foreground). Moreover this hides separator between titlebar and window contents. This only affects Mac OS X.
+
+ +

 

+
+ +
+
+ buttonaccesskeyaccept
+
+ Type: string
+
+ The access key to use for the "accept" button.
+
+

 

+ +

 

+
+ +
+
+ buttonaccesskeycancel
+
+ Type: string
+
+ The access key to use for the "cancel" button.
+
+
+ +
+
+ buttonaccesskeydisclosure
+
+ Type: string
+
+ The access key to use for the "disclosure" button.
+
+
+ +
+
+ buttonaccesskeyextra1
+
+ Type: string
+
+ The access key to use for the first extra button.
+
+
+ + +
+
buttonaccesskeyextra2
+
Type: string
+
The access key to use for the second extra button.
+
+
+ +
+
+ buttonaccesskeyhelp
+
+ Type: string
+
+ The access key to use for the "help" button.
+
+
+ +
+
+ buttonalign
+
+ Type: string
+
+ The value of the align attribute for the box containing the buttons.
+
+
+ + +
+
buttondir
+
Type: string
+
The value of the dir attribute for the box containing the buttons.
+
+
+ + +
+
buttondisabledaccept
+
Type: boolean
+
If true, the accept button is disabled.
+
+
+ + +
+
buttonlabelaccept
+
Type: string
+
The label to appear on the "accept" button.
+
+
+ + +
+
buttonlabelcancel
+
Type: string
+
The label to appear on the "cancel" button.
+
+
+ + +
+
buttonlabeldisclosure
+
Type: string
+
The label to appear on the "disclosure" button.
+
+
+ +
+
+ buttonlabelextra1
+
+ Type: string
+
+ The label to appear on the first extra button.
+
+ +

 

+
+ +
+
+ buttonlabelextra2
+
+ Type: string
+
+ The label to appear on the second extra button.
+
+ +

 

+
+ + +
+
buttonlabelhelp
+
Type: string
+
The label to appear on the "help" button.
+
+
+ + +
+
buttonorient
+
Type: string
+
The value of the orient attribute for the box containing the buttons.
+
+
+ + +
+
buttonpack
+
Type: string
+
The value of the pack attribute for the box containing the buttons.
+
+
+ +
+
+ buttons
+
+ 类型: 列表,下面的值用逗号分隔
+
+ 需要显示在对话框上的按钮的一个列表,使用逗号分隔。将按钮放置在合适的位置,将根据用户平台自动执行基本的事件处理。在列表中可以使用以下值: +
    +
  • accept:“确定”按钮,按下按钮时将接受更改。此按钮为默认按钮。
  • +
  • cancel:“取消”按钮,将取消操作。
  • +
  • help:“帮助”按钮,在对话框显示一个“帮助”按钮。
  • +
  • disclosure:“更多信息”按钮,显示一个“more info”按钮。该按钮可能是一个按钮或一个三角形。
  • +
  • extra1:一个可选的额外的按钮。你可以通过buttonlabelextra1 属性设置它的label。
  • +
  • extra2:第二个可选的额外的按钮。你可以通过 buttonlabelextra2 属性设置它的label。
  • +
+
+
+ +

 

+
+ + +
+
defaultButton
+
Type: string
+
Normally this attribute should not be set, but if it is, it specifies the default button in the dialog. Typically, this means that the button will be activated when the Enter key is pressed. This should be set to one of the same values as those for the buttons attribute.
+
+
+ + +
+
inactivetitlebarcolor
+
Type: color string
+
Specify background color of the window's titlebar when it is inactive (background). Moreover this hides separator between titlebar and window contents. This affects only on Mac OS X.
+
+
+ + +
+
ondialogaccept
+
Type: script code
+
The code in this attribute is called when the accept button is pressed, or when the acceptDialog method is called. If the handler returns true, the dialog will indeed go away, but if it returns false it will not.
+
+
+ + +
+
ondialogcancel
+
Type: script code
+
The code in this attribute is called when the "cancel" button is pressed or when the cancelDialog method is called. If the routine returns true, the dialog will indeed go away, but if it returns false it will not.
+
+
+ + +
+
ondialogdisclosure
+
Type: script code
+
The code in this attribute is called when the "disclosure" button is pressed.
+
+
+ + +
+
ondialogextra1
+
Type: script code
+
The code in this attribute is called when the first extra button is pressed.
+
+
+ + +
+
ondialogextra2
+
Type: script code
+
The code in this attribute is called when the second extra button is pressed.
+
+
+ + +
+
ondialoghelp
+
Type: script code
+
The code in this attribute is called when the "help" button is pressed.
+
+
+ + +
+
title
+
Type: string
+
The text to appear in the title bar of the window.
+
+

+

特性

+

+
buttons
类型: 列表,下面的值用逗号分隔
需要显示在对话框上的按钮的一个列表,使用逗号分隔。将按钮放置在合适的位置,将根据用户平台自动执行基本的事件处理。在列表中可以使用以下值:
  • accept:“确定”按钮,按下按钮时将接受更改。此按钮为默认按钮。
  • cancel:“取消”按钮,将取消操作。
  • help:“帮助”按钮,在对话框显示一个“帮助”按钮。
  • disclosure:“更多信息”按钮,显示一个“more info”按钮。该按钮可能是一个按钮或一个三角形。
  • extra1:一个可选的额外的按钮。你可以通过buttonlabelextra1 属性设置它的label。
  • extra2:第二个可选的额外的按钮。你可以通过 buttonlabelextra2 属性设置它的label。
+
+
+ +
+
defaultButton
+
Type: string
+
Normally this attribute should not be set, but if it is, it specifies the default button in the dialog. Typically, this means that the button will be activated when the Enter key is pressed. This should be set to one of the same values as those for the buttons attribute.
+

方法

+

+ + + + + +
+

Inherited Methods
+addEventListener(), appendChild(), blur, click, cloneNode(), compareDocumentPosition, dispatchEvent(), doCommand, focus, getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getBoundingClientRect(), getClientRects(), getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName(), getElementsByTagName(), getElementsByTagNameNS(), getFeature(), getUserData, hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isDefaultNamespace(), isEqualNode, isSameNode, isSupported(), lookupNamespaceURI, lookupPrefix, normalize(), querySelector(), querySelectorAll(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS(), setUserData

+ +
+
+ acceptDialog()
+
+ Return type: no return value
+
+ Accepts the dialog and closes it, similar to pressing the OK button.
+
+
cancelDialog()
+
Return type: no return value
+
Cancels the dialog and closes it, similar to pressing the Cancel button.
+
+
centerWindowOnScreen()
+
Return type: no return value
+
Centers the dialog on the screen.
+
+
+ getButton( type )
+
+ 返回值类型: button元素
+
+ 返回当前对话框中指定类型的button元素.
+
+
moveToAlertPosition()
+
Return type: no return value
+
Moves and resizes the dialog to a position and size suitable for an alert box.
+

+ +
Elements
dialogheader
+
+

diff --git a/files/zh-cn/mozilla/tech/xul/events/index.html b/files/zh-cn/mozilla/tech/xul/events/index.html new file mode 100644 index 0000000000..02cf21976d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/events/index.html @@ -0,0 +1,497 @@ +--- +title: Events +slug: Mozilla/Tech/XUL/Events +translation_of: Archive/Mozilla/XUL/Events +--- +
+

 

+ +

« XUL Reference

+ +

 

+ +

下列表格描述了对大部分 XUL 元素有效的事件句柄(Event Handler)。您可以使用 addEventListener 添加事件的监听器(Listener),并使用 removeEventListener 以移除这些监听器。

+ +

其中一些事件同样可以使用属性值绑定。当使用属性值绑定事件时,您要注意这样做始终只能绑定一个监听器——后一次绑定会覆盖掉前面一次的绑定。对应的属性名是事件名前加上“on”前缀。

+ +

继承的文档树事件

+ +

继承的文档树事件(Inherited DOM Events)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事件描述
+

blur

+
+

与 focus 事件相对,当一个元素失去焦点时会触发 blur 事件。
+ 属性:onblur

+
+

change

+
+

当文本框的值被修改且失去焦点后,会触发 change 事件。
+ 属性: onchange

+
+

click

+
+

当鼠标键被按下并松开后会触发 click 事件。您可以通过事件对象的 button 属性判断按下的是哪个按键。用户双击时同样会触发这个事件,您可以通过 detail 属性检查有多少次点击发生,用它来检查双击或者三击。在 XUL 中,您应当使用 command 事件响应用户操作,而不应使用 click 事件。

+ +

属性: onclick

+
+

dblclick

+
+

这个事件和 click 事件类似,但是仅当用户双击鼠标的时候触发。这是另一种检查 click 事件中 detail 属性的方法。
+ 属性: ondblclick

+
+

DOMMouseScroll

+
+

当用户滑动鼠标滚轮时会触发这个事件。不论鼠标滚轮的滑动是否造成了页面内容的滚动。事件的 target 属性是滑动滚轮时在鼠标指针下的对象,这与 click 事件相似。

+
+

focus

+
+

当一个元素收到焦点的时候,会触发 focus 属性。一旦某个元素获得了焦点,那么键盘事件将会被发送到这个元素上。焦点可以通过鼠标点击、按 Tab 键、按 back Tab 键切换到其他的元素上。
+ 属性: onfocus

+
+

keydown

+
+

当键盘按键被按下但是并未抬起时,会触发当前具有焦点的元素的 keydown 事件。
+ 属性: onkeydown

+
+

keypress

+
+

当键盘按键被按下并松开后,会触发当前具有焦点的元素的 keypress 事件。当用户按下并松开一个键时,会依次触发 keydown 事件、 keypress 事件和 keyup 事件。在一个文本框里,用户可以按住一个键来发送多个对应的字符,这时会像用户重复按了对应键多次一样触发多组按键事件。
+ 属性: onkeypress

+
+

keyup

+
+

当键盘按键被松开后,会触发当前具有焦点的元素的 keyup 事件。
+ 属性: onkeyup

+
+

load

+
+

当一个窗口(window)被完整加载后,会触发他的 load 事件。这个事件被用在窗口元素上和图片(image)元素或其他支持图片属性的上。用在图片元素上时,当图片元素被加载时会触发这个事件。图片元素的 load 事件不会起泡(bubble up),换句话说,不会因此触发窗口的 load 事件。
+ 属性: onload

+
+

mousedown

+
+

当鼠标点击了某个元素但尚未松开时,会触发 mousedown 事件。
+ 属性: onmousedown

+
+

mousemove

+
+

当鼠标在一个元素上移动时,会反复地发送 mousemove 事件。
+ 属性: onmousemove

+
+

mouseout

+
+

与 mouseover 事件相对,当用户将鼠标移出某个元素时,会触发这个元素的 mouseout 事件。
+ 属性: onmouseout

+
+

mouseover

+
+

当鼠标首次移动到某个元素上时,会触发这个元素的 mouseover 事件。您可以使用此事件来提供给用户反馈。
+ 属性: onmouseover

+
+

mouseup

+
+

当鼠标在某个元素上松开时,会触发 mouseup 事件。
+ 属性: onmouseup

+
+

select

+
+

This event is sent to a listbox or tree when an item is selected.
+ 属性: onselect

+
+

unload

+
+

This event is sent to a window when the window has closed. This is done after the close event. You should place this event handler on the window element.
+ 属性:onunload

+
+ +

Mutation 文档树事件

+ + + + + + + + + + + + + + + + + + + + +
事件描述
+

DOMAttrModified

+
+

当一个元素的属性被修改时,会触发 DOMAttrModified 事件。您可以通过 attrName 属性查看哪个属性被修改了,并通过 prevValuenewValue 属性查看对应属性的旧值和新值。

+
+

DOMNodeInserted

+
+

当一个节点作为一个元素的子节点被添加时,会触发 DOMNodeInsterted 事件。如果您在 document 层捕获这个事件,您可以收到所有对文档修改的动作。

+
+

DOMNodeRemoved

+
+

当一个节点被移除时,会触发 DOMNodeRemoved 事件。如果您在 document 层捕获这个事件,您可以收到所有对文档修改的动作。

+
+ +
+

请注意,向文档中添加任何 mutation 事件监听器会降低后续文档树操作的性能。而且在后续操作中移除这些监听器并不会使之好转。要了解详细信息,请参考  Mutation events ,并且参考 Mutation observers 考虑使用其他效率更好的方式。

+
+ +

通用 XUL 事件

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事件描述
+

broadcast

+
+

您应当将这个事件句柄置于观察者上。当对应元素(如广播者)的属性被改变时,会触发 boardcast 事件。
+ 属性: onbroadcast

+
+

close

+
+

当用户按下关闭按钮以要求关闭窗口时,会触发 close 事件。如果您在一个窗口元素上放置该事件的句柄,您可以陷入(trap)窗口的关闭。如果您在监听器中调用 event.preventDefault() ,可以阻止窗口的关闭。注意, close 事件仅针对用户按了标题栏上的关闭按钮,而不针对诸如点击了菜单中的文件—退出的操作。您可以考虑使用窗口的 unload 事件来处理所有关闭窗口的事件。
+ 属性: onclose

+
+

command

+
+

当一个元素被激活时,会触发 command 事件。对于不同的元素,这个事件触发的方式也不尽相同。例如,点击按钮可以触发这个事件,在按钮获得焦点时按回车键也可以触发这个事件,用鼠标选择菜单项时可以触发这个事件,用键盘快捷键选择某个菜单项时同样会触发这个事件。您应当考虑使用 command 事件,而非使用 click 事件,因为 command 事件可以在所有上面说的情况下被调用。
+ 属性: oncommand

+
+

commandupdate

+
+

This event occurs when a command update occurs on a <commandset> element. You would use this to update the disabled status of its commands.
+ 属性: oncommandupdate

+
+

contextmenu

+
+

当用户试图显示某个元素的菜单时,会触发 contextmenu 事件。因平台不同,这个事件的触发方式也有所不同,通常来说是通过右键单击来触发的。这个事件可以用来在用户点击时动态地设置菜单的内容。您还可以使用 popupshowing 事件。在事件句柄中返回 false 可以阻止菜单弹出。
+ 属性: oncontextmenu

+
+

drag

+
+

当拖拽一个节点时,会每秒数次地触发被拖拽节点的 drag 事件。
+ 属性: ondrag

+
+

dragdrop

+
+

当用户松开鼠标以释放一个被拖拽的对象时,会触发 dragdrop 事件。The element, if it accepts the drop, should respond in some manner such inserting the dragged object into itself.
+ 属性: ondragdrop

+
+

dragend

+
+

当拖拽事件结束时,会触发被拖拽的节点的 dragend 事件。
+ 属性: ondragend

+
+

dragenter

+
+

在拖拽过程中,当鼠标节点第一次进入某个对象的范围内时,会触发 dragenter 事件。这个事件与 mouseover 事件相似,不同点在于在拖拽的过程中触发。
+ 属性: ondragenter

+
+

dragexit

+
+

在拖拽的过程中,当鼠标指针从一个元素上移出的时候,会触发 dragexit 事件。这个事件同样会在释放元素后触发。这个事件与 mouseout 事件相似,不同点在于在拖拽的过程中触发。
+ 属性: ondragexit

+
+

draggesture

+
+

当用户开始拖拽一个元素时,会触发 draggesture 事件。一般来说,拖拽是由按住鼠标移动产生的。
+ 属性: ondraggesture

+
+

dragover

+
+

类似于 mouseover 事件,当有东西被拖拽到某个元素之上时,会触发 dragover 事件。这个事件应当判断被拖拽的对象是否可以释放。
+ 属性: ondragover

+
+

input

+
+

当用户在文本框输入的时候,会触发 input 事件。仅当显示的文本被修改时会触发这个事件,因此如果用户按了不会显示出来的按键时,这个事件是不会被触发的。
+ 属性: oninput

+
+

overflow

+
+

仅当 CSS 的 overflow 属性被设置为 visible 以外的值时才会触发 overflow 。当没有足够的空间显示某个元素当内容时,会触发 overflow 事件。例如,一个最大尺寸为 100 像素的盒,但是可用的空间只有 80 像素,那么就会触发 overflow 事件。如果因为用户修改窗口大小等因素导致大小被改变了,因此有了足够的空间时,会触发相应的 underflow 事件。
+ 属性: onoverflow

+
+

popuphidden

+
+

当一个弹出的元素被隐藏了时,会触发 popuphidden 事件。
+ 属性: onpopuphidden

+
+

popuphiding

+
+

当一个弹出的元素将被隐藏时,会触发 popuphiding 事件。
+ 属性: onpopuphiding

+
+

popupshowing

+
+

当一个弹出元素将被显示时,会触发 popupshowing 事件。这个事件经常被用来在用户需要显示弹出元素时动态地设置它的内容。在句柄中返回 false 可以阻止元素弹出。
+ 属性: onpopupshowing

+
+

popupshown

+
+

当一个弹出元素被显示了时,会触发 popupshown 事件。这类似于窗口上的 load 事件。
+ 属性: onpopupshown

+
+

syncfrompreference

+
+

因为选项的修改而导致元素改变时,会调用 syncfrompreference 事件。这个事件只会对 prefwindow 中的元素生效。这不是实际意义上的事件而仅仅是一个函数调用,所以这个事件必须使用属性形式的语法定义。函数可以返回不同于选项的特定的值。这个事件通常被用于为了让选项值更适合显式在用户界面中而调整选项值。
+ 属性: onsyncfrompreference

+
+

synctopreference

+
+

当与对象连接的属性值被修改时,会调用 synctopreference 事件。这不是实际意义上的事件而仅仅是一个函数调用,所以这个事件必须使用属性形式的语法定义。函数可以返回不同于选项的特定的值,以设置属性的值,而非使用元素的 value 。
+ 属性: onsynctopreference

+
+

underflow

+
+

当有了足够的空间完整地显示某个元素时,会触发这个元素的 underflow 事件。这个事件对所有 CSS 的 overflow 属性不为 visible 的盒或其他布局元素生效。这个事件说明滚动条已经没必要了。
+ 属性: onunderflow

+
+

DOMMenuItemActive

+
+

当鼠标在菜单或菜单项上时或某个菜单项没高亮时,会触发 DOMMenuItemActive 事件。这个事件是起泡的(bubbles)。

+
+

DOMMenuItemInactive

+
+

当鼠标移出菜单或菜单项或某个菜单项不再被高亮时,会触发 DOMMenuItemInactive 事件。这个事件是起泡的。

+
+ +

窗口事件

+ +

下列事件被绑定在顶级文档树窗口上,可以使用 window.addEventListener 监听。

+ + + + + + + + + + + + + + + + + + + + +
EventDescription
activate 当窗口变为活动窗口时触发。
deactivate 当窗口变为非活动窗口时触发。
sizemodechange +

当某个窗口被最小化,取消最小化,切换到全屏模式,或切换到窗口模式时触发。注意,这个事件可能被调用多次,或者因为修改窗口大小而被调用,(见 bug 715867 )。所以应当在事件中查看 window.windowState 检查窗口的状态。

+
+ +

可访问性事件

+ +

这些事件被用来通知可访问性系统。一般来说你不应该自行使用这些事件。

+ + + + + + + + + + + + + + + + +
EventDescription
+

CheckboxStateChange

+
+

当一个 checkbox 被选中或取消选中时,会触发 CheckboxStateChange 事件。这个事件可能由于用户动作触发,也可能由于脚本改变了选框的值。相比之下, command 事件只会因为用户的动作而触发,这时 CheckboxStateChange 事件在 command 事件之前触发。 CheckboxStateChange 事件是不起泡的。

+
+

RadioStateChange

+
+

当一个 radio 被选中时,会触发 RadioStateChange 事件。这个事件可能时由于用户动作触发,也可能时因为脚本修改了对应的值。相比之下, command 事件只会因为用户的动作而触发,这时 RadioStateChange 事件在 command 事件之前触发。 RadioStateChange 事件是起泡的,因此你可以在 radiogroup 绑定事件句柄。

+
+ +

+
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xul/image/index.html b/files/zh-cn/mozilla/tech/xul/image/index.html new file mode 100644 index 0000000000..f70f4a5f7d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/image/index.html @@ -0,0 +1,145 @@ +--- +title: image +slug: Mozilla/Tech/XUL/image +translation_of: Archive/Mozilla/XUL/image +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

Summary

+

用于图片显示的元素,与HTML中的img相似.使用 src可以指定图片的URL.

+

More information is available in the XUL tutorial.

+
+
+

Note: Prior to Gecko 8.0, images did not shrink down with the same ratio in both directions when specifying maximum sizes using maxheight or maxwidth. The new behavior aligns more with the HTML <img> element and shrinks both the width and height down proportionally.

+
+
+
+
+ Attributes
+
+ onerror, onload, src, validate
+
+
+
+ Properties
+
+ accessibleType, src
+
+
+
+ Style classes
+
+ alert-icon, error-icon, message-icon, question-icon
+
+

Examples

+
+ Image:Firefoxlogo2.png
+
<image src='Firefoxlogo.png' width='135' height='130'/>
+
+

Attributes

+

+ + +
+
onerror
+
Type: script code
+
This event is sent to an image element when an error occurs loading the image.
+
+
+ +

See

+ + + +
+ +
+
+ src
+
+ Type: URI
+
+ The URI of the content to appear in the element.
+
+ + +
+ +
+
+ validate
+
+ Type: + + one of the values below +
+
+ This attribute indicates whether to load the image from the cache or not. This would be useful if the images are stored remotely or you plan on swapping the image frequently. The following values are accepted, or leave out the attribute entirely for default handling:
+
+ + +

+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+ +
+
src
+
Type: URL
+
Gets and sets the value of the src attribute.
+
+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+

Style classes

+

+
+ alert-icon
+
+ Class that adds an alert icon. This typically looks like an exclamation mark. This and the other icon classes may be used by image elements or other elements which can have an image.
+
+
error-icon
+
Class that adds an error icon. This will typically be a red "X" icon.
+
+
message-icon
+
Class that adds a message box icon.
+
+
question-icon
+
Class that adds a question icon, which usually looks like a question mark.
+

+ +

See also the image and icon attributes.

+

Interfaces

+ +
+
diff --git a/files/zh-cn/mozilla/tech/xul/index.html b/files/zh-cn/mozilla/tech/xul/index.html new file mode 100644 index 0000000000..ac0e9697f5 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/index.html @@ -0,0 +1,79 @@ +--- +title: XUL +slug: Mozilla/Tech/XUL +tags: + - XUL +translation_of: Archive/Mozilla/XUL +--- +
+ 从这里开始
+   帮助你对XUL有一个比较直观的理解(该教程首发于 XULPlanet)
+
+

XUL 是一个Mozilla使用XML来描述用户界面的一种技术,使用XUL你可以快速的创建出跨平台,基于因特网的应用程序。基于XUL技术的应用程序可以很方便的使用好看的字体、图形以及方便的界面布局,而且也更容易部署和定制。如果程序员已经熟悉了Dynamic HTML (DHTML),那学习XUL将是更容易的事,也可以更快的开发基于XUL的应用程序.

+
+ + + + + + + +
+

推荐的文章

+
+
+ XUL模板手册
+
+ XUL模板是用于提供来自查询或是类似于结果集的内容块的一种方法.一个比较好的例子像数据库查询集.对于每个查询结果集,生成相关的内容块.XUL模板允许使用不的规则来生成基于特定要求的不同内容块,也允许给返回结果集设置属性.
+
+
+
+ XUL 教程
+
+ 这份教程教你如何进入XUL (XML User Interface Language,Mozilla的平台无关界面描述语言)神奇世界.设计一个简单的"查找文件"的界面, 对XUL的各种特性进行了解和学习.
+
+
+
+ XUL:用XUL做你意想不到的事
+
+ Vlad Vukicevic 写完了这个大杂烩式的 FAQ, 列出了在 XUL 中可以做的事情 (hopefully with bug numbers), 不可以做的事情 (hopefully with explanations), 以及如何解决它们的办法. 欢迎各位添加自己的 XUL 体验到文章里.
+
+
+
+ Mozilla's XML 用户接口语言 (表现层)
+
+ Ben Goodger 在阿姆斯特丹(Amsterdam)的 XTech 2005 大会上给出了这份关于 XUL 的表现层.
+
+
+
+ XUL应用程序教程
+
+ 这个教程被设计用来教你学会如何创建一个基于 XUL 的简单程序, 通过循序渐进地开发一个 XUL 程序来演示要讨论的概念.
+
+


+ 显示所有...

+
+

 

+

特色主题

+ +

其他页面

+ +

关联主题

+
+
+ JavaScript, XBL, CSS, RDF显示所有...
+
+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/key/index.html b/files/zh-cn/mozilla/tech/xul/key/index.html new file mode 100644 index 0000000000..13fabfbd2d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/key/index.html @@ -0,0 +1,166 @@ +--- +title: key +slug: Mozilla/Tech/XUL/key +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/key +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

The key element defines a keyboard shortcut. Event handlers can be used to respond when the appropriate keys are pressed. A key element must be placed inside a keyset element.

+

When a key matching the attributes on the key element is pressed, the command will be fired on the key element. The key pressed must match the key attribute (or keycode attribute) as well as the modifiers attribute in order for the key element to be activated and fire a command event.

+

For example, consider the following key:

+
<key key="r" modifiers="shift"/>
+
+

This key will only match when the Shift key is pressed as well as the R key, and no other keys. For instance, if the Shift, Control and R keys are all pressed, the key will not match.

+

To indiciate that a modifier key may optionally be pressed, place the word 'any' after listing the optional modifier key. For example:

+
<key key="r" modifiers="shift any control"/>
+
+

In this example, the shift key may or may not be pressed, while the control key must be pressed. This allows keys to match more loosely for modifier keys that aren't relevant, yet still allows specific modifiers to be required.

+

If the modifiers attribute is not specified, then no modifiers may be pressed for the key to match.

+

If neither the key or keycode attribute are used, the key element will handle all key events. However, if one of the attributes is set to an empty string, the element doesn't handle any key events. For example:

+
<!-- This element handles all key events -->
+<key/>
+
+<!-- These elements don't handle any key events -->
+<key key="" modifiers="control"/>
+<key keycode="" modifiers="control"/>
+
+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ command, disabled, key, keycode, keytext, modifiers, oncommand, phase
+
+

Examples

+

(example needed)

+

Attributes

+

+ +
+
+ command
+
+ Type: + + element id +
+
+ Set to the id of a command element that is being observed by the element.
+
+ +

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
key
+
Type: character
+
The character that must be pressed. This should be set to a displayable character.
+
+
+ + +
+
keycode
+
Type: string key code
+
For keys that do not have displayable characters, such as the Enter key or function keys, use this attribute instead of the key attribute. Valid keys are listed at Keyboard Shortcuts.
+
+
+ + +
+
keytext
+
Type: string
+
A label for the keyboard shortcut. This text would appear next to a menuitem label if that menuitem is associated with the key element via its key attribute.
+
+
+ + +
+
modifiers
+
Type: space-separated list of the values below
+
A list of modifier keys that should be pressed to invoke the keyboard shortcut. Multiple keys may be separated by spaces or commas. Keys will map to other keys on platforms that do not have them.
+
+ + +
+ + +
+
oncommand
+
Type: script code
+
This event handler is called when the command is activated. This occurs when a user selects a menu item or presses a keyboard shortcut attached to the command.
+
+ + +
+ + +
+
phase
+
Type: string
+
The event phase where the handler is invoked. This should be set to the value capturing to indicate during the event capturing phase or target to indicate at the target element or left out entirely for the bubbling phase.
+
+

+

Properties

+

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +

TBD

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/label/index.html b/files/zh-cn/mozilla/tech/xul/label/index.html new file mode 100644 index 0000000000..f6201f62c0 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/label/index.html @@ -0,0 +1,298 @@ +--- +title: label +slug: Mozilla/Tech/XUL/label +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/label +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

This element is used to provide a label for a control element. If the user clicks the label, it will move the focus to the associated control, specified with the control attribute.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ accesskey, control, crop, disabled, href, value
+
+
+
+ Properties
+
+ accessKey, accessibleType, control, crop, disabled, value
+
+
+
+ Style classes
+
+ header, indent, monospace, plain, small-margin, text-link
+
+

Examples

+
+ Image:XUL_ref_label.png
+
<label value="Email address" control="email"/>
+<textbox id="email"/>
+
+

Attributes

+

+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ +
+
+ control
+
+ Type: element id
+
+ This attribute specifies the id of the element with which the label is associated. When the user clicks on the label, the associated element is given focus.
+ 这个属性定义了元素的id,它与label相关联。当用户点击 label 的时候,相关联的元素将获得焦点。
+
+ +

 

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
href
+
类型: 文本
+
定义一个当元素被点击时将会打开的 URL 。需要引用类 text-link
+
+ + + + +
+ + +
+
value
+
Type: string
+
The text to be used for the label.
+
+

+

Properties

+

+
+
+ accessKey
+
+ Type: + + character +
+
+ Gets and sets the value of the accesskey attribute.
+
+ +

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ control
+
+ Type: element id
+
+ Gets and sets the value of the control attribute.
+
+
+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+ +

+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+

Style classes

+

The following classes may be used to style the element. These classes should be used instead of changing the style of the element directly since they will fit more naturally with the user's selected theme.

+

+
header
+
A class used for headings. Typically, this will cause the text to appear bold.
+
+
indent
+
This class causes the text to be indented on its left side.
+
+
monospace
+
This class causes the text to be displayed in a monospace font.
+
+
plain
+
This class causes the element to be displayed with no border or margin.
+
+
small-margin
+
This class causes the text to be displayed with a smaller margin.
+
+
text-link
+
Labels with this class may be focused and the click handler run or the address in the href attribute opened on a mouse click or Enter key press. Labels will appear like a link (blue and underlined).
+

+ +
+
+ Elements
+
+ description
+
+
+
+ Attributes
+
+ label
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULLabelElement
+
+

User notes

+

Remember that the label element has a "value" attribute, unlike value in HTML whereas buttons, checkboxes use label="foo" as the attribute

+
<label label="A Caption"/> <-- wrong -->
+<label value="A Caption"/>
+
+<label value="Click the button"/>
+<button label="A Button"/>
+<checkbox label="A Decision" value="1"/>
+
+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/list_of_commands/index.html b/files/zh-cn/mozilla/tech/xul/list_of_commands/index.html new file mode 100644 index 0000000000..54ff23cabf --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/list_of_commands/index.html @@ -0,0 +1,196 @@ +--- +title: List of commands +slug: Mozilla/Tech/XUL/List_of_commands +translation_of: Archive/Mozilla/XUL/List_of_commands +--- +

The following lists commands which might be usable by <command> or command dispatchers/controllers.

+

List of Commands (grouped by type)

+ + +

Editor commands (legal when the focus is anywhere where you can type text):

+ +

Other commands

+

The following list other commands (prefixed by cmd_ or Browser:) which have not been categorized here yet (though they are in the alphabetical list below):

+ +

 

+

List of commands (listed alphabetically)

+ +

Thanks for help of joe.user0 in compiling: http://readlist.com/lists/mozilla.or...l/3/15261.html . Also obtained from http://www.mozilla.org/unix/customizing.html

+

diff --git a/files/zh-cn/mozilla/tech/xul/listbox/index.html b/files/zh-cn/mozilla/tech/xul/listbox/index.html new file mode 100644 index 0000000000..04489bf06d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/listbox/index.html @@ -0,0 +1,480 @@ +--- +title: listbox +slug: Mozilla/Tech/XUL/listbox +translation_of: Archive/Mozilla/XUL/listbox +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

This element is used to create a list of items where one or more of the items may be selected. A listbox may contain multiple columns. There are numerous methods which allow the items in the listbox to be retrieved and modified.

+

You may specify the number of rows to display in the list using the rows attribute. Additional rows can be viewed using a scroll bar. A listbox is expected to contain listitem elements. All the rows in the listbox are the same height, which is the height of the tallest item in the list. If you wish to create a list with variable height rows, or with non-text content, you should instead use the richlistbox element.

+

See List Controls for more information.

+
+
+ Attributes
+
+ disabled, disableKeyNavigation, preference, rows, seltype, suppressonselect, tabindex, value
+
+
+
+ Properties
+
+ accessibleType, currentIndex, currentItem, disabled, disableKeyNavigation, itemCount, listBoxObject, selectedCount, selectedIndex, selectedItem, selectedItems, selType, suppressOnSelect, tabIndex, value
+
+
+
+ Methods
+
+ addItemToSelection, appendItem, clearSelection, ensureElementIsVisible, ensureIndexIsVisible, getIndexOfFirstVisibleRow, getIndexOfItem, getItemAtIndex, getNumberofVisibleRows, getRowCount, getSelectedItem, insertItemAt, invertSelection, moveByOffset, removeItemAt, removeItemFromSelection, scrollToIndex, selectAll, selectItem, selectItemRange, timedSelect, toggleItemSelection
+
+

Examples

+
+ Image:XUL_ref_listbox.png
+
 <listbox id="theList">
+   <listitem label="Ruby"/>
+   <listitem label="Emerald"/>
+   <listitem label="Sapphire" selected="true"/>
+   <listitem label="Diamond"/>
+ </listbox>
+
+
+

XulListBoxMultiColumn.PNG

+
<listbox id="theList" rows="10" width="400">
+  <listhead>
+     <listheader label="1ct Gem" width="240"/>
+     <listheader label="Price" width="150"/>
+  </listhead>
+  <listcols>
+    <listcol/>
+    <listcol flex="1"/>
+  </listcols>
+</listbox>
+
+var theList = document.getElementById('theList ');
+ gems = [  {gem: "Ruby", Price: "$3,500 - $4,600"},
+           {gem: "Emerald", Price: "$700 - 4,250"},
+           {gem: "Blue Sapphire", Price: "$3,400 - $4,500"},
+           {gem: "Diamond", Price: "$5,600 - $16,000"}  ];
+for (var i = 0; i < gems.length; i++)
+    {
+        var row = document.createElement('listitem');
+        var cell = document.createElement('listcell');
+        cell.setAttribute('label', gems[i].gem);
+        row.appendChild(cell);
+
+        cell = document.createElement('listcell');
+        cell.setAttribute('label',  gems[i].Price );
+        row.appendChild(cell);
+
+        theList.appendChild(row);
+    }
+
+
 
+

Attributes

+

+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
disableKeyNavigation
+
Type: boolean
+
If this attribute is not used, the user can navigate to specific items within the element by pressing keys corresponding to letters in the item's label. This is done incrementally, so typing more letters with select more specific items. This feature may be disabled by setting this attribute to true.
+
+
+ + +
+
preference
+
Type: id
+
Connects the element to a corresponding preference. This attribute only has any effect when used inside a prefwindow. More information is available in the Preferences System article.
+
+
+ +
+
+ rows
+
+ Type: integer
+
+ The number of rows to display in the element. If the element contains more than this number of rows, a scrollbar will appear which the user can use to scroll to the other rows. To get the actual number of rows in the element, use the getRowCount method.
+
+
+ + +
+
seltype
+
Type: one of the values below
+
Used to indicate whether multiple selection is allowed.
+
+
+
single
+
Only one row may be selected at a time. (Default in listbox and richlistbox.)
+
multiple
+
Multiple rows may be selected at once. (Default in tree.)
+
+
+
+

For trees, you can also use the following values:

+ +
+
cell
+
Individual cells can be selected
+
text
+
Rows are selected; however, the selection highlight appears only over the text of the primary column.
+
+ +

For richlistbox, this is new in Firefox 3.5.

+
+
+
+ + +
+
suppressonselect
+
Type: boolean
+
If this attribute is not specified, a select event is fired whenever an item is selected, either by the user or by calling one of the select methods. If set to true, the select event is never fired.
+
+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ +
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+ +

+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+ +
+
currentIndex
+
Type: integer
+
Set to the index of the currently focused item in the list. If no item is focused, the value will be -1. (or, on some platforms, typeof(listboxcurrentIndex) will be undefined) In a single selection list, the current index will always be the same as the selected index. In a multiple selection list, the currently focused row may be modified by the user without changing the selection by pressing the Control key and pressing the cursor keys to navigate.
+
+ +
+
currentItem
+
Type: listitem element
+
Returns the currently focused item in the list box, which is only useful in a multiple selection list box.
+
+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+
+
disableKeyNavigation
+
Type: boolean
+
Gets or sets the value of the disableKeyNavigation attribute.
+
+
+
itemCount
+
Type: integer
+
Read only property holding the number of child items.
+
+
+
+
+ listBoxObject
+
+ Type: nsIListBoxObject
+
+ The nsIListBoxObject behind the list box. This property is read-only. Most of the features of the list box are already available directly in the listbox, so you will rarely have need to use this box object directly.
+
+ +
+
selectedCount
+
Type: integer
+
Returns the number of items that are currently selected.
+
+
+
+ selectedIndex
+
+ Type: + + integer +
+
+ Returns the index of the currently selected item. You may select an item by assigning its index to this property. By assigning -1 to this property, all items will be deselected.
+
+ +

+
+
+ selectedItem
+
+ Type: + + element +
+
+ Holds the currently selected item. If no item is currently selected, this value will be null. You can select an item by setting this value. A select event will be sent to the element when it is changed either via this property, the selectedIndex property, or changed by the user.
+
+ +

+ +
+
selectedItems
+
Type: array of listitems
+
Returns an array of the selected items in the list.
+
+
+
+ selType
+
+ Type: string
+
+ Gets and sets the value of the seltype attribute.
+
+

 

+ +
+
suppressOnSelect
+
Type: boolean
+
Gets and sets the value of the suppressonselect attribute.
+
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+

Methods

+

+ + + + + +
+

Inherited Methods
+addEventListener(), appendChild(), blur, click, cloneNode(), compareDocumentPosition, dispatchEvent(), doCommand, focus, getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getBoundingClientRect(), getClientRects(), getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName(), getElementsByTagName(), getElementsByTagNameNS(), getFeature(), getUserData, hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isDefaultNamespace(), isEqualNode, isSameNode, isSupported(), lookupNamespaceURI, lookupPrefix, normalize(), querySelector(), querySelectorAll(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS(), setUserData

+ +
+
addItemToSelection( item )
+
Return type: no return value
+
Selects the given item, without deselecting any other items that are already selected.
+
+
+ appendItem( label, value )
+
+ Return type: element
+
+ Creates a new item and adds it to the end of the existing list of items. You may optionally set a value. The function returns the newly created element.
+
+
clearSelection()
+
Return type: no return value
+
Deselects all of the items.  A select event is sent before the items are deselected.
+
+
ensureElementIsVisible( element )
+
Return type: no return value
+
If the specified element is not currently visible to the user, the displayed items are scrolled so that it is. If the item is already visible, no scrolling occurs.
+
+
ensureIndexIsVisible( index )
+
Return type: no return value
+
If the item at the specified index is not currently visible to the user the displayed items are scrolled so that it is. If the item is already visible, no scrolling occurs.
+
+
getIndexOfFirstVisibleRow()
+
Return type: integer
+
Returns the index of the first displayed row. Note that this is not the same as the first row -- if the displayed items have been scrolled down, this function will retrieve the index of the first row that the user can see.
+
+
getIndexOfItem( item )
+
Return type: integer
+
Returns the zero-based position of the specified item. Items are numbered starting at the first item displayed in the list.
+
+
getItemAtIndex( index )
+
Return type: element
+
Returns the element that is at the specified index.
+
+
getNumberOfVisibleRows()
+
Return type: integer
+
Returns the number of rows that are currently visible to the user.
+
+
+ getRowCount()
+
+ Return type: integer
+
+ Returns the total number of rows in the element, regardless of how many rows are displayed.
+
+
getSelectedItem( index )
+
Return type: element
+
When multiple items are selected, you can retrieve each selected item using this method. The argument index specifies the index in the list of the selected items, not the row number of the item. The item index is zero-based, thus this example will return the first selected item: getSelectedItem(0).
+
+
+ insertItemAt( index, label, value )
+
+ Return type: element
+
+ This method creates a new item and inserts it at the specified position. You may optionally set a value. The new item element is returned.
+
+
invertSelection()
+
Return type: no return value
+
Reverses the selected state of all items. Selected items become deselected, and deselected items become selected.
+
+
moveByOffset( offset , isSelecting, isSelectingRange)
+
Return type: no return value
+
If offset is positive, adjusts the focused item forward by that many items. If offset is negative, adjusts the focused item backward by that many items. If isSelecting is true, then the selection is also adjusted. If isSelectingRange is also true, then the new item is selected in addition to any currently selected items. If isSelectingRange is false, any existing selection is cleared. Items that are hidden are skipped.
+
+
+ removeItemAt( index )
+
+ Return type: element
+
+ Removes the child item in the element at the specified index. The method returns the removed item.
+
+
removeItemFromSelection( item )
+
Return type: no return value
+
Deselects the specified item without deselecting other items.
+
+
scrollToIndex( index )
+
Return type: no return value
+
Scrolls the element to the specified index. This is different than ensureIndexIsVisible because the view is always scrolled.
+
+
+ selectAll()
+
+ Return type: no return value
+
+ Selects all of the items. A select event is sent after the selection is made.
+
+
+ selectItem( item )
+
+ Return type: no return value
+
+ Deselects all of the currently selected items and selects the given item. A select event is sent after the selection is made.
+
+
+ selectItemRange( startItem, endItem )
+
+ Return type: no return value
+
+ Selects the items between the two items given as arguments, including the start and end items. All other items are deselected. This method does nothing for single-selection list boxes. A select event is sent after the selection is made.
+
+
+ timedSelect( item, timeout )
+
+ Return type: no return value
+
+ Selects the item specified by the argument item after the number of milliseconds given by the timeout argument. All other items are deselected.
+
+
+ toggleItemSelection( item )
+
+ Return type: no return value
+
+ If the specified item is selected, it is deselected. If it is not selected, it is selected. Other items in the list box that are selected are not affected, and retain their selected state.
+

+ +
+
+ Elements
+
+ listcell, listcol, listcols, listhead, listheader, listitem
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULMultiSelectControlElement
+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/listheader/index.html b/files/zh-cn/mozilla/tech/xul/listheader/index.html new file mode 100644 index 0000000000..d71bcb6e83 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/listheader/index.html @@ -0,0 +1,180 @@ +--- +title: listheader +slug: Mozilla/Tech/XUL/listheader +translation_of: Archive/Mozilla/XUL/listheader +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

A header for a single column in a listbox.

+
+
+ Attributes
+
+ disabled
+
+
+
+ Properties
+
+ acesssibleType
+
+

Examples

+
+ Image:XUL_ref_listheader.png
+
<listbox>
+  <listhead>
+    <listheader label="Name"/>
+    <listheader label="Occupation"/>
+  </listhead>
+  <listitem>
+    <listcell label="George"/>
+    <listcell label="House Painter"/>
+  </listitem>
+  <listitem>
+    <listcell label="Mary Ellen"/>
+    <listcell label="Candle Maker"/>
+  </listitem>
+  <listitem>
+    <listcell label="Roger"/>
+    <listcell label="Swashbuckler"/>
+  </listitem>
+</listbox>
+
+

Attributes

+

+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ + + + + +

Inherited from XUL element
+align, +allowevents, +allownegativeassertions, +class, +coalesceduplicatearcs, +collapsed, +container, +containment, +context, +contextmenu, +datasources, +dir, +empty, +equalsize, +flags, +flex, +height, +hidden, +id, +insertafter, +insertbefore, +left, +maxheight, +maxwidth, +menu, +minheight, +minwidth, +mousethrough, +observes, +ordinal, +orient, +pack, +persist, +popup, +position, +preference-editable, +querytype, +ref, +removeelement, +sortDirection, +sortResource, +sortResource2, +statustext, +style, +template, +tooltip, +tooltiptext, +top, +uri, +wait-cursor, +width

+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +
+
+ Elements
+
+ listbox, listcell, listcol, listcols, listhead, listitem
+
diff --git a/files/zh-cn/mozilla/tech/xul/menu/index.html b/files/zh-cn/mozilla/tech/xul/menu/index.html new file mode 100644 index 0000000000..b204dcf14b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/menu/index.html @@ -0,0 +1,370 @@ +--- +title: menu +slug: Mozilla/Tech/XUL/menu +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/menu +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

An element, much like a button, that is placed on a menubar. When the user clicks the menu element, the child menupopup of the menu will be displayed. This element is also used to create submenus.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ acceltext, accesskey, allowevents, command, crop, disabled, image, label, menuactive, open, sizetopopup, tabindex, value
+
+
+
+ Properties
+
+ accessibleType, accessKey, command, control, crop, disabled, image, itemCount, label, labelElement, menupopup, open, parentContainer, selected, tabIndex, value
+
+
+
+ Methods
+
+ appendItem, getIndexOfItem, getItemAtIndex, insertItemAt, removeItemAt
+
+

Example

+
  <menubar id="sample-menubar">
+    <menu id="file-menu" label="File">
+      <menupopup id="file-popup">
+        <menuitem label="New"/>
+        <menuitem label="Open"/>
+        <menuitem label="Save"/>
+        <menuseparator/>
+        <menuitem label="Exit"/>
+      </menupopup>
+    </menu>
+    <menu id="edit-menu" label="Edit">
+      <menupopup id="edit-popup">
+        <menuitem label="Undo"/>
+        <menuitem label="Redo"/>
+      </menupopup>
+    </menu>
+  </menubar>
+
+

Attributes

+

+ +
+
+ acceltext
+
+ Type: + + string +
+
+ Text that appears beside beside the menu label to indicate the shortcut key (accelerator key) to use to invoke the command. If this value is set, it overrides an assigned key set in the key attribute. This attribute does not apply to menus directly on the menubar.
+
+ +

+
+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ + +
+
allowevents
+
Type: + boolean
+
+ 类型:boolean
+
If true, events are passed to children of the element. Otherwise, events are passed to the element only.
+ 如果为真,事件向子元素传递。否则,事件只传递到当前元素。
+
+ + + +

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ + +
+
menuactive
+
Type: boolean
+
This attribute is set on an item in a menu when it is being hovered over. Typcially, the theme will use this to highlight the item. A DOMMenuItemActive event will be sent to the item when the item is hovered over, and a DOMMenuItemInactive event will be sent to the item when the selection moves away.
+
+
+ + +
+
open
+
Type: boolean
+
For the menu type buttons, the open attribute is set to true when the menu is open. The open attribute is not present if the menu is closed.
+
+
+ + +
+
sizetopopup
+
Type: one of the values below
+
Indicates how the menu width and the menupopup width are determined. If the sizetopopup attribute is left out or set to none, the menu will be its preferred width and the popup may extend outside of this width, unaffected by the maximum width of the menu itself. Otherwise, the menu will size itself to at least the size of the popup. If the menu has a maximum width, the popup will also be this width.
+
+
+
none
+
The width of the popup will not be constrained to the size of the menu.
+
pref
+
The preferred width of the menu label or button will be the size needed for the popup contents. This is the default value for menulists.
+
always
+
Both the preferred and minimum width of the menu label or button will be the same as that necessary for the menupopup.
+
+
+
+
+ +
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+ +

+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ control
+
+ Type: + + menu element +
+
+ Returns the enclosing menu that the item is inside, if any, or null if there is no enclosing menu.
+
+ +

+
+
itemCount
+
Type: integer
+
Read only property holding the number of child items.
+
+
+ +
+
menupopup
+
Type: menupopup element
+
A reference to the menupopup used by the menu or menulist. This property is read-only.
+
+
+
+ open
+
+ Type: boolean
+
+ This property will be set to true when the menu is open. The menu may be opened by setting the open property to true and closed by setting it to false.
+
+
+
+ parentContainer
+
+ Type: + + menu element +
+
+ Read only property that returns the containing menu element, or null if there isn't a containing menu.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+

Methods

+

+ + + + + +
+

Inherited Methods
+addEventListener(), appendChild(), blur, click, cloneNode(), compareDocumentPosition, dispatchEvent(), doCommand, focus, getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getBoundingClientRect(), getClientRects(), getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName(), getElementsByTagName(), getElementsByTagNameNS(), getFeature(), getUserData, hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isDefaultNamespace(), isEqualNode, isSameNode, isSupported(), lookupNamespaceURI, lookupPrefix, normalize(), querySelector(), querySelectorAll(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS(), setUserData

+ +
+
+ appendItem( label, value )
+
+ Return type: element
+
+ Creates a new item and adds it to the end of the existing list of items. You may optionally set a value. The function returns the newly created element.
+
+
getIndexOfItem( item )
+
Return type: integer
+
Returns the zero-based position of the specified item. Items are numbered starting at the first item displayed in the list.
+
+
getItemAtIndex( index )
+
Return type: element
+
Returns the element that is at the specified index.
+
+
+ insertItemAt( index, label, value )
+
+ Return type: element
+
+ This method creates a new item and inserts it at the specified position. You may optionally set a value. The new item element is returned.
+
+
+ removeItemAt( index )
+
+ Return type: element
+
+ Removes the child item in the element at the specified index. The method returns the removed item.
+

+ +
+
+ Elements
+
+ menubar, menuitem, menulist, menupopup, menuseparator
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULContainerElement, nsIDOMXULContainerItemElement, nsIDOMXULSelectControlItemElement
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/menubar/index.html b/files/zh-cn/mozilla/tech/xul/menubar/index.html new file mode 100644 index 0000000000..d7946debf9 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/menubar/index.html @@ -0,0 +1,113 @@ +--- +title: menubar +slug: Mozilla/Tech/XUL/menubar +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/menubar +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

A container that usually contains menu elements. On the Macintosh, the menubar is displayed along the top of the screen, and all non-menu related elements inside the menubar will be ignored.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ grippyhidden, statusbar
+
+
+
+ Properties
+
+ accessibleType, statusbar
+
+

Examples

+
+ Image:XUL_ref_menu.png
+
<menubar id="sample-menubar">
+  <menu id="action-menu" label="Action">
+    <menupopup id="action-popup">
+      <menuitem label="New"/>
+      <menuitem label="Save" disabled="true"/>
+      <menuitem label="Close"/>
+      <menuseparator/>
+      <menuitem label="Quit"/>
+    </menupopup>
+  </menu>
+  <menu id="edit-menu" label="Edit">
+    <menupopup id="edit-popup">
+      <menuitem label="Undo"/>
+      <menuitem label="Redo"/>
+    </menupopup>
+  </menu>
+</menubar>
+
+

Attributes

+

+ + +
+
grippyhidden
+
SeaMonkey only
+
Type: boolean
+
When set to true, the grippy will be hidden. When set to false, the default, the grippy will be shown.
+
+
+ + +
+
statusbar
+
Type: id
+
If you set this attribute to the id of a statusbar element, the label on the statusbar will update to the statustext of the items on the menu as the user moves the mouse over them.
+
+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+ +
+
statusbar
+
Type: id of statusbar element
+
Gets and sets the value of the statusbar attribute.
+
+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +
+
+ Elements
+
+ menu, menuitem, menulist, menupopup, menuseparator
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider
+
+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/menuitem/index.html b/files/zh-cn/mozilla/tech/xul/menuitem/index.html new file mode 100644 index 0000000000..a231f6a348 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/menuitem/index.html @@ -0,0 +1,575 @@ +--- +title: menuitem +slug: Mozilla/Tech/XUL/menuitem +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/menuitem +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

A single choice in a menupopup element. It acts much like a button but it is rendered on a menu.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ acceltext, accesskey, allowevents, autocheck, checked, command, crop, description, disabled, image, key, label, name, selected, tabindex, type, validate, value
+
+
+
+ Properties
+
+ accessibleType, accessKey, command, control, crop, disabled, image, label, labelElement, parentContainer, selected, tabIndex, value
+
+
+
+ Style classes
+
+ menuitem-iconic, menuitem-non-iconic
+
+

Example

+
<menu id="edit-menu" label="Edit">
+  <menupopup id="edit-popup">
+     <menuitem label="Undo"/>
+     <menuitem label="Redo"/>
+  </menupopup>
+</menu>
+
+

Attributes

+

+ +
+
+ acceltext
+
+ Type: + + string +
+
+ Text that appears beside beside the menu label to indicate the shortcut key (accelerator key) to use to invoke the command. If this value is set, it overrides an assigned key set in the key attribute. This attribute does not apply to menus directly on the menubar.
+
+ +

+
+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ + +
+
allowevents
+
Type: + boolean
+
+ 类型:boolean
+
If true, events are passed to children of the element. Otherwise, events are passed to the element only.
+ 如果为真,事件向子元素传递。否则,事件只传递到当前元素。
+
+ + + +

+
+ + +
+
autocheck
+
类型: + boolean +
+
如果此属性为 true,或空白, 每次点击按钮时,此按钮的状态检查都会被执行一次。如果此属性为false, 检查会手动的被拒绝。当autocheck值为true的时候,按钮将会变为多选框或者单选框。
+
+ + + +

+
+ +
+
+ checked
+
+ Type: + + boolean +
+
+ Indicates whether the element is checked or not.
+
+ Use hasAttribute() to determine whether this attribute is set instead of getAttribute().
+
+ For buttons, the type attribute must be set to checkbox or radio for this attribute to have any effect.<magic name="\"PAGENAME\"/"></magic>
+
+

+
+ Note: if the checked attribute is set to true, and you persist its value via the persist attribute, Mozilla will fail to persist its value when the menuitem is unchecked because of bug 15232. A workaround is to set the autocheck attribute to false, then programmatically set the checked attribute when the user selects the item, and set it to false instead of removing the attribute (i.e. do menuitem.setAttribute("checked", "false") instead of menuitem.removeAttribute("checked")) when the user unchecks the menuitem, as a value of false will both correctly hide the checkmark and persist its hidden state.
+

+ +
+
+ command
+
+ Type: + + element id +
+
+ Set to the id of a command element that is being observed by the element.
+
+ +

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ +
+
+ description
+
+ Type: + + string +
+
+ Descriptive text to appear in addition to the dialog title.
+
+ +

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ +
+
+ image
+
+ Type: + + image URL +
+
+ The URL of the image to appear on the element. If this attribute is empty or left out, no image appears. The position of the image is determined by the dir and orient attributes.
+
+ +

+
+ +
+
+ key
+
+ Type: + + element id +
+
+ Set to the id of a key element whose key shortcut is displayed in the menuitem.
+
+ +

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ +
+
+ name
+
+ Type: + + string name +
+
+ Radio menuitems with the same name as put into a group. Only one menuitem in each radio group can be checked at a time.
+
+ +

+
+ +
+
+ selected
+
+ Type: + + boolean +
+
+ Indicates whether the element is selected or not. This value is read-only. To change the selection, set either the selectedIndex or selectedItem property of the containing element.
+
+ +

+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ +
+
+ type
+
+ Type: + + one of the values below +
+
+ Can be used to create checkable menuitems or for radio button menuitems.
+
+ +

More information on adding checkmarks to menus in the XUL tutorial

+ +

+
+ +
+
+ validate
+
+ Type: + + one of the values below +
+
+ This attribute indicates whether to load the image from the cache or not. This would be useful if the images are stored remotely or you plan on swapping the image frequently. The following values are accepted, or leave out the attribute entirely for default handling:
+
+ + +

+
+ +
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+ +

+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ accessKey
+
+ Type: + + character +
+
+ Gets and sets the value of the accesskey attribute.
+
+ +

+
+
+ command
+
+ Type: + + element id +
+
+ Gets and sets the value of the command attribute.
+
+ +

+
+
+ control
+
+ Type: + + menu element +
+
+ Returns the enclosing menu that the item is inside, if any, or null if there is no enclosing menu.
+
+ +

+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+ +

+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+
+
+ image
+
+ Type: + + image URL +
+
+ Gets and sets the value of the image attribute.
+
+ +

+
+
+ label
+
+ Type: + + string +
+
+ Gets and sets the value of the label attribute.
+
+ +

+
+
+ labelElement
+
+ Type: + + label element +
+
+ The label element associated with the control. This is set when a label has a control attribute pointing to this element. This property will be null when no label is associated with the control.
+
+ +

+
+
+ parentContainer
+
+ Type: + + menu element +
+
+ Read only property that returns the containing menu element, or null if there isn't a containing menu.
+
+ +

+
+
+ selected<magic name="\"PAGENAME\"/"></magic>
+
+ Type: + + boolean +
+
+ This property's value is true if this element is selected, or false if it is not. This property is read only.
+
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+

Style classes

+

+
+ menuitem-iconic
+
+ Use this class to have an image appear on the menuitem. Specify the image using the image attribute.
+
+ +

+
+ menuitem-non-iconic
+
+ Normally, menuitems have a margin to the left for an image or checkmark. This class may be used to remove this margin so that the menuitem appears on the left edge of the menupopup.
+
+ +

+ +
+
+ Elements
+
+ menu, menubar, menulist, menupopup, menuseparator
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULContainerItemElement, nsIDOMXULSelectControlItemElement
+
+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/menulist/index.html b/files/zh-cn/mozilla/tech/xul/menulist/index.html new file mode 100644 index 0000000000..7273d413e7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/menulist/index.html @@ -0,0 +1,509 @@ +--- +title: menulist +slug: Mozilla/Tech/XUL/menulist +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/menulist +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

An element that can be used for drop-down choice lists. The user may select one of the elements displayed in the menulist. The currently selected choice is displayed on the menulist element. To create the drop-down, put a menupopup inside the menulist containing the choices as menuitem elements. The command event may be used to execute code when the menulist selection changes.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ accesskey, crop, disableautoselect, disabled, editable, focused, image, label, oncommand, open, preference, readonly, sizetopopup, tabindex, value
+
+
+
+ Properties
+
+ accessibleType, crop, description, disableautoselect, disabled, editable, editor, image, inputField, itemCount, label, menuBoxObject, menupopup, open, selectedIndex, selectedItem, tabIndex, value
+
+
+
+ Methods
+
+ appendItem, contains, getIndexOfItem, getItemAtIndex, insertItemAt, removeAllItems, removeItemAt, select
+
+

Examples

+
  <menulist>
+    <menupopup>
+      <menuitem label="option 1" value="1"/>
+      <menuitem label="option 2" value="2"/>
+      <menuitem label="option 3" value="3"/>
+      <menuitem label="option 4" value="4"/>
+    </menupopup>
+  </menulist>
+
+

Attributes

+

+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ + +
+
disableautoselect
+
Type: boolean
+
If this attribute is true or omitted, the selected item on the menu will update to match what the user entered in the textbox. If the text does not match any of the items in the list, the menu selection is cleared. If this attribute is false, the selection is never updated to match the text box. This attribute applies only to editable menulists.
+
+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
editable
+
Type: boolean
+
Indicates that the value of the menulist can be modified by typing directly into the value field. This is rendered as a textbox with a drop-down arrow beside it. The user may enter text into the textbox or select one of the choices by clicking from the drop-down.
+
+
+ + +
+
focused
+
Type: boolean
+
This attribute is true if the element is focused.
+
+
+ +
+
+ image
+
+ Type: + + image URL +
+
+ The URL of the image to appear on the element. If this attribute is empty or left out, no image appears. The position of the image is determined by the dir and orient attributes.
+
+ +

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ + +
+
oncommand
+
Type: script code
+
This event handler is called when the command is activated. This occurs when a user selects a menu item or presses a keyboard shortcut attached to the command.
+
+ + +
+ + +
+
open
+
Type: boolean
+
For the menu type buttons, the open attribute is set to true when the menu is open. The open attribute is not present if the menu is closed.
+
+
+ + +
+
preference
+
Type: id
+
Connects the element to a corresponding preference. This attribute only has any effect when used inside a prefwindow. More information is available in the Preferences System article.
+
+
+ + +
+
readonly
+
Type: boolean
+
If set to true, then the user cannot change the value of the element. However, the value may still be modified by a script.
+
+
+ + +
+
sizetopopup
+
Type: one of the values below
+
Indicates how the menu width and the menupopup width are determined. If the sizetopopup attribute is left out or set to none, the menu will be its preferred width and the popup may extend outside of this width, unaffected by the maximum width of the menu itself. Otherwise, the menu will size itself to at least the size of the popup. If the menu has a maximum width, the popup will also be this width.
+
+
+
none
+
The width of the popup will not be constrained to the size of the menu.
+
pref
+
The preferred width of the menu label or button will be the size needed for the popup contents. This is the default value for menulists.
+
always
+
Both the preferred and minimum width of the menu label or button will be the same as that necessary for the menupopup.
+
+
+
+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ +
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+ +

+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+ +

+ +
+
description
+
Type: string
+
Set to the description of the currently selected menuitem.
+
+ +
+
disableautoselect
+
Type: boolean
+
Gets and sets the value of the disableautoselect attribute.
+
+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+
+
+ editable
+
+ Type: boolean
+
+ Returns true if the element is editable. Autocomplete fields are editable so this property always returns true for those.
+
+

 

+ +
+
editor
+
Type: nsIEditor
+
A reference to the nsIEditor for editable text. This property is read only.
+
+ +
+
image
+
Type: image URL
+
The image associated with the currently selected item.
+
+ +
+
inputField
+
Type: textbox element
+
A reference to the textbox element used for editable menu lists. This property is read only and applies to editable menulists only.
+
+ +
+
+
itemCount
+
Type: integer
+
Read only property holding the number of child items.
+
+
+
+
+ label
+
+ Type: + + string +
+
+ Gets and sets the value of the label attribute.
+
+ +

+ +
+
menuBoxObject
+
Type: nsIMenuBoxObject
+
A reference to the nsIMenuBoxObject which implements the menu.
+
+ +
+
menupopup
+
Type: menupopup element
+
A reference to the menupopup used by the menu or menulist. This property is read-only.
+
+
+
+ open
+
+ Type: boolean
+
+ Gets and sets the value of the open attribute.
+
+
+
+
+ selectedIndex
+
+ Type: + + integer +
+
+ Returns the index of the currently selected item. You may select an item by assigning its index to this property. By assigning -1 to this property, all items will be deselected.
+
+ +

+
+
+ selectedItem
+
+ Type: + + element +
+
+ Holds the currently selected item. If no item is currently selected, this value will be null. You can select an item by setting this value. A select event will be sent to the element when it is changed either via this property, the selectedIndex property, or changed by the user.
+
+ +

+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+

Methods

+

+ + + + + +
+

Inherited Methods
+addEventListener(), appendChild(), blur, click, cloneNode(), compareDocumentPosition, dispatchEvent(), doCommand, focus, getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getBoundingClientRect(), getClientRects(), getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName(), getElementsByTagName(), getElementsByTagNameNS(), getFeature(), getUserData, hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isDefaultNamespace(), isEqualNode, isSameNode, isSupported(), lookupNamespaceURI, lookupPrefix, normalize(), querySelector(), querySelectorAll(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS(), setUserData

+ +
+
appendItem( label, value, description )
+
Return type: element
+
Creates a new menuitem element and adds it to the end of the menulist. You may optionally set a value and description. The function returns the new item.
+
+
contains( item )
+
Return type: boolean
+
Returns true if the menulist contains the specified menuitem as one of its items.
+
+
getIndexOfItem( item )
+
Return type: integer
+
Returns the zero-based position of the specified item. Items are numbered starting at the first item displayed in the list.
+
+
getItemAtIndex( index )
+
Return type: element
+
Returns the element that is at the specified index.
+
+
+ insertItemAt( index, label, value )
+
+ Return type: element
+
+ This method creates a new item and inserts it at the specified position. You may optionally set a value. The new item element is returned.
+
+
removeAllItems()
+
Return type: no return value
+
Removes all of the items in the menu.
+
+
+ removeItemAt( index )
+
+ Return type: element
+
+ Removes the child item in the element at the specified index. The method returns the removed item.
+
+
select()
+
Return type: no return value
+
Select all the text in the menulist's textbox. This method applies to editable menulists only.
+

+ +
+
+ Elements
+
+ menu, menubar, menuitem, menupopup, menuseparator
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULMenuListElement
+
+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/menupopup/index.html b/files/zh-cn/mozilla/tech/xul/menupopup/index.html new file mode 100644 index 0000000000..23b103ebb9 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/menupopup/index.html @@ -0,0 +1,324 @@ +--- +title: menupopup +slug: Mozilla/Tech/XUL/menupopup +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/menupopup +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

A container used to display the contents of a popup menu. When a menupopup is open, it floats above the window and may extend outside the window border. There are several ways in which a menupopup may be used:

+
    +
  1. It may be placed inside a menu, menulist, toolbarbutton, or a button with the type attribute set to "menu" to create a popup that will open when the menu or button is pressed.
  2. +
  3. It may be attached to any element using the popup attribute. When the element is clicked with the left mouse button, the menupopup will be displayed.
  4. +
  5. It may be attached to any element using the context attribute. When a context menu is opened, the menupopup will be displayed. A context menu may be opened by right-clicking the element, or by pressing the menu key on the keyboard.
  6. +
+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ ignorekeys, left, onpopuphidden, onpopuphiding, onpopupshowing, onpopupshown, position, top
+
+
+
+ Properties
+
+ accessibleType, popupBoxObject, popup, state
+
+
+
+ Methods
+
+ hidePopup, moveTo, openPopup, openPopupAtScreen, showPopup, sizeTo
+
+

Examples

+

The following example shows how a menupopup may be attached to a menulist.

+
<menulist>
+  <menupopup>
+    <menuitem label="Mozilla" value="http://mozilla.org"/>
+    <menuitem label="Slashdot" value="http://slashdot.org"/>
+    <menuitem label="Sourceforge" value="http://sf.net"/>
+    <menuitem label="Freshmeat" value="http://freshmeat.net"/>
+  </menupopup>
+</menulist>
+
+

The following example shows how a menupopup can be used a context menu for an element. When the label is right-clicked, the menu will be displayed.

+
+ Image:XUL_ref_popup.png
+
<menupopup id="clipmenu">
+  <menuitem label="Cut"/>
+  <menuitem label="Copy"/>
+  <menuitem label="Paste"/>
+</menupopup>
+<label value="Right click for popup" context="clipmenu"/>
+
+

Attributes

+

+ + +
+
ignorekeys
+
Type: boolean
+
If true, keyboard navigation between items in the popup is disabled.
+
+
+ + +
+
left
+
Type: integer
+
Overrides the horizontal position of the popup specified by the showPopup method.
+
+
+ + +
+
onpopuphidden
+
Type: script code
+
This event is sent to a popup after it has been hidden.
+
This event may also be received while the popup is still open, but when sub-menus contained within this popup are hidden.
+
+

Example:

+
+
+ +
<menupopup id="top" onpopuphidden="console.log('The onpopuphidden method of id=top was called.');">
+    <menuitem label="item 1"/>
+    <menuitem label="item 2"/>
+    <menu id="submenu1" label="submenu 1">
+        <menupopup id="submenu1-popup">
+            <menuitem label="submenu1 item 1"/>
+            <menuitem label="submenu1 item 2"/>
+        </menupopup>
+    </menu>
+    <menu id="submenu2" label="submenu 1">
+        <menupopup id="submenu2-popup">
+            <menuitem label="submenu2 item 1"/>
+            <menuitem label="submenu2 item 2"/>
+        </menupopup>
+    </menu>
+<menupopup/>
+
+ + +
+ + +
+
onpopuphiding
+
Type: script code
+
This event is sent to a popup when it is about to be hidden.
+
+
+ +
+
+ onpopupshowing
+
+ Type: script code
+
+ This event is sent to a popup just before it is opened. This handler is usually used to dynamically set the contents when the user requests to display it. Returning false from this event handler prevents the popup from appearing.
+
+ 该事件在 popup 打开之前传给它。它用于动态生成菜单项。如果返回 false 值,则 popup 将不会显示菜单项。
+
+ +

 

+
+ +
+
+ onpopupshown
+
+ Type: script code
+
+ This event is sent to a popup after it has been opened, much like the onload event is sent to a window when it is opened.
+
+ 该事件在 popup 打开之后触发,与 window 的 onload 事件比较类似。
+
+ +

 

+
+ + +
+
position
+
Type: string
+
The position attribute determines where the popup appears relative to the element the user clicked to invoke the popup. This allows you to place the popup on one side of a button.  Note that a context menu will never respect this attribute, always appearing relative to the mouse cursor.
+

+ This value can be specified either as a single word offering pre-defined alignment positions, or as 2 words specifying exactly which part of the anchor and popup should be aligned.
+

+ If specified as 2 words, the value indicates which corner or edge of the anchor (the first word) is aligned which which corner of the popup (the second word).  The anchor value (ie, the first word) can be one of topleft, topright, bottomleft, bottomright, leftcenter, rightcenter, topcenter or bottomcenter.  The popup value (ie, the second word) can be one of topleft, topright, bottomleft or bottomright.
+

+ Positions specified as a single word string are shortcuts for the values above.  Valid single-word values are after_start, after_end, before_start, before_end, end_after, end_before, start_after, start_before, overlap, at_pointer or after_pointer.
+
For more details, including examples, please see popup positioning
+
+ + +
+ + +
+
top
+
Type: integer
+
Overrides the vertical position of the popup specified by the showPopup method.
+
+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ popupBoxObject
+
+ Type: nsIPopupBoxObject
+
+ This read-only property holds the nsIPopupBoxObject that implements the popup. You wouldn't normally need to use this property as all of its functions are available via the popup itself.
+
+
+
+ position
+
+ Type: string
+
+ Gets and sets the value of the position attribute.
+
+
+
+ state
+
+ Type: string
+
+ This read only property indicates whether the popup is open or not. Four values are possible: +
    +
  • closed: The popup is closed and not visible.
  • +
  • open: The popup is open and visible on screen.
  • +
  • showing: A request has been made to open the popup, but it has not yet been shown. This state will occur during the popupshowing event.
  • +
  • hiding: The popup is about to be hidden. This state will occur during the popuphiding event.
  • +
+
+

+

Methods

+

+ + + + + +
+

Inherited Methods
+addEventListener(), appendChild(), blur, click, cloneNode(), compareDocumentPosition, dispatchEvent(), doCommand, focus, getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getBoundingClientRect(), getClientRects(), getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName(), getElementsByTagName(), getElementsByTagNameNS(), getFeature(), getUserData, hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isDefaultNamespace(), isEqualNode, isSameNode, isSupported(), lookupNamespaceURI, lookupPrefix, normalize(), querySelector(), querySelectorAll(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS(), setUserData

+ +
+
+ hidePopup()
+
+ Return type: no return value
+
+ Closes the popup immediately.
+
+
+ moveTo( x, y )
+
+ Return type: no return value
+
+ Moves the popup to a new location defined by screen coordinates (and not client coordinates).
+
+ If both x and y have the value -1 the call will realign the popup with its anchor node.
+
+
+ openPopup( anchor , position , x , y , isContextMenu, attributesOverride, triggerEvent )
+
+ Return type: no return value
+
+

Opens the popup relative to a specified node at a specific location.

+
+
+ anchor
+
+ The popup may be either anchored to another node or opened freely. To anchor a popup to a node, supply an anchor node and set the position to a string indicating the manner in which the popup should be anchored. The anchor node does not need to be in the same document as the popup. Unanchored popups may be created by supplying null as the anchor node. The direction in which the popup is oriented depends on the direction of the anchor.
+
+ position
+
+ Possible values for position are: before_start, before_end, after_start, after_end, start_before, start_after, end_before, end_after, overlap, and after_pointer. Check Positioning of the Popup Guide for a precise description of the effect of the different values.
+
+ x, y
+
+ For an anchored popup, the x and y arguments may be used to offset the popup from its anchored position by some number, measured in CSS pixels. An unanchored popup appears at the position specified by x and y, relative to the viewport of the document containing the popup node. In this case, the position and attributesOverride arguments are ignored.
+
+ isContextMenu
+
+ The isContextMenu argument should be true for context menus and false for all other types of popups. It affects menu item highlighting; that is, while a context menu is open, menus opened earlier do not highlight or execute their items.
+
+ attributesOverride
+
+ If the attributesOverride argument is true, the position attribute on the popup node overrides the position value argument. If attributesOverride is false, the attribute is only used if the position argument is empty.
+
+ triggerEvent
+
+ The event that triggered the popup (such as a mouse click, if the user clicked something to open the popup).
+
+
+ openPopupAtScreen( x, y, isContextMenu )
+
+ Return type: no return value
+
+ Open the popup at a specific screen position specified by x and y. This position may be adjusted if it would cause the popup to be off of the screen. The x and y coordinates are measured in CSS pixels.
+
+
showPopup( element, x, y, popupType, anchor, align ) Deprecated since Gecko 1.9
+
Return type: no return value
+ Deprecated in favor of openPopup and openPopupAtScreen
+
Opens a popup element. There are two ways of specifying where the popup appears, either at a specific screen position, or relative to some element in the window. If either x or y are set to values, the popup will appear at the screen coordinate (x,y). If x and y are -1, the popup will be positioned relative to the element specified as the first argument. This is what you might do to show a popup below a button, for example. In this latter case, the anchor and align arguments may be used to further control where the popup appears relative to the element. The anchor argument corresponds to the popupanchor attribute on the element. The align argument corresponds to the popupalign attribute on the element. The anchor and align arguments are ignored if either x or y are not -1.
+
+ +
+
To have a popup appear relative to another element yet still offset by some number of pixels, determine the actual screen position of the element using the boxObject.screenX and boxObject.screenY properties of the element, and use those as the x and y arguments offset by the desired values.
+
+ +
+
The popupType should be one of the strings popup, context, or tooltip. Each type of popup is intended to be displayed only temporarily; they are not expected to be displayed permanently.
+
+
+ sizeTo( width, height )
+
+ Return type: no return value
+
+ Changes the current size of the popup to the new width and height.
+

+ +
+
+ Elements
+
+ menu, menubar, menuitem, menulist, menuseparator
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULPopupElement
+
+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/menuseparator/index.html b/files/zh-cn/mozilla/tech/xul/menuseparator/index.html new file mode 100644 index 0000000000..5b00451c60 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/menuseparator/index.html @@ -0,0 +1,435 @@ +--- +title: menuseparator +slug: Mozilla/Tech/XUL/menuseparator +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/menuseparator +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

Used to create a separator between menu items. Typically drawn as a thin line.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ acceltext, accesskey, allowevents, command, crop, disabled, image, label, selected, tabindex, value
+
+
+
+ Properties
+
+ accessibleType, accessKey, command, control, crop, disabled, image, label, labelElement, parentContainer, selected, tabIndex, value
+
+

Examples

+
<menu label="Help">
+  <menupopup>
+    <menuitem label="Contents"/>
+    <menuseparator/>
+    <menuitem label="Release Notes"/>
+  </menupopup>
+</menu>
+
+

Attributes

+

+ +
+
+ acceltext
+
+ Type: + + string +
+
+ Text that appears beside beside the menu label to indicate the shortcut key (accelerator key) to use to invoke the command. If this value is set, it overrides an assigned key set in the key attribute. This attribute does not apply to menus directly on the menubar.
+
+ +

+
+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ + +
+
allowevents
+
Type: + boolean
+
+ 类型:boolean
+
If true, events are passed to children of the element. Otherwise, events are passed to the element only.
+ 如果为真,事件向子元素传递。否则,事件只传递到当前元素。
+
+ + + +

+
+ +
+
+ command
+
+ Type: + + element id +
+
+ Set to the id of a command element that is being observed by the element.
+
+ +

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ +
+
+ image
+
+ Type: + + image URL +
+
+ The URL of the image to appear on the element. If this attribute is empty or left out, no image appears. The position of the image is determined by the dir and orient attributes.
+
+ +

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ +
+
+ selected
+
+ Type: + + boolean +
+
+ Indicates whether the element is selected or not. This value is read-only. To change the selection, set either the selectedIndex or selectedItem property of the containing element.
+
+ +

+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ +
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+ +

+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ accessKey
+
+ Type: + + character +
+
+ Gets and sets the value of the accesskey attribute.
+
+ +

+
+
+ command
+
+ Type: + + element id +
+
+ Gets and sets the value of the command attribute.
+
+ +

+
+
+ control
+
+ Type: + + menu element +
+
+ Returns the enclosing menu that the item is inside, if any, or null if there is no enclosing menu.
+
+ +

+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+ +

+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+
+
+ image
+
+ Type: + + image URL +
+
+ Gets and sets the value of the image attribute.
+
+ +

+
+
+ label
+
+ Type: + + string +
+
+ Gets and sets the value of the label attribute.
+
+ +

+
+
+ labelElement
+
+ Type: + + label element +
+
+ The label element associated with the control. This is set when a label has a control attribute pointing to this element. This property will be null when no label is associated with the control.
+
+ +

+
+
+ parentContainer
+
+ Type: + + menu element +
+
+ Read only property that returns the containing menu element, or null if there isn't a containing menu.
+
+ +

+
+
+ selected<magic name="\"PAGENAME\"/"></magic>
+
+ Type: + + boolean +
+
+ This property's value is true if this element is selected, or false if it is not. This property is read only.
+
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +
+
+ Elements
+
+ menu, menubar, menuitem, menulist, menupopup
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULContainerItemElement, nsIDOMXULSelectControlItemElement
+
+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/method/extra1/index.html b/files/zh-cn/mozilla/tech/xul/method/extra1/index.html new file mode 100644 index 0000000000..33546b4a30 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/extra1/index.html @@ -0,0 +1,15 @@ +--- +title: extra1 +slug: Mozilla/Tech/XUL/Method/extra1 +translation_of: Archive/Mozilla/XUL/Method/extra1 +--- +
+ « XUL Reference home
+
+
+ extra1()
+
+ 返回值类型:无返回值
+
+ 调用该方法可以模拟对extra1按钮的点击,同时也会触发并执行该元素的onextra1属性上设置的代码.
+
diff --git a/files/zh-cn/mozilla/tech/xul/method/focus/index.html b/files/zh-cn/mozilla/tech/xul/method/focus/index.html new file mode 100644 index 0000000000..690ba10358 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/focus/index.html @@ -0,0 +1,15 @@ +--- +title: focus +slug: Mozilla/Tech/XUL/Method/focus +translation_of: Archive/Mozilla/XUL/Method/focus +--- +
+ « XUL Reference home
+
+
+ focus()
+
+ 返回值类型: 无返回值
+
+ 让指定的元素获得键盘焦点.
+
diff --git a/files/zh-cn/mozilla/tech/xul/method/getbrowserfortab/index.html b/files/zh-cn/mozilla/tech/xul/method/getbrowserfortab/index.html new file mode 100644 index 0000000000..483579d074 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/getbrowserfortab/index.html @@ -0,0 +1,15 @@ +--- +title: getBrowserForTab +slug: Mozilla/Tech/XUL/Method/getBrowserForTab +translation_of: Archive/Mozilla/XUL/Method/getBrowserForTab +--- +
+ « XUL Reference home
+
+
+ getBrowserForTab( tab )
+
+ 返回值类型: browser元素
+
+ 返回于指定的tab元素相关联的browser元素.
+
diff --git a/files/zh-cn/mozilla/tech/xul/method/getbutton/index.html b/files/zh-cn/mozilla/tech/xul/method/getbutton/index.html new file mode 100644 index 0000000000..11b4f91e6d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/getbutton/index.html @@ -0,0 +1,15 @@ +--- +title: getButton +slug: Mozilla/Tech/XUL/Method/getButton +translation_of: Archive/Mozilla/XUL/Method/getButton +--- +
+ « XUL Reference home
+
+
+ getButton( type )
+
+ 返回值类型: button元素
+
+ 返回当前对话框中指定类型的button元素.
+
diff --git a/files/zh-cn/mozilla/tech/xul/method/increase/index.html b/files/zh-cn/mozilla/tech/xul/method/increase/index.html new file mode 100644 index 0000000000..b7431b355b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/increase/index.html @@ -0,0 +1,21 @@ +--- +title: increase +slug: Mozilla/Tech/XUL/Method/increase +translation_of: Archive/Mozilla/XUL/Method/increase +--- +
+ « XUL Reference home
+
+
+
+ 拥有该方法的元素类型: scale textbox
+
+
+
+
+ increase()
+
+ 返回值类型: 无返回值
+
+ 增大刻度条控件(scale元素)或者数字输入框控件(type属性为number的textbox元素)中的数字值(按照其increment属性指定的值).
+
diff --git a/files/zh-cn/mozilla/tech/xul/method/index.html b/files/zh-cn/mozilla/tech/xul/method/index.html new file mode 100644 index 0000000000..e5d7d023c0 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/index.html @@ -0,0 +1,170 @@ +--- +title: Methods +slug: Mozilla/Tech/XUL/Method +tags: + - XUL Methods +translation_of: Archive/Mozilla/XUL/Method +--- +

« XUL Reference home

+ + + diff --git a/files/zh-cn/mozilla/tech/xul/method/reset/index.html b/files/zh-cn/mozilla/tech/xul/method/reset/index.html new file mode 100644 index 0000000000..258f4d53df --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/reset/index.html @@ -0,0 +1,15 @@ +--- +title: reset +slug: Mozilla/Tech/XUL/Method/reset +translation_of: Archive/Mozilla/XUL/Method/reset +--- +
+ « XUL Reference home
+
+
+ reset()
+
+ 返回值:无返回值
+
+ 将用户偏好重置为默认值.
+
diff --git a/files/zh-cn/mozilla/tech/xul/method/stop/index.html b/files/zh-cn/mozilla/tech/xul/method/stop/index.html new file mode 100644 index 0000000000..181a6123ae --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/method/stop/index.html @@ -0,0 +1,15 @@ +--- +title: stop +slug: Mozilla/Tech/XUL/Method/stop +translation_of: Archive/Mozilla/XUL/Method/stop +--- +
+ « XUL Reference home
+
+
+ stop()
+
+ 返回值: 无返回值
+
+ 效果等同于按下了停止按钮,停止当前页面中文档的加载.
+
diff --git a/files/zh-cn/mozilla/tech/xul/namespaces/index.html b/files/zh-cn/mozilla/tech/xul/namespaces/index.html new file mode 100644 index 0000000000..73a5099ae6 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/namespaces/index.html @@ -0,0 +1,73 @@ +--- +title: Namespaces +slug: Mozilla/Tech/XUL/Namespaces +translation_of: Archive/Mozilla/XUL/Namespaces +--- +

 

+ +

除此文档外,请参阅Namespaces Crash Course

+ +

XML namespaces 提供了区分重复元素和属性名称的方法。当XML文档包含来自两个或多个不同的XML模式 (或者DTD)的元素和属性时,可能会出现重复元素和属性名称。引用 Wikipedia: "一般来说,namespaces是一个抽象的容器,为项目提供上下文... 它拥有并且允许消除具有相同名称的项目的消歧。"

+ +

如果你熟悉C++命名空间、Java包、Perl包或者Python模块导入,那么你已经熟悉了namespaces概念。

+ +

XML namespace 由唯一的名称 (称为URI, 而不是URL, 即使它看起来像URL)标识。URI 可以是任何字符串,虽然大多数人选择基于URL的URI,因为URL是实现我们期望的唯一性的一种简单的方法。虽然没有任何理由去阻止其他人使用这个namespaces http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul, 但是不太可能有人会不小心选择这个namespaces。即使他们意外的选择了这个namespaces,他们也不可能在他们的模式/DTD中定义与XUL相同的元素 。

+ +

XML namespace中的任何元素类型或者属性名称都可以通过其XML  namespace和其“local name”来唯一标识。 这两个项目一起定义了一个限定名称,或者 QName.

+ +

例如: <xul:textbox/> 使用名为"xul"的namespace和本地名称 "textbox"。它不同于例子所示,例如: <foobar:textbox/> 可能出现在同一个文档中。xulfoobar namespaces必须定义在它们所使用的XML文档的顶部, 如下:

+ +
 <foobar:some-element
+     xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+     xmlns:foobar="the-foobar-namespace">
+   <xul:textbox id="foo" value="bar"/>
+   <foobar:textbox favorite-food="pancakes"/>
+ </foobar:some-element>
+
+ +

注意我已经在同一个文档中混合了两个<textboxes/> 。区分他们的唯一的方法是他们有不同含义的namespaces.

+ +

还有一个事情需要了解:“default namespace(默认namespace)”。每个XML元素有一个 "default namespace", 而且它总是和XUL 元素一起使用。在XUL 文档中,您通常会看到:

+ +
 <window
+     id="foo"
+     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+   ...
+   ...
+ </window>
+
+ +

在XHTML 文档中,您会看到:

+ +
 <html xmlns="http://www.w3.org/1999/xhtml">
+   ...
+   ...
+ </html>
+
+ +

与之前相比,这里有一个非常微妙的差别。 我之前写过xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" ,但是这儿的:xul 部分被省略。这意味着对XML解析器来说,http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul 是元素及其后代元素的 default namespace (除非在后代元素上被default namespace覆盖),并且,如果没有namespace 的任何元素(即,没有前缀和colon)属于default namespace。这就是为什么我们可以使用简写<textbox/>来代替XUL中的 <xul:textbox/> (即使后者在没有使用http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul 作为default namespace是正确的) -- XUL namespace被定义为最顶层元素的默认值。换句话说,default namespace允许一种简短的概括被用于一个元素的所有后代元素。

+ +

这里有一个问题:在下面的XML文档中,什么namespace包含了foo元素?

+ +
  <foo/>
+
+ +

答案是它不在namespace, 或者它在namespace中由空字符串表示:

+ +
  <foo xmlns=""/>
+
+ +

第二个例子在语义上等同于第一个例子。

+ +

那么第二个问题是:  bar、 baz 和 quux 是什么名称空间中的属性?

+ +

 

+ +
  <foo bar="value">
+    <element xmlns="namespace!" baz="value">
+      <element quux="value"/>
+    </element>
+  </foo>
+
+ +

bar 显然不在namespace中。那么 bazquux怎么样呢?答案是他们也不在namespace中。实际上,在namespace中没有任何前缀不确定的属性,主要是因为XML最初没有namespaces,而且从那时起,所有的XML必须保持在无namespace.这是XML namespaces常年混乱的根源。

diff --git a/files/zh-cn/mozilla/tech/xul/popup/index.html b/files/zh-cn/mozilla/tech/xul/popup/index.html new file mode 100644 index 0000000000..05ce34c3bc --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/popup/index.html @@ -0,0 +1,23 @@ +--- +title: popup +slug: Mozilla/Tech/XUL/popup +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/popup +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

The popup element is equivalent to the menupopup element which should be used instead. See the documentation on the menupopup element for more information.

+

popup元素和menupopup元素在功能上是等价的,具体用法可以参考menupopup的说明文档。

+

 

+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/accessibletype/index.html b/files/zh-cn/mozilla/tech/xul/property/accessibletype/index.html new file mode 100644 index 0000000000..ae445e8bdb --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/accessibletype/index.html @@ -0,0 +1,183 @@ +--- +title: accessibleType +slug: Mozilla/Tech/XUL/Property/accessibleType +translation_of: Archive/Mozilla/XUL/Property/accessibleType +--- +
+ « XUL Reference
+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+
+

Possible values are:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ConstantValue
XULAlert1001
XULButton1002
XULCheckbox1003
XULColorPicker1004
XULColorPickerTile1005
XULCombobox1006
XULDropmarker1007
XULGroupbox1008
XULImage1009
XULLink100A
XULListbox100B
XULListCell1026
XULListHead1024
XULListHeader1025
XULListitem100C
XULMenubar100D
XULMenuitem100E
XULMenupopup100F
XULMenuSeparator1010
XULPane1011
XULProgressMeter1012
XULScale1013
XULStatusBar1014
XULRadioButton1015
XULRadioGroup1016
XULTab1017
XULTabBox1018
XULTabs1019
XULText101A
XULTextBox101B
XULThumb101C
XULTree101D
XULTreeColumns101E
XULTreeColumnItem101F
XULToolbar1020
XULToolbarSeparator1021
XULTooltip1022
XULToolbarButton1023
+

</div>

+
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/accesskey/index.html b/files/zh-cn/mozilla/tech/xul/property/accesskey/index.html new file mode 100644 index 0000000000..7b49328080 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/accesskey/index.html @@ -0,0 +1,21 @@ +--- +title: accessKey +slug: Mozilla/Tech/XUL/Property/accessKey +translation_of: Archive/Mozilla/XUL/Property/accessKey +--- +
+ « XUL Reference
+
+
+ accessKey
+
+ Type: + + character +
+
+ Gets and sets the value of the accesskey attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/browser.preferences/index.html b/files/zh-cn/mozilla/tech/xul/property/browser.preferences/index.html new file mode 100644 index 0000000000..7a0bd25201 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/browser.preferences/index.html @@ -0,0 +1,15 @@ +--- +title: browser.preferences +slug: Mozilla/Tech/XUL/Property/browser.preferences +translation_of: Archive/Mozilla/XUL/Property/browser.preferences +--- +
+ « XUL Reference
+
+
+ preferences
+
+ 类型: nsIPrefService
+
+ 这是一个只读属性,其值为一个nsIPref对象,可以用来读取或设置用户的首选项.
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/buttons/index.html b/files/zh-cn/mozilla/tech/xul/property/buttons/index.html new file mode 100644 index 0000000000..67304e8fa1 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/buttons/index.html @@ -0,0 +1,10 @@ +--- +title: buttons +slug: Mozilla/Tech/XUL/Property/buttons +translation_of: Archive/Mozilla/XUL/Property/buttons +--- +
« XUL Reference
+
buttons
类型: 列表,下面的值用逗号分隔
需要显示在对话框上的按钮的一个列表,使用逗号分隔。将按钮放置在合适的位置,将根据用户平台自动执行基本的事件处理。在列表中可以使用以下值:
  • accept:“确定”按钮,按下按钮时将接受更改。此按钮为默认按钮。
  • cancel:“取消”按钮,将取消操作。
  • help:“帮助”按钮,在对话框显示一个“帮助”按钮。
  • disclosure:“更多信息”按钮,显示一个“more info”按钮。该按钮可能是一个按钮或一个三角形。
  • extra1:一个可选的额外的按钮。你可以通过buttonlabelextra1 属性设置它的label。
  • extra2:第二个可选的额外的按钮。你可以通过 buttonlabelextra2 属性设置它的label。
+
+

Note: If you don't want to display any buttons in the dialog box, set the value of this attribute to "," (a single comma).

+
diff --git a/files/zh-cn/mozilla/tech/xul/property/command/index.html b/files/zh-cn/mozilla/tech/xul/property/command/index.html new file mode 100644 index 0000000000..10993a17e6 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/command/index.html @@ -0,0 +1,21 @@ +--- +title: command +slug: Mozilla/Tech/XUL/Property/command +translation_of: Archive/Mozilla/XUL/Property/command +--- +
+ « XUL Reference
+
+
+ command
+
+ Type: + + element id +
+
+ Gets and sets the value of the command attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/crop/index.html b/files/zh-cn/mozilla/tech/xul/property/crop/index.html new file mode 100644 index 0000000000..54a99a746b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/crop/index.html @@ -0,0 +1,21 @@ +--- +title: crop +slug: Mozilla/Tech/XUL/Property/crop +translation_of: Archive/Mozilla/XUL/Property/crop +--- +
+ « XUL Reference
+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/defaultvalue/index.html b/files/zh-cn/mozilla/tech/xul/property/defaultvalue/index.html new file mode 100644 index 0000000000..7aca9067cb --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/defaultvalue/index.html @@ -0,0 +1,15 @@ +--- +title: defaultValue +slug: Mozilla/Tech/XUL/Property/defaultValue +translation_of: Archive/Mozilla/XUL/Property/defaultValue +--- +
+ « XUL Reference
+
+
+ defaultValue
+
+ 类型: 字符串
+
+ 获取或设置一个textbox元素中显示的默认值.
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/disabled/index.html b/files/zh-cn/mozilla/tech/xul/property/disabled/index.html new file mode 100644 index 0000000000..500640dc2a --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/disabled/index.html @@ -0,0 +1,21 @@ +--- +title: disabled +slug: Mozilla/Tech/XUL/Property/disabled +translation_of: Archive/Mozilla/XUL/Property/disabled +--- +
+ « XUL Reference
+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/image/index.html b/files/zh-cn/mozilla/tech/xul/property/image/index.html new file mode 100644 index 0000000000..5079e489cd --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/image/index.html @@ -0,0 +1,21 @@ +--- +title: image +slug: Mozilla/Tech/XUL/Property/image +translation_of: Archive/Mozilla/XUL/Property/image +--- +
+ « XUL Reference
+
+
+ image
+
+ Type: + + image URL +
+
+ Gets and sets the value of the image attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/index.html b/files/zh-cn/mozilla/tech/xul/property/index.html new file mode 100644 index 0000000000..caec3163d8 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/index.html @@ -0,0 +1,266 @@ +--- +title: Property +slug: Mozilla/Tech/XUL/Property +tags: + - XUL Properties +translation_of: Archive/Mozilla/XUL/Property +--- +

« XUL Reference +

+ + + +
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/label/index.html b/files/zh-cn/mozilla/tech/xul/property/label/index.html new file mode 100644 index 0000000000..83f85cc1e3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/label/index.html @@ -0,0 +1,21 @@ +--- +title: label +slug: Mozilla/Tech/XUL/Property/label +translation_of: Archive/Mozilla/XUL/Property/label +--- +
+ « XUL Reference
+
+
+ label
+
+ Type: + + string +
+
+ Gets and sets the value of the label attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/labelelement/index.html b/files/zh-cn/mozilla/tech/xul/property/labelelement/index.html new file mode 100644 index 0000000000..6baead11d3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/labelelement/index.html @@ -0,0 +1,21 @@ +--- +title: labelElement +slug: Mozilla/Tech/XUL/Property/labelElement +translation_of: Archive/Mozilla/XUL/Property/labelElement +--- +
+ « XUL Reference
+
+
+ labelElement
+
+ Type: + + label element +
+
+ The label element associated with the control. This is set when a label has a control attribute pointing to this element. This property will be null when no label is associated with the control.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/markupdocumentviewer/index.html b/files/zh-cn/mozilla/tech/xul/property/markupdocumentviewer/index.html new file mode 100644 index 0000000000..8719292f2d --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/markupdocumentviewer/index.html @@ -0,0 +1,15 @@ +--- +title: markupDocumentViewer +slug: Mozilla/Tech/XUL/Property/markupDocumentViewer +translation_of: Archive/Mozilla/XUL/Property/markupDocumentViewer +--- +
+ « XUL Reference
+
+
+ markupDocumentViewer
+
+ 类型: nsIMarkupDocumentViewer
+
+ 这个只读的属性包含 nsIMarkupDocumentViewer 接口,负责document文档的绘制。
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/max/index.html b/files/zh-cn/mozilla/tech/xul/property/max/index.html new file mode 100644 index 0000000000..3d20dae617 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/max/index.html @@ -0,0 +1,15 @@ +--- +title: max +slug: Mozilla/Tech/XUL/Property/max +translation_of: Archive/Mozilla/XUL/Property/max +--- +
+ « XUL Reference
+
+
+ max
+
+ 类型:整数
+
+ 获取或设置max特性(attribute)的值.
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/menuitem.control/index.html b/files/zh-cn/mozilla/tech/xul/property/menuitem.control/index.html new file mode 100644 index 0000000000..a8cd738934 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/menuitem.control/index.html @@ -0,0 +1,21 @@ +--- +title: menuitem.control +slug: Mozilla/Tech/XUL/Property/menuitem.control +translation_of: Archive/Mozilla/XUL/Property/menuitem.control +--- +
+ « XUL Reference
+
+
+ control
+
+ Type: + + menu element +
+
+ Returns the enclosing menu that the item is inside, if any, or null if there is no enclosing menu.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/parentcontainer/index.html b/files/zh-cn/mozilla/tech/xul/property/parentcontainer/index.html new file mode 100644 index 0000000000..f8a29d42ae --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/parentcontainer/index.html @@ -0,0 +1,21 @@ +--- +title: parentContainer +slug: Mozilla/Tech/XUL/Property/parentContainer +translation_of: Archive/Mozilla/XUL/Property/parentContainer +--- +
+ « XUL Reference
+
+
+ parentContainer
+
+ Type: + + menu element +
+
+ Read only property that returns the containing menu element, or null if there isn't a containing menu.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/selected/index.html b/files/zh-cn/mozilla/tech/xul/property/selected/index.html new file mode 100644 index 0000000000..eee4b31285 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/selected/index.html @@ -0,0 +1,18 @@ +--- +title: selected +slug: Mozilla/Tech/XUL/Property/selected +translation_of: Archive/Mozilla/XUL/Property/selected +--- +
+ « XUL Reference
+
+
+ selected<magic name="\"PAGENAME\"/"></magic>
+
+ Type: + + boolean +
+
+ This property's value is true if this element is selected, or false if it is not. This property is read only.
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/selectedindex/index.html b/files/zh-cn/mozilla/tech/xul/property/selectedindex/index.html new file mode 100644 index 0000000000..22d1a4fba1 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/selectedindex/index.html @@ -0,0 +1,21 @@ +--- +title: selectedIndex +slug: Mozilla/Tech/XUL/Property/selectedIndex +translation_of: Archive/Mozilla/XUL/Property/selectedIndex +--- +
+ « XUL Reference
+
+
+ selectedIndex
+
+ Type: + + integer +
+
+ Returns the index of the currently selected item. You may select an item by assigning its index to this property. By assigning -1 to this property, all items will be deselected.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/selecteditem/index.html b/files/zh-cn/mozilla/tech/xul/property/selecteditem/index.html new file mode 100644 index 0000000000..1583c5f526 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/selecteditem/index.html @@ -0,0 +1,21 @@ +--- +title: selectedItem +slug: Mozilla/Tech/XUL/Property/selectedItem +translation_of: Archive/Mozilla/XUL/Property/selectedItem +--- +
+ « XUL Reference
+
+
+ selectedItem
+
+ Type: + + element +
+
+ Holds the currently selected item. If no item is currently selected, this value will be null. You can select an item by setting this value. A select event will be sent to the element when it is changed either via this property, the selectedIndex property, or changed by the user.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/selectionstart/index.html b/files/zh-cn/mozilla/tech/xul/property/selectionstart/index.html new file mode 100644 index 0000000000..27ecd267c6 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/selectionstart/index.html @@ -0,0 +1,16 @@ +--- +title: selectionStart +slug: Mozilla/Tech/XUL/Property/selectionStart +translation_of: Archive/Mozilla/XUL/Property/selectionStart +--- +
« XUL Reference
+ +
+
selectionStart
+
类型: integer
+
获取或设置字段文本的选定部分的开始。 与selectionEnd 属性结合使用。 该值指定第一个选定字符的索引。
+
+ +
+

+
diff --git a/files/zh-cn/mozilla/tech/xul/property/spinbuttons/index.html b/files/zh-cn/mozilla/tech/xul/property/spinbuttons/index.html new file mode 100644 index 0000000000..aadb3a3a31 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/spinbuttons/index.html @@ -0,0 +1,15 @@ +--- +title: spinButtons +slug: Mozilla/Tech/XUL/Property/spinButtons +translation_of: Archive/Mozilla/XUL/Property/spinButtons +--- +
+ « XUL Reference
+
+
+ spinButtons
+
+ 类型:spinbuttons元素
+
+ 一个只读属性,返回了数字输入框元素(type属性为number的textbox元素)中包含的spinbuttons元素(也就是右侧调整数字大小的上下小箭头).
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/tabindex/index.html b/files/zh-cn/mozilla/tech/xul/property/tabindex/index.html new file mode 100644 index 0000000000..5e41049910 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/tabindex/index.html @@ -0,0 +1,21 @@ +--- +title: tabIndex +slug: Mozilla/Tech/XUL/Property/tabIndex +translation_of: Archive/Mozilla/XUL/Property/tabIndex +--- +
+ « XUL Reference
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/property/textbox.value/index.html b/files/zh-cn/mozilla/tech/xul/property/textbox.value/index.html new file mode 100644 index 0000000000..860ed2fd39 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/textbox.value/index.html @@ -0,0 +1,15 @@ +--- +title: textbox.value +slug: Mozilla/Tech/XUL/Property/textbox.value +translation_of: Archive/Mozilla/XUL/Property/textbox.value +--- +
+ « XUL Reference
+
+
+ value
+
+ 类型:字符串
+
+ 读取或设置该textbox元素中的文本内容.
+
diff --git a/files/zh-cn/mozilla/tech/xul/property/value/index.html b/files/zh-cn/mozilla/tech/xul/property/value/index.html new file mode 100644 index 0000000000..b56deb5fc4 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/property/value/index.html @@ -0,0 +1,21 @@ +--- +title: value +slug: Mozilla/Tech/XUL/Property/value +translation_of: Archive/Mozilla/XUL/Property/value +--- +
+ « XUL Reference
+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/radio/index.html b/files/zh-cn/mozilla/tech/xul/radio/index.html new file mode 100644 index 0000000000..ecadeea308 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/radio/index.html @@ -0,0 +1,379 @@ +--- +title: radio +slug: Mozilla/Tech/XUL/radio +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/radio +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

An element that can be turned on and off. Radio buttons are almost always grouped together in groups. Only one radio button within the same radiogroup may be selected at a time. The user can switch which radio button is turned on by selecting it with the mouse or keyboard. Other radio buttons in the same group are turned off. A label, specified with the label attribute may be added beside the radio button.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ accesskey, command, crop, disabled, focused, group, image, label, selected, tabindex, value
+
+
+
+ Properties
+
+ accessKey, accessibleType, control, crop, disabled, image, label, radioGroup, selected, tabIndex, value
+
+

Examples

+
+ Image:XUL_ref_radio.png
+
<radiogroup>
+  <radio id="orange" label="Red" accesskey="R"/>
+  <radio id="violet" label="Green"  accesskey="G" selected="true"/>
+  <radio id="yellow" label="Blue"  accesskey="B" disabled="true"/>
+</radiogroup>
+
+

Attributes

+

+ + + + +
+
accesskey
+
类型: + character【字符】 +
+
本属性允许为控件(元素)设定一个字符作为快捷键,这个字符应该是 label 属性文本中的一个字符。该字符将会被加下划线以重点强调,平台和主体的变换并不影响这一表现行为。 当用户点击 ALT (在其他平台上具有类似功能的键) 和这个字符对应的按键时, 控件(元素)将立刻被从窗口中的某处激活或/并且获得焦点 。虽说字符不分大小写,但是当label中存在大写字符和小写字符时,快捷键的字符将首先选择与之完全匹配的那一个,如果label中存在两个或更多的与accesskey字符相同的字符,其中的第一个字符将被加下划线。
+
      *(有些键在监听按键事件时,分别对应event.ctrlKey和event.metaKey。)
+
+ +

 

+ +

Example

+ +
Image:XUL_ref_accesskey_attr.png
+ +
<vbox>
+  <label value="Enter Name" accesskey="e" control="myName"/>
+  <textbox id="myName"/>
+  <button label="Cancel" accesskey="n"/>
+  <button label="Ok" accesskey="O"/>
+</vbox>
+
+ +

See also

+ +

label attribute, acceltext attribute

+ +

+
+ +
+
+ command
+
+ Type: + + element id +
+
+ Set to the id of a command element that is being observed by the element.
+
+ +

+
+ +
+
+ crop
+
+ Type: + + one of the values below +
+
+ If the label of the element is too big to fit in its given space, the text will be cropped on the side specified by the crop attribute. An ellipsis will be used in place of the cropped text. If the box direction is reversed, the cropping is reversed.
+
+ + +

+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
focused
+
Type: boolean
+
This attribute is true if the element is focused.
+
+
+ + +
+
group
+
Type: string group name
+
Buttons with type="radio" and the same value for their group attribute are put into the same group. Only one button from each group can be checked at a time. If the user selects one the buttons, the others in the group are unchecked.
+
+
+ +
+
+ image
+
+ Type: + + image URL +
+
+ The URL of the image to appear on the element. If this attribute is empty or left out, no image appears. The position of the image is determined by the dir and orient attributes.
+
+ +

+
+ +
+
+ label
+
+ Type: string
+
+ The label that will appear on the element. If this is left out, no text appears.
+ label 在元素上显示。如果左侧出界,则不显示任何文字。
+
+ +

+
+ +
+
+ selected
+
+ Type: + + boolean +
+
+ Indicates whether the element is selected or not. This value is read-only. To change the selection, set either the selectedIndex or selectedItem property of the containing element.
+
+ +

+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ +
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+ +

+

+

Properties

+

+
+
+ accessKey
+
+ Type: + + character +
+
+ Gets and sets the value of the accesskey attribute.
+
+ +

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+ +
+
control
+
Type: radiogroup element
+
Returns the enclosing radiogroup that the radio element is contained within, which may or may not be its direct parent.
+
+
+
+ crop
+
+ Type: + + string +
+
+ Gets and sets the value of the crop attribute.
+
+ +

+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+
+
+ image
+
+ Type: + + image URL +
+
+ Gets and sets the value of the image attribute.
+
+ +

+
+
+ label
+
+ Type: + + string +
+
+ Gets and sets the value of the label attribute.
+
+ +

+ +
+
radioGroup
+
Type: radiogroup element
+
Equivalent to the control property.
+
+
+
+ selected<magic name="\"PAGENAME\"/"></magic>
+
+ Type: + + boolean +
+
+ This property's value is true if this element is selected, or false if it is not. This property is read only.
+
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +
+
+ Elements
+
+ radiogroup, checkbox
+
+
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULSelectControlItemElement, nsIDOMXULLabeledControlElement
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/radiogroup/index.html b/files/zh-cn/mozilla/tech/xul/radiogroup/index.html new file mode 100644 index 0000000000..a91c7aa8e0 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/radiogroup/index.html @@ -0,0 +1,275 @@ +--- +title: radiogroup +slug: Mozilla/Tech/XUL/radiogroup +tags: + - radiogroup + - 单选按钮组 +translation_of: Archive/Mozilla/XUL/radiogroup +--- +
+ « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+ +

一组单选按钮。在单选按钮组内一次只能选择一个单选按钮。radio 按钮可以指示单选按钮组或后代的子节点。 如果您想要一个边框或 caption ,请将Radiogroup放在一个 groupbox内。radiogroup 默认为垂直方向。

+ +

更多信息可以在 XUL 教程 中找到。

+ +
+
Attributes
+
disabled, focused, preference, tabindex, value
+
+ +
+
Properties
+
accessibleType, disabled, focusedItem, itemCount, selectedIndex, selectedItem, tabIndex, value
+
+ +
+
Methods
+
appendItem, checkAdjacentElement, getIndexOfItem, getItemAtIndex, insertItemAt, removeItemAt
+
+ +

范例

+ +
Image:XUL_ref_radios.png
+ +
<radiogroup>
+  <radio id="orange" label="Red"/>
+  <radio id="violet" label="Green" selected="true"/>
+  <radio id="yellow" label="Blue"/>
+</radiogroup>
+
+ +

Attributes

+ +

+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
focused
+
Type: boolean
+
This attribute is true if the element is focused.
+
+
+ + +
+
preference
+
Type: id
+
Connects the element to a corresponding preference. This attribute only has any effect when used inside a prefwindow. More information is available in the Preferences System article.
+
+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ +
+
+ value
+
+ Type: + + string +
+
+ The string attribute allows you to associate a data value with an element. It is not used for any specific purpose, but you can access it with a script for your own use.
+
+ +

+

+ +

Properties

+ +

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+ +
+
focusedItem
+
Type: radio element
+
Holds the currently focused item in the radiogroup, which may or may not be the same as the selected item. You can change the focused item by setting this property.
+
+
+
itemCount
+
Type: integer
+
Read only property holding the number of child items.
+
+
+
+
+ selectedIndex
+
+ Type: + + integer +
+
+ Returns the index of the currently selected item. You may select an item by assigning its index to this property. By assigning -1 to this property, all items will be deselected.
+
+ +

+
+
+ selectedItem
+
+ Type: + + element +
+
+ Holds the currently selected item. If no item is currently selected, this value will be null. You can select an item by setting this value. A select event will be sent to the element when it is changed either via this property, the selectedIndex property, or changed by the user.
+
+ +

+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+
+
+ value
+
+ Type: + + string +
+
+ Gets and sets the value of the value attribute.
+
+ +

+ +

Methods

+ +

+ + + + + +
+

Inherited Methods
+addEventListener(), appendChild(), blur, click, cloneNode(), compareDocumentPosition, dispatchEvent(), doCommand, focus, getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getBoundingClientRect(), getClientRects(), getElementsByAttribute, getElementsByAttributeNS, getElementsByClassName(), getElementsByTagName(), getElementsByTagNameNS(), getFeature(), getUserData, hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isDefaultNamespace(), isEqualNode, isSameNode, isSupported(), lookupNamespaceURI, lookupPrefix, normalize(), querySelector(), querySelectorAll(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS(), setUserData

+ +
+
+ appendItem( label, value )
+
+ Return type: element
+
+ Creates a new item and adds it to the end of the existing list of items. You may optionally set a value. The function returns the newly created element.
+
+
checkAdjacentElement( dir )
+
Return type: no return value
+
Deselects the currently selected radio button in the group and selects the one adjacent to it. If the argument dir is true, the next radio button is selected. If it is false, the previous radio button is selected.
+
+
getIndexOfItem( item )
+
Return type: integer
+
Returns the zero-based position of the specified item. Items are numbered starting at the first item displayed in the list.
+
+
getItemAtIndex( index )
+
Return type: element
+
Returns the element that is at the specified index.
+
+
+ insertItemAt( index, label, value )
+
+ Return type: element
+
+ This method creates a new item and inserts it at the specified position. You may optionally set a value. The new item element is returned.
+
+
+ removeItemAt( index )
+
+ Return type: element
+
+ Removes the child item in the element at the specified index. The method returns the removed item.
+

+ + + +
+
Interfaces
+
nsIAccessibleProvider, nsIDOMXULSelectControlElement
+
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/script/index.html b/files/zh-cn/mozilla/tech/xul/script/index.html new file mode 100644 index 0000000000..6006a33298 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/script/index.html @@ -0,0 +1,117 @@ +--- +title: script +slug: Mozilla/Tech/XUL/script +translation_of: Archive/Mozilla/XUL/script +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

Much like the HTML script element, this is used to declare a script to be used by the XUL window. You should usually put scripts in a separate file pointed to by the src attribute, but you may also place the script inline inside the opening and closing script tags.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ src, type
+
+

Examples

+
 <script src="test.js"/>
+ <script src="http://example.com/js/test.js"/>
+ <script>
+   function foo(){
+     // code
+    }
+  </script>
+
+

Attributes

+

+ + +
+
src
+
Type: URI
+
The URI of the script.
+
+
+ + +
+
type
+
Type: language content type
+
The language of the script. Usually, you would set this to application/javascript.
+
+ Note: If the JavaScript file is in chrome://, setting this attribute to application/javascript will always use the latest available JavaScript version. If you omit this attribute, the default (and older) JavaScript version is used (like you get when including a JavaScript file from web content without specifying a version number).
+
+
+ + + + + +

Inherited from XUL element
+align, +allowevents, +allownegativeassertions, +class, +coalesceduplicatearcs, +collapsed, +container, +containment, +context, +contextmenu, +datasources, +dir, +empty, +equalsize, +flags, +flex, +height, +hidden, +id, +insertafter, +insertbefore, +left, +maxheight, +maxwidth, +menu, +minheight, +minwidth, +mousethrough, +observes, +ordinal, +orient, +pack, +persist, +popup, +position, +preference-editable, +querytype, +ref, +removeelement, +sortDirection, +sortResource, +sortResource2, +statustext, +style, +template, +tooltip, +tooltiptext, +top, +uri, +wait-cursor, +width

+

+

Properties

+

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +

diff --git a/files/zh-cn/mozilla/tech/xul/statusbar/index.html b/files/zh-cn/mozilla/tech/xul/statusbar/index.html new file mode 100644 index 0000000000..dec688952e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/statusbar/index.html @@ -0,0 +1,131 @@ +--- +title: statusbar +slug: Mozilla/Tech/XUL/statusbar +translation_of: Archive/Mozilla/XUL/statusbar +--- +

+

已废弃
该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。

+

+
+ 我建议使用附加组件栏来代替.
+
+  
+
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+
+  
+

用来创建状态栏的元素,通常位于窗口底部.可以包含多个statusbarpanel元素.

+
+
+ 属性
+
+ accessibleType
+
+

示例

+
<statusbar>
+  <statusbarpanel label="Left panel"/>
+  <spacer flex="1"/>
+  <progressmeter mode="determined" value="82"/>
+  <statusbarpanel label="Right panel"/>
+</statusbar>
+
+

Image:XUL_ref_statusbar.png

+

XUL属性(Attribute)

+

+ + + + + +

Inherited from XUL element
+align, +allowevents, +allownegativeassertions, +class, +coalesceduplicatearcs, +collapsed, +container, +containment, +context, +contextmenu, +datasources, +dir, +empty, +equalsize, +flags, +flex, +height, +hidden, +id, +insertafter, +insertbefore, +left, +maxheight, +maxwidth, +menu, +minheight, +minwidth, +mousethrough, +observes, +ordinal, +orient, +pack, +persist, +popup, +position, +preference-editable, +querytype, +ref, +removeelement, +sortDirection, +sortResource, +sortResource2, +statustext, +style, +template, +tooltip, +tooltiptext, +top, +uri, +wait-cursor, +width

+

+

DOM属性(Propertie)

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

方法

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +
+
+ 元素
+
+ statusbarpanel
+
+
+
+ 接口
+
+ nsIAccessibleProvider
+
diff --git a/files/zh-cn/mozilla/tech/xul/style/index.html b/files/zh-cn/mozilla/tech/xul/style/index.html new file mode 100644 index 0000000000..173c741e34 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/style/index.html @@ -0,0 +1,6 @@ +--- +title: Style classes +slug: Mozilla/Tech/XUL/Style +translation_of: Archive/Mozilla/XUL/Style +--- +

This page was auto-generated because a user created a sub-page to this page.

diff --git a/files/zh-cn/mozilla/tech/xul/style/menuitem-iconic/index.html b/files/zh-cn/mozilla/tech/xul/style/menuitem-iconic/index.html new file mode 100644 index 0000000000..8b41b0497e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/style/menuitem-iconic/index.html @@ -0,0 +1,16 @@ +--- +title: menuitem-iconic +slug: Mozilla/Tech/XUL/Style/menuitem-iconic +translation_of: Archive/Mozilla/XUL/Style/menuitem-iconic +--- +
+ « XUL Reference
+
+
+ menuitem-iconic
+
+ Use this class to have an image appear on the menuitem. Specify the image using the image attribute.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/style/menuitem-non-iconic/index.html b/files/zh-cn/mozilla/tech/xul/style/menuitem-non-iconic/index.html new file mode 100644 index 0000000000..c9873b5c31 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/style/menuitem-non-iconic/index.html @@ -0,0 +1,16 @@ +--- +title: menuitem-non-iconic +slug: Mozilla/Tech/XUL/Style/menuitem-non-iconic +translation_of: Archive/Mozilla/XUL/Style/menuitem-non-iconic +--- +
+ « XUL Reference
+
+
+ menuitem-non-iconic
+
+ Normally, menuitems have a margin to the left for an image or checkmark. This class may be used to remove this margin so that the menuitem appears on the left edge of the menupopup.
+
+
+  
+

diff --git a/files/zh-cn/mozilla/tech/xul/tabbox/index.html b/files/zh-cn/mozilla/tech/xul/tabbox/index.html new file mode 100644 index 0000000000..c0decfea4f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tabbox/index.html @@ -0,0 +1,156 @@ +--- +title: tabbox +slug: Mozilla/Tech/XUL/tabbox +translation_of: Archive/Mozilla/XUL/tabbox +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

A container used to display a set of tabbed pages of elements. A row of tabs is displayed at the top of tabbox which may be used to switch between each page. The tabbox should contain two children, the first a tabs element which contains the tabs and the second a tabpanels element which contains the contents of the pages.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ eventnode, handleCtrlPageUpDown, handleCtrlTab
+
+
+
+ Properties
+
+ accessibleType, eventNode, handleCtrlPageUpDown, handleCtrlTab, selectedIndex, selectedPanel, selectedTab, tabs, tabpanels
+
+

Examples

+
<tabbox id="myTabList" selectedIndex="2">
+  <tabs>
+    <tab label="A First tab"/>
+    <tab label="Second tab"/>
+    <tab label="Another tab"/>
+    <tab label="Last tab"/>
+  </tabs>
+  <tabpanels>
+    <tabpanel><!-- tabpanel First elements go here --></tabpanel>
+    <tabpanel><!-- tabpanel Second elements go here --></tabpanel>
+    <tabpanel><button label="Click me"/></tabpanel>
+    <tabpanel><!-- tabpanel Fourth elements go here --></tabpanel>
+  </tabpanels>
+</tabbox>
+
+

Image:XUL_REF_tabboxes.gif

+

Attributes

+

+ + +
+
eventnode
+
Type: one of the values below
+
Indicates where keyboard navigation events are listened to. If this attribute is not specified, events are listened to from the tabbox. Thus, if this attribute is not used, the tabbox or an element inside it must have the focus for the keyboard navigation to apply.
+
+
+
parent
+
Keyboard navigation is captured at the parent of the tabbox.
+
window
+
Keyboard navigation is captured at the window level. Tab navigation will occur as long as any element in the window is focused.
+
document
+
Keyboard navigation is captured at the document level. Tab navigation will occur as long as any element in the document is focused.
+
+
+
+
+ +
+ + +
+
handleCtrlTab
+
Type: boolean
+
If set to true or omitted, the tabbox will switch to the next tab when the Control and Tab keys are pressed. If the Shift key is also held down, the previous tab will be displayed. If this attribute is set to false, these keys do not navigate between tabs.
+
+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+ +
+
eventNode
+
Type: EventTarget
+
Indicates the node where keyboard navigation events listener is set up. The initial value for this property is determined by the value of the eventnode attribute.
+
+ +
+
handleCtrlPageUpDown
+
Type: boolean
+
Gets and sets the value of the handleCtrlPageUpDown attribute.
+
+ +
+
handleCtrlTab
+
Type: boolean
+
Gets and sets the value of the handleCtrlTab attibute.
+
+
+
+ selectedIndex
+
+ Type: + + integer +
+
+ Returns the index of the currently selected item. You may select an item by assigning its index to this property. By assigning -1 to this property, all items will be deselected.
+
+ +

+ +
+
selectedPanel
+
Type: element
+
Holds a reference to the currently selected panel within a <tabbox> element. Assigning a value to this property will modify the selected panel. A select event will be sent when the selected panel is changed.
+
+ +
+
selectedTab
+
Type: tab element
+
A reference to the currently selected tab, which will always be one of the tab elements in the tabs element. Assign a value to this property to modify the currently selected tab.
+
+ +
+
tabs
+
Type: tabs element
+
The tabs element contained within the tabbox.
+
+ +
+
tabpanels
+
Type: tabpanels element
+
The tabpanels element contained within the tabbox.
+

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +
+
+ Elements
+
+ tabs, tab, tabpanels, tabpanel.
+
+

diff --git a/files/zh-cn/mozilla/tech/xul/template_guide/index.html b/files/zh-cn/mozilla/tech/xul/template_guide/index.html new file mode 100644 index 0000000000..9a6ac79352 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/template_guide/index.html @@ -0,0 +1,68 @@ +--- +title: Template Guide +slug: Mozilla/Tech/XUL/Template_Guide +translation_of: Archive/Mozilla/XUL/Template_Guide +--- +

Basics of XUL Templates

+ +

RDF Template Syntax

+ +

XML Template Syntax

+ +

SQL Template Syntax

+ +

Common Template Syntax

+ +

Building Trees with Templates

+ +

Template Modifications

+ +

Additional Topics

+ +

Alternative Approaches

+ +

Interwiki Language Links

+

diff --git a/files/zh-cn/mozilla/tech/xul/textbox/index.html b/files/zh-cn/mozilla/tech/xul/textbox/index.html new file mode 100644 index 0000000000..4d032ca259 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/textbox/index.html @@ -0,0 +1,653 @@ +--- +title: textbox +slug: Mozilla/Tech/XUL/textbox +translation_of: Archive/Mozilla/XUL/textbox +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

An input field where the user can enter text. It is similar to the HTML input element. Only one line of text is displayed by default. The multiline attribute can be specified to display a field with multiple rows.

+

More information is available in the XUL tutorial.

+
+
+ Attributes
+
+ cols, decimalplaces, disabled, , emptytext, hidespinbuttons, increment, label, max, maxlength, min, multiline, newlines, onchange, oninput, placeholder, preference, readonly, rows, searchbutton, size, spellcheck, tabindex, timeout, type, value, wrap, wraparound
+
+
+
+ Properties
+
+ accessibleType, clickSelectsAll, decimalPlaces, decimalSymbol, defaultValue, disabled, editor, emptyText, increment, inputField, label, max, maxLength, min, placeholder, readOnly, searchButton, selectionEnd, selectionStart, size, spinButtons, tabIndex, textLength, timeout, type, value, valueNumber, wrapAround
+
+
+
+ Methods
+
+ decrease, increase, reset, select, setSelectionRange
+
+
+
+ Style classes
+
+ plain
+
+

Examples

+
+ Image:XUL_ref_textbox.png
+
<vbox>
+<label control="your-name" value="Enter your name:"/>
+<textbox id="your-name" value="John"/>
+</vbox>
+
+

Attributes

+

+ + +
+
cols
+
Type: integer
+
For multiline textboxes, the number of columns to display.
+
+
+ + +
+
decimalplaces
+
Type: integer
+
The number of decimal places to display. The default is 0, which doesn't show any decimal places. The value Infinity may be used if you want no limit on the number of decimal places. Note that decimal numbers are stored as floats.
+
+
+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
emptytext Deprecated since Gecko 2
+
Type: string
+
A string that appears in the textbox when it has no value. This is superseded by the placeholder attribute in Gecko 2.0. The old name is retained for compatibility, but you should update your code.
+
+
+ + +
+
hidespinbuttons
+
Type: boolean
+
If true, the number box does not have arrow buttons next to it to allow the user to adjust the value. The value may still be adjusted with the keyboard. The default value is false.
+
+
+ +
+
+ increment
+
+ 类型:整数
+
+ 拖动刻度条控件(scale元素)中的拉杆,点击滚动条控件(scrollbar元素)中的箭头(拖动拉杆也可以),点击数字输入框(type属性为numbertextbox元素)中的箭头时,其curpos属性或者value属性每次改变的数字值,默认值为1.
+
+
+ + +
+
label
+
Type: string
+
If present and not empty, this will be exposed to screen readers through the label property.
+
+
+ +
+
+ 类型:整数
+
+ 设置刻度条控件(scale元素)或者数字输入框控件(type属性为number的textbox元素)中能输入的最大数字.刻度条控件中,该属性的默认值为100,数字输入框中,该属性的默认值为无穷大.
+
+ +

 

+
+ + +
+
maxlength
+
Type: integer
+
The maximum number of characters that the textbox allows to be entered.
+
+
+ +
+
+ min
+
+ 类型:整数
+
+ 该控件可以有的最小的整数值,默认值为0.
+
+

 

+
+ + +
+
multiline
+
Type: boolean
+
If true, the textbox displays multiple lines. If the user presses Enter, a new line is started. If false, the textbox only allows entry of one line.
+
+
+ + +
+
newlines
+
Type: one of the values below
+
How the text box handles pastes with newlines in them.
+
Possible values: +
+
pasteintact
+
Paste newlines unchanged
+
pastetofirst
+
Paste text up to the first newline, dropping the rest of the text
+
replacewithcommas
+
Pastes the text with the newlines replaced with commas
+
replacewithspaces
+
Pastes the text with newlines replaced with spaces
+
strip
+
Pastes the text with the newlines removed
+
stripsurroundingwhitespace
+
Pastes the text with newlines and adjacent whitespace removed
+
+
+
+
+ + +
+
onchange
+
Type: script code
+
This event is sent when the value of the textbox is changed. The event is not sent until the focus is moved to another element.
+
+ + +
+ + +
+
oninput
+
Type: script code
+
This event is sent when a user enters text in a textbox. This event is only called when the text displayed would change, thus it is not called when the user presses non-displayable keys.
+
+ + +
+ + +
+
placeholder
+
Type: string
+
A string that appears in the textbox when it has no value.
+
+
+ + +
+
preference
+
Type: id
+
Connects the element to a corresponding preference. This attribute only has any effect when used inside a prefwindow. More information is available in the Preferences System article.
+
+
+ + +
+
readonly
+
Type: boolean
+
If set to true, then the user cannot change the value of the element. However, the value may still be modified by a script.
+
+
+ +
+
+ rows
+
+ Type: integer
+
+ The number of rows to display in the element. If the element contains more than this number of rows, a scrollbar will appear which the user can use to scroll to the other rows. To get the actual number of rows in the element, use the getRowCount method.
+
+
+ + +
+
searchbutton
+
Type: boolean
+
If true, the search field will only fire a command event when the user presses the search button or presses the Enter key. Otherwise, the command event is fired whenever the user modifies the value. This attribute only applies to textboxes with the type search.
+
+
+ + +
+
size
+
Type: integer
+
The number of characters that can be displayed in the textbox.
+
+
+ + +
+
spellcheck
+
Type: boolean
+
If true, spell checking is enabled by default for the text box; if false, spell checking is disabled by default.
+
If not specified, this defaults to false
+
+ +

The HTML

+ +
+

The spellcheck attribute uses values of true or false (you cannot simply add the spellcheck attribute to a given element):

+ +
<!-- spellcheck everything! -->
+<input type="text" spellcheck="true" /><br />
+<textarea spellcheck="true"></textarea>
+<div contenteditable="true" spellcheck="true">I am some content</div>
+
+<!-- spellcheck nothing! -->
+<input type="text" spellcheck="false" /><br />
+<textarea spellcheck="false"></textarea>
+<div contenteditable="true" spellcheck="false">I am some content</div>
+ +

You can use spellcheck on INPUTTEXTAREA, and contenteditable elements.  Thespellcheck attribute works well paired with the autocomplete, autocapitalize, and autocorrect attributes too!

+ +

Added from David Walsh's article on Spell Check.

+
+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ + +
+
timeout
+
Type: integer
+
For autocomplete textboxes, the number of milliseconds before the textbox starts searching for completions. The default is 50 milliseconds. For search textboxes, the number of milliseconds before the timer fires a command event. The default is 500 milliseconds. For timed textboxes, the number of milliseconds before the timer fires a command event. There is no default. The timer starts after the user types a character. If the user types another character, the timer resets.
+
+
+ + +
+
type
+
Type: one of the values below
+
You can set the type attribute to one of the values below for a more specialized type of textbox. Don't set the type if you wish to use a regular textbox.
+
+
+
autocomplete
+
A textbox that supports autocomplete. For more information about autocomplete textboxes, see the autocomplete documentation (XPFE [Thunderbird/SeaMonkey]) (Firefox)
+
number
+
 A textbox that only allows the user to enter numbers. In addition, arrow buttons appear next to the textbox to let the user step through values. There are several attributes that allow the number textbox to be configured, including decimalplaces, min, max, increment, wraparound, hidespinbuttons, and textbox.value.
+
password
+
A textbox that hides what is typed, used for entering passwords.
+
search
+
 A textbox intended for searching. The command event will fire as the user modifies the value. A listener for the command event should update search results. If the searchbutton attribute is set to true, the command event is only fired if the user presses the search button or presses the Enter key. You may specify grey text to appear when the search box is empty using the emptytext attribute, and a timeout may be set for the command event using the timeout attribute (defaults to 500).
+
timed
+
This textbox will fire a command event after the user types characters and a certain time has passed. The delay is set with the timeout attribute. The command event will fire if the user presses the Enter key. The timed type is deprecated in Gecko 1.9.1 and the search textbox may be used instead.
+
+
+
+ + +
+ + +
+
value
+
Type: string
+
The default value entered in a textbox. The attribute only holds the default value and is never modified when the user enters text. To get the updated value, use the value property. For number boxes, the default is 0 or the minimum value returned by the min property, whichever is higher.
+
+ + +
+ + +
+
wrap
+
Type: string
+
Set this attribute to the value off to disable word wrapping in the textbox. If this attribute is not specified, word wrapping is enabled.
+
+
+ + +
+
wraparound
+
Type: boolean
+
If true, the value of the number box will wrap around when the maximum or minimum value is exceeded. The minimum and maximum values must both not be infinity.
+
+

+

Properties

+

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+
+
+ clickSelectsAll
+
+ Type: boolean
+
+ If set to true, the contents of the textbox are selected when focused; otherwise, the cursor is left unchanged.
+
+
+
+ decimalPlaces
+
+ Type: integer
+
+ Gets and sets the value of the decimalplaces attribute.
+
+
+
+ decimalSymbol
+
+ Type: string
+
+ The character used for the decimal place indicator. The default value is a period (.)
+
+
+
+ defaultValue
+
+ 类型: 字符串
+
+ 获取或设置一个textbox元素中显示的默认值.
+
+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+ +
+
editor
+
Type: nsIEditor
+
A reference to the nsIEditor for editable text. This property is read only.
+
+ +
+
emptyText Deprecated since Gecko 2
+
Type: string
+
Gets and sets a string that appears in the textbox when it has no value. This is superseded by the  placeholder property in Gecko 2.0. The old name is retained for compatibility, but you should update your code.
+
+
+
+ increment
+
+ Type: integer
+
+ Gets and sets the value of the increment attribute.
+
+ +
+
inputField
+
Type: textbox element
+
In Mozilla, the XUL textbox is implemented as a wrapper around an HTML input element. This read only property holds a reference to this inner input element.
+
+ +
+
label
+
Type: string
+
Sets the label attribute. Gets the label attribute if it is present and not empty. Otherwise it returns the value of the associated label element, if applicable. Otherwise it returns the placeholder or emptyText property. The getter is mostly useful for screen readers. +
+

Note: Prior to Firefox 3, and always in Thunderbird and SeaMonkey, the label property of an autocomplete textbox returns its value, for compatibility with the menulist element.

+
+
+
+
+
+ max
+
+ 类型:整数
+
+ 获取或设置max特性(attribute)的值.
+
+ +
+
maxLength
+
Type: integer
+
The maximum number of characters that the textbox allows to be entered.
+
+
+
+ min
+
+ Type: integer
+
+ Gets and sets the value of the min attribute.
+
+ +
+
placeholder
+
Type: string
+
Gets and sets a string that appears in the textbox when it has no value.
+
+
+
+ readOnly
+
+ Type: boolean
+
+ If set to true, then the user cannot modify the value of the element.
+
+ +
+
searchButton
+
Type: boolean
+
Gets and sets the value of the searchbutton attribute.
+
+ +
+
selectionEnd
+
Type: integer
+
Get or set the end of the selected portion of the field's text. Use in conjuction with the selectionStart property. The value specifies the index of the character after the selection. If this value is equal to the value of the selectionStart property, no text is selected, but the value indicates the position of the caret (cursor) within the textbox.
+
+ +
+
selectionStart
+
Type: integer
+
Get or set the beginning of the selected portion of the field's text. Use in conjuction with the selectionEnd property. The value specifies the index of the first selected character.
+
+ +
+
size
+
Type: integer
+
Gets and sets the value of the size attribute.
+
+
+
+ spinButtons
+
+ 类型:spinbuttons元素
+
+ 一个只读属性,返回了数字输入框元素(type属性为number的textbox元素)中包含的spinbuttons元素(也就是右侧调整数字大小的上下小箭头).
+
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+ +
+
textLength
+
Type: integer
+
Holds the length of the text entered in the textbox. This property is read-only.
+
+ +
+
timeout
+
Type: integer
+
Gets and sets the value of the timeout attribute.
+
+
+
+ type
+
+ Type: string
+
+ Gets and sets the value of the type attribute.
+
+
+
+
+ value
+
+ 类型:字符串
+
+ 读取或设置该textbox元素中的文本内容.
+
+
+
+ valueNumber
+
+ Type: number
+
+ In contrast to the value property which holds a string representation, the valueNumber property is a number containing the current value of the number box.
+
+
+
+ wrapAround
+
+ Type: boolean
+
+ Gets and sets the value of the wraparound attribute.
+

+

Methods

+

+
+ decrease()
+
+ Return type: no return value
+
+ Decreases the value of the scale or number box by the increment.
+
+
+ increase()
+
+ 返回值类型: 无返回值
+
+ 增大刻度条控件(scale元素)或者数字输入框控件(type属性为number的textbox元素)中的数字值(按照其increment属性指定的值).
+
+
+ reset()
+
+ 返回值:无返回值
+
+ 将用户偏好重置为默认值.
+
+
+ select()
+
+ Return type: no return value
+
+ Selects all the text in the textbox.
+
+
+ setSelectionRange( start, end )
+
+ Return type: no return value
+
+ Sets the selected portion of the textbox, where the start argument is the index of the first character to select and the end argument is the index of the character after the selection. Set both arguments to the same value to move the cursor to the corresponding position without selecting text.
+
+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+

Style classes

+

The following classes may be used to style the element. These classes should be used instead of changing the style of the element directly since they will fit more naturally with the user's selected theme.

+

+
plain
+
This class causes the element to be displayed with no border or margin.
+

+

Notes

+

The maxlength attribute does not work when in multiline mode. A workaround using JavaScript and the onkeypress event handler as shown in abstract below may be your solution.

+

The XUL script:

+
<textbox id="pnNote" multiline="true" rows="2" cols="70" onkeypress="return pnCountNoteChars(event);"/>
+
+

The Javascript:

+
function pnCountNoteChars(evt) {
+    //allow non character keys (delete, backspace and and etc.)
+    if ((evt.charCode == 0) && (evt.keyCode != 13))
+      return true;
+
+    if(evt.target.value.length < 10) {
+        return true;
+    } else {
+        return false;
+    }
+}
+ +
+
+ Interfaces
+
+ nsIAccessibleProvider, nsIDOMXULTextboxElement
+
+

diff --git a/files/zh-cn/mozilla/tech/xul/toolbarpalette/index.html b/files/zh-cn/mozilla/tech/xul/toolbarpalette/index.html new file mode 100644 index 0000000000..7df0ea3483 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/toolbarpalette/index.html @@ -0,0 +1,103 @@ +--- +title: toolbarpalette +slug: Mozilla/Tech/XUL/toolbarpalette +translation_of: Archive/Mozilla/XUL/toolbarpalette +--- +
+ + « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+

Firefox only

+

The item is a palette of available toolbar items. It is not displayed, but is used by the toolbar customization dialog to display the list of items. The children of the toolbarpalette should be the complete list of toolbarbuttons and toolbaritems that can be added to the toolbar. Do not add the various spacing items, as those are added automatically.

+

这个控件(item不知道是不是这个意思,下同)是一个调色板控件,它不会显示出来,但是是被工具栏用来个性化对话框从而显示控件列表的。toolbarpalette的子类应该是一个可以被添加入工具栏toolbarbutton和toolbaritem的完整列表。不要加入spacing items,因为它们是被自动添加的。

+

You can add your own custom buttons to the Firefox browser by using an overlay that overlays the toolbarpalette with the idBrowserToolbarPalette.

+

你可以通过overlay来向火狐浏览器添加个性化的按钮,这是通过用BrowserToolbarPalette覆盖toolbarpalette实现的

+

不过个人感觉这个palette好像不怎么用

+

Examples(实例)

+
<toolbarpalette id="BrowserToolbarPalette">
+  <toolbarbutton id="toolbarpalette-button"
+                 class="toolbarbutton-class"
+                 label="&mylabel;"
+                 tooltiptext="&mytiptext;"
+                 oncommand="somefunction()"/>
+</toolbarpalette>
+
+

Attributes

+

+ + + + + +

Inherited from XUL element
+align, +allowevents, +allownegativeassertions, +class, +coalesceduplicatearcs, +collapsed, +container, +containment, +context, +contextmenu, +datasources, +dir, +empty, +equalsize, +flags, +flex, +height, +hidden, +id, +insertafter, +insertbefore, +left, +maxheight, +maxwidth, +menu, +minheight, +minwidth, +mousethrough, +observes, +ordinal, +orient, +pack, +persist, +popup, +position, +preference-editable, +querytype, +ref, +removeelement, +sortDirection, +sortResource, +sortResource2, +statustext, +style, +template, +tooltip, +tooltiptext, +top, +uri, +wait-cursor, +width

+

+

Properties

+

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+

Methods

+

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +
+
+ Elements(意思应该是这里面含有的元素吧,看样子既然toolbox都在里面说明这个item还是挺大的)
+
+ toolbar, toolbarbutton, toolbargrippy, toolbaritem, toolbarseparator, toolbarset, toolbarspacer, toolbarspring, toolbox
+
+

diff --git a/files/zh-cn/mozilla/tech/xul/toolbars/creating_toolbar_buttons/index.html b/files/zh-cn/mozilla/tech/xul/toolbars/creating_toolbar_buttons/index.html new file mode 100644 index 0000000000..363a3b9e2b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/toolbars/creating_toolbar_buttons/index.html @@ -0,0 +1,183 @@ +--- +title: 添加工具栏按钮 (定制工具栏) +slug: Mozilla/Tech/XUL/Toolbars/Creating_toolbar_buttons +translation_of: Archive/Mozilla/XUL/Toolbars/Creating_toolbar_buttons +--- +

此文章解释如何使用 overlays 为工具包(firefox,Thunderbird 或 Kompozer) 添加工具栏按钮(就是浏览器右上方一系列按钮,home,下载之类的)。适用用户是拥有 XULCSS 基础知识的 扩展 开发人员。

+

我们假设您已经会创建基础的火狐插件,并且已经成功创建了 Hello World extension ,另外,还有一份更加完全的初学者示例指南,请查看 自定义工具栏按钮。

+

创建一个 overlay

+

The first step is to create an overlay for the document containing the toolbar you wish to enhance. Explaining overlays is beyond the scope of this tutorial -- you can read about them in the XUL Tutorial.

+

To overlay a document, you need to know its URI. You can find a list of URIs for the most commonly overlaid documents at the bottom of this page.

+
+ Note: Some people overlay chrome://messenger/content/mailWindowOverlay.xul. That should cause the button to appear on all windows that mailWindowOverlay.xul is applied to (i.e. Main window and View Message window). This needs to be looked into.
+

在工具栏添加按钮

+

Toolkit applications have customizable toolbars; therefore, it's common practice for extensions to add their toolbar buttons to the toolbar palette, rather than adding them directly to the toolbar. The latter is possible but is not recommended and is harder to implement.

+

Adding a button to the toolbar palette is very easy. Just add code like this to your overlay:

+
<toolbarpalette id="BrowserToolbarPalette">
+  <toolbarbutton id="myextension-button" class="toolbarbutton-1"
+    label="&toolbarbutton.label;" tooltiptext="&toolbarbutton.tooltip;"
+    oncommand="MyExtension.onToolbarButtonCommand(event);"/>
+</toolbarpalette>
+
+

注意:

+ +
onclick="checkForMiddleClick(this, event)"
+ +
<toolbarpalette id="BrowserToolbarPalette">
+  <toolbarbutton id="myextension-button" class="toolbarbutton-1"
+    label="&toolbarbutton.label;" tooltiptext="&toolbarbutton.tooltip;"
+    onclick="MyExtension.onclick(event);"/>
+</toolbarpalette>
+
onclick: function(event) {
+  switch(event.button) {
+    case 0:
+      // Left click
+      break;
+    case 1:
+      // Middle click
+      break;
+    case 2:
+      // Right click
+      break;
+  }
+}
+
+

To add more buttons, put more <toolbarbutton> elements inside the <toolbarpalette> element. Wrap elements other than <toolbarbutton> in <toolbaritem>.

+

为按键应用风格

+

Most toolbar buttons have an icon. To attach an image to the button we use standard Mozilla skinning facilities. If you're unfamiliar with how that works, read the skinning section of Jonah Bishop's excellent Toolbar Tutorial. Although the article covers creating an entire toolbar, rather than just a button, it has a great explanation of the techniques we'll use here.

+

图标大小

+

Toolbar buttons can have two different sizes -- big and small. This means you'll need to provide two icons for each of your toolbar buttons. The dimensions of the icons in various applications for both modes are summarized in the following table (feel free to add information about other applications):

+ + + + + + + + + + + + + + + + + + +
Application (Theme name)Big icon sizeSmall icon size
Firefox 1.0 (Winstripe)24x2416x16
Thunderbird 1.0 (Qute)24x2416x16
+

CSS 样式表

+

To set the image for your toolbar button, use the following CSS rules:

+
/*  skin/toolbar-button.css  */
+
+#myextension-button {
+  list-style-image: url("chrome://myextension/skin/btn_large.png");
+}
+
+toolbar[iconsize="small"] #myextension-button {
+  list-style-image: url("chrome://myextension/skin/btn_small.png");
+}
+
+

应用样式表

+

Remember to attach the stylesheet you created to both the overlay file and the Customize Toolbar window. To attach it to the overlay, put this processing instruction (PI) at the top of the overlay file:

+
<?xml-stylesheet href="chrome://myextension/skin/toolbar-button.css" type="text/css"?>
+
+
+ Note: The CSS file with your toolbar styles needs to be included in the overlay file, as you would expect, but also in the chrome.manifest file. This is very important because the toolbar customization dialog won't work correctly without this.
+

To include the style on your chrome.manifest file:

+
style chrome://global/content/customizeToolbar.xul chrome://myextension/skin/toolbar-button.css
+
+

If you are developing for Firefox 1.0, attach it to the Customize Toolbar window (chrome://global/content/customizeToolbar.xul) using skin/contents.rdf. The code looks like this:

+
<?xml version="1.0"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
+
+  <Seq about="urn:mozilla:skin:root">
+    <li resource="urn:mozilla:skin:classic/1.0"/>
+  </Seq>
+
+  <Description about="urn:mozilla:skin:classic/1.0">
+    <chrome:packages>
+      <Seq about="urn:mozilla:skin:classic/1.0:packages">
+        <li resource="urn:mozilla:skin:classic/1.0:myextension"/>
+      </Seq>
+    </chrome:packages>
+  </Description>
+
+  <Seq about="urn:mozilla:stylesheets">
+    <li resource="chrome://global/content/customizeToolbar.xul"/>
+  </Seq>
+
+  <Seq about="chrome://global/content/customizeToolbar.xul">
+    <li>chrome://myextension/skin/toolbar-button.css</li>
+  </Seq>
+</RDF>
+
+

The skin/contents.rdf file is denigrated in developing for later releases of Firefox. Extensions for Firefox/Thunderbird 1.5 and above should instead use something like this in their chrome.manifest:

+
skin	myextension	classic/1.0	chrome/skin/
+style	chrome://global/content/customizeToolbar.xul	chrome://myextension/skin/toolbar-button.css
+ia
+

Take note of the Packaging section in this article; you may need to include .jar references if you are delivering your extension as a .xpi file.

+

常见错误

+

This is a list of the most common mistakes made by extension authors, including both symptoms and solutions.

+

Problem: The whole set of default buttons is painted on the toolbar or in the Customize Toolbars window, instead of your own icon.

+

Caused by: Malformed or not applied stylesheet.

+

Solution: Check to be sure your stylesheet is correct, make sure your contents.rdf (or chrome.manifest) is correct, and be sure you didn't forget to apply the stylesheet to customizeToolbar.xul.

+

常见工具栏的 overlayed windows

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
URLApplication and affected window(s)Palette id
chrome://browser/content/browser.xulFirefox - Main windowBrowserToolbarPalette
chrome://navigator/content/navigator.xulSeaMonkey 2.0 - Browser windowBrowserToolbarPalette
chrome://messenger/content/messenger.xulThunderbird - Main windowMailToolbarPalette
chrome://messenger/content/messenger...gercompose.xulThunderbird - Compose windowMsgComposeToolbarPalette
chrome://messenger/content/addressbo...ddressbook.xulThunderbird - Address bookAddressBookToolbarPalette
chrome://editor/content/editor.xulKompozer - Main windowNvuToolbarPalette
chrome://calendar/content/calendar.xulSunbird - Main windowcalendarToolbarPalette
+

更多信息

+ diff --git a/files/zh-cn/mozilla/tech/xul/toolbars/custom_toolbar_button/index.html b/files/zh-cn/mozilla/tech/xul/toolbars/custom_toolbar_button/index.html new file mode 100644 index 0000000000..9030e502a8 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/toolbars/custom_toolbar_button/index.html @@ -0,0 +1,332 @@ +--- +title: 自定义工具栏按钮 +slug: Mozilla/Tech/XUL/Toolbars/Custom_toolbar_button +translation_of: Archive/Mozilla/XUL/Toolbars/Custom_toolbar_button +--- +

此教程教您一步步为 Firefox, SeaMonkey 2.0, Thunderbird 或 Sunbird 制作工具栏按钮 (对于 SeaMonkey 1.x,请查看 Custom Toolbar Button:SeaMonkey.)

+

你不需要任何技巧和工具,所以需要的信息全部在本页。

+

 

+

介绍

+

本页所述技术不包括任何黑科技。你可以自己定制属于自己的扩展。

+

适用示例上的代码可以制作出很多很有用的按钮,如果你懂得 JS 编程,你可以自己编代码,实现更多其他功能。

+

如果你需要创建一个具某项功能的按钮,那么你来对地方了

+

在此页你也能学到扩展程序的基础知识,有利于将来写更复杂的插件。注意,扩展程序非常简单,你或许得查看其他教程,那么-主 扩展 页就是您该去的地方。另外, 创建工具栏按钮 这篇文章(译注:建议先看本文再看这个,那里面有几句没说清楚该放哪去)和 创建一个扩展 更好的展示了创建过程。

+

支持的程序

+

本文中步骤适用于下列 Mozilla 应用:

+ +

提前发行版一般都支持 (alphas, betas 和 release candidates) 。

+

译注:本文的例子适用于很多Mozilla 开发的应用程序,原文用Application 代表这些程序,所以我按照原文翻译成了应用/程序,所以如果将来遇到应用/程序等字样,就是指Firefox 等。

+
+

Note:  There is a similar tutorial for SeaMonkey 1.x on the page: Custom Toolbar Button:SeaMonkey

+

Earlier versions and other Mozilla applications also support extensions, but some parts of this tutorial are not appropriate for them.

+
+

所需工具

+

需要两个工具,系统一般都默认提供了:

+ +
字符编码
+

有些文本编辑器有调整字符编码的选项。

+

如果你使用拉丁 (ASCII) 字符,那就将你的文本编辑器设为除 Unicode 外的任意编码

+

如果你的语言包含非拉丁字符,那保存文件时请选择 UTF-8 编码。

+

要想测试编辑器,新建一个文件test.txt。在文件中输入属于您语言的文字,然后保存。

+

使用火狐打开此文件,(例如,直接将文件拖动到火狐上,或在菜单中选择 文件 – 打开文件)。

+

在火狐的菜单栏中,选择 查看– 字符编码 – Unicode (UTF-8)。然后看在此设置下,文本中的文字是否能正常显示。

+

如果你的文本编辑器不支持 UTF-8,自己上网搜索装一个。

+

可选工具

+

可以使用任意图像编辑器编辑图片。

+

可以使用 jar 工具或 zip 工具将此按钮项目压缩成跨平台的安装文件 (XPI),方便别人安装使用。

+

制作一个按钮

+

按照下面10步完成

+

完成所有步骤后,文件夹结构应该如下图所示:

+
+
+ Directory and file structure
+
+

 profile 和 extensions 文件夹已存在,需要添加图中其他的文件和文件夹(当然此目录下可能还会有其他文件,只是没显示.)

+
+
+ 1.
+ 前往应用程序的配置文件夹,然后找到extensions 文件夹。 +

注意:  至于如何找到配置文件夹,请查看:配置文件夹

+

说明:  配置文件夹包含用户指定的设置,和主程序分开存放。所以程序重装或升级之后,这些信息不受影响。

+
+ 2.
+ 在 extensions 文件夹中,创建一个文件夹,名称如下: +

建议直接复制粘贴,以免出错

+
+
+ custom-toolbar-button@example.com
+
+

按照后面的步骤,创建两个文件和一个文件夹。

+

说明:  此文件夹名称是用于区分不同扩展程序的唯一标识符。在稍后的部分会有详细的标识符。

+
+ 3.
+ 创建一个文本文档,名称为 install.rdf. +

完整复制下面内容,粘贴到文档中:

+
<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description
+    about="urn:mozilla:install-manifest"
+
+    em:name="Custom Button"
+    em:description="My custom toolbar button"
+    em:creator="My name"
+
+    em:id="custom-toolbar-button@example.com"
+    em:version="1.0"
+    em:homepageURL="http://developer.mozilla.org/en/docs/Custom_Toolbar_Button"
+
+    em:iconURL="chrome://custombutton/content/icon.png" >
+
+    <em:targetApplication><!-- Firefox -->
+      <Description
+        em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
+        em:minVersion="1.4"
+        em:maxVersion="99" />
+    </em:targetApplication>
+
+    <em:targetApplication><!-- Thunderbird -->
+      <Description
+        em:id="{3550f703-e582-4d05-9a08-453d09bdfdc6}"
+        em:minVersion="1.4"
+        em:maxVersion="99" />
+    </em:targetApplication>
+
+    <em:targetApplication><!-- Sunbird -->
+      <Description
+        em:id="{718e30fb-e89b-41dd-9da7-e25a45638b28}"
+        em:minVersion="0.2.9"
+        em:maxVersion="99" />
+    </em:targetApplication>
+
+    <em:file>
+      <Description
+        about="urn:mozilla:extension:custombutton"
+        em:package="content/custombutton/" />
+    </em:file>
+
+  </Description>
+
+</RDF>
+
+

可选:改变 name, description 和 creator。改变这三行中双引号间的文字即可

+

根据需求,移除不需要的软件说明部分(译注:假如你只想给firefox创建插件,那么就可以删掉别的部分)。

+

保存文件

+

说明:  此文件包含应用程序扩展管理器需要的信息。target applications这一大段表示能运行扩展程序的应用以及版本号。 最后一段描述此插件会添加内容到应用程序。

+
+ 4.
+ 创建一个文本文档,名称为 chrome.manifest. +

完整复制下面内容,粘贴到文档中:

+
content custombutton chrome/
+style chrome://global/content/customizeToolbar.xul chrome://custombutton/content/button.css
+
+# Firefox
+overlay	chrome://browser/content/browser.xul chrome://custombutton/content/button.xul
+
+# Thunderbird mail
+overlay	chrome://messenger/content/messenger.xul chrome://custombutton/content/button.xul
+
+# Thunderbird compose
+overlay	chrome://messenger/content/messengercompose/messengercompose.xul chrome://custombutton/content/button.xul
+
+# Thunderbird address book
+overlay	chrome://messenger/content/addressbook/addressbook.xul chrome://custombutton/content/button.xul
+
+# Sunbird
+overlay	chrome://calendar/content/calendar.xul chrome://custombutton/content/button.xul
+
+

移除不需要的部分(同上段说明)。

+

保存文件

+

说明:  此文件定义扩展的内容结构。先给工具栏窗口应用一个样式表。然后给每个工具栏都指定一个 overlay 。

+
+ 5.
+ 创建文件夹: chrome. +

按照下放说明,创建 5 个文件。

+

说明:   chrome 文件夹包含扩展的可执行部分,即扩展是干什的。

+
+ 6.
+ 创建一个文本文档,名称为 button.xul. +

完整复制下面内容,粘贴到文档中:

+
<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/css"
+  href="chrome://custombutton/content/button.css"?>
+
+<!DOCTYPE overlay >
+<overlay id="custombutton-overlay"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script type="application/javascript"
+  src="chrome://custombutton/content/button.js"/>
+
+<!-- Firefox -->
+<toolbarpalette id="BrowserToolbarPalette">
+  <toolbarbutton id="custom-button-1"/>
+  </toolbarpalette>
+
+<!-- Thunderbird mail -->
+<toolbarpalette id="MailToolbarPalette">
+  <toolbarbutton id="custom-button-1"/>
+  </toolbarpalette>
+
+<!-- Thunderbird compose -->
+<toolbarpalette id="MsgComposeToolbarPalette">
+  <toolbarbutton id="custom-button-1"/>
+  </toolbarpalette>
+
+<!-- Thunderbird address book -->
+<toolbarpalette id="AddressBookToolbarPalette">
+  <toolbarbutton id="custom-button-1"/>
+  </toolbarpalette>
+
+<!-- Sunbird -->
+<toolbarpalette id="calendarToolbarPalette">
+  <toolbarbutton id="custom-button-1"/>
+  </toolbarpalette>
+
+
+<!-- button details -->
+<toolbarbutton id="custom-button-1"
+  label="Custom"
+  tooltiptext="My custom toolbar button"
+  oncommand="CustomButton[1]()"
+  class="toolbarbutton-1 chromeclass-toolbar-additional custombutton"
+  />
+
+</overlay>
+
+

可选:你可以自定义最后一块中的 label 和 tooltiptext 。更改双括号间的内容即可。

+

可选地,移除不需要的部分。。

+

保存文件。

+

说明: XUL 文件会添加一个按钮到应用程序的 toolbar customization palette。此文件还链接了CSS样式表 和 JavaScript 脚本。最后一部分描述按钮的信息(译注;就是按钮名+鼠标放上面会提示什么文字)

+
+ 7.
+ 创建一个文本文档,名称为: button.css. +

完整复制下面内容,粘贴到文档中:

+
#custom-button-1,
+#wrapper-custom-button-1
+  {list-style-image: url("chrome://custombutton/content/button-1.png");}
+
+/* common style for all custom buttons */
+.custombutton
+  {-moz-image-region: rect( 0px 24px 24px  0px);}
+
+.custombutton:hover
+  {-moz-image-region: rect(24px 24px 48px  0px);}
+
+[iconsize="small"] .custombutton
+  {-moz-image-region: rect( 0px 40px 16px 24px);}
+
+[iconsize="small"] .custombutton:hover
+  {-moz-image-region: rect(24px 40px 40px 24px);}
+
+

没有什么能优化的,保存文件即可

+

说明: CSS 样式表定义按钮如何显示。它链接到了按钮图片,指定了图片四个部分的尺寸。(译注;这里你就可以看文章开头提到的文章了,比这里举的例子更好实现,你只需在css中指定一大一小两个图片即可)

+
+ 8.
+ 创建一个文本文档,名称为: button.js. +

完整复制下面内容,粘贴到文档中:

+
+
CustomButton = {
+
+1: function () {
+  alert("Just testing")
+  },
+
+}
+
+
+

没有什么能优化的,保存文件即可

+

接下来一部分的教程包含几个实例代码,你可以用他们来实现有用的功能。

+

说明:  此文件指定当按钮按下时执行什么操作。它使用  JavaScript 语言,加应用自己提供的一些特性。

+
+ 9.
+ 下载按钮图片。 +

右击图片,另存为,保存到 chrome 目录下。请确保文件名为: button-1.png

+
+ button-1.png
+

说明:  此图片包含四个部分。左上方是常用的图标。左下是深色的,按下按钮后显示,右侧的是小图标,工具栏设置成使用小图标时需要用。

+
+ 10.
+ 下载扩展的图片。 +

右击图片,另存为,保存到 chrome 目录下。请确保文件名为:icon.png

+
+ icon.png
+

说明:  此图片显示在应用扩展管理窗口中。

+
+

测试您的按钮

+

重启应用程序(firefox)

+

右击工具栏,选中定制,或者在菜单中,依次选择:查看 – 工具栏 – 定制

+

将刚才的新按钮拖动到工具栏,点击“退出定制”保存设置。

+

点击按钮,应该能看到弹出信息了。

+

进一步开发

+

此部分描述如何进一步开发按钮。

+

卸载按钮

+

如果想卸载按钮,删掉步骤 2 创建的文件夹即可。

+

或者,使用程序自己的 扩展管理窗口 正常卸载应用,在下次重启时应用就会删掉此文件夹。

+

重启程序

+

排错

+

如果按钮没在工具栏中显示,或是其他问题,可以按照下列步骤排查。

+

如果有必要,卸载按钮,重头开始,这次不要修改任何内容

+

在能成功让按钮工作后,小心的修改文件。

+

要想看到修改后的结果,需要重启应用。

+
高级排错
+

如果你有一定的技术只是,那么你可以使用应用程序的 JavaScript console 查看错误信息。但是不一定都有用,而且易混淆,或是看到了其他程序的执行结果。

+

在 工具栏 - 开发者(web developer) - Browser Console 中开启 JS 选项。或使用快捷键"Ctrl + Shift + J"

+

 JavaScript console 里会显示 JavaScript, XUL 或 CSS 文件的信息。

+
+ Note: The preference setting javascript.options.strict imposes restrictions that are not appropriate for the simple scripts in this tutorial. If you choose to use this setting, either ignore the warnings that it generates, or change the coding style to keep it quiet.
+

为按钮编程

+

要想改变按钮功能,去修改步骤 8 里的 button.js

+

移除行: alert("Just testing") ,替换成其他 js 语句。

+

可以在 Code Samples 查看很多代码示例,不用知道编程知识就能修改并使用。

+

需要重启才能生效变更。

+

添加更多的按钮

+

要想添加更多的按钮,请编辑 button.xul 文件,对于每个应用,复制指定 custom-button-1 的那行,然后将新行指定成 custom-button-2

+

重复最后一部分。在 idoncommand 参数中,将 1 改为 2。然后改变 labeltooltiptext不要改变 class 参数。

+

然后编辑 button.css。复制前三行,改变新行成为 button-2.

+

编辑 button.js 为新按钮添加 js 语句。请确保添加的语句在最后一个花括号的前面,例如,这么添加命令:

+
2: function () {
+  alert("Just testing again")
+  },
+
+

为新按钮创建图标,命名为 button-2.png。下面提供的文件有40 像素宽,48像素高,256色,透明背景,PNG格式,其他格式也能工作。

+

你可以下载使用下列图片:

+
+ button-2.png
+
+ button-3.png
+
+ button-4.png
+
+ button-5.png
+

重启程序,并将新按钮添加到工具栏。

+

你可以重复这些步骤,创建更多按钮

+

将您的按钮分发给其他用户

+

如果你想将按钮程序分发给他人,那就必须做些修改以和其他扩展程序做区分。

+

创建一个扩展 ID,格式为:

+
+
+ something@domain-name
+
+

必须包含at符号 (@),格式和邮箱地址挺像,但不必是真实邮箱地址。@符号的前后,只能使用字符 : A-Z, a-z, 0-9, 英文句号( . ), 连字符(-)和下划线(_)。如果您没有域名(domain-name),可以自己编个,如果你想让这域名看着不像真正的域名,那就在结尾加个 .invalid

+

使用你的 扩展ID (extension ID)重命名文件夹,然后在 install.rdf 文件中指定相同的 ID。

+

在 install.rdf 文件中,移除您扩展不能正常工作的应用项。例如,如果您的按钮只能在 Thunderbird 上运行,就删除 Firefox 和 Sunbird 的部分。同样道理,修改 button.xulchrome.manifest.

+

改变所有文件中的 "custombutton", "custom-button" 和 "CustomButton" 字样。

+

可以自己更改的:

+ +

使用 jar 工具或 zip 工具打包整个文件夹的内容命名为 .xpi 文件。方便用于其他程序。

+

用户可在应用程序的扩展管理窗口中安装此 XPI 文件。

diff --git a/files/zh-cn/mozilla/tech/xul/toolbars/index.html b/files/zh-cn/mozilla/tech/xul/toolbars/index.html new file mode 100644 index 0000000000..b028d9cd69 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/toolbars/index.html @@ -0,0 +1,65 @@ +--- +title: Toolbars +slug: Mozilla/Tech/XUL/Toolbars +tags: + - NeedsTranslation + - TopicStub +translation_of: Archive/Mozilla/XUL/Toolbars +--- +

Toolbars, implemented using the XUL toolbar element, are containers for toolbar buttons and other user interface objects. The following articles provide details about implementing and working with toolbars.

+ + + + + + + +
+

Documentation

+
+
XUL School: Adding Toolbars and Toolbar Buttons
+
A helpful tutorial to creating toolbars and toolbar buttons.
+
Toolbar customization events
+
A look at the events that are sent during toolbar customization; you can use these to be kept aware of changes to toolbars.
+
Creating toolbar buttons
+
How to use overlays to add toolbar buttons to Mozilla applications.
+
Custom toolbar button
+
Another example of how to create a toolbar button, complete with a sample extension you can download and try.
+
Code snippets: Toolbar
+
Code snippets that are helpful when working with toolbars.
+
+
+

View all pages tagged with "Toolbars"...

+
+

Community

+ +

Tools

+ +

... more tools ...

+ + + +
diff --git a/files/zh-cn/mozilla/tech/xul/toolbox/index.html b/files/zh-cn/mozilla/tech/xul/toolbox/index.html new file mode 100644 index 0000000000..4417170b3e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/toolbox/index.html @@ -0,0 +1,6 @@ +--- +title: toolbox +slug: Mozilla/Tech/XUL/toolbox +translation_of: Archive/Mozilla/XUL/toolbox +--- +

This page has no content. Enrich MDC by contributing.

diff --git a/files/zh-cn/mozilla/tech/xul/tree/index.html b/files/zh-cn/mozilla/tech/xul/tree/index.html new file mode 100644 index 0000000000..7e2de0b669 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tree/index.html @@ -0,0 +1,512 @@ +--- +title: tree +slug: Mozilla/Tech/XUL/tree +translation_of: Archive/Mozilla/XUL/tree +--- +
+ « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+ +

tree是用来显示表格或层级行元素的容器。 包含若干行 (rows )和列(columns)。树的每行包含若干缩进显示的子行(child rows)。 和其他元素不同的是,用来显示的数据不是通过标签(tags),而是通过一个显示对象(view object)来确定的。这个显示对象(view object)实现了接口 nsITreeView . The view is queried for the data to appear in the tree. 树的使用有以下几种方法, 第二列列出了通过树的 view属性(property)的可用的接口. 第三列指示treeitem 元素是否使用.

+ +

If you would like to allow the tree to be horizontally scrolled, simply set the width attributes for each column to make the tree wider than its containing object.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tree typeView interfacesHas DOM nodes?Description
Content treensITreeView, nsITreeContentViewYesThis tree has treeitem elements placed within the treechildren element. In this situation, a content view (which implements the interface nsITreeContentView) which is a more specialized type of view, uses the treeitem elements and their descendants to determine the data to display in the tree. However, the treeitems are not displayed directly; they are used only as data to the content view. However, the content view will automatically update the tree if treeitems are changed.
RDF treensITreeView, nsIXULTreeBuilderNoThis tree is generated from an RDF datasource. It is used when a tree has a datasources attribute, and has dont-build-content in its flags attribute. For this tree, the data comes directly from the RDF datasource. DOM treeitems are not created. Even though the template uses treeitem elements to define the content, DOM nodes for these elements are not created. This is the type that should be used for RDF generated trees with lots of rows.
RDF content treensITreeView, nsIXULTreeBuilder, nsITreeContentViewYesThis tree is generated from an RDF datasource. It is similar to the previous type but is used when the tree does not have dont-build-content in its flags attribute. DOM treeitems are created, so you can access the data using RDF functions or DOM functions. This type is suitable for RDF generated trees with a fairly small number of rows.
Custom tree viewnsITreeViewNoFor this tree you implement the nsITreeView interface yourself. The tree's data is retrieved from this custom view. The custom view should be attached to the tree by setting its view property.
+ +

More information is available in the XUL tutorial. Also Tree Widget Changes.

+ + + + + + + +
Relevant accessbility guidelines + +
    +
  • Provide alternative access (e.g., via menus) to column picker and for header behaviors like sorting (these have no default keyboard access).
  • +
+
+ +
+
Attributes
+
disableKeyNavigation, disabled, editable, enableColumnDrag, flags, hidecolumnpicker, onselect, rows, seltype, statedatasource, tabindex, treelines
+
+ +
+
Properties
+
accessibleType, builderView, columns, contentView, currentIndex, disableKeyNavigation, disabled, editingColumn, editingRow, enableColumnDrag, firstOrdinalColumn, inputField, selType, selstyle, tabIndex, treeBoxObject, view
+
+ +

Examples

+ +

A tree with several columns

+ +
<tree flex="1" rows="2">
+
+  <treecols>
+    <treecol id="sender" label="Sender" flex="1"/>
+    <treecol id="subject" label="Subject" flex="2"/>
+  </treecols>
+
+  <treechildren>
+    <treeitem>
+      <treerow>
+        <treecell label="joe@somewhere.com"/>
+        <treecell label="Top secret plans"/>
+      </treerow>
+    </treeitem>
+    <treeitem>
+      <treerow>
+        <treecell label="mel@whereever.com"/>
+        <treecell label="Let's do lunch"/>
+      </treerow>
+    </treeitem>
+  </treechildren>
+
+</tree>
+
+ +
Image:trees1.png
+ +

A tree with several columns and nested items

+ +
<tree id="myTree" flex="1" hidecolumnpicker="false" seltype="single" class="tree"
+      rows="5">
+  <treecols id="myTree2-treeCols">
+    <treecol id="myTree2-treeCol0" primary="true" flex="2" label="Column A"
+             persist="width" ordinal="1"/>
+    <splitter class="tree-splitter" ordinal="2"/>
+    <treecol id="myTree2-treeCol1" flex="1" label="Column B"
+             persist="width" ordinal="3"/>
+  </treecols>
+  <treechildren>
+    <treeitem>
+      <treerow>
+        <treecell label="1"/>
+        <treecell label="a"/>
+      </treerow>
+    </treeitem>
+    <!-- Make sure to set container="true" -->
+    <treeitem container="true" open="true">
+      <treerow>
+        <treecell label="2"/>
+        <treecell label="b"/>
+      </treerow>
+      <treechildren>
+        <treeitem>
+          <treerow>
+            <treecell label="2a"/>
+            <treecell label="ba"/>
+          </treerow>
+        </treeitem>
+      </treechildren>
+    </treeitem>
+  </treechildren>
+</tree>
+
+ +

Attributes

+ +

+ + +
+
disabled
+
 
+
+
类型:boolean
+
+
+
表示元素是被禁用的。
+ +

如果这个元素的disabled属性被设置为true,表示元素被禁用,被禁用的属性在页面上通常会显示灰色文本,它无法响应用户的操作,它也无法得到光标。

+ +

然而,这个元素仍然能够响应鼠标事件,如果要启用这个元素,把disabled设置为false

+
+
+ +

示例:

+ +
Image:XUL_ref_attr_disabled.png
+ +
// Disabling an element
+document.getElementById('buttonRemove').setAttribute("disabled", "true");
+
+// Enabling back an element by removing the "disabled" attribute
+document.getElementById('buttonRemove').removeAttribute("disabled");
+ +

+

Firefox 3.5 note

+

For keyset elements, support for this attribute was added in Firefox 3.5.

+

+
+ + +
+
disableKeyNavigation
+
Type: boolean
+
If this attribute is not used, the user can navigate to specific items within the element by pressing keys corresponding to letters in the item's label. This is done incrementally, so typing more letters with select more specific items. This feature may be disabled by setting this attribute to true.
+
+
+ + +
+
editable
+
Type: boolean
+
Indicates that the cells of the tree may be edited.
+
+
+ + +
+
enableColumnDrag
+
Type: boolean
+
When set to true, the user may drag the column headers around to change the order in which they are displayed.
+
+
+ + +
+
flags
+
Type: space-separated list of the values below
+
A set of flags used for miscellaneous purposes. Two flags are defined, which may be the value of this attribute. +
    +
  • dont-test-empty: For template generated content, the builder will not check that a container is empty.
  • +
  • dont-build-content: This flag may be used on a tree to indicate that content elements should not be generated. This results in a performance enhancement, but you will not be able to use the DOM functions to retrieve the tree rows.
  • +
+
+
+
+ + +
+
hidecolumnpicker
+
Type: boolean
+
When set to false, a drop-down will appear in the upper right corner of the tree, which the user may use to show and hide columns. When set to true, the column picker will be hidden. The default value is false.
+
+
+ + +
+
onselect
+
Type: script code
+
This event is sent to a tree when a row is selected, or whenever the selection changes. The user can select multiple rows by holding down Shift or Control and clicking on a row. The onselect event will be sent for each item added to or removed from the selection.
+
+ + +
+ +
+
+ rows
+
+ Type: integer
+
+ The number of rows to display in the element. If the element contains more than this number of rows, a scrollbar will appear which the user can use to scroll to the other rows. To get the actual number of rows in the element, use the getRowCount method.
+
+
+ + +
+
seltype
+
Type: one of the values below
+
Used to indicate whether multiple selection is allowed.
+
+
+
single
+
Only one row may be selected at a time. (Default in listbox and richlistbox.)
+
multiple
+
Multiple rows may be selected at once. (Default in tree.)
+
+
+
+

For trees, you can also use the following values:

+ +
+
cell
+
Individual cells can be selected
+
text
+
Rows are selected; however, the selection highlight appears only over the text of the primary column.
+
+ +

For richlistbox, this is new in Firefox 3.5.

+
+
+
+ + +
+
statedatasource
+
Type: URI
+
Chrome XUL may specify an RDF datasource to use to store tree state information. This is used to hold which tree items are open and which items are collapsed. This information will be remembered for the next time the XUL file is opened. If you do not specify this attribute, state information will be stored in the local store (rdf:local-store).
+
+
+ + +
+
tabindex
+
Type:integer
+
当用户按下 "tab" 键时焦点移动到元素上的顺序。tabindex 数字越大,顺序越靠后。
+
+ + + +

+
+ +
treelines
+
Type: boolean
When set to true, lines are drawn connecting the lines in the tree; when false, the lines are not drawn. This is false by default.
+
+

+ +

Properties

+ +

+
+
+ accessibleType
+
+ Type: + + integer +
+
+ A value indicating the type of accessibility object for the element.
+
+ +

+ +
+
builderView
+
Type: nsIXULTreeBuilder
+
A reference to the tree builder which constructed the tree data. The builder provides access to the RDF resources for each row in the tree, and allows sorting the data by column. In newer versions of Mozilla, the builderView property is actually a synonym for the view property, since the two interfaces are flattened together into a single interface in JavaScript. This property is read-only.
+
+
+
+ columns
+
+ Type: nsITreeColumns
+
+ Returns the columns for the tree as an nsITreeColumns object.
+
+
+
+ contentView
+
+ Type: nsITreeContentView
+
+ For trees built with a content builder - that is, those that do not have flags set -- the contentView will be a reference to the nsITreeContentView for the tree. This interface lets you retrieve the DOM element corresponding to a given a row index and vice versa. For trees that are not built with a content builder, the functions of nsITreeContentView will not be available, since there are no DOM nodes to retrieve. In newer versions of Mozilla, the contentView property is actually a synonym for the view property, since the two interfaces are flattened together into a single interface in JavaScript. This property is read-only.
+
+
+
+ currentIndex
+
+ Type: integer
+
+

Set to the row index of the tree caret in the tree. For trees with focus, the caret's position is indicated by the focus ring, but unfocused trees won't show  a focus ring, naturally. For unfocused trees, the (undrawn) caret's position can still be obtained by this property. If the caret isn't present for any row (for example, because the tree has never been focused), the value will be -1.

+

You cannot rely on this property to change or determine a tree selection, except for trees with seltype="single". (All trees have seltype="multiple" by default.) To reliably change or determine a selection, instead use the nsITreeSelection interface methods available via tree.view.selection.

+
+
+
+
+
+ disabled
+
+ Type: + + boolean +
+
+ Gets and sets the value of the disabled attribute.
+
+ +

+
+
disableKeyNavigation
+
Type: boolean
+
Gets or sets the value of the disableKeyNavigation attribute.
+
+ +
+
editingColumn
+
Type: nsITreeColumn
+
The column of the tree cell currently being edited, or null if there is no cell being edited.
+
+ +
+
editingRow
+
Type: integer
+
The row index of the tree cell currently being edited, or -1 if there is no cell currently being edited.
+
+ +
+
enableColumnDrag
+
Type: boolean
+
When set to true, the user may drag the column headers around to change the order in which they are displayed.
+
+ +
+
firstOrdinalColumn
+
Type: treecol element
+
A reference to the first treecol element, which or may not be the first column displayed in the tree.
+
+ +
+
inputField
+
Type: textbox element
+
Read-only property that holds the textbox that is used for editing.
+
+
+
+ selType
+
+ Type: string
+
+ Gets and sets the value of the seltype attribute.
+
+

 

+
+
+ selstyle
+
+ Type: string
+
+ If set to the value primary, only the label of the primary column will be highlighted when an item in the tree is selected. Otherwise, the entire row will be highlighted. To see the difference, compare the selection style in the folder list and the message list in Mozilla mail.
+
+
+
+ tabIndex
+
+ Type: + + integer +
+
+ Gets and sets the value of the tabindex attribute.
+
+ +

+ +
+
treeBoxObject
+
Type: nsITreeBoxObject
+
The box object is responsible for rendering the tree on the window. This object implements the nsITreeBoxObject interface and contains functions for retrieving the cells at certain coordinates, redrawing cells and scrolling the tree. This property is equivalent to the boxObject property.
+
+
+
+ view
+
+ Type: nsITreeView
+
+ The view for the tree, which is the object which generates the data to be displayed. You can assign an object which implements nsITreeView to this property. Trees built from RDF or those which use treeitems directly will already have a view. Functions available in the view allow one to retrieve the data within the cells, and determine which rows are nested within others. For a complete list of view functions, see the nsITreeView interface.
+

+ +

Methods

+ +

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+
startEditing( row, column )
+
Return type: no return value
+
Activates user editing of the given cell, which is specified by row index number and the nsITreeColumn in which it is located. The tree view's nsITreeView.getCellText() method is called to obtain the cell contents.
+
+
stopEditing( shouldaccept )
+
Return type: no return value
+
Stops editing the cell currently being edited. If the shouldAccept parameter is true, the cell's label is changed to the edited value (the tree view's nsITreeView.setCellText() method is called to change the cell contents). Otherwise the cell label is reverted to the value it had prior to editing.
+

+ + + +
+
Elements
+
treecols, treecol, treechildren, treeitem, treerow, treecell and treeseparator.
+
Interfaces
+
nsIAccessibleProvider, nsIDOMXULTreeElement, nsIDOMXULMultiSelectControlElement
+
+ +

Script Examples

+ +

To have alternating colors for each row, use the style rules like the following: pma at daffodil dot uk dot com

+ +
treechildren::-moz-tree-row(selected) { background-color: #FFFFAA; }
+treechildren::-moz-tree-row(odd) { background-color: #EEEEEE; }
+treechildren::-moz-tree-row(odd, selected) { background-color: #FFFFAA; }
+treechildren::-moz-tree-cell-text(selected) { color: #000000; }
+treechildren::-moz-tree-cell-text(odd, selected) { color: #000000; }
+
+ +

If using a content tree view, use the following to get the value of the id attribute for each of the selected rows of a tree: tcooper_mont at yahoo dot com

+ +
var idList = [];
+var rangeCount = tree.view.selection.getRangeCount();
+for (var i = 0; i < rangeCount; i++)
+{
+   var start = {};
+   var end = {};
+   tree.view.selection.getRangeAt(i, start, end);
+   for(var c = start.value; c <= end.value; c++)
+   {
+      idList.push(tree.view.getItemAtIndex(c).firstChild.id);
+   }
+}
+
+ +

The following returns a array of the indicies of the rows where the value is checked in a checkbox type column: jfabre at ismans dot fr

+ +
function getCellChecked(tree, columnid)
+{
+  var arr = [];
+  var column = tree.columns.getNamedColumn(columnid);
+  for (var i = 0; i < tree.view.rowCount; i++){
+    if (tree.view.getCellValue(i, column) == 'true')
+      arr.push(i);
+  }
+  return arr;
+}
+
+ +

To get the text value for a specific column (e.g. column 'age') from the currently focused row in the tree:

+ +
var t = document.getElementById('mytree');
+document.title = t.view.getCellText(t.currentIndex,t.columns.getNamedColumn('age'));
+
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/adding_buttons/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/adding_buttons/index.html new file mode 100644 index 0000000000..607e4d0abc --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/adding_buttons/index.html @@ -0,0 +1,98 @@ +--- +title: XUL_教程/增加一些按钮 +slug: Mozilla/Tech/XUL/Tutorial/Adding_Buttons +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/Adding_Buttons +--- +

 

+

+

« 上一页下一页 »

+

+

 

+

在本章,我们将学习如何向window添加button。

+

添加多个按钮到一个窗口

+

到目前为止我们创建的这个窗口里面什么也没有,因此还不算非常有趣. 在这一节中,我们将添加两个按钮, 一个“查找”按钮和一个“取消”按钮.我们还将学到一个简单的方法在窗口上来定位它们.

+

像HTML, XUL也有许多标记,它们被用来当作创建用户接口的元素. 最基本的一个 button 标记. 这个元素被用来创建简单的按钮。

+

按钮元素有两个主要的属性,一个label和一个image。你可以要一个或两个都要。因此,按钮可以只有一个标签,一个图片或标签和图片都有。通常在对话框中会使用“确定”和“取消”按钮。

+

按钮的语法

+

button标签有下面的语法要求:

+
<button
+    id="identifier"
+    class="dialog"
+    label="OK"
+    image="images/image.jpg"
+    disabled="true"
+    accesskey="t"/>
+
+

可用的属性如下,有一些是可选的:

+
+
+ id 
+
+ 你用来标识按钮的唯一标识。你会在所有的元素中看到此属性。你可以在样式表(style)或脚本(script)中通过它来引用按钮。因此,你几乎可以在所有的元素中添加这个属性。在这个教程中它不是一直都出现在元素中(It isn't always placed on elements in this tutorial for simplicity)。
+
+ class 
+
+ 按钮的样式表。在这里的用法和在HTML中是一样的。它是使用在显示按钮里面的样式。在这节中的dialog值就使用了。多数情况下,你不用在按钮上使用此属性。
+
+ label 
+
+ 标签会显示在按钮上。例如,“确定”或者“取消”。如果没人设置这个参数,在按钮上就不会显示文字。
+
+ image 
+
+ 在按钮上显示指定路径的图片。如果没有给出此属性,则不会显示图片。你通常可以使用如下的样式表属性list-style-image来指定要显示的图片。
+
+ disabled 
+
+ 如果这个属性被设置为true,按钮就会被禁用。这样通常按钮上的文字将会显示为灰色(grey)。如果按钮被禁用,按钮上的功能就不可以被执行。如果这个属性没有设置,按钮就是启用的。你可以用JavaScript来对按钮的可用状态进行控制。
+
+ accesskey 
+
+ 这个属性让你可以设置一个字母它的功能就像是一个快捷键。这个字母会被划上下划线并显示在标签里。当用户按ALT键(或者在每个平台中一个功能类似的键)的同时按下这里设置的键时,不论按钮在窗口的任何地方都能取得到焦点。
+
+

注释:按钮支持比上面列出的更多的属性。其他的属性可以参考 discussed later.

+

更多的按钮例子

+

Example 1 : Source View

+
+ image:Buttons1.png
+
<button label="Normal"/>
+<button label="Disabled" disabled="true"/>
+
+

上面的这些例子是在图片里面生成按钮。第一个按钮是一个标准的按钮。第二个按钮是禁用的,所以它整个显示为灰色。

+

注:label属性不应该指定中文名称,否则解析xul时会报错。对于本地化,应该通过locale包来完成。

+

我们将从为查找文件工具创建一个简单的查找按钮开始。下面这个例子的源码显示怎么去做这件事。

+
<button id="find-button" label="Find"/>
+
+
+ 注释:Firefox不允许你从网页上打开chrome,因此查看教程中的链接时会显示在一个标准的浏览器窗口中。至此,按钮会显示在窗口中间并自动伸展。你可以增加align="start"到window标签阻止其自动伸展。
+
+
例子 findfile.xul
+

请添加我们在前面章节创建的这些代码到findfile.xul文件。这些代码必须插入到 window 标签里面。代码是下面红色显示的部份:

+
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<window
+    id="findfile-window"
+    title="Find Files"
+    orient="horizontal"
+     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <button id="find-button" label="Find"/>
+  <button id="cancel-button" label="Cancel"/>
+
+</window>
+
+
+ Image:buttons2.png
+

你也可以注释掉“取消”按钮。窗口提供水平对齐地显示两个按钮。如果你在Mozilla中打开这个文件,你就可以获得和这里显示的图片一样的效果。

+
+

 

+
+ 注解:我们不能直接在XUL文件中写文本标签。我们可以使用 实体替换这样文本可以很容易地进行翻译.
+

在下一节,我们将会学会怎么向窗口中增加标签和图片

+

查看更多参考 更多按钮特性

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/adding_event_handlers/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/adding_event_handlers/index.html new file mode 100644 index 0000000000..ef85e01bd1 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/adding_event_handlers/index.html @@ -0,0 +1,161 @@ +--- +title: 添加事件处理函数 +slug: Mozilla/Tech/XUL/Tutorial/Adding_Event_Handlers +translation_of: Archive/Mozilla/XUL/Tutorial/Adding_Event_Handlers +--- +

« Previous Next »

+ +

 

+ +

  

+ +

 

+ +

    到此为止我们的 findfile 看起来很棒。我们还没有搞定它,因为到此为止我们仅只是建立了一个简单的用户界面。接下来我们将给他添加脚本。

+ +
+

使用脚本

+ +
Edit section
+ +

    为了使 find files 对话框工作,我们需要添加一些脚本来完成与用户的交互。我们想要为查找按钮、取消按钮以及各级菜单项添加脚本。我们会像在 HTML 中一样使用 JavaScript 来写一些函数。

+ +

    你可以使用 script 元素为 XUL 文件引入脚本。你可以直接在 <script>  </script>标签之间嵌入脚本,但是最好是使用独立的文件来包含脚本,这样 XUL 窗口加载会快一些。 src 属性用于引入外部脚本文件。

+ +
+
+
 find files 的例子
+ +
Edit section
+ +

    让我们为 find file 对话框添加脚本。尽管脚本文件的文件名无关紧要,但通常的它采用与 XUL 文件相同的文件名并以 .js 作为后缀。我们建立一个 findfile.js 文件。把下面的一行加到 window 开标记之后,所有元素之前

+ +
<script src="findfile.js"/>
+
+ +

    当我们知道改在脚本文件里添加什么之后,我们再建立这个文件。我们会在这个文件中定义一些函数,并且我们把这些函数称为事件处理函数。

+
+
+ +

    你可以通过使用多个 script 标记向 XUL 文件添加多个脚本文件,此时你可以使用相对或绝对 URLs。比如下面的例子:

+ +
<script src="findfile.js"/>
+<script src="chrome://findfiles/content/help.js"/>
+<script src="http://www.example.com/js/items.js"/>
+
+ +

    本教程不涉及与事件处理无关的 JavaScript 的使用。因为这实在有太多的内容需要讲述,而且也可以从很多其他其他的资料获得所需的知识。

+ +
默认的 JavaScript 仅在页面上显示错误。为了显示在 chrome JavaScript 中的错误,有必要更改以下设置: javascript.options.showInConsole = true
+如果设置 javascript.options.strict = true 那么任何不标准的,写法不良的,有语法上导致逻辑错误的,都将会写到日志中。
+
+ +
+

响应事件

+ +
Edit section
+ +

    脚本需要响应一系列的事件包括用户触发的或是其他状态引起的。起码有三种不同的事件需要用不同的方法来处理。一种是用户按下鼠标键或是按下一个键盘按键。每一个 XUL 元素都有能力在不同的状态触发特定事件。一些事件仅由特定元素触发。

+ +

    每一个事件都有一个名字,如 'mousemove' 是用户在一个 UI 元素上移动鼠标所触发的事件。XUL 与 DOM Events使用同样的机制来处理事件。当一个动作发生就会触发一个事件,比如用户移动鼠标,就会由一个相应类型的事件对象产生。 事件对象中包含一系列的属性包括:鼠标位置,哪个键被按下等。

+ +

    事件按阶段被发送到 XUL。

+ + + +

    可以在路由及返回阶段响应事件。一旦事件完成以上传播过程而为得以处理将使用默认的动作来处理该事件。

+ +

    比如,当鼠标在一个包含在 box 中的按钮上移动时,产生一个 'mousemove' 事件,这个事件先被发送到窗口,紧接着是文件,然后是这个 box ,这样就完成了路由过程。然后事件被发送给按钮。最后,返回阶段,事件被发给 box、文件及窗口。返回阶段本质上是路由过程的逆过程。需要说明的是,有些事件没有返回阶段。

+ +

    在事件传播的每一个阶段你都可以在任何元素上监听。由于事件会传递给所有祖先你可以在继承关系的更高层来添加监听器。当然,一个高层收到事件会通知它的全部子元素,而对于按钮的事件仅属于这个按钮。这一点对与你希望使用同样的代码控制一些元素是有用的。

+ +

    大多数公共事件使用 'command' 事件。 当使用者启动一个元素 command 事件会被触发,例如按按钮,选择菜单项等。对与不同的触发元素 command 会自动的按照不同的方式进行处理,比如,无论用户是使用鼠标点击按钮还是通过快捷键都会触发 command 事件。

+ +

    有两种办法来为一个元素添加事件监听器。其一,把脚本本身作为其属性;其二,使用元素的 addEventListener 方法。 前者只处理返回事件但写起来更方便。后者可以控制事件的任何阶段,并且对同一个元素、事件可以使用多个监听器。对大多数元素来说,更多的使用属性的方式。

+
+ +
+

事件监听器属性

+ +
Edit section
+ +

    使用属性形式,在你希望监听的元素上加一个属性,名字是待监听的事件名前加'on'。如,为了响应事件  'command' 属性名为 'oncommand'。属性值是处理此事件的一段脚本。通常代码短小,或者就是调用独立脚本文件中的函数。下面的例子响应按钮按下。

+ +

Example 1  : Source View

+ +
<button label="OK" oncommand="alert('Button was pressed!');"/>
+
+ +

    由于 'command' 事件会返回,也可以把事件监听器添加到封装元素中。下面的例子监听器会响应全部两元素。

+ +

Example 2  : Source View

+ +
<vbox oncommand="alert(event.target.tagName);">
+  <button label="OK"/>
+  <checkbox label="Show images"/>
+</vbox>
+
+ +

    在这个例子中,command 事件会有 button 或 checkbox 返回到设置了事件处理的 vbox 上。如果在按钮上在加一个监听器 (oncommand 属性) ,按钮上的代码会先调用,然后是 vbox 的。事件处理函数会传递一个隐含参数 'event',这参数可以获得事件的额外信息。一个常用的属性是 'target' ,它保存着事件是由谁产生的。这个例子里,显示事件产生者的标签名。target 很有用,因为你可以在一段代码里为一系列按钮作响应。

+ +

    你可能注意到这里使用的语法与 HTML 中的一样。事实上, HTML 和 XUL 共用统计的事件机制。一个重要的不同是 'click' 事件 (或  onclick 属性) 在 HTML 中它仅用于响应按钮,而在 XUL 中 command 事件被用于替代它。XUL 有一个 click 事件,但是仅响应鼠标点击,不响应键盘。因此点击事件在XUL中应避免使用,除非你希望一个元素仅可以通过鼠标触发。补充一下,如果元素的 disable 属性为 true 时 command 事件不会被发送,而 click 事件则不然。

+ +
+
+
find files 的例子
+ +
Edit section
+ +

     command 处理器可以用于响应查找和取消按钮,按查找按钮开始查找,当然由于我们没有实现这部分,我们现在还不能,这部分我们以后再完成,按取消按钮关闭窗口,下面的代码显示怎么做。并且我们也为关闭菜单也写了相同的代码。

+ +
<menuitem label="Close" accesskey="c" oncommand="window.close();"/>
+...
+
+<button id="cancel-button" label="Cancel"
+     oncommand="window.close();"/>
+
+ +

      这里加了两个处理器。oncommand 被加到关闭菜单项中了。通过使用这个处理器,用户可以使用鼠标点击菜单或使用键盘来选择此菜单来关闭窗口。oncommand 处理器也加到了取消按钮上。

+
+
+
+ +

DOM 事件监听器

+ +
Edit section
+ +

    为一个元素添加事件处理的另一种方法是使用元素的 addEventListener 方法,这允许你动态的监听事件或在路由阶段处理事件。语法如下。

+ +

Example 3  : Source View

+ +
<button id="okbutton" label="OK"/>
+
+<script>
+function buttonPressed(event){
+  alert('Button was pressed!');
+}
+
+var button = document.getElementById("okbutton");
+button.addEventListener('command', buttonPressed, true);
+</script>
+
+ +

     getElementById() 函数返回给定 id 的元素,这里返回这个按钮。addEventListener() 函数新建一个路由阶段的事件监听器。第一个参数是待监听的事件名,第而个参数是事件发生时要调用的函数名,最后一个参数如是 true 表示这是一个路由阶段的监听器,设为 false 则监听返回阶段。作为事件处理函数的第二个参数需要带一个参数(这个事件对象),就像上面定义的 buttonPressed 函数一样。

+ +
Find files example so far  : Source View
+ +

 

+ +

    接下来,我们详细的看看 事件对象event object)。

+ +

 

+ +
+

« Previous Next »

+
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/adding_html_elements/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/adding_html_elements/index.html new file mode 100644 index 0000000000..6e1f8c38c6 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/adding_html_elements/index.html @@ -0,0 +1,113 @@ +--- +title: XUL_教程/增加HTML元素 +slug: Mozilla/Tech/XUL/Tutorial/Adding_HTML_Elements +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/Adding_HTML_Elements +--- +

+

« 上一页下一页 »

+

+

 

+

增加HTML元素到窗口

+

除了可以使用XUL的所有元素,你也可以直接将HTML元素添加到XUL文件的内部。现在你可以在XUL文件中使用任意的HTML元素,意思是说可以在窗口中布置JAVA小应用程序(applet)和表格。如果可以你应该避免在XUL文件中使用HTML元素。(这是有原因的,主要涉及版面的控制这将在后面进行描述)。然而,不管怎样这节将描述如何使用它们。记住XML是大小写敏感的,因此你必须用小写输入标签和属性。

+

XHTML命名空间(namespace)

+

为了在XUL文件中使用HTML元素,你必须声明你要用到的XHTML命令空间。这个方法是Mozilla从XUL中区分HTML标签的。 下面的属性应该加在XUL文件的window 标签中,或者放到HTML元素的最外面。

+
xmlns:html="http://www.w3.org/1999/xhtml"
+
+

这个HTML的声明很像我们用过的XUL声明。要正常显示必须正确地输入这句,否则它不能正常运行。注意:Mozilla不会去下载这个URL的内容,但它会在运行HTML时对它进行验证。

+

这是一个可以加到文件查找窗口的例子:

+
 <?xml version="1.0"?>
+ <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+ <window
+   id="findfile-window"
+   title="Find Files"
+   orient="horizontal"
+   xmlns:html="http://www.w3.org/1999/xhtml"
+   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+

因此,你可以像平常一样使用HTML,下面列出需注意的守则:

+ +

使用HTML元素

+

你可以像headbody使用所有的HTML标签,不是真的有益。下面演示一些使用HTML元素的例子。

+
<html:img src="banner.jpg"/>
+
+<html:input type="checkbox" value="true"/>
+
+<html:table>
+  <html:tr>
+    <html:td>
+      A simple table
+    </html:td>
+  </html:tr>
+</html:table>
+
+

这些示例将从banner.jpg创建一个图像,一个多选项和一个只有一个单元格的表。如果XUL的特性是可用的你应该总是使用它们并且你不应该在XUL中使用表格作为布局。(XUL有自己的布局元素可以用)。注意html:前缀需要添加到每个标签的前面。这是Mozilla为什么会知道它是一个HTML标签而不是一个XUL标签。如果你没有加上html:部份,浏览器就会认为元素是一个XUL元素并且它们不能被正常显示,因为 img, input, table, 等都不是有效的XUL标签。

+

在XUL,你可以使用descriptionlabel元素添加文本标签。当你要用时应该使用这些元素。你也可以使用HTML的label元素添加文本标签的操作或者你可以像下面的例子一样简单地将文本放在不同的HTML元素之间(就像pdiv)。

+

例1 : Source View

+
<html:p>
+  搜索:
+  <html:input id="find-text"/>
+  <button id="okbutton" label="确定"/>
+</html:p>
+
+

这段代码的目的是显示'搜索:',接着显示一个文本输入框元素和一个确定按钮。注意XUL按钮可以显示在HTML元素之间,在这里它可以正常使用。在HTML元素之间的纯文本仅仅用来显示通常用来显示文字(就像p标签)。放在外面的文本是不能被显示的,除非XUL元素允许将文本放在里面(例如:description元素)。下面的例子可以帮助你理解。

+

HTML元素的实例

+

下面是在窗口在添加HTML元素的一些例子。在每个例子的窗口边都能找到简单的说明信息。

+

带多选框的对话框

+

例2 : Source View

+
+ Image:htmlelem-ex1.png
+
<html:p>
+  点击下面方框会记住这个结果。
+  <html:p>
+    <html:input id="rtd" type="checkbox"/>
+    <html:label for="rtd">记住这个结果</html:label>
+  </html:p>
+</html:p>
+
+

在这个例子,一个 p 标签用来放置文本,另外一人用来放置分离的多行文本。

+

在HTML块外面的文本

+

例3 : Source View

+
+ Image:htmlelem-ex2.png
+
<html:div>
+    你想保存下面的文档吗?
+    <html:hr/>
+</html:div>
+Expense Report 1
+What I Did Last Summer
+<button id="yes" label="Yes"/>
+<button id="no" label="No"/>
+
+

从图像上可以看到,在div标签里面的文本可以显示出来但其它的文本没有显示(Expense Report 1 和 What I Did Last Summer)。这是因为要显示的文本没有被HTML或XUL元素围绕起来。要显示这些文本,你必须将它放在div标签里面,或者用description 标签将它围起来。

+

无效的HTML元素

+
<html:po>Case 1</html:po>
+<div>Case 2</div>
+<html:description value="Case 3"/>
+
+

上面这三个样例不能被显示,每个都有一个不同的原因。

+
+
+ 样例1 
+
+ po不是一个正确的HTML标签,所以Mozilla不知怎么去处理它。
+
+ 样例2 
+
+ div是有效的,但是只能用在HTML中。如果要在这里使用,你必须为它添加html:限定符。
+
+ 样例3 
+
+ description元素仅仅在XUL中是有效的,而不是在HTML中。它不可以有html:限定符。
+
+

接下来,我们将要学习如何用 在元素间添加定位格.

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/adding_labels_and_images/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/adding_labels_and_images/index.html new file mode 100644 index 0000000000..e3850373fc --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/adding_labels_and_images/index.html @@ -0,0 +1,40 @@ +--- +title: XUL_教程/增加标签和图像 +slug: Mozilla/Tech/XUL/Tutorial/Adding_Labels_and_Images +translation_of: Archive/Mozilla/XUL/Tutorial/Adding_Labels_and_Images +--- +

+

« 上一页下一页 »

+
 

+

 

+

这一章描述了向窗口中加入标签和图像的方法。另外,我们将看到如何将一些元素包含到一个组中。

+

文本元素

+

在不使用标记的情况下,你不能直接向XUL文件中插入文本,它也不会做任何显示。为了达到这个目的你使用如下两个XUL元素来完成。

+

标签元素

+

将文本加入到将文本加入到窗体中的一个最基本的方法就是使用label元素。请看下面的例子:

+

Example 1 : Source View

+
<label value="This is some text"/>
+
+

value属性被用于指定要显示的文本。这样设置的文本在显示的时候不会换行,所以适合于较短的文本。这种语法适用于多数情况中使用的标签。

+

如果文本需要换行,你可以如下例所示将文本放在开启和关闭元素之间:

+

Example 2 :

+
<label>This is some longer text that will wrap onto several lines.</label>
+
+

就像HTML,换行和多余的空格将被压缩为一个空格。 接下来, 我们可以在 找到怎么去控制元素的宽度 这样我们就可以很容易地控制换行。

+
操作(Control)属性
+

你可以使用 control 属性去设置关联的标签。当用户在标签上进行点击操作时,已关联的控件就会被触发。accessibility这种关联的辅助操作很重要,这样屏幕阅读器就可以对选中的文本进行语音提示。设置control属性的值会触发与这个值对应的id的元素。 Example 3 : Source View

+
<label value="Click here:" control="open-button"/>
+<button id="open-button" label="Open"/>
+
+

在上面这个例子中,在标签上点击会使得按钮被触发。

+

描述(Descriptive)元素

+

在没有一些特定的关联操作的文本时你可以使用 description 标签。 这个元素使用于在对话框的上面或实例的一组控制的文本提示信息. 与 label 元素一样, 你既可以在 value 属性中指定单行的文本也可以在开合标签之间填充一大块的文本。在描述元素的大多数属性和文本内容的语法是与标签元素(label)是一样的。

+

例4 : Source View

+
<description>
+  This longer section of text is displayed.
+</description>
+
+

从内部看, 标签元素(label)和描述元素( description)是相同的。标签元素(label)用于有操作的标签,就像一个文本框(text field)。 操作属性仅仅为标签提供支持。 描述元素(description)用于其他描述性的情况,如对话框(dialog)上面的提示信息文本。

+

+

« 上一页下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/adding_more_elements/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/adding_more_elements/index.html new file mode 100644 index 0000000000..9af4cc954f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/adding_more_elements/index.html @@ -0,0 +1,115 @@ +--- +title: 增加更多的元素 +slug: Mozilla/Tech/XUL/Tutorial/Adding_More_Elements +translation_of: Archive/Mozilla/XUL/Tutorial/Adding_More_Elements +--- +
+

添加元素

+
+
+
+

 

+

 

+
+

« Previous Next »

+
+

  

+

 

+

    我们继续通过为findfile对话框添加一些box来讨论box。

+
+
+

为 find files 的例子添加元素

+
+ Edit section
+

    现在我们将为findfile对话框添加一些元素,首先添加选择其他检索信息的能力(如尺寸和数据):

+
<hbox>
+  <menulist id="searchtype">
+    <menupopup>
+      <menuitem label="Name"/>
+      <menuitem label="Size"/>
+      <menuitem label="Date Modified"/>
+    </menupopup>
+  </menulist>
+  <spacer style="width: 10px;"/>
+  <menulist id="searchmode">
+    <menupopup>
+      <menuitem label="Is"/>
+      <menuitem label="Is Not"/>
+    </menupopup>
+  </menulist>
+  <spacer style="width: 10px;"/>
+  <textbox id="find-text" flex="1" style="min-width: 15em;"/>
+</hbox>
+
+
+ Image:boxfinal1.png
+

    加了两个 drop down boxes 。一个 spacer 加进来用于分割各元素,每个空白有10像素,你会看到当窗口尺寸改变时,文本框会改变尺寸而其他元素不会 ,也会看到标签被移除了。

+

    如果垂直的改变窗口尺寸,元素不会改变尺寸,这是因为他们在水平的box中。 Find 和 Cancel 按钮总在春光看的底部是合适的。这很容易通过在两个水平box间添加空白实现。

+
<spacer style="height: 10px"/>
+<hbox>
+  <menulist id="searchtype">
+    <menupopup>
+      <menuitem label="Name"/>
+      <menuitem label="Size"/>
+      <menuitem label="Date Modified"/>
+    </menupopup>
+  </menulist>
+  <spacer style="width: 10px;"/>
+  <menulist id="searchmode">
+    <menupopup>
+      <menuitem label="Is"/>
+      <menuitem label="Is Not"/>
+    </menupopup>
+  </menulist>
+  <spacer style="width: 10px;"/>
+  <textbox id="find-text" flex="1" style="min-width: 15em;"/>
+</hbox>
+
+<spacer style="height: 10px" flex="1"/>
+
+<hbox>
+
+

    现在当窗口改变尺寸,这两个按钮会移动以确保总在窗口的底部。 spacer 被添加在标题和检索条件之间。

+

    在检索条件上画上边框可能会更好看。可以使用 CSS border 属性或使用 groupbox 元素,第一种方法需要设置box的样式。我们使用后一种方法。  groupbox 可以画出适合当前主题的漂亮的边框。

+

    把box改为 groupbox

+
<groupbox orient="horizontal">
+  <caption label="Search Criteria"/>
+  <menulist id="searchtype">
+  .
+  .
+  .
+  <spacer style="width: 10px;"/>
+  <textbox id="find-text" flex="1" style="min-width: 15em;"/>
+</groupbox>
+
+
+ Image:boxfinal2.png
+

   当然还有其他的美化方案,比如让组框延伸到窗口底边。也可以修饰一下边界让他们看起来更漂亮。

+

    我们会在这个教程中看到更多关于box的例子及其功能因为我们还有在findfile对话框中添加新的元素。

+

Find files example so far Source View

+
+
+


+      下一章,create stacks.

+

 

+
+

« Previous Next »

+
+

  

+

 

+
+
+
+
+

Retrieved from "https://developer.mozilla.org/En/XUL_Tutorial/Adding_More_Elements"

+
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/adding_style_sheets/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/adding_style_sheets/index.html new file mode 100644 index 0000000000..630627f941 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/adding_style_sheets/index.html @@ -0,0 +1,10 @@ +--- +title: 添加样式表 +slug: Mozilla/Tech/XUL/Tutorial/Adding_Style_Sheets +translation_of: Archive/Mozilla/XUL/Tutorial/Adding_Style_Sheets +--- +
<?xml version="1.0"?>
+<?xml-stylesheet href="css/ued.css" type="text/css"?>
+
+
+

用xml-stylesheet引入CSS文件!可以是本地或来自网络的文件。使用http或chrome协议均可。

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/anonymous_content/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/anonymous_content/index.html new file mode 100644 index 0000000000..6362be89f6 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/anonymous_content/index.html @@ -0,0 +1,166 @@ +--- +title: XUL_教程/匿名内容 +slug: Mozilla/Tech/XUL/Tutorial/Anonymous_Content +translation_of: Archive/Mozilla/XUL/Tutorial/Anonymous_Content +--- +

 

+

+

« 上一页Anonymous_Content">下一页 »

+

+

在这一节,我们将讲解用XBL创建content。

+

XBL Content

+

XBL被用来自动在另一个元素中添加一组元素。当内部元素用XBL描述时,XUL文件只需要指定外部元素。对于创建由其它控件构成的单独的控件来说这是很有用的,但只被认为是单独的控件。这里讲解了向由外部元素指定的内部元素添加属性的机理。

+

Declaring Scrollbar Example

+

以下的例子指出了滚动条是怎么声明的(从实例简化1bit)

+
<bindings xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <binding id="scrollbarBinding">
+    <content>
+      <xul:scrollbarbutton type="decrement"/>
+      <xul:slider flex="1">
+        <xul:thumb/>
+      </xul:slider>
+      <xul:scrollbarbutton type="increment"/>
+    </content>
+  </binding>
+</bindings>
+
+

这个文件包含一个用binding元素声明的单独的binding。ID属性应该设置为binding的标识符。这会在css文件中设置-moz-binding属性时用到。

+

content标签被用来声明将被增进滚动条的anonymous content。content标签里的所有元素将被添加进被绑定界面元素内部。这种 binding将被绑定到滚动条,虽然没必要这样。将CSS -moz-binding 属性的设置为binding的URI的任何元素都将使用它。

+

使用上述 binding会导致下面的XUL的行会如下扩展,假设滚动条与上述的XBL相关联:

+
<scrollbar/>
+
+expands to:
+
+<scrollbar>
+  <xul:scrollbarbutton type="decrement"/>
+    <xul:slider flex="1">
+      <xul:thumb/>
+    </xul:slider>
+  <xul:scrollbarbutton type="increment"/>
+</scrollbar>
+
+

含有content标签的元素被无记录的添加到滚动条。虽然无记录内容被显示在屏幕上,但在正常方式下,不能通过脚本得到它。对于XUL,就像只有一个元素,尽管它实际上由大量元素构成。

+

检查 Mozilla窗口中的滚动条,就会发现它由一个arrow按钮、一个slider、内部thumb和一个末尾的second arrow 按钮组成。它们都是XBL上面出现过的元素。这些元素将依次绑定在运用基础XUL元素的其它bindings上。请注意 content元素需要XUL姓名空间(他们出现在XUL之前:),因为他们是XUL元素,而且在XBL中无效。这个命名空间声明在bindings标签内。如果您不想使用XUL元素的命名空间, Mozilla将假定元素都是XBL,不理解这里,您的元素可能不会正常工作。

+

Filename Input Field Example

+

另一个例子是关于输入一个文件名的域:

+
<binding id="fileentry">
+  <content>
+    <textbox/>
+    <button label="Browse..."/>
+  </content>
+</binding>
+
+

连接这个元素的binding将会导致输入浏览按钮之后的文本时它包含一个域。这个内部内容被匿名的创建了,而且用DOM不能查看到。

+

Override the Bound Element

+

Anonymous content被匿名的创建在 binding连接到一个元素的任何地方。如果您在XUL里放置子元素,他们将覆盖由binding提供的元素。例如XUL段,假设它早期与滚动条XBL绑定:(如果在xul文件中,给被绑定界面元素添加子元素,那么会覆盖掉binding中的元素。例如下面的xul片断,假设它被绑定到了前面的scrollbar的binding上)

+
<scrollbar/>
+
+<scrollbar>
+  <button label="Overridden"/>
+</scrollbar>
+
+

第一个滚动条,因为它没有自己的内容,它将从在XBL文件里声明的binding来生成它的内容。第二个滚动条有它自己的内容,因此它将不会运用XBL内容,这产生了不完全是滚动条的产品。请注意比如滚动条这样的内建元素,从toolkit包的bindings目录得到它们的XBL。

+

这只应用于在content标签内定义的元素。不论content是否从XBL而来或不论XUL是否提供自己的content,XBL的属性、方法和其它方面仍然可用。

+

Using the Children Element

+

当您想将XBL的内容和由XUL文件提供的内容一起都显示出来,可能需要重复几次。您能运用children元素来实现。在XUL中添加的子元素被添加来替代children元素。当创建自定义菜单控件时,这是很容易操作的。例如,一个简单的可编辑的menulist元素,可能如下创建:

+
XUL:
+
+<menu class="dropbox">
+  <menupopup>
+    <menuitem label="1000"/>
+    <menuitem label="2000"/>
+  </menupopup>
+</menu>
+
+CSS:
+
+menu.dropbox {
+    -moz-binding:  url('chrome://example/skin/example.xml#dropbox');
+}
+
+XBL:
+
+<binding id="dropbox">
+  <content>
+    <children/>
+    <xul:textbox flex="1"/>
+    <xul:button src="chrome://global/skin/images/dropbox.jpg"/>
+  </content>
+</binding>
+
+

这个例子用旁边的按钮创建了一个输入域,menupopup将添加到由children元素指定位置。请注意对DOM结构来说,这些内容将与在XUL文件中显示的一样,因此menupopup将成为menu的一个子元素。对于开发者来说xbl的内容是看不到的,所以也没必要知道它的位置。

+

结果内容应该是:

+
<menu class="dropbox">
+  <menupopup>
+    <menuitem label="1000"/>
+    <menuitem label="2000"/>
+  </menupopup>
+  <textbox flex="1"/>
+  <button src="chrome://global/skin/images/dropbox.jpg"/>
+</menu>
+
+

includes Attribute

+

某些情况下,您可能希望只包括特定类型的内容。或者您只希望在不同的位置放置不同类型的内容。includes属性能够用来使只有某些元素才能在children的内容里出现。它的值应该设定到一个单独的标签名。或者到一个由“|”分隔的标签列表

+
<children includes="button"/>
+
+

所有的button将会被添加到被绑定元素的children所指明的位置。其它元素将不会与这个标签匹配。您能够放置多个children 元素到一个binding中,来在不同的地方放置不同类型的内容。如果XUL中一个元素没有匹配任何children元素,那个元素(和其他任何不匹配的元素)将会被用来替代这个绑定的内容。

+

这里有另一个例子。让我们来介绍一下创建一个控件,并用两边的zoom in 和zoom out 按钮显示图象的方法。这将用一个box来创建,它包含图象和两个按钮。因为每个用法不同,这个图象元素得放置在XBL外部。

+
XUL:
+
+<box class="zoombox">
+  <image src="images/happy.jpg"/>
+  <image src="images/angry.jpg"/>
+</box>
+
+XBL:
+
+<binding id="zoombox">
+  <content>
+    <xul:box flex="1">
+      <xul:button label="Zoom In"/>
+      <xul:box flex="1" style="border: 1px solid black">
+        <children includes="image"/>
+      </xul:box>
+      <xul:button label="Zoom Out"/>
+    </xul:box>
+  </content>
+</binding>
+
+

XUL文件中详述的子元素将放置在children标签位置。有两幅图象,因此两个都将被添加到彼此的旁边。显示结果等价如下:

+
<binding id="zoombox">
+  <content>
+    <xul:box flex="1">
+      <xul:button label="Zoom In"/>
+      <xul:box flex="1" style="border: 1px solid black">
+        <xul:image src="images/happy.jpg"/>
+        <xul:image src="images/angry.jpg"/>
+      </xul:box>
+      <xul:button label="Zoom Out"/>
+    </xul:box>
+  </content>
+</binding>
+
+

从 DOM的观点来看,子元素仍然在初始的存储单元。这就是说,外部的XUL box有两个子元素,它们是这两幅图像。里边带边框的box有一个子元素,就是children 标签。当使用带XBL的DOM时,这是一个重要的区别。这也可以应用于CSS选择器规则。

+

多个子元素

+

您也能够使用多个children元素而且可以把某些元素放置在一个地方,其它元素放置在其它地方,通过添加一个includes属性和将它设置成标签的垂直的bar-separated列表,您能够使得只有在那个列表里的元素被放置在那个地方。例如,下面的XBL将导致文本标签和按钮出现在与其他元素不同的地方。

+

Source

+
<binding id="navbox">
+  <content>
+    <xul:vbox>
+      <xul:label value="Labels and Buttons"/>
+      <children includes="label|button"/>
+    </xul:vbox>
+    <xul:vbox>
+      <xul:label value="Other Elements"/>
+      <children/>
+    </xul:vbox>
+  </content>
+</binding>
+
+

第一个children元素只含有标签和按钮元素,正如它的includes属性指示的一样。第二个children元素因为它没有includes属性,它将包含所有的剩余的元素。

+

See also Anonymous Content section of the XBL reference.

+

(Next)在下一节,我们将研究属性如何被继承到 anonymous  content中.

+

+

« 上一页Anonymous_Content">下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/box_model_details/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/box_model_details/index.html new file mode 100644 index 0000000000..7b647957ba --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/box_model_details/index.html @@ -0,0 +1,6 @@ +--- +title: 分组细节 +slug: Mozilla/Tech/XUL/Tutorial/Box_Model_Details +translation_of: Archive/Mozilla/XUL/Tutorial/Box_Model_Details +--- +

This page has no content. Enrich MDC by contributing.

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/content_panels/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/content_panels/index.html new file mode 100644 index 0000000000..b2909f9a05 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/content_panels/index.html @@ -0,0 +1,63 @@ +--- +title: 内容面板 +slug: Mozilla/Tech/XUL/Tutorial/Content_Panels +translation_of: Archive/Mozilla/XUL/Tutorial/Content_Panels +--- +

这一节我们来看看如何向HTML页面或者其他XUL文件中添加面板。

+

添加子面板

+

你可能经常想要使用不同页面的文件中的一部分。有时候你或许想将一个窗口中的一部分进行改变。一个很好的例子是一个一步接一步的向导,可以通过很多页面、询问一系列问题来指导你。每当用户点击下一步按钮的时候,向导就会显示下一个画面。

+

你可以通过为每个不同的画面打开一个新的窗口来创建向导。但这样有三个问题。首先,每个窗口会出现在不同的位置。第二,后退和下一步按钮都是一样的,如果这是内容区域变化将会更好。第三,当在不同的窗口中运行的时候使用脚本会非常困难。

+

注意,XUL有一个wizard元素可以用来创建向导接口。这将会在后面的章节中进行描述。

+

另一种方法是使用iframe元素。这与HTML中有相同的名字。它可以在一个窗口中创建独立的文档。其优点是可以在任何需要内容的地方加载不同的文件。将文档的URL设置这个框架的src属性。这个URL可以指向任意类型的文件,尽管通常是指向一个HTML文件或者其他XUL文件。你可以使用脚本来控制iframe中的内容而不需要影响主窗口。

+

在mozilla浏览器中,网页显示的区域就是用iframe创建的。当用户输入一个URL或者点击一个文档的链接的时候,这个frame的资源就变化了。

+

Iframe例子

+

例子1:

+ + + + + + +
+

<toolbox>

+

  <toolbar id="nav-toolbar">

+

    <toolbarbutton label="Back"/>

+

    <toolbarbutton label="Forward"/>

+

    <textbox id="urlfield"/>

+

  </toolbar>

+

</toolbox>

+

 

+

<iframe id="content-body" src="http://www.mozilla.org/index.html" flex="1"/>

+
+

这个例子为浏览器创建了一个非常简单的接口。创建了一个格子来容纳两个元素,一个是工具栏一个是iframe。一个后退按钮,一个前进按钮,以及一个用来输入URL的输入区。在iframe里面将会出现一个网页。这里会默认的出现index.html文件。

+

这个例子功能并不完全。下面我们将会添加一个脚本在需要的时候来改变src属性,例如当用户按回车键的时候。

+

 browser

+

还有一种内容面板,使用browser标签。如果你想创建一个像浏览器一样显示内容的框架就可以使用这个元素。事实上iframe也可以完成这样的功能,但是browser又很多附加特性。例如browser可以保持历史页面用来进行前进和后退。Browser还可以加载带有参照页和其他标志的页面。需要的时候,你可以使用browser标签来常见一个像浏览器一样的接口,但是如果只需要一个简单的面板的话可以使用iframe来实现。

+

一个类似的元素tabbrowser,可以提供browser的全部功能而且还提供一个tab标签来在多个页面中切换。这是用在mozilla浏览器中的标签页浏览的小工具。元素tabbrowser事实上提供了一个含有一系列browser的tabbox元素。两种类型的browser都提供了相同的页面显示控制方式。

+

Browser实例

+

例子2:

+ + + + + + +
+

<browser src="http://www.mozilla.org" flex="1"/>

+
+

与iframe一样,你可以使用src属性来指定browser的URL。对tabbrowser,你不可以设置直接像这样设置URL,因为他不会仅仅显示一个URL,相反的,你必须使用脚本调用loadURL函数来实现。

+

有三种类型的browser,基于你想要显示的内容的内部机制。可以使用type属性来指定其类型。

+

第一种类型如果不指定的话是默认的类型。这种情况,加载内容的内部browser就是与应用程序相同的,而且可以在外部窗口中访问。这意味着当一个脚本在browser内部加载文件的时候会获取最顶层的窗口。,会获得XUL窗口中的最外部的窗口。

+

这可能对于一个应用程序的子XUL面板比较合适,但是当你想要用browser来加载网页的时候,就不是你想要的了。相反的,你可能想现限制网页仅仅获取网页的内容,你可能注意到mozilla浏览器窗口的工具条和状态条有一个XUL内容以及更高级的tabbrowser组成了主要的区域。这个内部的区域显示了一个网页,但是网页无法访问其周围的XUL。这是因为使用的是第二种类型的browser,指定type属性为content。这可以阻止内容穿越到XUL窗口中,示例如下:

+ + + + + + +
+

<browser src="http://www.mozilla.org" type="content" flex="1"/>

+
+

元素tabbrowser的每个标签页在创建的时候默认类型都设置为content。因此你不需要明确的为它指定类型。

+

第三种类型在你的程序中包含多个browser元素的时候使用的,例如,你有一个侧边栏来显示额外的内容,将主browser元素的type属性设置为content-primary来表明其内容是窗口中的主内容。这与content值一样,只是里面的内容只有使用XUL窗口的content属性才可以访问。这使得用脚本访问主窗口的内容时变得容易。对tabbrowser自动将可见的browser设置为content-primary,也就是说,这样你总是可以在当前可见的窗口中看到内容。

+

下一节,我们看看如何创建分隔线

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/creating_a_skin/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/creating_a_skin/index.html new file mode 100644 index 0000000000..4fabb4c388 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/creating_a_skin/index.html @@ -0,0 +1,177 @@ +--- +title: 创建一个皮肤 +slug: Mozilla/Tech/XUL/Tutorial/Creating_a_Skin +translation_of: Archive/Mozilla/XUL/Tutorial/Creating_a_Skin +--- +

本节讲述如何创建一个简单的皮肤,简单起见,我们只将其应用于查找文件对话框。

+ +

一个简单的皮肤。

+ +

下图是当前的查找文件对话框的样子。我们将创建一个应用于其上的皮肤。当然,一个皮肤可以应用于任何程序,但是当我们只关注于文件查找对话框时,事情就回简单些。因此我们只修改findfile.css 而 不修改global.css 文件。本节假设你正在使用经典的皮肤。你可能希望再工作之前留有一个原来皮肤的备份。

+ +

Image:cskin1.jpg

+ +

你需要再用户皮肤中创建文件'findfile.css' 。或者你可以临时把他放在内容目录中并用样式表指令引用。你也可以直接修改当前的findfile.css文件,看看他会变的怎样,或者你可以创建一个用户皮肤并连接到其上。

+ +

创建用户皮肤包

+ +

创建皮肤,步骤如下:(如果使用火狐1.5或以上,参见 配置文件 代替以下步骤)

+ +
    +
  1. 创建一个放置皮肤文件的文件夹。
  2. +
  3. 从经典或现代皮肤文件夹中复制配置文件 (contents.rdf) 到这个新建的文件夹。
  4. +
  5. 修改配置文件引用你的皮肤。比如:将 'classic/1.0' 改为 'blueswayedshoes/1.0'.
  6. +
  7. 在文件‘chrome/installed-chrome.txt’ 中增加如下一行: skin,install,url,file:///stuff/blueswayedshoes/ 其中最后一部分是你现在创建的目录。务必在最后加一个斜杠。
  8. +
+ +

把文件findfile.css 复制到新目录。我们将使用它作为新皮肤的基础。我们可以使用 'chrome://findfile/skin/findfile.css'来引用它

+ +

添加样式规则

+ +

首先决定要做怎样的改变。我们会修改颜色、改变按钮样式、稍微改变间隔,让我们从菜单、工具栏、标签面板开始。

+ +

把下面的内容加到findfile.css 就会产生如下图的改变。

+ +
window > box {
+  background-color: #0088CC;
+}
+
+menubar,menupopup,toolbar,tabpanels {
+  background-color: lightblue;
+  border-top: 1px solid white;
+  border-bottom: 1px solid #666666;
+  border-left: 1px solid white;
+  border-right: 1px solid #666666;
+}
+
+caption {
+  background-color: lightblue;
+}
+
+ +

Image:cskin2.jpg

+ + + +

上面的第一条规则(用于 'window > box') 制定窗口的内框使用不同的颜色,这可能不是最好的办法,我们可以使用样式类来做出这样的改变。那样做的话,我们可以修改XUL文件,不必要求box是窗口的第一个子元素。

+ +
CSS:
+.findfilesbox {
+  background-color: #0088CC;
+}
+
+XUL:
+<vbox class="findfilesbox" orient="vertical" flex="100%">
+<toolbox>
+
+ +

把标签修圆

+ +

下面,修改标签。我们将要使选中的标签变为粗体,并且修圆标签。

+ +
tab:first-child {
+  -moz-border-radius: 4px 0px 0px 0px;
+}
+
+tab:last-child {
+  -moz-border-radius: 0px 4px 0px 0px;
+}
+
+tab[selected="true"] {
+  color: #000066;
+  font-weight: bold;
+  text-decoration: underline;
+}
+
+ +
Image:cskin3.jpg
+ +

这里添加了两条规则,第一条将第一个标签修圆,第二条将最后一个标签修圆。这里使用了一个特殊的样式规则, -moz-border-radius, 他再边框的角上创建一个圆弧。第一个标签的左上角,第二个标签的右上角用4个像素修圆而其他的角都设为0,这相当于没有修圆,值越大就越接近圆,值越小就越接近矩形。

+ +

最后的规则只有当标签的属性 selected 设为 true时才有效,他是使选中的标签的文字以粗体,下划线、深蓝色显示,注意图中只有第一个标签这样显示,第二个不会,因为他没有被选中。

+ +

添加工具栏按钮

+ +

有时候我们很难区分工具栏上的按钮和菜单栏的命令,如果我们为工具栏的按钮添加图标就会更清楚。火狐的创造者为例如打开保存等按钮创建了图标,我们直接用再这里可以节省时间。我们可以使用 list-style-image CSS 属性为按钮添加图标。

+ +
#opensearch {
+  list-style-image: url("chrome://editor/skin/icons/btn1.gif");
+  -moz-image-region: rect(48px 16px 64px 0);
+  -moz-box-orient: vertical;
+}
+
+#savesearch {
+  list-style-image: url("chrome://editor/skin/icons/btn1.gif");
+  -moz-image-region: rect(80px 16px 96px 0);
+  -moz-box-orient: vertical;
+}
+
+ +
Image:cskin4.jpg
+ +

Mozilla provides a custom style property -moz-image-region which can be used to make an element use part of an image. You can think of it as a clip region for the image. You set the property to a position and size within an image and the button will display only that section of the image. This allows you to use the same image for multiple buttons and set a different region for each one. When you have lots of buttons, with states for hover, active and disabled, this saves space that would normally be occupied by mutliple images. In the code above, we use the same image for each button, but set a different image region each one. If you look at this image (btn1.gif), you will notice that it contains a grid of smaller images, each one 16 by 16 pixels.

+ +

The -moz-box-orient property is used to orient the button vertically, so that the image appears above the label. This property has the same meaning as the orient attribute. This is convenient because the skin cannot change the XUL. Most of the box attributes have corresponding CSS properties.

+ +

其他改变

+ +

Next, we'll make a couple of changes to the buttons along the bottom, again reusing some icons from Mozilla to save time. If creating your own skin, you will need to create new icons or copy the icons to new files. If following the example in this section, just copy the files to your new skin and change the URLs accordingly.

+ +
#find-button {
+  list-style-image: url("chrome://global/skin/checkbox/images/cbox-check.jpg");
+  font-weight: bold;
+}
+
+#cancel-button {
+  list-style-image: url("chrome://global/skin/icons/images/close-button.jpg");
+}
+
+button:hover {
+  color: #000066;
+}
+
+ +
Image:cskin5.jpg
+ +

We add some images to the buttons and make the Find button have bold text to indicate that it is the default button. The last rule applies to buttons when the mouse is hovering over them. We set the text color to dark blue in this case. Finally, some minor changes to the spacing around the items, by setting margins:

+ +
tabbox {
+  margin: 4px;
+}
+
+toolbarbutton {
+  margin-left: 3px;
+  margin-right: 3px;
+}
+
+ +

After those changes, the find files dialog now looks like the image.

+ +

Image:cskin6.jpg

+ +

As you can see, some simple changes to the style rules has resulted in quite a different appearance to the find files dialog. We could continue by changing the menus, the grippies on the toolbar and the input and checkbox elements.

+ +

创建全局皮肤

+ +

The skin created above is simple and only applies to the find files dialog. Some of the changes made to the skin could be placed in the global style sheets (those in the global directory of the skin) to be applied to all applications. For example, having different images for the check boxes in the find files dialog as other windows looks a little odd. This change should really be moved into the global style sheet.

+ +

Try moving the CSS styles from findfile.css into global.css and then look at some of the dialogs in Mozilla. (The cookie viewer is a good example.) You will notice that it has adopted the rules that we have added. Some of the rules conflict with those already in the global stylesheets. For example, rules are already defined for buttons and tabs and so on and we defined additional rules for them. When changing the global skin, you would need to merge the changes into the existing rules.

+ +

For the best skinnability, it is best to declare appearance related style rules in the global directory rather than in individual style files. This includes colors, fonts and general widget appearances. If you change the color of something in a local skin file (such as findfile.css), the dialog may look odd if the user changes their global skin. Don't expect the user to be using the default one.

+ +
+

Our Find files example with this skin: Source View Stylesheet

+
+ +

See also

+ +

Mozilla CSS extensions, and CSS reference

+ +


+ 下一章讨论 XUL程序的本地化

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/creating_a_window/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/creating_a_window/index.html new file mode 100644 index 0000000000..5a7329bac3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/creating_a_window/index.html @@ -0,0 +1,116 @@ +--- +title: 创建一个窗口 +slug: Mozilla/Tech/XUL/Tutorial/Creating_a_Window +translation_of: Archive/Mozilla/XUL/Tutorial/Creating_a_Window +--- +

+

« 上一页下一页 »

+

+ +

 

+ +

前面提到: 我们要在本教程中创建一个简单的查找文件工具。不过开始之前,我们得先看看XUL文件的基本语法。

+ +

 

+ +

创建一个 XUL 文件

+ +

一个 XUL 文件可以有任何名字,但它必须拥有一个 .xul 的扩展名。最简单的 XUL 文件具有下述结构:

+ +
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window
+    id="findfile-window"
+    title="查找文件"
+    orient="horizontal"
+    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<!-- Other elements go here -->
+</window>
+
+ +

这个窗口不会做任何事情,因为它没有包含任何用户界面元素。那些元素会在下面的部分中添加。这里对上面的代码进行逐行断开解释:

+ +
    +
  1. <?xml version="1.0"?>
    + 这一行只是简单声明这是一个 XML 文件。你通常在每一个 xul 文件的顶端都会添加这一行,非常像在一个 HTML 文件的顶端添加 HTML 的标识。
  2. +
  3. <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
    + 这一行是用来指定文件使用的样式表的。这是 XML 文件用以导入样式表的语法。在这种情况下,我们从一个皮肤包的全局部分导入样式。我们没有指定特定的文件,所以 Mozilla 会确定使用文件夹中的哪一个文件。在这种情况下,会选中最重要的 global.css 文件。这个文件包括了所有 XUL 元件的默认声明。因为 XML 并不知道如何显示元件,因此这个文件指出怎样去做。通常,你会将这一行放在每一个 XUL 文件的顶部。你也可以采用类似语法导入其他的样式表。需要注意的是你一般都会在你的样式表文件中导入全局样式表。
  4. +
  5. <window
    + 这一行说明你在描述一个 window 。每一个用户界面窗口都在一个单独的文件中进行描述。这个标记非常类似 HTML 中包围全部内容的 BODY 标记。 一些属性可以放到 window 标记中——在本例中有四个属性。在本例中,每一个属性都占一个单独的行,但并不是必须这样做。
  6. +
  7. id="findfile-window"
    + id 属性用作标识以便窗口被脚本所引用。你通常会为所有的软件放上 id 属性。虽然名字可由你任起,但应该是有一定关联的。
  8. +
  9. title="查找文件"
    + The title Attribute 属性描述显示时将在窗口的标题栏上显现的文本。在本例中将显示'查找文件'。
  10. +
  11. orient="horizontal"
    + orient 属性确定窗口中元件的排布。值 horizontal 意味着元件应该横过窗口水平放置。你也可以使用值 vertical,这表示元件将成一列放置。这是默认值,所以如果你希望使用垂直方向的话可以将这个属性完全关闭。
  12. +
  13. xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    + 这一行声名了 XUL 的名空间,你应该将它放到窗口元件以表示它的所有子元件都是 XUL。注意这个 URL 实际上不需要下载的。Mozilla 内部会识别这个 URL。
  14. +
  15. <!-- 其他元件写到这里 -->
    + 将这个注释块替换成其他显示在窗口中的元件(按钮、菜单以及其他用户界面组件)。我们在接下面的部分将添加一些元件。
  16. +
  17. </window>
    + 最后,我们需要在文件的结尾关闭 window 标记。
  18. +
+ +

打开窗口

+ +

声明完一个窗口,如果打开它呢?这里有几种方法:

+ + + +

不过,因为我们的XUL中没有定义其它元素,因此使用Mozilla打开时,什么也看不到。并且在浏览器中打开时,窗口会显示在浏览器中,这不是一个真正的应用,不过进行测试没有关系。

+ + + +

-chrome参数并不会带来特殊权限,而是chrome URL备具特殊权限。

+ +

到这里可以把已经学过的做一个测试。包的组织不一定要是content/skin/locale这种形式。象我的测试就是:

+ +
+

d:\project\test\xul\findfile

+
+ +

现在目录下有两个文件:

+ +
+

findfile.xul和contents.rdf

+
+ +

然后修改installed-chrome.txt文件。

+ +

切换到Mozilla目录,然后在命令行下输入:

+ +
+

mozilla -chrome chrome://findfile/content/filefile.xul

+
+ +

不过执行完后,什么都没有,就一个标题条。

+ +

(英文原文: XUL_Tutorial:Creating_a_Window ) 本篇wiki基于limodou的学习记录: XUL学习:XUL Tutorial(五) -- Creating a Window

+ +

 

+ +

+

« 上一页下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/creating_an_installer/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/creating_an_installer/index.html new file mode 100644 index 0000000000..aef43ec39b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/creating_an_installer/index.html @@ -0,0 +1,98 @@ +--- +title: 创建安装程序 +slug: Mozilla/Tech/XUL/Tutorial/Creating_an_Installer +translation_of: Archive/Mozilla/XUL/Tutorial/Creating_an_Installer +--- +

 

+
+

Parts of this page show the use of the XPInstall API. The majority of this API is now deprecated and as of Gecko 1.9 no longer available. Extension, theme, and plug-in developers must switch away from install.js based packages to the new packaging scheme with an install.rdf manifest. In particular plugin developers should see how to package a plugin as an extension.

+
+

 

+

 

+
+

« Previous Next »

+
+

  

+

 

+

This section will describe packaging a XUL application into an installer.

+
+

XPInstall Packages

+
+ Edit section
+

Mozilla provides a mechanism which can be used to package XUL windows, scripts, skins and other files into single file installers. You can place this installer file somewhere for users to download. A simple script can be used to have the package downloaded and installed. This mechanism is called XPInstall (Cross platform Install).

+

XPInstall installers are packaged into JAR files. Inside the JAR file, you can add all the various files that you want to have installed. In addition, installers should contain an install script (a file named install.js) which can be used to script the installation process. This script has access to various install functions which can be used to install files and components.

+

The JAR file installers typically have the extension .xpi (pronounced zippy) to distinguish them from other archives. The installers will be usually used to install Mozilla components such as new skins, plugins and packages.

+

There are several steps involved in launching an installer and installing components. These are described step by step below.

+
    +
  1. Create a Web page from which the user can download the software to be installed. This page will contain an install trigger which is a small piece of script which launches the install.
  2. +
  3. The user is presented with a dialog which indicates the package being installed. It is possible for the install trigger to launch multiple installers. In this case, they will be presented in a list. The user may choose to continue or cancel.
  4. +
  5. If the user chooses to continue, the installer XPI file is downloaded. A progress bar is displayed to the user during this process.
  6. +
  7. The file install.js is extracted from the install archive and executed. This script will call install functions which will indicate which files from the archive should be installed.
  8. +
  9. Once the script is complete, the new package has been installed. If multiple packages are being installed, their scripts will run in sequence.
  10. +
+
+
+

Install Triggers

+
+ Edit section
+

As indicated above, the install process is started by an install trigger. This involves the use of the special global object InstallTrigger. It contains a number of methods which can be used to start an installation. You can use this object in local or remote content, meaning that it is suitable for a download from a Web site.

+

Let's create an example install trigger. This involves the use of the function InstallTrigger.install(). This function takes two arguments, the first is a list of packages to install, and the second is a callback function which will be called when the installation is complete. Here is an example:

+
function doneFn ( name , result ){
+  alert("The package " + name + " was installed with a result of " + result);
+}
+
+var xpi = new Object();
+xpi["Calendar"] = "calendar.xpi";
+InstallTrigger.install(xpi,doneFn);
+
+

First, we define a callback function doneFn() which will be called when the install is complete. You can name the function whatever you like of course. This function has two arguments. The first is the name of the package that was just installed. This is important if you are installing multiple components. The second argument is a result code. If the result is 0, the installation completed successfully. If the result is non-zero, an error occured and the value is an error code. The function doneFn() here just displays an alert box to the user.

+

Next, we create an array xpi which will hold the name (Calendar) and URL (calendar.xpi) of the installer. You can add an additional similar such line for each package you wish to have installed. Finally, we call the install function.

+

When this section of script is executed, the file calendar.xpi will be installed.

+
+
+

Our find files example

+
+ Edit section
+

Let's try this with the find files dialog.

+
function doneFn ( name , result ){
+  if (result) alert("An error occured: " + result);
+}
+
+var xpi = new Object();
+xpi["Find Files"] = "findfile.xpi";
+InstallTrigger.install(xpi,doneFn);
+
+
+
+
+

The XPI Archive

+
+ Edit section
+
+ Note: If you want to create a new XULRunner application, extension, or theme, see Bundles.
+

The installer XPI file is required to contain one file called install.js which is a JavaScript file which is executed during the installation. The remaining files are the files to be installed. These files will typically be placed inside a directory in the archive but they do not have to be. For chrome files, they might be structured like the chrome directory.

+

Often, the only files placed in an XPI archive will be the install script (install.js) and a JAR file. This JAR file contains all of the files used by your application. The components provided with Mozilla are stored in this manner.

+

Because the XPI file is just a special ZIP file, you can create it and add files to it using a zip utility.

+
+
+

Our find files example

+
+ Edit section
+

For the find files dialog, we'll create a structure in the archive much like the following:

+
install.js
+findfile
+  content
+    contents.rdf
+    findfile.xul
+    findfile.js
+  skin
+    contents.rdf
+    findfile.css
+  locale
+    contents.rdf
+    findfile.dtd
+
+
+
+

A directory has been added for each part of the package, the content, the skin and the locale. The contents.rdf files have also been added because they will be needed to register the chrome files.

+

Next, we'll look further at the install script.

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/creating_dialogs/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/creating_dialogs/index.html new file mode 100644 index 0000000000..1b3dbb2fab --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/creating_dialogs/index.html @@ -0,0 +1,6 @@ +--- +title: Creating Dialogs +slug: Mozilla/Tech/XUL/Tutorial/Creating_Dialogs +translation_of: Archive/Mozilla/XUL/Tutorial/Creating_Dialogs +--- +

This page has no content. Enrich MDC by contributing.

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/document_object_model/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/document_object_model/index.html new file mode 100644 index 0000000000..15112d1cc7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/document_object_model/index.html @@ -0,0 +1,220 @@ +--- +title: 文档对象模型 +slug: Mozilla/Tech/XUL/Tutorial/Document_Object_Model +tags: + - DOM + - XUL_教程_cn +translation_of: Archive/Mozilla/XUL/Tutorial/Document_Object_Model +--- +
+
+

 

+

 

+
+

« Previous Next »

+
+

  

+

 

+

    XUL元素的文档对象模型 (DOM) 可以用于获取信息或修改他们。

+
+

DOM 介绍

+
+ Edit section
+

    文档对象模型 (DOM) 用于储存XUL节点树。当一个XUL文件加载后,标记被解析并转换成节点的继承关系结构。每个节点包含标记及一个文本块。DOM 结构可以使用一系列方法检查并修改。特殊的XUL 元素也提供了附加的方法可供使用。

+

    每一个加载了的XUL 文件都有一个可以显示在窗口或框架内的文档。尽管在特定时间只有一个文档与窗口相关,也有一系列方法使你可以加载更多的文档。

+

    Mozilla中, DOM 可以被JavaScript访问并操作。大量的文件对象包含可以被脚本使用的函数。然而,需要了解的是 DOM 是一个可以被 JavaScript 访问的 API 。JavaScript 本身仅是一种脚本语言,它能够访问这些对象是因为 Mozilla 为他提供了这些。

+

    JavaScript 中,由一个全局对象总可以被访问。你可以不使用对象就引用这个全局对象的属性及方法。比如,如果这个全局对象由一个 'name' 属性,你可以用这样的代码来改变它 'name = 7',而不用指明你所使用的对象。在浏览器环境中,window 是这个全局对象,对于XUL同样。当然对于不同的窗口这个全局对象也有所不同。每一个框架都含有一个独立的窗口对象。

+

    窗口经常使用 window property 引用,尽管这是可选的。有时这仅是为了澄清你所引用的方法的范围。举例来说,下面的两行等效的打开了一个新窗口。

+
window.open("test.xul","_new");
+open("test.xul","_new");
+
+

    当你在脚本的顶层定义一个函数或变量时,你实际上是为全局对象定义了一个属性。在 XUL中你定义的每一个函数都会被设为窗口对象的属性,比如下面的代码会在提示框中显示 'Message' 两次。

+
function getText(){
+  return "Message";
+}
+
+alert(getText());
+alert(window.getText());
+
+

    如果你希望访问在另一个窗口的脚本中定义的变量或函数,你值需要使用另一个窗口的 window 对象。比如,把上面的两个例子做成一个我们希望在另一个窗口(比如test.xul窗口)中调用getText()函数,可以这样做:

+
alert(window.opener.getText());
+
+

    每一个窗口都有一个 opener 属性,它保存着这个窗口对象是由谁打开的。在这个例子中,我们得到窗口的打开者,并调用这个窗口的 getText() 函数。注意,我们使用窗口属性前缀 'window' 仅为了清晰。

+

    窗口的 open() 方法也返回一个新窗口的引用,我们也可以从 opener调用新窗口的函数。提示: open() 在窗口完全加载前返回函数可能不会有效。

+

    窗口对象并不是有由 DOM 标准定义的,但在 Mozilla中有时把这部分称作 DOM Level 0——一个一些开发者称呼那些还未加入标准的类 DOM 功能的名字。在春光看中显示的文档可以通过窗口的 document 属性获得。由于它是窗口最常用的属性 document 属性经常不使用 'window.' 前缀。

+

     Mozilla 为不同的文档提供了一系列文档对象。三个主要的是HTMLDocument, XMLDocument, a及 XULDocument, 分别支持 HTML, XMLXUL 文档。这三种文件类型十分相似,事实上他们共享基本实现。然而,一些函数在一种或几种文档类型是特殊的。

+
+
+

检索元素

+
+ Edit section
+

    最常用的检索元素的方法是给出待检索元素的id 属性利用getElementById() 方法检索。在 find file 对话框中我们为不少元素都添加了id属性,比如,我们可以使用这样的代码获得check box 的状态。

+
var state = document.getElementById('casecheck').checked;
+
+

     casecheck 代表待检索 checkbox 的id,如果我们需要检查是否它被选中,我们只需按上面的方法检查。我们可以对其他的单选框或其他有id的元素作相同的检查。比如获得输入框中的字符。;

+
+
+

find files 的例子

+
+ Edit section
+

    要让 progress bartree data在findfile对话框显示时就显示出来,这不是难题。只要加在XUL文件中就可以了。现在我们要先去掉它,然后在按下 Find 按钮后显示。 首先,应将他们初始化化为不可见。hidden 属性用于确定元素是否显示。

+

    把进度条初始化为隐藏,同时为了能够用脚本引用添加一个 id 属性。同样的为了隐藏tree我们也将splitter 隐藏。

+
<tree id="results" hidden="true" flex="1">
+  .
+  .
+  .
+<splitter id="splitbar" resizeafter="grow" hidden="true"/>
+
+<hbox>
+
+  <progressmeter id="progmeter" value="50%"
+    style="margin: 4px;" hidden="true"/>
+
+

    添加 hidden 属性并设值为 true。这将导致窗口首次显示时该元素不可见。

+

    接下来,我们添加一个在Find按钮按下时调用的函数。我们把脚本写在findfile.js里,在上一章,我们已经在XUL文件中添加了脚本( script元素,如果你还不知道如何添加,请看下面的例子。 oncommand 控制器也被加到 Find 按钮上。

+
<script src="findfile.js"/>
+  .
+  .
+  .
+<button id="find-button" label="Find"
+   oncommand="doFind();"/>
+
+

    现在与findfile.xul相同的目录中创建一个叫 findfile.js 的文件,我们在文件中写一个 doFind() 函数。 script 标签允许直接编写脚本代码,但是出于包括格式在内的多种原因,脚本经常写在独立的文件里,除非它可以直接放到处理器中。

+
function doFind(){
+  var meter = document.getElementById('progmeter');
+  meter.hidden = false;
+}
+
+

    这个函数首先通过进度条的id引用它,然后改变的hidden属性。

+

    最后用一个提示框显示需要检索的文字。当然,这不是最后的版本,但现在我们需要让它发生些什么以使我们确认。

+
function doFind(){
+  var meter=document.getElementById('progmeter');
+  meter.hidden = false;
+  var searchtext=document.getElementById('find-text').value;
+  alert("Searching for \"" + searchtext + "\"");
+}
+
+

    现在,由于提示框的存在,我们知道当点击Find按钮时,会发生什么。同样,我们也需要为 drop-down boxes 添加代码以获得用用户选项。

+
+
+
+
+

XUL 元素的 DOM

+
+ Edit section
+

    每一个 XUL 元素都还有一系列的属性,功能及子元素。

+
    +
  • 属性是在源文件中定义的,如flex="1"将 flex 属性设为 1
  • +
  • JavaScript 中属性使用点语法。例如:element.hidden 引用延伸的hidden 属性
  • +
  • 子元素的是指嵌在源文件标签中的元素。
  • +
+

    使用DOM方法可以动态的处理一个元素的属性,方法及子元素。

+

    注意属性及方法是不一样的东西。有一个属性并不意味着有一个同名的方法,当然通常会有这样一个方法。比如说获得元素的flex属性可以使用flex方法。这种情况下方法的代码就返回这属性。对于其他的方法 XUL 会进行更复杂的处理

+

    你可以用以下的方法处理元素的属性:

+
+
+ getAttribute ( name )
+
+ 返回给定元素的属性。
+
+ hasAttribute ( name )
+
+ 如果元素有指定名字的属性返回真。
+
+ setAttribute ( name , value )
+
+ 将value 为给定名字为name 的属性赋值。
+
+ removeAttribute ( name )
+
+ 删除给定名字的属性。
+
+

    这些方法可以让你在任何时候取得或改变属性的值。比如:

+
 var box = document.getElementById('somebox');
+ var flex = box.getAttribute("flex");
+
+ var box2 = document.getElementById('anotherbox');
+ box2.setAttribute("flex", "2");
+
+

   当然 flex 属性有对应的脚本方法 可以用以代替。它并不更为有效,当更为简洁。下面的例子与上面的效果相同。

+
 var box = document.getElementById('somebox');
+ var flex = box.flex;
+
+ var box2 = document.getElementById('anotherbox');
+ box2.flex = 2;
+
+

    一旦你引用了元素你就可以引用它的方法。比如,为了获得一个元素的 hidden 方法可以使用element.hidden 。你可能已经注意到了在方法参考中,一项会同时出现在属性及方法中,这是不一样的。比如,对于隐藏的元素 getAttribute("hidden") 返回字符串 'true' ,而 hidden 方法返回‘值true’  。用方法会自动完成类型转换。

+

    像 HTMLXML 元素一样,每一个 XUL 元素实现 XULElement 接口。一个 XUL 元素可以是任何定义在 XUL 名空间中的元素。所以XUL有非XUL 元素没有的属性及方法。XULElement 接口有一系列属性及方法来定义XUL 元素,其中有很多继承至 DOM 元素接口。

+

    一个名空间用一个URI 描述元素,下面是例子。

+
<button xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
+<button xmlns="http://www.w3.org/1999/xhtml"/>
+<html:button xmlns:html="http://www.w3.org/1999/xhtml"/>
+<html:button xmlns:html="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
+

    名空间使用 xmlns 属性

+
    +
  • 第一个按钮是被置于XUL名空间在的 XUL 元素。
  • +
  • 第二个按钮是被置于XHTML名空间在的 XHTML 元素。
  • +
  • 第三个例子,前缀 'html' 关联到 'http://www.w3.org/1999/xhtml',当你的文档中需要多个名空间时,你也可以使用使用冒号语法来使用前缀名空间。本例创建一个 XHTML 按钮。
  • +
  • 第四个按钮是XUL按钮,尽管使用的‘html’前缀,这要看前缀关联到哪个名空间。
  • +
+

    这是一个很重要的区别,不过在真正的文档中会为不同的名空间使用不同的前缀。

+

    DOM 提供了与无名空间相似的名空间相关的方法。比如 getAttributeNS()getAttribute() 相似除了需要一个指明名空间的参数。

+

    许多XUL元素有不同于其他元素的方法。参见 element reference

+
+
+

DOM遍历

+
+ Edit section
+

    DOM是一个只有一个根的树。可以使用documentElement 方法获取根节点。根节点只要一个,但其他节点则不一定。一个元素对应与源文件中的标签,但也有文本节点、注释节点、及其他类型的节点。在XUL文档中根节点是源文件中的window标签。 树中的每一个节点都可能有其子节点,每个子节点又有它字节的子节点。由于DOM是树结构所以可以用一系列方法来遍历它。常用的几个列在下面:

+
+
+ firstChild
+
+ 引用元素的第一个子节点。
+
+ lastChild
+
+ 引用元素的最后一个子节点。
+
+ childNodes
+
+ 返回元素子节点的列表。
+
+ parentNode
+
+ 返回元素的亲节点。
+
+ nextSibling
+
+ 引用下一个兄弟节点。
+
+ previousSibling
+
+ 引用前一个兄弟节点。
+
+

    这些方法允许你以多种方法遍历文件,比如,使用 firstChild 方法获得第一个子节点并用 nextSibling 方法遍历子节点,或者可以用childNodes 返回子节点列表。在Mozilla中后者更有效。

+

    这个例子展示如何遍历根节点的全部子节点:

+
var childNodes = document.documentElement.childNodes;
+for (var i = 0; i < childNodes.length; i++) {
+  var child = childNodes[i];
+  // do something with child
+}
+
+

    变量 childNodes 保存着文档根节点的全部子节点。然后像处理数组一样用一个 for 循环枚举全部元素。

+
+ Find files example so far: Source View
+

See also: A re-introduction to JavaScript and the JavaScript reference

+

    下一章学习修改DOM modify the DOM.

+

 

+
+

« Previous Next »

+
+

  

+

 

+
+
+
+
+
+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/element_positioning/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/element_positioning/index.html new file mode 100644 index 0000000000..df6c75dee6 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/element_positioning/index.html @@ -0,0 +1,254 @@ +--- +title: XUL_教程/元素定位 +slug: Mozilla/Tech/XUL/Tutorial/Element_Positioning +tags: + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial/Element_Positioning +--- +

+

« 上一页下一页 »

+

+ +

分组元素定位

+ +

迄今为止, 我们知道怎么在一个分组里面将元素进行水平或垂直定位。我们通常需要在分组内对元素的定位和尺寸进行更多的控制。为此,我们首先需要知道一个分组是怎么工作的。

+ +

一个元素的定位由他所属容器的布局样式决定。例如,在水平分组中的一个按钮在前面的按钮的右边。一个元素的尺寸由两个因素决定:元素期望的大小和用户指定的大小。元素期望的大小由该元素所包含的内容决定。例如,一个按钮的宽度由按钮上所显示文本的长度决定。

+ +

一般来说元素的大小仅够容纳它的内容。一些元素,像文本输入框会使用一个默认的尺寸。分组会分配足够的尺寸去将元素放在它里面。一个包括三个按钮的水平分组将会包含比三个按钮更多的宽度,插入一些填充。

+ +
Image:boxstyle1n.png
+ +

在图片中,开始两个按钮为它们的文本提供了合适的尺寸。第三个按钮比较长因为它包含更多的内容。分组的宽度包含按钮间的填充空间和按钮的宽度总和。按钮的高度采用能够放置它的文本的合适尺寸。

+ +

宽度和高度属性

+ +

在窗口中你可能需要对元素的尺寸进行更多的控制。有更多的特性允许你去控制元素的尺寸。有一个快捷的方法可以通过在元素中简单添加widthheight 属性,更像你在HTML中的 img 标签的用法。下面展示了一个例子:

+ +

例1 : Source View

+ +
<button label="确认" width="100" height="40"/>
+
+ +

然而,不推荐这样做。这么做适用性不好且可能与某些主题不匹配。一个更好的方法是使用样式表属性,它可以像中HTML中的样式表一样工作。可以使用下面的CSS属性。

+ +
+
width 
+
指定元素的宽度。
+
height 
+
指定元素的高度。
+
+ +

随便设置这两属性中的一个,元素将会创建它的宽度和高度。如果你只指定一个尺寸属性,另一个需要被算出。这些样式表属性的尺寸可以指定一个数字后面跟着一个单位。

+ +

可伸缩元素

+ +

非伸缩元素可以很简单快捷地计算尺寸。它们的宽度和高度可以直接被指定,如果没有指定尺寸,元素的默认尺寸就是刚好能放下它的内容的大小。对于可伸缩元素,计算需要一点窍门。

+ +

可伸缩元素有一个可以设置为大于0的属性flex。被用来设置在可伸缩性元素中可以扩展和收缩的有用填充空间。它们的默认尺寸可以像非伸缩元素一样被计算。下面的例子做了这个的演示:

+ +

例2 : Source View

+ +
<window orient="horizontal"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<hbox>
+  <button label="Yes" flex="1"/>
+  <button label="No"/>
+  <button label="I really don't know one way or the other"/>
+</hbox>
+
+</window>
+
+ +

这个窗口会像之前的图片所显示的一样。前面两个按钮将一个合适尺寸作为默认宽度,第三个按钮将会比较大因为它有一个较长的标签。第一个按钮被建成是可伸缩的,并且将所有的三元素放在一个分组里面。分组的宽度被设置成全部三个元素的总宽度(图片的宽度大约是430像素)。

+ +

如果你增加窗口的宽度,元素会被检查清楚它们是否是可伸缩的,然后被分配到填充的空白空间。按钮只是可伸缩元素,但它不会增加宽度。这是因为按钮所在的分组不是可伸缩的。一个非伸缩元素在空间有效时也不会改变尺寸,所以按钮不会比其他情况下变得更宽。因此,按钮不会变得更宽。

+ +

这个解决方案也用于创建可伸缩性的分组。于是,当你创建一个更宽的窗口时,因此分组会伸长以便填充多余的空间。因为分组比较大,更多的空余空间可以被放在它里面,放在它里面的可伸缩按钮可以填充有效空间而得到扩展。这会被许多内嵌的分组重复处理。

+ +

设置最小和最大尺寸

+ +

你可以允许一个元素能够扩展但限制它的尺寸不能比一个确定的尺寸更大。或者,你可设置一个最小尺寸。你可以通过以下四个属性来达到这个目的:

+ +
+
minwidth 
+
指定元素的最小宽度。
+
minheight 
+
指定元素的最小高度。
+
maxwidth 
+
指定元素的最大宽度。
+
maxheight 
+
指定元素的最大高度。
+
+ +

这个值的单位是像素。你也可以使用相应的CSS属性:min-widthmin-heightmax-widthmax-height

+ +

这些属性只可以用于可伸缩元素。例如,设置一个最大高度,一个可伸缩的按钮将只能扩展到一个 确定的最大高度。你可以更改窗口的尺寸超过这个值但按钮会在指定的尺寸停止扩展。分组中的按钮将会一直扩展到你设置的分组最大高度时止。

+ +

如果两个按钮都具有相等的弹性值,普通情况下它们两个会共享相同的多余空间。如果一个按钮有一个最大宽度,第二个将会一直扩展直到用光所有的空间为止。

+ +

如果一个分组有一个最大宽度或高度,子分组不会扩展超出它的最大尺寸。如果一个分组有一个最小宽度或高度,它的子分组不能缩小到比它的最小尺寸更小。

+ +
设置宽度和高度的例子
+ +
<button label="1" style="width: 100px;"/>
+<button label="2" style="width: 100em; height: 10px;"/>
+<button label="3" flex="1" style="min-width: 50px;"/>
+<button label="4" flex="1" style="min-height: 2ex; max-width: 100px"/>
+<textbox flex="1" style="max-width: 10em;"/>
+<description style="max-width: 50px">This is some boring but simple
+wrapping text.</description>
+
+ +
+
例1 
+
第一个按钮将显示成宽度为100像素的(px 的意思是像素)。你必须增加单位否则宽度将被忽略。
+
例2 
+
第二个按钮将显示成高度为10像素和宽度为100em(em是当前字体一个字符的尺寸)。
+
例3 
+
第三个按钮是可伸缩的所以它可以基于包含它的分组的尺寸进行扩展。然而,按钮不能收缩到比50像素更小。其它可伸缩组件像定位格可以吸收保留空间,而不管弹性比率。
+
例4 
+
第四个按钮是可伸缩的并且不能有一个比2ex(ex是当前字体中的字母x的高度)小的高度或比100像素更大的宽度。
+
例5 
+
文本输入框是可伸缩的但不能扩展超过10em。你会经常去使用em单位作为指定文本内容它们的尺寸。这个单位用于文本输入框因此字体可以更改并且文本输入框可以一直有个合适的尺寸,如果字体非常大时也一样。
+
例6 
+
description 元素包含50像素的最大宽度。在50像素后,文本会自动被截到下一行。
+
+ +
+
我们的文件查找对话框
+ +

让我们将这些样式增加到文件查找对话框。我们将会创建它因此文本输入框可以在输入窗口中改变尺寸。

+ +
<textbox id="find-text" flex="1" style="min-width: 15em;"/>
+
+ +
Image:boxstyle1.png
+在这里,文本输入框被做成可伸缩的。这样,它可以在用户改变对话框的尺寸时进行扩展。这可以用于如果用户想要输入一个很长的文本字符串时。通常地,设置了一个最小宽度为15em则输入框会一直显示为至少15个字符的宽度。如果用户更改对话框的尺寸到很小,文本输入框不会缩小超过15个字符长度。在窗口里面的输入框将会被画出来,并超出窗口的范围。注解:在图片中文本输入框被扩展为充满窗口的尺寸。
+ +

Box Packing

+ +

Let's say you have a box with two child elements, both of which are not flexible, but the box is flexible. For example:

+ +

Example 3 : Source View

+ +
<box flex="1">
+  <button label="Happy"/>
+  <button label="Sad"/>
+</box>
+
+ +

If you resize the window, the box will stretch to fit the window size. The buttons are not flexible, so they will not change their widths. The result is extra space that will appear on the right side of the window, inside the box. You may wish, however, for the extra space to appear on the left side instead, so that the buttons stay right aligned in the window.

+ +

You could accomplish this by placing a spacer inside the box, but that gets messy when you have to do it numerous times. A better way is to use an additional attribute pack on the box. This attribute indicates how to pack the child elements inside the box. For horizontally oriented boxes, it controls the horizonal positioning of the children. For vertically oriented boxes, it controls the vertical positioning of the children. You can use the following values:

+ +
+
start 
+
This positions elements at the left edge for horizontal boxes and at the top edge for vertical boxes. This is the default value.
+
center 
+
This centers the child elements in the box.
+
end 
+
This positions elements at the right edge for horizontal boxes and at the bottom edge for vertical boxes.
+
+ +

The pack attribute applies to the box containing the elements to be packed, not to the elements themselves.

+ +

We can change the earlier example to center the elements as follows:

+ +

Example 4 : Source View

+ +
<box flex="1" pack="center">
+  <button label="Happy"/>
+  <button label="Sad"/>
+</box>
+
+ +

Now, when the window is resized, the buttons center themselves horizontally. Compare this behavior to that of the previous example.

+ +

Box Alignment

+ +

If you resize the window in the Happy-Sad example above horizontally, the box will grow in width. If you resize the window vertically however, you will note that the buttons grow in height. This is because the flexibility is assumed by default in the other direction.

+ +

You can control this behavior with the align attribute. For horizontal boxes, it controls the position of the children vertically. For vertical boxes, it controls the position of the children horizontally. The possible values are similar to those for pack.

+ +
+
start 
+
This aligns elements along the top edge for horizontal boxes and along the left edge for vertical boxes.
+
center 
+
This centers the child elements in the box.
+
end 
+
This aligns elements along the bottom edge for horizontal boxes and along the right edge for vertical boxes.
+
baseline 
+
This aligns the elements so that the text lines up. This is only useful for horizontal boxes.
+
stretch 
+
This value, the default, causes the elements to grow to fit the size of the box, much like a flexible element, but in the opposite direction.
+
+ +

As with the pack attribute, the align attribute applies to the box containing the elements to be aligned, not to the elements themselves.

+ +

For example, the first box below will have its children stretch, because that is the default. The second box has an align attribute, so its children will be placed centered.

+ +

Example 5 : Source View

+ +
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window id="yesno" title="Question" orient="horizontal"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <hbox>
+    <button label="Yes"/>
+    <button label="No"/>
+  </hbox>
+  <hbox align="center">
+    <button label="Maybe"/>
+    <button label="Perhaps"/>
+  </hbox>
+
+</window>
+
+ +
Image:boxstyle2-b.png
+ +

You can also use the style properties -moz-box-pack and -moz-box-align instead of specifying attributes.

+ +
You may find the Box Alignment Example useful for trying out the various box properties.
+ +

Cropping Text and Buttons

+ +

You could potentially create a button element that contains a label that is larger than the maximum width of the button. Of course, a solution would be to increase the size of the button. However, buttons (and other elements with a label) have a special attribute called crop that allows you to specify how the text may be cropped if it is too big.

+ +

If the text is cropped, an ellipsis (...) will appear on the button where the text was taken out. Four possible values are valid:

+ +
+
left 
+
The text is cropped on its left side
+
right 
+
The text is cropped on its right side
+
center 
+
The text is cropped in the middle.
+
none 
+
The text is not cropped. This is the default value.
+
+ +

This attribute is really only useful when a dialog has been designed to be useful at any size. The crop attribute can also be used with other elements that use the label attribute for labels. The following shows this attribute in use:

+ +

Example 6 : Source View

+ +
Image:boxstyle2.png
+ +
<button label="Push Me Please!" crop="right" flex="1"/>
+
+ +

Notice how the text on the button has had the right side of it cropped after the window is made smaller.

+ +
+

Find files example so far : Source View

+
+ +

Next, a summary and some additional details of the box model are described.

+ +

+

« 上一页下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/features_of_a_window/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/features_of_a_window/index.html new file mode 100644 index 0000000000..cae533b206 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/features_of_a_window/index.html @@ -0,0 +1,6 @@ +--- +title: Features of a Window +slug: Mozilla/Tech/XUL/Tutorial/Features_of_a_Window +translation_of: Archive/Mozilla/XUL/Tutorial/Features_of_a_Window +--- +

This page has no content. Enrich MDC by contributing.

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/grids/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/grids/index.html new file mode 100644 index 0000000000..47201b797c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/grids/index.html @@ -0,0 +1,175 @@ +--- +title: 网格 +slug: Mozilla/Tech/XUL/Tutorial/Grids +translation_of: Archive/Mozilla/XUL/Tutorial/Grids +--- +

XUL有一系列的元素来创建表格布局

+

 XUL的表格布局

+

使用grid元素可以在XUL中使用一系列的元素来进行元素的布局。这与HTML中的table有很大的相似性。网格本身不会有任何的显示,它仅仅是使用行和列的形式来定位其他元素。

+

一个网格内部的元素排列成行。在grid里面,你需要声明两种东西,columns和rows。正如HTML的table,你可以将label和button等内容放在row里面。但是,grid只支持单独的row或者单独的column,因此你可以将内容放在rows里面或者columns里面。通常是使用rows。但是在grid中你还是可以使用column并制定其大小和显示方式。或者你可以将内容放在columns里面,然后用row来指定其显示方式。首先看看以row的方式组织元素的方法。

+

声明一个网格

+

使用rows标签来声明一系列的row。Rows必须是grid的子元素。在rows里面你可以添加row元素,row用在每一行。在row元素中你可以放任何你想要的内容在里面。

+

相似的,列由columns来声明。其中有单独的column元素,每个你想添加的列都是一个column元素。

+

用一个例子更容易理解。

+

例子1:

+

+ + + + + + +
+

<grid flex="1">

+

  <columns>

+

    <column flex="2"/>

+

    <column flex="1"/>

+

  </columns>

+

  <rows>

+

    <row>

+

      <button label="Rabbit"/>

+

      <button label="Elephant"/>

+

    </row>

+

    <row>

+

      <button label="Koala"/>

+

      <button label="Gorilla"/>

+

    </row>

+

  </rows>

+

</grid>

+
+

添加了一个两行两列的grid。每个列由一个column标签声明。每一列都设置了flex属性。每行航油两个元素都是半年。每个单元格不需要进行声明,可以直接将内容放在row元素里面。

+

带有更多元素的网格

+

你可以使用任何元素来代替上面的button元素,。如果你想要一个详细的关于容纳多个元素的单元,你可以使用嵌套的hbox或者其他box元素。一个hbox元素是一个单一的元素,但是你可以在里面放任意多的元素。例如:

+

例子2:

+ + + + + + +
+

<grid flex="1">

+

 

+

  <columns>

+

    <column/>

+

    <column flex="1"/>

+

  </columns>

+

 

+

  <rows>

+

    <row>

+

      <label control="doctitle" value="Document Title:"/>

+

      <textbox id="doctitle" flex="1"/>

+

    </row>

+

    <row>

+

      <label control="docpath" value="Path:"/>

+

      <hbox flex="1">

+

        <textbox id="docpath" flex="1"/>

+

        <button label="Browse..."/>

+

      </hbox>  

+

    </row>

+

  </rows>

+

 

+

</grid>

+
+

+

注意第二列的第二行,含有一个box,box里面有一个文本框和一个按钮。你可以添加嵌套的box或者在里面放置另外一个grid。

+

由于第二行和文本框都设置了flex属性,所以改变窗口尺寸的时候文本框会改变大小,而其他元素不会改变。

+

一列的宽度由该列中最宽的元素决定。同牙膏的一行的高度由这一行中最高的元素决定。你可以使用minwidth和maxwidth以及相关的属性来对尺寸作更多的定义。

+

按列组织

+

你也可以在列中添加元素,这样一来,row元素就只是用来表示有多少行了。

+

例子3:

+ + + + + + +
+

<grid>

+

  <rows>

+

    <row/>

+

    <row/>

+

    <row/>

+

  </rows>

+

 

+

  <columns>

+

    <column>

+

      <label control="first" value="First Name:"/>

+

      <label control="middle" value="Middle Name:"/>

+

      <label control="last" value="Last Name:"/>

+

    </column>

+

    <column>

+

      <textbox id="first"/>

+

      <textbox id="middle"/>

+

      <textbox id="last"/>

+

    </column>

+

  </columns>

+

 

+

</grid>

+
+

这个网格有桑航两列。元素row仅仅表示有多少行。你可以添加flex属性来使其自适应。内容在每一列中。

+

如果你在列和行中都填内容,内容将会相互覆盖,不过他们会在grid中合适的进行排列。就像在网格中有堆元素一样。

+

Grid中元素的顺序决定了哪一个会显示在上面,哪一个在下面。如果rows元素放在columns元素后面,在rows中的内容会显示在上面。如果columns放在rows元素后面,列中的内容会显示在上面。事件的获取也一样。

+

网格自适应

+

网格的一个优点是在一系列嵌套box中你可以创建在水平和竖直方向上都自适应的单元格。你可以通过使用flex属性在row和column元素上来实现。下面的例子说明了这一点:

+

例子4:

+ + + + + + +
+

<grid flex="1">

+

 <columns>

+

  <column flex="5"/>

+

  <column/>

+

  <column/>

+

 </columns>

+

 <rows>

+

  <row flex="10">

+

    <button label="Cherry"/>

+

    <button label="Lemon"/>

+

    <button label="Grape"/>

+

  </row>

+

  <row flex="1">

+

    <button label="Strawberry"/>

+

    <button label="Raspberry"/>

+

    <button label="Peach"/>

+

  </row>

+

 </rows>

+

</grid>

+
+

第一列和所有两行都设置为自适应。这样的结果是第一列中的单元格在水平方向上自适应,另外每个单元格都会在竖直方向上自适应,因为两行都是自适应的,不过第一行还不止这样。第一列和第一行的单元格将会在水平方向上以5的倍率伸缩,在竖直方向上以10的倍率伸缩。

+

元素grid也要设置flex属性,这样所有的网格才能自适应,否则就只会在一个方向上自适应。

+

列宽扩展

+

让很多行和列中的一个单元格扩展是没有意义的。但是可以让一行或者一列整个的扩展。为了实现这一点只需要在rows元素中添加一个元素。比如可以使用一个box样式。让回将其他元素放在里面。下面是一个简单的例子:

+

例子5:

+ + + + + + +
+

<grid>

+

  <columns>

+

    <column flex="1"/>

+

    <column flex="1"/>

+

  </columns>

+

 

+

  <rows>

+

    <row>

+

      <label value="Northwest"/>

+

      <label value="Northeast"/>

+

    </row>

+

    <button label="Equator"/>

+

    <row>

+

      <label value="Southwest"/>

+

      <label value="Southeast"/>

+

    </row>

+

  </rows>

+

</grid>

+
+

按钮将会扩展以适合整个grid的宽带,因为它不是一个grid的行中的元素。你也可以将相似的方式用在两个列中。这样就会扩展以一与网格的高度相适应。你可以在行和列上都使用,如果你想这样做。

+

下一节我们来看看内容面板

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/groupboxes/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/groupboxes/index.html new file mode 100644 index 0000000000..c62dd0f004 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/groupboxes/index.html @@ -0,0 +1,85 @@ +--- +title: 分组框 +slug: Mozilla/Tech/XUL/Tutorial/Groupboxes +translation_of: Archive/Mozilla/XUL/Tutorial/Groupboxes +--- +

    本章介绍在组框中添加元素的方法。

+
+

Groupboxes

+
+ Edit section
+

    HTML 通过了 fieldset 元素来使元素分组,一般的会在元素的边上画一个框来显示元素的关系。比如一系列单选按钮。XUL 也通过了 groupbox 元素来完成相似的功能。

+

    就像名字暗示的一样 groupbox 是一类box,这意味着在其中的元素可以安装box指定的形式排列。与一般的box相比groupbox有两点不同。

+ +

    因为组框是一种box,你可以使用如 orient flex 等属性。你可以把任何你想放入box中的元素放入组框中,无论他们有什么关系。

+

    组框顶端的标签使用 caption 元素创建,类似于 HTML 中的legend 元素,请把 caption 作为第一个元素放入组框。

+
+

一个组框的例子

+
+ Edit section
+

    下面的例子显示一个简单组框。

+

Example 1  : Source View

+
+ Image:titledbox1.png
+
<groupbox>
+  <caption label="Answer"/>
+  <description value="Banana"/>
+  <description value="Tangerine"/>
+  <description value="Phone Booth"/>
+  <description value="Kiwi"/>
+</groupbox>
+
+

    以上代码表示:四条文本被一个以 Answer 为标签的box框起来,注意组框默认的定向方式为垂直定向,所以元素会排成一列。

+
+
+

更复杂的标题

+
+ Edit section
+

    你可以在 caption 元素中添加子元素构造一个更复杂的标题,比如,Mozilla的字体选择面板使用一个下拉菜单作为标题。尽管任何元素都可以在这里使用,通常的是使用下拉菜单和复选框。

+

Example 2  : Source View

+
+ Image:groupbox2.png
+
<groupbox flex="1">
+  <caption>
+    <checkbox label="Enable Backups"/>
+  </caption>
+  <hbox>
+    <label control="dir" value="Directory:"/>
+    <textbox id="dir" flex="1"/>
+  </hbox>
+  <checkbox label="Compress archived files"/>
+</groupbox>
+
+


+     这个例子里一个 checkbox 被作为标题。我看可以根据复选框是否被选中,使用脚本来控制组框中的元素是否有效。组框中包含了一个有 label textbox 的水平框,文本框和组框均被设定为是可变的,所以元素会随着窗口延伸。复选框出现在组框底下是因为组框默认为垂直定向。下一章我们为find files 对话框添加一个组框。

+
+
+
+

单选组

+
+ Edit section
+

    你可以使用 radiogroup 把单选按钮组织在一起。 radiogroup 是一种box,你可以在其中放置任何元素,并且他对 radio 按钮具有特殊的处理。

+

    那些放在单选组里的单选按钮会被组织起来,即使它在其他的box中 。也可添加额外的元素,如下例:

+

Example 3  : Source View

+
<radiogroup>
+  <radio id="no" value="no" label="No Number"/>
+  <radio id="random" value="random" label="Random Number"/>
+  <hbox>
+    <radio id="specify" value="specify" label="Specify Number:"/>
+    <textbox id="specificnumber"/>
+  </hbox>
+</radiogroup>
+
+

    注意 radiogroup 不会画出边框。如果需要边框及标题请放置在 groupbox 中。

+

    接下来,我们使用学到的新知识来为findfile对话框添加元素。(additional elements to the find files dialog.)

+

 

+
+

« Previous Next »

+
+

  

+

 

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/index.html new file mode 100644 index 0000000000..a164d16f7f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/index.html @@ -0,0 +1,171 @@ +--- +title: XUL 教程 +slug: Mozilla/Tech/XUL/Tutorial +tags: + - XUL + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial +--- +

+ 这份XUL的教程是源自 Neil Deakin之手。很感谢他能给MDC授权使用这篇文章。

+ +

这篇教程会教你如何开发和设计基于XUL(XML User-interface Language XML用户交互语言)的应用程序. XUL是Mozilla创建的并且应用在Mozilla的应用程序的界面描述语言。

+ +
第一章 引言
+ + + +
简单的示例
+ + + +
箱模型
+ + + +
更多的布局元素
+ + + +
工具栏和菜单
+ + + +
事件和脚本
+ + + +
文档对象模型
+ + + +
+ + + +
RDF 和模板
+ + + +
本地化和皮肤
+ + + +
绑定
+ + + +
特殊的窗口类型
+ + + +
安装
+ + + +
+
关于原始文档的信息
+ + +
+ +

 

+ +

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/input_controls/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/input_controls/index.html new file mode 100644 index 0000000000..d901c50eeb --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/input_controls/index.html @@ -0,0 +1,110 @@ +--- +title: XUL_教程/输入控件 +slug: Mozilla/Tech/XUL/Tutorial/Input_Controls +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/Input_Controls +--- +

+

« 上一页下一页 »

+

+

 

+

文本输入框

+

HTML有一个输入元素可以用于文本输入操作。 XUL 有一个相似的元素, textbox, 用于文本输入。 不用任何属性, textbox 元素创建一个框让用户可以输入文本。文本框具有像HTML的输入操作相同的许多属性。下面列出其中一部份:

+
+
+ id 
+
+ 控件的唯一性标识。
+
+ class 
+
+ 输入框的样式。
+
+ value 
+
+ 如果你要输入框显示一个默认值,可以指定此属性。
+
+ disabled 
+
+ 如果需要禁用文本输入框可以将这个属性设为true
+
+ type 
+
+ 你可以将这个属性的值设为password, 创建一个输入框隐藏用户的输入内容。 通常用于密码输入框。
+
+ maxlength 
+
+ 输入框允许输入的字符最大数量。
+
+

注解:在HTML里, 使用input元素区分几个不同类型的字段,在XUL里用每种类型对元素进行区分。

+

下面列出输入框的一些属性:

+

例1 : Source View

+
<label control="some-text" value="Enter some text"/>
+<textbox id="some-text"/>
+<label control="some-password" value="Enter a password"/>
+<textbox id="some-password" type="password" maxlength="8"/>
+
+

多行文本输入框

+

上面的textbox 例子创建的输入框仅仅可以输入一行文本。HTML也有一个textarea元素用来创建一个大的文本输入区域。在XUL,你可以使用textbox元素达到很好的效果 -- 这两种元素都不是很常用。如果你设置multiline属性为true,文本输入框将显示为多行。

+

例2 : Source View

+
<textbox multiline="true"
+           value="This is some text that could wrap onto multiple lines."/>
+
+

就像HTML中的textarea,你可以使用 rowscols 属性设置大小。这可以设置显示字符的行和列数量。

+
+

我们文件查找的例子

+

让我们给文件查找对话框添加一个搜索输入框。我们将要使用 textbox 元素。

+
<label value="Search for:" control="find-text"/>
+<textbox id="find-text"/>
+
+<button id="find-button" label="Find"/>
+
+
+
+ Image:inputs1.png
+
+

将这些行插入到在前一节最后我们创建的按钮的前面。如果你打开这个窗口,你将会看到像显示的图片一样的效果。

+

注解:标签和文本输入框现在已经显示在窗口里。文本输入框已具有完全的功能你可以在它里面输入文本和选中文本。使用control 属性后因此当label 被点击后输入框被选中。

+

多选和单选按钮

+

另外两个元素是用于创建多选输入框和单选按钮。它们是按钮的变体。多选输入框元素(checkbox element)有多个选择项,可以被选或不选。单选按钮的用法相似,它有一个集合并且只能选择其中之一。

+

你可以像使用按钮的属性一样使用多选输入框和单选按钮。下面的例子向你展示一些简单的多选输入框和单选按钮。

+
<checkbox id="case-sensitive" checked="true" label="Case sensitive"/>
+<radio id="orange" label="Orange"/>
+<radio id="violet" selected="true" label="Violet"/>
+<radio id="yellow" label="Yellow"/>
+
+

第一行创建一个简单的 checkbox。当用户点击多选项,它在选中和非选中之间切换。checked 属性可以用在表明它的默认状态。你可以将它的值设为true或者falselabel属性可以用于设置显示在多选项旁边的文本。对于radio 按钮,你可以使用 selected 属性代替 checked 属性。设置它的值为 true 让默认选中其中的一个单选按钮,或者不选中其他的单选按钮。

+

单选项组元素

+

为了把单选按钮组合在一起,你需要用到radiogroup 元素。 在单选按钮组中同一时间只允许其中的一个单选按钮被选中。在其中的一个中点击将会把同一组中的其他按钮都设成关闭。下面的例子很好地示范了这一点。

+

例3 : Source View

+
<radiogroup>
+  <radio id="orange" label="Orange"/>
+  <radio id="violet" selected="true" label="Violet"/>
+  <radio id="yellow" label="Yellow"/>
+</radiogroup>
+
+

属性

+

像按钮一样,多选框和单选按钮可以用文本标签和图片进行包装,当它被按下时通过切换图片来表达选中或没选中。多选项有很多与按钮相同的属性:

+
+
+ label 
+
+ 在多选项或单选按钮上的文本标签。
+
+ disabled 
+
+ 设为truefalse 去禁用或启用多选项或单选按钮。
+
+ accesskey 
+
+ 用于选中元素的快捷键。字母会在标签中以下划线显示。
+
+
+

到目前为止文件查找的例子 : Source View

+
+

在下一节,我们将可以看到一些适用于输入和选择数值的元素。

+
+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/introduction/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/introduction/index.html new file mode 100644 index 0000000000..5e80393d30 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/introduction/index.html @@ -0,0 +1,70 @@ +--- +title: XUL_教程/引言 +slug: Mozilla/Tech/XUL/Tutorial/Introduction +tags: + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial/Introduction +--- +

+

下一页 »

+

+ +

这份教程可以帮助你如何用 XUL (XML用户界面语言) 来创建跨平台的可描述界面的应用程序.

+ +

这份教程将设计出一个"查找文件"的应用程序界面, 类似于Macintosh的Sherlock或是Windows的文件查找的窗口. 只会提供基本的界面以及一些简单的功能函数. 真正的文件查找功能并没有实现,.

+ +

什么是XUL,及为什么要创建它?

+ +

XUL (发音是 zool,有点像cool) 是为开发更快更简单的Mozilla浏览器而开发的. 这是一个基于 XML 可扩展描述语言 的语言 ,所以XML的所有特性都适用于XUL.

+ +

大多数应用程序在开发的时候都需要应用某个特定平台的特性,这就使得创建一个跨平台的软件变得费时费力。而这对于某些用户或许并非重要,但是对那些想在其它设备上,比如手持设备或机顶盒上,运行一个应用程序的用户来说却,跨平台确是至关重要的。

+ +

在过去诸多跨平台的解决方案都已被开发出来。比如Java的可移植性就是其主要卖点。XUL则是一个那样的语言,它被设计出用于创建可移植的用户界面。

+ +

创建一个应用程序是要花费好多时间的,哪怕它只工作在某个平台下。编译和排错需要的时间可能会很多。而使用XUL,一个界面可以被快速方便地制作和修改。

+ +

XUL具备所有其它XML语言的所有优点。举例来说,XHTML或者其它XML语言,比如MathML 数学标记语言 或 SVG 可伸缩矢量图,可以被插入到XUL当中。同样,XUL中的文本也可以很容易地被本地化,那意味着它可以稍加努力就可以被翻译成其它国家的语言。样式表可以被提供用于修改用户界面的外观(就像WinAmp的主题和皮肤或者某些窗口管理器)。

+ +

用XUL可以做些什么类型的用户界面?

+ +

XUL有能力创建现代图形界面中的大多数元件。它的应用广泛到可以满足特定设备特殊要求,而它的强大足以使开发者创建出复杂的界面。

+ +

下列组件可以被创建:

+ + + +

显示的内容创建自XUL文件及数据源的数据,在Mozilla中,数据源包含用户邮件箱、书签、搜索结果等等,菜单、树状列表和其它元素都能从那添加,也可以从RDF文件添加自定义的数据。

+ +

创建XUL应用程序的方法有几种:

+ + + +

前三种类型需要在用户电脑做安装操作,但是这样程序就没有安全限制了,可以访问本地文件和读写属性。例如扩展,所包含的XUL文件、脚本和图像将被打包成单一文件,用户下载后安装到本地。基于Mozilla的程序比如Firefox,提供了扩展管理器来对包进行安装管理,而不需要很多代码操作。 XUL也可以从远程WEB站点打开,然而这样很多类型操作会有限制,以及一些XUL外观效果会失效。如果你需要从远程站点载入XUL内容,WEB服务器必须设置XUL文件头格式为'application/vnd.mozilla.xul+xml'。通常XUL文件使用.xul为扩展名,你可以从Mozilla浏览器打开它,跟打开其它文件一样,点击菜单【打开文件】或者直接在地址栏输入URL地址。

+ +

学习这份教程之前,我需要做些什么知识准备?

+ +

你需要理解HTML,以及了解XML和CSS一些基础知识,下面几点建议需要注意:

+ + + +

基于Mozilla和Gecko平台的程序都支持XUL,例如Mozilla Firefox和Netscape6。随着时间推移XUL在语法有些不同,你可能需要使用适当的版本来进行工作。在大多例子里使用的是Mozilla 1.0或更高版本。XUL在Firefox和其它基于Mozilla浏览器中是相似的,虽然也存在一些细微的差别,例如工具栏。 该指南将最大限度介绍XUL方方面面,然而还是无法讲述所有的特征。一旦你熟悉XUL,可以使用XUL Element Reference来查找其它标签的属性特征。

+ +

+

下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/introduction_to_rdf/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/introduction_to_rdf/index.html new file mode 100644 index 0000000000..03e0c64a88 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/introduction_to_rdf/index.html @@ -0,0 +1,109 @@ +--- +title: XUL_教程/RDF介绍 +slug: Mozilla/Tech/XUL/Tutorial/Introduction_to_RDF +translation_of: Archive/Mozilla/XUL/Tutorial/Introduction_to_RDF +--- +

 

+

+

« 上一页下一页 »

+

+

 

+

    本章我们关注与RDF (资源描述框架).

+

资源描述框架

+

    我们可以使用 tree 元素呈现数据集,就像书签和邮件管理器一样。然而这样却使向 XUL 文件中直接添加数据变得很不方便。直接在XUL文件中修改书签变得十分困难。这就需要RDF 数据结构。

+

    RDF (资源描述框架)是一种用于储存像书签或邮件这样的资源的格式。其他形式的数据可以被编码为RDF,也可以有RDF创建其他形式的数据。这是 Mozilla 处理像书签、邮件、历史等的方法。Mozilla 为这些常用的数据提供了数据源,使我们很容易使用他们。

+

    你可以使用任意的RDF数据源来填充树结构,或者仅把RDF指向一个存有数据的XML文件。这使得显示含有许多行的树变得非常容易。RDF 也可以填充其他的 XUL 元素比如列表及菜单,见下一章。

+

    这里是关于RDF的一个非常简略的概述,希望看到更为详尽的内容请访问XULPlanet上的 Introduction to the RDF Model。如果你刚刚接触RDF请继续向下阅读。

+

    更多信息参见 RDF specification.

+

RDF/XML

+

    RDF 包含这数据的图表示形式。 RDF/XML 时一种用于表示RDF数据的XML语言。它包含非常简单的元素集,下面的例子显示一个简单的RDF模板。

+
<?xml version="1.0"?>
+<RDF:RDF
+  xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+  ...
+</RDF:RDF>
+
+

    与XUL头有些相似,window 元素被 RDF 元素代替。同样为RDF定义了名空间,在RDF元素中将填充一些数据。可以在Mozilla文件夹中找到一些 RDF/XML 文件的例子,他们以rdf作为后缀。

+

RDF 数据库

+

    让我们来以有RDF产生的书签列表为例。书签列表包含一系列记录,每项记录都有一系列数据相关联,比如书签标题,URL,访问日期等。

+

    把书签当作数据库来考虑,这个数据库是一个含有多个域的表格。这个列表需要分级,因为我们需要利用文件夹来分组书签。每一个域都来源与RDF数据库,都由名字相关联。名字用URI描述。

+

    例如Mozilla书签列表的名字的RUI描述如下:

+ + + + + + + + + + + + + + + + + + + + + + + +
Namehttp://home.netscape.com/NC-rdf#NameBookmark name
URLhttp://home.netscape.com/NC-rdf#URLURL to link to
Descriptionhttp://home.netscape.com/NC-rdf#DescriptionBookmark description
Last Visitedhttp://home.netscape.com/WEB-rdf#LastVisitDateDate of last visit
+

    这些是按照名空间加域名构造的。下一章,我们利用它来自动填充数据域。注意访问日期的名空间与其他的不同。

+

RDF/XML 文件样例

+

    下面是一个RDF/XML文件,有三条记录和三个域。

+
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:ANIMALS="http://www.some-fictitious-zoo.com/rdf#">
+
+  <RDF:Seq about="http://www.some-fictitious-zoo.com/all-animals">
+    <RDF:li>
+       <RDF:Description about="http://www.some-fictitious-zoo.com/mammals/lion">
+         <ANIMALS:name>Lion</ANIMALS:name>
+         <ANIMALS:species>Panthera leo</ANIMALS:species>
+         <ANIMALS:class>Mammal</ANIMALS:class>
+       </RDF:Description>
+    </RDF:li>
+    <RDF:li>
+       <RDF:Description about="http://www.some-fictitious-zoo.com/arachnids/tarantula">
+         <ANIMALS:name>Tarantula</ANIMALS:name>
+         <ANIMALS:species>Avicularia avicularia</ANIMALS:species>
+         <ANIMALS:class>Arachnid</ANIMALS:class>
+       </RDF:Description>
+    </RDF:li>
+    <RDF:li>
+       <RDF:Description about="http://www.some-fictitious-zoo.com/mammals/hippopotamus">
+         <ANIMALS:name>Hippopotamus</ANIMALS:name>
+         <ANIMALS:species>Hippopotamus amphibius</ANIMALS:species>
+         <ANIMALS:class>Mammal</ANIMALS:class>
+       </RDF:Description>
+    </RDF:li>
+  </RDF:Seq>
+</RDF:RDF>
+
+

    对每一种动物使用一条记录描述。每一个 RDF:Description 标签描述一条记录。每条记录定义了三个域:namespeciesclass。虽然没有必要让每一条记录拥有相同的域,但是最好如此。

+

    三个域都在 ANIMALS名空间下, ANIMALS名空间在RDF标签中定义。选择这个名字是因为它的意思,但完全可以选择其他名字。这里的名空间定义是有用的,因为如果使用样式表class 域可能发生冲突。

+

     Seqli 元素在列表中区分每一条记录,与HTML 列表中的定义很相似。 Seq 指明记录是有序的紧挨着的,对于无序内容使用 Bag 标签, Alt 用于指明其中的记录只能选择其一(如映射 URL)。

+

    在XUL文件中可以通过名空间和域名来引用其中的数据,在上例中,下面的URI描述其中的数据域:

+ + + + + + + + + + + + + + + +
Namehttp://www.some-fictitious-zoo.com/rdf#name
Specieshttp://www.some-fictitious-zoo.com/rdf#species
Classhttp://www.some-fictitious-zoo.com/rdf#class
+

    记下来,看看如何使用RDF来填充XUL数据。

+

+

« 上一页下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/list_controls/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/list_controls/index.html new file mode 100644 index 0000000000..27486e030b --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/list_controls/index.html @@ -0,0 +1,133 @@ +--- +title: XUL_教程/列表控件 +slug: Mozilla/Tech/XUL/Tutorial/List_Controls +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/List_Controls +--- +

+

« 上一页下一页 »

+

+

 

+

列表控件

+

列表控件用来在列表中显示许多的项目。用户可以从列表中选择一个项。

+

XUL提供两种类型的元素去创建列表,listbox元素用于创建多行的列表框,和menulist元素用于创建下拉列表框。它们的工作方法类似于在HTML中的 select元素,它们执行的功能相同,但XUL的元素包括更多的特性。

+

简单列表框使用listbox元素创建列表框,和使用listitem元素创建每个项目。例如,这个列表框有四行,每个项目使用一行。

+

例1 : Source View

+
+ 图像:lists1.png
+
<listbox>
+  <listitem label="Butter Pecan"/>
+  <listitem label="Chocolate Chip"/>
+  <listitem label="Raspberry Ripple"/>
+  <listitem label="Squash Swirl"/>
+</listbox>
+
+

如HTML中的option元素,你可以使用value为每个项指定一个值。你也可以在脚本中使用这个值。列表框会默认设置一个合适的尺寸,但你可以通过rows属性来控制尺寸。通过设置它来确定在列表框中显示的行数。如果列表包括的项超出这个值,在显示时将会出现滚动条。

+

下面这个例子演示这些不同的特性:

+

例2 : Source View

+
<listbox rows="3">
+  <listitem label="Butter Pecan" value="bpecan"/>
+  <listitem label="Chocolate Chip" value="chocchip"/>
+  <listitem label="Raspberry Ripple" value="raspripple"/>
+  <listitem label="Squash Swirl" value="squash"/>
+</listbox>
+
+

这个例子已改成一次只显示3行。已经为列表中的每个项目添加了值。列表框还有其他的一些特性,将在后面进行描述。

+

多列列表框

+

列表框也支持多列。每个单元格可以有独有的内容,即使只使用文本。当用户选择列表中的一个项目时,当前的行将被选中。你不能只选中其中的一个单元格。

+

在列表框中有两个标签可以使用。listcols元素用来对列信息进行控制,每个列指定一个listcol元素。在列表框中你将需要为每个列指定一个listcol元素。

+

listcell元素用于一行中的每个单元格。 如果你需要3列,你就需要增加3个listcell元素到每个listitem里面。要给单元格指定文本内容,替换listcell元素里面的label属性。

+

一个简单的例子,如果只有一个列,你也需要将 label属性直接地填充在listitem元素里面的listcell元素中, 看起来像前面的例子里一样。

+

下面是一个有2列和3行的列表框的例子:

+

例3 : Source View

+
<listbox>
+  <listcols>
+    <listcol/>
+    <listcol/>
+  </listcols>
+  <listitem>
+    <listcell label="George"/>
+    <listcell label="House Painter"/>
+  </listitem>
+  <listitem>
+    <listcell label="Mary Ellen"/>
+    <listcell label="Candle Maker"/>
+  </listitem>
+  <listitem>
+    <listcell label="Roger"/>
+    <listcell label="Swashbuckler"/>
+  </listitem>
+</listbox>
+
+

表头行

+

列表框一直允许使用一个特殊的表头行。 这和正常的行显示有很大不同。你可以使用它来创建列头。有两个新的元素可以使用。

+

listhead元素用于表头行,就像listitem元素用于普通行。表头行不是普通行,因此使用脚本去获取列表的首行时获得的将是表头行的下一行。

+

listheader元素用于表头行里的单元格。使用 label属性设置表头行单元格的标签。

+

这是一个带表头行的简单例子:

+

例4 : Source View

+
+ Image:morelists1.png
+
<listbox>
+
+  <listhead>
+    <listheader label="Name"/>
+    <listheader label="Occupation"/>
+  </listhead>
+
+  <listcols>
+    <listcol/>
+    <listcol flex="1"/>
+  </listcols>
+
+  <listitem>
+    <listcell label="George"/>
+    <listcell label="House Painter"/>
+  </listitem>
+  <listitem>
+    <listcell label="Mary Ellen"/>
+    <listcell label="Candle Maker"/>
+  </listitem>
+  <listitem>
+    <listcell label="Roger"/>
+    <listcell label="Swashbuckler"/>
+  </listitem>
+
+</listbox>
+
+

在这个例子中,flex属性用于制作灵活的列。这个属性将在最后一节中说明,这里它允许列进行水平扩展。你可以调整窗口的大小去查看列根据窗口而进行伸缩的效果。如果你水平缩小,表格中的标签会自动截成带省略号(...)的样子。你可以在表格或项中使用crop属性的值为none去禁止标签被截。

+

下拉列表

+

在HTML里可以使用select元素创建下拉列表。用户可以在文本框内看到一个单选并且点击箭头或其他类似按钮文本制做成不同的选项。其他的选择将会显示在一个弹出的窗口中。 XUL有一个menulist元素可以实现这种效果。它是使用在一个文本框的旁边加一个按钮。选中这个名字是因为当它被选中时会弹出一个菜单。

+

描述一个下拉列表需要三个元素。第一个是menulist 元素, 在按钮的旁边创建一个文本输入框。第二,menupopup,当按钮被点击时创建并显示弹出窗口。第三,menuitem,创建单独的选择。

+

下面的范例很好地描述了它的语法:

+

Example 5 : Source View

+
+ Image:inputs2.png
+
<menulist label="Bus">
+  <menupopup>
+    <menuitem label="Car"/>
+    <menuitem label="Taxi"/>
+    <menuitem label="Bus" selected="true"/>
+    <menuitem label="Train"/>
+  </menupopup>
+</menulist>
+
+

这个菜单列表包括了四个项,全部都使用一个menuitem 元素。要显示菜单里的项,点击菜单列表中的箭头按钮。当一个被选中,它会在菜单列表中显示为选中。selected属性用于设置哪个被默认选中。

+

可编辑的菜单列表

+

默认情况,你只可以从列表中进行选择。你不能在它上面输入你自己的文本。一个特别的菜单列表允许编辑文件框中的文本。例如,浏览器的地址输入框有一个下拉列表去选择以前输入过的地址,但你也可以输入你自己的地址。

+

创建一个可编辑的菜单列表,像下面这样添加editable 属性:

+

例6 : Source View

+
<menulist editable="true">
+  <menupopup>
+    <menuitem label="www.mozilla.org"/>
+    <menuitem label="www.xulplanet.com"/>
+    <menuitem label="www.dmoz.org"/>
+  </menupopup>
+</menulist>
+
+

这里创建的地址输入框由三个预设的选择,用户可以从中选择或者他们可以在文本框内输入一个他们自己的地址。用户输入的文本不会添加到新的选择中。因为label属性没有用在这个例子中,默认是空的。

+

在下一节我们将会学习creating progress meters

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/localization/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/localization/index.html new file mode 100644 index 0000000000..ffa7dd99de --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/localization/index.html @@ -0,0 +1,296 @@ +--- +title: 本地化 +slug: Mozilla/Tech/XUL/Tutorial/Localization +translation_of: Archive/Mozilla/XUL/Tutorial/Localization +--- +

 

+
+

« Previous Next »

+
+

  

+

 

+

XUL 和 XML 提供的实体(entities)是一个本地化的好方法。

+
+

实体

+
+ Edit section
+

    不少软件都希望将界面上的语言尽可能简单的翻译为另外的语言。通常他们会为每一种语言创建一份字符串列表,来代替在代码中进行硬编码。代码中的每一段文本都代表字符串列表中的一项, XML 提供的实体正好实现这一目的。

+

    如果你写过 HTML 代码,你应该对实体很熟悉 , 像这样的代码 &lt;&gt; 是作为“小于”和“大于”在文本中的替代出现的。XML 的语法允许你定义用户实体。你可以使用这些实体代替它实际的值,当然这个值可以是一段文本。实体可以用在任何文本应该出现的地方,包括属性。下面的例子在一个按钮中使用了实体。

+
<button label="&findLabel;"/>
+
+

    出现在按钮上的文本将是 &findLabel; 所代表的值。对每一种所要支持的语言需要创建一个文件包含对实体的定义。在英语中,&findLabel; 实体可能代表文本 "Find"。

+
+
+

DTD 文件

+
+ Edit section
+

    实体在 Document Type Definition (DTD) 文件中定义。这类文件往往用于特定 XML 文件的语法和语义的定义,当然也可以用来定义实体。在  Mozilla 的 chrome 体系中,你会在 locales 子目录中找到 DTD 文件。对应一个XUL 文件,一般会有一个 DTD 文件 (extension .dtd)。

+

    如果你查看 chrome 目录,你会看到一个针对你所用语言的压缩包 (en-US.jar 默认是英语的语言包) 。你也可能会找到多种语言的语言包:美式英语 (en-US) 、法语 (fr)等。在这些压缩包中,你会发现它保存着每个窗口的本地化文本。这种压缩包的结构与 skins 是很相似的。

+

    你可以把你定义实体的 DTD 文件放置到语言包里,一般的,你应该为每一个 XUL 文件建立一个 DTD 文件,通常使用相同的文件名但以 .dtd 作为后缀。因此对应我们的 findfile 对话框,我们需要一个 findfile.dtd 文件。

+

    对于非安装的 chrome 文件,你可以简单的把 DTD 文件放在与 XUL 相同的目录中。

+
+ 注意: 你需要将含有非 ASCII 字符的 DTD 文件的字符编码设为 UTF-8。也就是说你应该按照 UTF-8 格式 (without BOM)保存。参见 Mozilla Language Packs.
+

    一旦为你的 XUL 文件创立 DTD 文件,你应该在 XUL 文件上添加一行以声明使用 DTD 文件。否则会发生找不到实体的错误,在 XUL 文件的头部加如下一行。

+
<!DOCTYPE window SYSTEM "chrome://findfile/locale/findfile.dtd">
+
+

    这一行表示这个 URL 被当作一个 DTD 使用。在这个例子中,我们引入了我们需要的 findfile.dtd 文件,这一行通常放在 window 元素之前。

+

    你同样需要在 chrome.manifest 文件中添加本地化信息,如下:

+
locale findfile en-US locale/
+
+
+
+

申明实体

+
+ Edit section
+

    实体的申明使用如下语法:

+
<!ENTITY findLabel "Find">
+
+

    上例创建了一个名为 findLabel 值为 "Find" 的实体,这意味着在文本中的任意位置出现的 "&findLabel;" 都将会被 "Find" 替代。注意实体申明无需反斜杠结束。在不同语言的 DTD 文件中,文件使用的不同的语言替代即可。

+
日文:
+<!ENTITY findLabel "検索">
+
+

    例如,下面的文字:

+
<description value="&findLabel;"/>
+
+

被翻译为:

+
英文版:
+<description value="Find"/>
+
+日文版:
+<description value="検索"/>
+
+

    你应该为你在界面中出现的每一个标签或字符串申明一个实体,在XUL文件中不应出现任何的显示文本。

+

    补充来说你可以在任何因语言不同而不同的的地方使用实体。以 Access keys 及 keyboard shortcuts 为例。

+
 XUL
+ <menuitem label="&undo.label;" accesskey="&undo.key;"/>
+ DTD
+ <!ENTITY undo.label "Undo">
+ <!ENTITY undo.key "u">
+
+

    上面的例子使用了两个实体,一个由于 Undo 菜单项的标签,第二个用于快捷键。

+
+
+

改写 Find Files 的例子

+
+ Edit section
+

    让我们看一看如何使用DTD文件修改我们的find files 对话框并将所有文本放在一起。整个文件列在下面。

+
<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+<?xml-stylesheet href="findfile.css" type="text/css"?>
+
+<!DOCTYPE window SYSTEM "chrome://findfile/locale/findfile.dtd">
+
+<window
+  id="findfile-window"
+  title="&findWindow.title;"
+  persist="screenX screenY width height"
+  orient="horizontal"
+  onload="initSearchList()"
+  xmlns="http://www.mozilla.org/keymaster/gat...re.is.only.xul">
+
+<script src="findfile.js"/>
+
+<popupset>
+   <menupopup id="editpopup">
+     <menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;"/>
+     <menuitem label="&copyCmd.label;" accesskey="&copyCmd.accesskey;"/>
+     <menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" disabled="true"/>
+   </menupopup>
+</popupset>
+
+<keyset>
+   <key id="cut_cmd" modifiers="accel" key="&cutCmd.commandkey;"/>
+   <key id="copy_cmd" modifiers="accel" key="&copyCmd.commandkey;"/>
+   <key id="paste_cmd" modifiers="accel" key="&pasteCmd.commandkey;"/>
+   <key id="close_cmd" keycode="VK_ESCAPE" oncommand="window.close();"/>
+</keyset>
+
+<vbox flex="1">
+
+ <toolbox>
+
+  <menubar id="findfiles-menubar">
+    <menu id="file-menu" label="&fileMenu.label;"
+        accesskey="&fileMenu.accesskey;">
+      <menupopup id="file-popup">
+        <menuitem label="&openCmd.label;"
+                  accesskey="&openCmd.accesskey;"/>
+        <menuitem label="&saveCmd.label;"
+                  accesskey="&saveCmd.accesskey;"/>
+        <menuseparator/>
+        <menuitem label="&closeCmd.label;"
+                  accesskey="&closeCmd.accesskey;" key="close_cmd" oncommand="window.close();"/>
+      </menupopup>
+    </menu>
+    <menu id="edit-menu" label="&editMenu.label;"
+          accesskey="&editMenu.accesskey;">
+      <menupopup id="edit-popup">
+        <menuitem label="&cutCmd.label;"
+                  accesskey="&cutCmd.accesskey;" key="cut_cmd"/>
+        <menuitem label="&copyCmd.label;"
+                  accesskey="&copyCmd.accesskey;" key="copy_cmd"/>
+        <menuitem label="&pasteCmd.label;"
+                  accesskey="&pasteCmd.accesskey;" key="paste_cmd" disabled="true"/>
+      </menupopup>
+    </menu>
+  </menubar>
+
+  <toolbar id="findfiles-toolbar">
+    <toolbarbutton id="opensearch" label="&openCmdToolbar.label;"/>
+    <toolbarbutton id="savesearch" label="&saveCmdToolbar.label;"/>
+  </toolbar>
+ </toolbox>
+
+ <tabbox>
+  <tabs>
+    <tab label="&searchTab;" selected="true"/>
+    <tab label="&optionsTab;"/>
+  </tabs>
+
+  <tabpanels>
+
+   <tabpanel id="searchpanel" orient="vertical" context="editpopup">
+
+   <description>
+     &findDescription;
+   </description>
+
+   <spacer class="titlespace"/>
+
+   <groupbox orient="horizontal">
+     <caption label="&findCriteria;"/>
+
+     <menulist id="searchtype">
+       <menupopup>
+         <menuitem label="&type.name;"/>
+         <menuitem label="&type.size;"/>
+         <menuitem label="&type.date;"/>
+       </menupopup>
+     </menulist>
+   <spacer class="springspace"/>
+     <menulist id="searchmode">
+       <menupopup>
+         <menuitem label="&mode.is;"/>
+         <menuitem label="&mode.isnot;"/>
+       </menupopup>
+     </menulist>
+   <spacer class="springspace"/>
+
+   <menulist id="find-text" flex="1"
+             editable="true"
+             datasources="file:///mozilla/recents.rdf"
+             ref="http://www.xulplanet.com/rdf/recent/all">
+     <template>
+       <menupopup>
+         <menuitem label="rdf:http://www.xulplanet.com/rdf/recent#Label" uri="rdf:*"/>
+       </menupopup>
+     </template>
+   </menulist>
+
+   </groupbox>
+
+  </tabpanel>
+
+  <tabpanel id="optionspanel" orient="vertical">
+     <checkbox id="casecheck" label="&casesensitive;"/>
+     <checkbox id="wordscheck" label="&matchfilename;"/>
+    </tabpanel>
+
+  </tabpanels>
+ </tabbox>
+
+ <tree id="results" style="display: none;" flex="1">
+   <treecols>
+     <treecol id="name" label="&results.filename;" flex="1"/>
+     <treecol id="location" label="&results.location;" flex="2"/>
+     <treecol id="size" label="&results.size;" flex="1"/>
+   </treecols>
+
+   <treechildren>
+     <treeitem>
+       <treerow>
+         <treecell label="mozilla"/>
+         <treecell label="/usr/local"/>
+         <treecell label="&bytes.before;2520&bytes.after;"/>
+       </treerow>
+     </treeitem>
+   </treechildren>
+ </tree>
+
+ <splitter id="splitbar" resizeafter="grow" style="display: none;"/>
+
+ <spacer class="titlespace"/>
+
+ <hbox>
+   <progressmeter id="progmeter" value="50%" style="display: none;"/>
+   <spacer flex="1"/>
+   <button id="find-button" label="&button.find;"
+           oncommand="doFind()"/>
+   <button id="cancel-button" label="&button.cancel;"
+           oncommand="window.close();"/>
+ </hbox>
+</vbox>
+
+</window>
+
+

    每一个字符串均被实体引用代替。一个 DTD 文件被包含在XUL文件的开头。每一个被引用的实体必须在DTD文件中申明,如果发现引用的实体没有申明,则窗口不会显示。

+

    注意实体的名字并不重要,在上面的例子里实体的名字被分成几段来写,请你不要这样,请按照其他代码的书写习惯来写实体引用。

+

    你可能已经注意到里字符串 '2520 bytes' 被两个实体代替。这是因为在别的语言中可能会有不同的语法要求。比如,可能要求数字写在后面而把 'bytes' 写在前面。当然对于 KB 、MB 会有更复杂的顺序要求。

+

    键盘访问键及快捷键也被翻译为实体因为对不同的语言这些也会不同。

+

    下面是 DTD 文件 - findfile.dtd:

+
<!ENTITY findWindow.title "Find Files">
+<!ENTITY fileMenu.label "File">
+<!ENTITY editMenu.label "Edit">
+<!ENTITY fileMenu.accesskey "f">
+<!ENTITY editMenu.accesskey "e">
+<!ENTITY openCmd.label "Open Search...">
+<!ENTITY saveCmd.label "Save Search...">
+<!ENTITY closeCmd.label "Close">
+<!ENTITY openCmd.accesskey "o">
+<!ENTITY saveCmd.accesskey "s">
+<!ENTITY closeCmd.accesskey "c">
+<!ENTITY cutCmd.label "Cut">
+<!ENTITY copyCmd.label "Copy">
+<!ENTITY pasteCmd.label "Paste">
+<!ENTITY cutCmd.accesskey "t">
+<!ENTITY copyCmd.accesskey "c">
+<!ENTITY pasteCmd.accesskey "p">
+<!ENTITY cutCmd.commandkey "X">
+<!ENTITY copyCmd.commandkey "C">
+<!ENTITY pasteCmd.commandkey "V">
+<!ENTITY openCmdToolbar.label "Open">
+<!ENTITY saveCmdToolbar.label "Save">
+<!ENTITY searchTab "Search">
+<!ENTITY optionsTab "Options">
+<!ENTITY findDescription "Enter your search criteria below and select the Find button to begin the search.">
+<!ENTITY findCriteria "Search Criteria">
+<!ENTITY type.name "Name">
+<!ENTITY type.size "Size">
+<!ENTITY type.date "Date Modified">
+<!ENTITY mode.is "Is">
+<!ENTITY mode.isnot "Is Not">
+<!ENTITY casesensitive "Case Sensitive Search">
+<!ENTITY matchfilename "Match Entire Filename">
+<!ENTITY results.filename "Filename">
+<!ENTITY results.location "Location">
+<!ENTITY results.size "Size">
+<!ENTITY bytes.before "">
+<!ENTITY bytes.after "bytes">
+<!ENTITY button.find "Find">
+<!ENTITY button.cancel "Cancel">
+
+

    现在,为一个新语言添加文本仅需创建一个新的DTD文件。使用 chrome 系统把 DTD 文件加到另一个 locales 中,这样同一个 XUL 文件就可以使用不同的语言。

+

Find files example so far: Source

+
+
+

 

+

    下一章,看看 property files.

+

 

+
+

« Previous Next »

+
+

  

+

 

+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/manifest_files/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/manifest_files/index.html new file mode 100644 index 0000000000..10dcc5a2dd --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/manifest_files/index.html @@ -0,0 +1,113 @@ +--- +title: Manifest Files +slug: Mozilla/Tech/XUL/Tutorial/Manifest_Files +translation_of: Archive/Mozilla/XUL/Tutorial/Manifest_Files +--- +

Contents.rdf 文件

+

这部分内容,我们将了解如何将chrome和XUL文件打成包,以及为它们创建manifest文件。

+

<big></big>

+

一个包,就是一组XUL文件和定义了用户界面功能的脚本的集合,它可以直接存成一个目录,也可以打成JAR文件。包可以被安装到Mozilla里,并且可以被chrome URL 引用。一个包里面包含了多种类型的文件,这些文件也可以划分到包内的不同的子目录里。

+

<big>Manifest 文件</big>

+

manifest文件描述了包在硬盘上的物理存放位置与chrome URL的映射关系。当一个Mozilla应用启动时,它将检查chrome文件夹中的manifest文件,从而知道已经安装了哪些包。也就是说,当安装了一个新包时,你需要在应用程序的chrome目录下或者用户自己的chrome目录中加入一个新的manifest文件。一般情况下,当应用程序没有足够的权限向其目录中写入manifest文件时,才会将manifest文件放到用户自己的chrome目录中。

+

如果你想在Firefox浏览器中测试一下XUL代码的效果,只要在manifest文件中加入一行,就可以轻松实现了:

+
    +
  1. 创建一个目录. 例如, 在系统盘下创建一个目录, 就可以用 C:\testfiles
  2. +
  3. 在chrome目录下创建一个新的名为 test.manifest 的文件(实际上,文件叫什么名字并不重要,只要扩展名是.manifest就可以了),则用下面一句:
  4. +
+

content tests file:///C:/testfiles/

+
+ 这里的文件路径是指向上面创建的目录的。如果你不知道应该怎么写这个文件路径,可以在浏览器中打开那个目录,然后将地址栏里面的URL拷贝下来,就可以了。
+

好了,现在,你只需要向上面新建的那个目录中加入一些XUL文件,然后,按照chrome://tests/content/<filename> 的格式键入chrome URL,就可以看到你的成果了。当然,为了你的修改能够起作用,需要重启浏览器。如果你创建的文件没有被加载,确认一下你键入的文件路径是否是正确的。

+

manifest 文件中每一行的基本语法是:

+

content <packagename> <filepath>

+

第一个字段指明了包类型。主题包是'skin',语言地区包是'locale'。上面例子中,包名为'tests',也就意味着chrome URL中第一个部分是'tests',例如:chrome://tests/content/sample.xul。如果包名为'browser',那么chrome URL就变成chrome://browser/content/。基本语法中最后一个字段为文件所在的路径。这既可以是用file URL(译者注:如file:///c:/dir/a)表示的本地文件路径,又可以是下面我们马上要说到的jar URL表示的JAR包。在manifest文件中添加多行,可以指定多个包。

+

Firefox用到的browser.manifest文件看起来是这样的:

+
content branding jar:browser.jar!/content/branding/ xpcnativewrappers=yes
+content browser jar:browser.jar!/content/browser/ xpcnativewrappers=yes
+overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul
+overlay chrome://global/content/viewPartialSource.xul chrome://browser/content/viewSourceOverlay.xul
+overlay chrome://browser/content/pageInfo.xul chrome://pippki/content/PageInfoOverlay.xul
+
+

这里有两个包,'branding'和'browser'。此外还有三个overlay,它们使得来自不同包的内容可以组合在一起。扩展(Extension)中会大量使用overlay,因为overlay的功能是将包的用户界面与浏览器的用户界面融合在一起。

+

由于内容被打包成jar,branding和browser包中文件的路径使用了jar URL。一个jar包可以通过ZIP工具来生成。在chrome目录中的JAR文件,语法相当简单:

+

jar:<filename.jar>!/<path_in_archive>

+

browser包对应的JAR包是browser.jar,与manifest文件放在同一个chrome目录中。'content/browser'指明了在JAR压缩包中XUL的路径。若压缩包里面不含任何目录,则无需指明任何路径。在我们的例子中,压缩包里面有目录,所以这里需要指明。

+

对于上面我们建立的'tests'包,文件没有压缩到一个jar包里,所以我们用直接的文件路径来代替jar路径。这样做有利于开发——我们就不用每次在改动文件后重新打包。不过,在发布一个扩展或者应用是,为了避免安装一堆的小文件,通产都会采用打包的方式。

+

在manifest文件的最后,xpcnativewrappers=yes是一个可选的标志。JavaScript可以将网页中内置的函数替换成自己的代码。如果有xpcnativewrappers标志,这就表明在特权环境(privileged context)下的脚本不运行覆盖的版本而是运行原始自带的版本。否则,如果一个扩展试图调用一个修改版的脚本,就有可能无法正常工作甚至更糟——产生安全漏洞。添加这个标志就是为了避免类似的问题,在新的扩展中应当坚持使用,而对于那些无法兼容改变的老扩展可以不用这个标志。

+

主题(Themes)和本地化(Locales)

+

主题(Themes)和本地化(Locales)的打包语法,与内容(content)打包的语法上是相似的。如果你要提供一个主题(Themes)和本地化(Locales)时,你需要了解更多细节。例如:

+

skin browser classic/1.0 jar:classic.jar!/skin/classic/browser/
+ locale browser en-US jar:en-US.jar!/locale/browser/

+

如上面例子, 浏览器用来表示皮肤和本地化的特殊的项被加入。皮肤的名称是 'classic/1.0'。这里, 版本号被作为主体的一部分来使用, 但如果你制作自己的主题它是可选的。 Mozilla浏览器并不是用特殊方式来处理版本号;版本号仅仅作为主体名称的一部分。本地化语言是 'en-US'。映射的chrome URL应该是chrome://browser/skin和chrome://browser/locale。如果你正在创作你自己的主题或者本地化浏览器,你说要做的全部是建立一个包含着两行内容的manifest文件,再修改内容来适应你的主题(Themes)和本地化(Locales)。

+

如果必要,也能够合并全部的三种类型内容放到一个单独文件里面。这种情况通常发生在当创建一个扩展(extension/Add on)时,你也许会把所有部分放到一个文件里面。例如,我们想做一个查找文件对话框时可以这样做。在chrome目录建立一个名称为findfiles.manifest的文件。把下面的内容加到文件里面:

+
content findfiles file:///findfiles/content/
+skin findfiles classic/1.0 file:///findfiles/skin/
+locale findfiles en-US file:///findfiles/locale/
+
+

通常, 你希望目录路径内够适应你的系统(不同的文件系统,目录的结构不同)。 这种情况下, 我们仅仅建立测试路径。如果我们在发布这个包,我们应该把全部内容打包成一个JAR文件,并且修改路径。这里只是一个例子,今后可以参照这个例子来做。注意,例子里的skinhe和 locale行的第二项被指定为'findfiles'。这意味着,skin和locale可以访问和修改在第一行定义的findfiles包。

+

上述的三个路径每部分有自己的子路径,意味着你可以给每一部分建立和指定的特殊子路径。

+

安装包

+

为了安装一个应用,你将需要建立一个安装器,或者把它作为另一个应用的一部分。方式依赖于你所创建的是那种应用,一般来说不同的应用类型安装包是不同的。例如扩展,你需要建立一个名为install.rdf的安装描述文件,它描述了哪些东西被安装,以及扩展的作者和兼容性(那一个版本的浏览器,与那些程序兼容等等)。 还需要一个专用的目录结构,安装文件也许被安装到里面,并被限制在这个目录。一个扩展通常打包成一个 XPI 文件。 XPI 是XPInstall的缩写,被以Mozilla为基础的浏览器用来安装组件。类似于JAR文件,一个 XPI文件仅仅是一个带有不同的扩展的ZIP文件,所以你可以用ZIP格式兼容的工具来创建和察看 XPI 文件。

+

Firefox的扩展管理器能够自动的安装 XPI 文件内部的扩展包。他建议上传你的扩展到[Add-ons site],用户通常在这个地址寻找扩展包来安装特殊的应用。当然他们也可以从任何网址安装,不过不是Firefox默认的网址。

+

也可以用JavaScript写一个安装脚本来安装文件。这样你可以把文件复制到任何位置并执行文件管理任务。但是,用脚本安装的应用不能够被扩展管理器列出,意味着不能像其他应用那样自动地卸载。所以通常不使用脚本安装文件。

+

标准的应用,可以使用XULRunner来打包。由于与执行文件分离,可以被发布成与浏览器版本无依赖的应用。

+

创建扩展的更多信息请参照构建一个扩展XULRunner的更多信息请参照http://developer.mozilla.org/en/docs/XULRunner

+

旧版本应用程序

+

如果你为旧版本的Mozilla软件创建应用程序,比如Firefox 1.5或者Mozilla 1.8,那么这一章就很重要的。以下便是讲解怎样为先前版本建立包。如果你正在写新的扩展或者XUL应用程序的话,完全可以跳过此章。

+

1. 在你的磁盘上创建一个目录。许多人喜欢在Mozilla的chrome目录下面创建一个子目录,这样是没有必要的。这个目录可以在任何地方建立,随你喜欢。然后将你的XUL文件放置其中。

+

2. 创建一个名为contents.rdf,并放置在前面你所建立的目录中。将下面的文本框中的内容复制粘贴进新的contents.rdf文件中。这个文件是用来区别应用程序的id,它的名字,作者,版本等等的。

+ + + + + + +
+
+     <?xml version="1.0"?>
+
+
+     <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+              xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
+
+
+       <RDF:Seq about="urn:mozilla:package:root">
+         <RDF:li resource="urn:mozilla:package:myapplication"/>
+       </RDF:Seq>
+
+
+       <RDF:Description about="urn:mozilla:package:myapplication"
+               chrome:displayName="Application Title"
+               chrome:author="Author Name"
+               chrome:name="myapplication"
+               chrome:extension="true"/>
+
+
+     </RDF:RDF>
+
+
+

3. 将文本中的高亮显示部分改换成你自己的信息。比如红色部分“myapplication”应该是你应用程序的ID。你把它填写上,这个ID和你的应用程序名是相似的。用你的应用程序的题目和作者来替换文本中的蓝色高亮部分。

+

4. 如果'chrome:extension'字段为真,那么这个应用程序是Mozilla Firefox Extension(即Mozilla Firefox的扩展),而且还会在浏览器相应的附加软件窗口中见到。否则,它将不会显示。

+

5. 保存contents.rdf文件,同时确认它在你在步骤一中创建的那个文件内。

+

6. 打开<mozilla-directory>/chrome/installed-chrome.txt 这个文件,<mozilla-directory>就是Mozilla程序所安装的那个目录。记住在此之前先退出Mozilla程序。

+

7. 接下来,你必须在注册新的应用程序,这样Mozilla程序就可以找到它。在installed-chrome.txt中的最后添加新的一行,来指向你在步骤一中创建的那个目录。

+

 

+
     content,install,url,file:///main/app/
+
+
+ 用你的目录的URL来替换掉上面高亮的文字。并且必须在最后的保留一个斜杠再加一个回车。如果你不能确定那个URL是什么,那么就用Mozilla浏览器来打开该目录,并复制地址栏中所显示的URL。注意这一项必须是个目录的显示,而不是具体到文件的显示。
+

8. 删除 <mozilla-directory>/chrome/chrome.rdf 文件.

+

9. 打开 Mozilla 程序.你将可以看到任何你放到那个目录下的XUL文件,以下面的URL:chrome://applicationid/content/file.xul其中file.xul是文件名。主XUL文件应该是:applicationid.xul,你可以用以下的方式打开它chrome://applicationid/content/

+

如果你要创建skin和locale这两项的话,重复以上步骤,除了contents.rdf的形式略有不同。可以参考contents.rdf为其它应用程序所设置的细节。

+

创建一个chrome包是一件艰难的事情,诊断问题也很困难。以下是一些小小的提示,如果你遇到困难时也许用得着。

+ +
+
+ << 前页 后页 >>
diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/modifying_a_xul_interface/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/modifying_a_xul_interface/index.html new file mode 100644 index 0000000000..3ee3d691e0 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/modifying_a_xul_interface/index.html @@ -0,0 +1,118 @@ +--- +title: XUL_教程/修改XUL界面 +slug: Mozilla/Tech/XUL/Tutorial/Modifying_a_XUL_Interface +tags: + - DOM + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/Modifying_a_XUL_Interface +--- +

 

+

+

« 上一页下一页 »

+

+

    

+

DOM 提供了一系列方法来修改文档。

+

创建新元素 

+

    你可以使用文档对象的 createElement() 方法创建新元素。它有一个参数,待创建元素的标签名。可以使用元素的 setAttribute() 方法设置属性,使用 appendChild() 方法将其加入到XUL文件之中。例如下面的例子将一个按钮加入的XUL窗口中。

+

Example 1 : Source View

+
<script>
+function addButton(){
+  var aBox = document.getElementById("aBox");
+  var button = document.createElement("button");
+  button.setAttribute("label","A new Button");
+  aBox.appendChild(button);
+}
+</script>
+
+<box id="aBox" width="200">
+  <button label="Add" oncommand="addButton();"/>
+</box>
+
+ +

    createElement() 方法将为文档创建一个默认类型的元素。对于XUL 文档,通常会创建一个XUL元素。对于 HTML 文档会创建一个HTML元素,它会包含HTML元素的功能及方法。 createElementNS() 方法用于在不同的名空间创建元素。

+

     appendChild() 方法用于像一个元素添加另一个元素。有三个相关的方法: insertBefore()replaceChild()removeChild 语法如下。

+
parent.appendChild(child);
+parent.insertBefore(child, referenceChild);
+parent.replaceChild(newChild, oldChild);
+parent.removeChild(child);
+
+

    下面是这桑函数的简单说明。

+ +

    注意,以上所有的方法中的 referenceChild 及 child 必须是一个已经存在的节点否则会出错。

+

    通常你会希望移除一个现有的节点,并把它放到其他的位置。那么你没有必要先删除它。因为一个节点在同一时间只能在一个位置,插入方法总是先将节点从当前位置删除再插入新位置。这是一个在文档中移动节点的好方法。

+

拷贝节点

+

    可以使用 cloneNode() 方法复制节点。这方法复制现有的节点,你可以将新的节点放置到任何位置(原始节点不动),此方法带一个 boolean 型参数确定是否复制此元素的全部子节点。如果‘否’只复制此节点,不包含任何子节点。如果‘是’,将复制全部子节点。此函数会递归调用,如需复制树结构请传递true给函数,如下例。

+

Example 2 : Source View

+
<hbox height="400">
+  <button label="Copy"
+          oncommand="this.parentNode.appendChild(this.nextSibling.cloneNode(true));"/>
+
+  <vbox>
+    <button label="First"/>
+    <button label="Second"/>
+  </vbox>
+</hbox>
+
+

当 Copy 按钮按下:

+ +

    注意:有些元素,如listboxmenulist 提供了一些其他的修改方法,可以使用他们来代替,下一章( next section)会讨论。

+

处理基本元素

+

    像按钮,复选框,单选按钮这些XUL的注意元素可以通过脚本属性处理。这些属性列在 element reference 。一些公共的属性如 label, value, checkeddisabled 。可以根据需要来设定他们。

+

例:标签和值特性

+

    这里有一个改变按钮标签的例子。

+

Example 3 : Source View

+
<button label="Hello" oncommand="this.label = 'Goodbye';"/>
+
+

    当按钮按下时label会改变。对于有标签的元素这是通用的。比如文本框。同样的可以修改 value 属性。

+

Example 4 : Source View

+
<button label="Add" oncommand="this.nextSibling.value += '1';"/>
+<textbox/>
+
+

    当按钮按下时文本框中的内容每次加 '1' 。 nextSibling 重当前元素转移到下一个元素(textbox)。 += 用于像当前值加一个值,此处把 1 加到文本的末尾。注意此时你仍可以在文本框中输入,你也可以获取现在的标签和值属性的值,如下例。

+

Example 5 : Source View

+
<button label="Hello" oncommand="alert(this.label);"/>
+
+

标记checkbox

+

    Checkboxes 有 checked 属性可以是 check 或 uncheck 。很容易知道怎么样。下一个例子,当按钮按下时把checked属性取反 注意 labelvalue 属性是字符串,而 checked 属性是布尔值。

+

Example 6 : Source View

+
<button label="Change" oncommand="this.nextSibling.checked = !this.nextSibling.checked;"/>
+<checkbox label="Check for messages"/>
+
+

    单选按钮也可以用属性选中或取消,注意在一个组中一次只能选中一个,这无需手工操作。单选组的 selectedIndex属性用在这里 selectedIndex 属性用于获得被选中的单选按钮的序号,同样可改变它。

+

激活或无效一个元素

+

    在某些情况下一些操作将不被支持,有些内容将会无效。比如,在参数选择对话框中,能选择一系列参数但只有一项允许用户改变。下面的例子创建这样的一个界面。

+

Example 7 : Source View

+
<script>
+function updateState(){
+  var name = document.getElementById("name");
+  var sindex = document.getElementById("group").selectedIndex;
+  name.disabled = sindex == 0;
+}
+</script>
+
+<radiogroup id="group" onselect="updateState();">
+  <radio label="Random name" selected="true"/>
+  <hbox>
+    <radio label="Specify a name:"/>
+    <textbox id="name" value="Jim" disabled="true"/>
+  </hbox>
+</radiogroup>
+
+

    当单选组中的一个选择事件发生时会调用updateState() 方法。这个函数用selectedIndex 属性返回当前被选中的 radio 元素。。注意hbox中的元素也被包含在单选组中。如果第一个按钮 (序0)被选中,通过设置文本框的 disabled 属性,使文本框无效,第二个按钮被选中时,文本框又被激活了。

+

下一章将提供关于单选框和列表的更多信息。

+

+

« 上一页下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/modifying_the_default_skin/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/modifying_the_default_skin/index.html new file mode 100644 index 0000000000..5bf9abae27 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/modifying_the_default_skin/index.html @@ -0,0 +1,63 @@ +--- +title: 修改默认的皮肤 +slug: Mozilla/Tech/XUL/Tutorial/Modifying_the_Default_Skin +translation_of: Archive/Mozilla/XUL/Tutorial/Modifying_the_Default_Skin +--- +

  本章论述如何修改窗口的皮肤。

+ +
+

关于皮肤Edit section  

+ +

皮肤 是一组样式表,图片及应用于XUL的行为文件。 通过使用不同的皮肤,你可以再不改变窗口的功能的前提下改变其外观。火狐提供了一个默认的皮肤,并且你也可以下载到其他的一些。对于所有的皮肤来说XUL是一样的,只是,他们使用的样式表及图片不同罢了。

+ +

  如果你想让你的火狐窗口看起来更有个性,你可以简单的改变与之关联的样式表文件。当然可以创建一个全新的皮肤来进行进一步的修改。火狐有一个主题管理器用以修改默认的皮肤(尽管在底层代码中,人们把皮肤和用户界面叫“主题”,但实际上他们就是指一个相同的东西)。

+ +

  皮肤使用 CSS描述,允许你定义绘图元素使用的颜色、边框和图片。再文件classic.jar中包含有皮肤的定义。此包中的全局目录中有一个主样式定义,他用于定义一系列XUL元素是如何显示的。通过修改这些文件,你就能改变XUL程序的外观。。

+
+ +
+

  使用userChrome.css定制Edit section 

+ +

  在你的profile文件夹中,'chrome'文件夹下放置一个'userChrome.css' 文件你就可以通过覆盖而不是修改主题包来改变程序外观。当你创建一个profile 是就会创建这样一个文件夹,并且其中会包含一些内容。文件'userContent.css' 定制网页, 文件'userChrome.css' 定制chrome 文件。

+ +

  下例,把下面这行加到文件的底部,你会发现所有的菜单栏都变成了红色背景。

+ +
menubar {
+  background-color: red;
+}
+
+ +

  当你进行了以上修改之后,你会发现所有的火狐窗口都已改变,所有的菜单栏都是红色的。因为他改变了用户样式表,并且作用于所有的窗口。也就是说,浏览器菜单栏、书签菜单栏甚至是查找菜单栏都是红色的。

+
+ +

 

+ +

皮肤包

+ +
Edit section
+ +

  仅改变一个窗口,你需要修改与XUL文件相关的样式表。比如,为书签管理器的菜单命令增加一个红色的边框,把下面的内容加到classic.jar或你要用的其他主题包的 bookmarksManager.css 文件最后。

+ +
menuitem {
+  border: 1px solid red;
+}
+
+ +

  如果你观察一个皮肤包,你就会注意到其中包含有一系列的样式表及图片。样式表引用图片。当你希望你的程序可以改变皮肤时,你应该避免在XUL文件中直接引用图片。这是因为一个别的什么皮肤设计者可能不希望使用图片,但是如果在XUL文件中直接使用了图片,就会使他的工作变得复杂。请使用CSS间接引用图片,这样就很容易被移除。

+ +

  使用list-style-image属性,你可以为按钮、复选框或是其他什么元素设计图形,如下例:

+ +
checkbox {
+  list-style-image: url("chrome://findfile/skin/images/check-off.jpg");
+}
+
+checkbox[checked="true"] {
+  list-style-image: url("chrome://findfile/skin/images/check-on.jpg");
+}
+
+ +

  这些代码改变了与复选框相关的图形,首先复选框有一个一般的外观,然后为选中的复选框设置了一个新的图像。修饰'checked=true' makes the style only apply to elements which have their checked attributes set to true.

+ +

See also  : creating a skin for Firefox and CSS getting started

+ +

下一节,创建一个新皮肤

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/more_button_features/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/more_button_features/index.html new file mode 100644 index 0000000000..a5dc1c3a54 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/more_button_features/index.html @@ -0,0 +1,216 @@ +--- +title: 沙盒 +slug: Mozilla/Tech/XUL/Tutorial/More_Button_Features +tags: + - test + - 沙盒 + - 练习 +translation_of: Sandbox +--- +
+
+

{{EmbedLiveSample('Sample')}}

+ +

How To Edit The Sandbox For Publication

+ +

There should be a video editing add-on.

+ +

Another in this article section (maybe)

+ +

Nesting?

+ +

Hmmm, maybe this works? I don't know.

+ +

I will get there!

+ +

link testing

+ +
let there = 999999999;
+
+let stepCount = 1;
+
+while(!there) {
+  stepCount++;
+}
+//you cannot got there
+alert('I GOT THERE!!!!!!');
+ +

H4 heading

+ +
h5 indicates that you've dug too deep!
+ +

Code Sample

+ +
#include <iostream>
+
+int main()
+
+{
+
+print("This is a sample code!");
+
+return 3;
+
+}
+ +

Alert's in Javascript

+ +

HTML

+ +
<p id='test_code'>
+  Test Sample Code
+</p>
+ +

CSS

+ +
#test_code {
+  background-color: purple;
+}
+ +

JavaScript

+ +
console.log("Hi there !!");
+ +

Result

+ +

{{EmbedLiveSample('My_Alert')}}

+ +

Hello World

+ +

HTML

+ +
<input type="date">
+ +

Result

+ +

{{EmbedLiveSample('Hello_World')}}

+ +

结论

+ +

本文档提供了JavaScript中alerts---警告的基本信息

+ +

WebGL 基本原理

+ +

WebglRenderingContext的shaderSource方法非常酷!

+ +

子导航

+ + +
+
+ +
+
+

中文 (简体) 翻译:

+
+ + + +
+
+
+ +
草稿已自动保存:
+
+ +
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +

如何编辑沙盒页面的发布版本test

+ +

这里应该有一个视频编辑插件。

+ +

本文的另一个小节(大概

+ +

嵌套?

+ +

嗯, 这样能行吧? 我也不知道

+ +

我会做到的!

+ +

链接测试

+ +
let there = 999999999;
+
+let stepCount = 1;
+
+while(!there) {
+  stepCount++;
+}
+
+alert('I GOT THERE!!!!!!');
+ +

H4 标题

+ +
h5 表明你钻研的太深奥了(有么?)
+ +

代码示例

+ +
#include <iostream>
+
+int main()
+
+{
+
+print("This is a sample code!");
+
+return 3;
+
+}
+ +

我的警示

+ +

HTML

+ +
<p id='test_code'>
+  测试示例代码
+</p>
+ +

CSS

+ +
#test_code {
+  background-color: purple;
+}
+ +

JavaScript

+ +
console.log("嗨,我在这儿 !!");
+ +

结果

+ +

{{EmbedLiveSample('My_Alert')}}

+ +

大家好

+ +

本文档旨在健全科学。

+ +

WebGL基本原理

+ +

WebglRenderingContext中的shaderSource方法非常酷炫!

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/more_event_handlers/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/more_event_handlers/index.html new file mode 100644 index 0000000000..efb14f298f --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/more_event_handlers/index.html @@ -0,0 +1,183 @@ +--- +title: 其他事件处理器 +slug: Mozilla/Tech/XUL/Tutorial/More_Event_Handlers +translation_of: Archive/Mozilla/XUL/Tutorial/More_Event_Handlers +--- +
+

更多关于事件处理

+
+
+
+

 

+

 

+
+

« Previous Next »

+
+

  

+

 

+

    在这一章,详细讨论事件对象,并引入一些新事件。

+
+

事件对象

+
+ Edit section
+

    每一个事件处理函数都包含一个保存这事件( event )对象的参数。在以属性的发生添加的事件监听器里也有一个隐含的事件对象(event)被当作参数传递到事件监听器中。在 addEventListener 的形式中,事件监听器的第一个参数就是事件对象。实践大学有一系列的属性,完整列表参见  reference

+

    我们已经在上一章知道了target 属性,它保存这产生事件元素的一个引用。一个相似的 currentTarget 属性当前处理此事件的元素,下面的例子 currentTarget 总是 vbox,而 target 可能是不同的元素, button 或 checkbox。

+

Example 1  : Source View

+
<vbox oncommand="alert(event.currentTarget.tagName);">
+  <button label="OK"/>
+  <checkbox label="Show images"/>
+</vbox>
+
+
+

停止事件传播

+
+ Edit section
+

    一旦你处理一个事件,无论事件传播到什么程度,你都希望停止事件继续向下传播。因为添加事件监听器的方式不同有以下两种方式停止事件传播。

+

    由于路由阶段先于返回阶段发生所以路由监听器会先于返回监听器触发。如果路由阶段停止事件传播,那么其后的路由监听器及所有返回监听器都不会触发。手动停止事件对象传播使用 stopPropagation 方法,如下例。

+

Example 2  : Source View

+
<hbox id="outerbox">
+  <button id="okbutton" label="OK"/>
+</hbox>
+
+<script>
+function buttonPressed(event){
+  alert('Button was pressed!');
+}
+
+function boxPressed(event){
+  alert('Box was pressed!');
+  event.stopPropagation();
+}
+
+var button = document.getElementById("okbutton");
+button.addEventListener('command',buttonPressed,true);
+
+var outerbox = document.getElementById("outerbox");
+outerbox.addEventListener('command',boxPressed,true);
+</script>
+
+

    这里分别在按钮和box上添加事件监听器,在调用box的监听器中使用了 stopPropagation 方法,因此按钮的监听器永远不会被调用。如果去掉此命令两个监听器的显示都会出现。

+
+
+

阻止默认响应

+
+ Edit section
+

    如果没有注册事件处理,那么当完成路由及返回后,元素会以一种默认的方式对事件作出响应。这种默认响应依赖于元素的定义。比如, 'popupshowing' 事件在快捷菜单显示之前被发送。默认的响应就是显示快捷菜单。如果默认的响应被阻止,那么快捷菜单就不会显示。默认的响应可以使用事件对象的 preventDefault 方法阻止,如下例。

+

Example 3  : Source View

+
<button label="Types" type="menu">
+  <menupopup onpopupshowing="event.preventDefault();">
+    <menuitem label="Glass"/>
+    <menuitem label="Plastic"/>
+  </menupopup>
+</button>
+
+

     另一种方式, 对于以属性形式使用的可以在代码中直接返回 false 。 注意阻止默认响应不同于 stopPropagation 方法,即使默认响应被阻止,事件依然会传播下去。同样的,定义 stopPropagation 方法也不会阻止默认响应。如果需要,必须同时调用。

+

    注意一旦传播或默认调用被阻止,都不可恢复。

+

    下面的几章列出可能用到的一些事件,一个完整的列表在这里 XULPlanet event reference

+
+
+
+

鼠标事件

+
+ Edit section
+

    这里的一些事件用来描述鼠标动作,简单的描述如下:

+
+
+ click 
+
+ 当鼠标键在一个元素上按下并释放后调用。
+
+
+
+ dblclick 
+
+ 当鼠标双击时调用。
+
+
+
+ mousedown 
+
+ 当鼠标键在一个元素上按下时调用,事件处理会被立即调用,甚至在鼠标键释放之前。
+
+
+
+ mouseup 
+
+ 当鼠标键在一个元素上释放时调用。
+
+
+
+ mouseover 
+
+ 当鼠标移动到一个元素之上时调用,你可以使用它来高亮显示该元素,然而CSS提供了一个方案自动实现它,所以你可能不会使用它,当然你也可以在状态栏显示一些提示信息。
+
+
+
+ mousemove 
+
+ 当鼠标在一个元素上移动时调用,在移动过程中可能会多次调用事件处理,请务必避免冗长,复杂操作。
+
+
+
+ mouseout 
+
+ 当指针移除元素时调用。你可以将该元素取消高亮或移除状态栏提示。
+
+

    也有一些与拖动相关的事件,当用户按下鼠标键并移动鼠标时产生,这一部分参见 Drag and Drop.

+
+

鼠标键事件属性

+
+ Edit section
+

    当一个鼠标键事件产生,一系列附件属性也随之产生用以描述哪个鼠标键被按下及鼠标指针的位置。事件的 button 可以用于确定哪个按键被按下。0 代表左键,1 代表中键 ,2代表右键。如果鼠标设置不同,值也不同。

+

    detail 保存着鼠标键被短时间内快速点击的次数。这允许你检查这是一次单击,双击还是三击。当然如果你希望检查双击你可以使用 dblclick 事件代替。一旦第一次点击开始 click 事件就会触发,第二次点击会再触发一次,第三次又一次。但 dblclick 事件仅在双击发生时触发。

+

     buttondetail 仅支持与鼠标键相关的事件,对鼠标移动事件无效。对于鼠标移动事件这两个值均为0。

+
+
+

鼠标位置事件属性

+
+ Edit section
+

    所以的鼠标事件都提供事件发生时鼠标的坐标位置。有两个坐标系统。其一是 screenXscreenY 属性他们是基于屏幕左上角的。另一个是 clientXclientY 他们是相对于文件左上角的。这里有一个显示当前鼠标位置的例子。

+

Example 4  : Source View

+
<script>
+
+function updateMouseCoordinates(e){
+  var text = "X:" + e.clientX + " Y:" + e.clientY;
+  document.getElementById("xy").value = text;
+}
+</script>
+
+<label id="xy"/>
+<hbox width="400" height="400" onmousemove="updateMouseCoordinates(event);"/>
+
+

    在这个例子里,box 的尺寸被准确设定,这样更容易看出结果。事件处理器得到 clientXclientY 属性并根据他们创建一个字符串。这个字符串又被设置成为 label.value 的值。注意事件对象必须作为参数传递给updateMouseCoordinates 函数。如果快速的在剥削的边缘上移动鼠标,你可能会发现坐标并不会准确的停到 400。这是因为 mousemove 事件触发的间隔取决于鼠标移动的速度。因为当鼠标移动过一段距离后新的事件才触发,因为发送鼠标每一像素的移动是十分没有效率的。

+
+
+

元素相关坐标

+
+ Edit section
+

    你经常想知道事件发生时对元素的坐标而非对于这个窗口。这时你可以使用减法来计算,示例如下。

+
var element = event.target;
+var elementX = event.clientX - element.boxObject.x;
+var elementY = event.clientY - element.boxObject.y;
+
+

      XUL 元素有一个 box 对象可以通过 boxObject 属性获得。在后一章我们会学习更多相关内容,但记住它保存着如何显示元素包括元素的x,y 位置。在这个例子中,这些坐标被从事件坐标中减去,这样就得到了事件相对于元素的坐标。

+
+
+
+

加载事件

+
+ Edit section
+

    一旦XUL文件加载完成 load 事件就会被发送到文件 ( window 标记),此时正是内容显示之前。这个事件通常被用于初始化操作及完成一些任务使得用户可以使用窗口。你可以通过调用一个顶层的脚本函数来使用这一事件处理以上这些事情。这是因为XUL文件为完全加载,一些事情可能会处理出错。使用 load 事件,在 window 标记处放置 onload 属性,调用处理加载事件的处理器来完成必要的界面初始化。

+

    也有unload 事件,它当窗口关闭时被调用,或者作为浏览器的内容时,页面换为另一URL 时调用。你可以使用这一事件保存任何改变的信息。

+


+      接下来我们看看如何添加键盘快捷方式( keyboard shortcuts).

+

 

+
+

« Previous Next »

+
+

  

+

 

+
+
+
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/more_menu_features/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/more_menu_features/index.html new file mode 100644 index 0000000000..30cc1b3046 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/more_menu_features/index.html @@ -0,0 +1,108 @@ +--- +title: XUL_教程/更多菜单特性 +slug: Mozilla/Tech/XUL/Tutorial/More_Menu_Features +tags: + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial/More_Menu_Features +--- +

 

+

+

« 上一页下一页 »

+

+

在本节中,我们来学习如何创建子菜单和check菜单。

+

创建子菜单

+

使用已存在元素可以在其它菜单(递归菜单)中创建子菜单。记住可以在menupopup中放置任意元素。我们已经学过在menuseparators中放置menuitems。但是,还可以通过在menupopup元素中简单的放置menu元素来创建子菜单。这样也可以运行,因为菜单元素即使不直接放在菜单栏里面它也是有效的。下面的示例在 文件 菜单中创建了一个简单的子菜单:

+

Example 1 : Source View

+
+ Image:menubar-ex3.png
+
<toolbox flex="1">
+  <menubar id="sample-menubar">
+    <menu id="file-menu" label="File">
+      <menupopup id="file-popup">
+        <menu id="new-menu" label="New">
+          <menupopup id="new-popup">
+            <menuitem label="Window"/>
+            <menuitem label="Message"/>
+          </menupopup>
+        </menu>
+        <menuitem label="Open"/>
+        <menuitem label="Save"/>
+        <menuseparator/>
+        <menuitem label="Exit"/>
+      </menupopup>
+    </menu>
+  </menubar>
+</toolbox>
+
+
+

在我们的 查找文件 示例中加入菜单

+

让我们在查找文件对话框中加入菜单。我们仅加入少量简单的命令至 文件 菜单和 编辑 菜单中。这与上面示例类似。

+
<toolbox>
+
+ <menubar id="findfiles-menubar">
+  <menu id="file-menu" label="File" accesskey="f">
+    <menupopup id="file-popup">
+      <menuitem label="Open Search..." accesskey="o"/>
+      <menuitem label="Save Search..." accesskey="s"/>
+      <menuseparator/>
+      <menuitem label="Close" accesskey="c"/>
+    </menupopup>
+  </menu>
+  <menu id="edit-menu" label="Edit" accesskey="e">
+    <menupopup id="edit-popup">
+      <menuitem label="Cut" accesskey="t"/>
+      <menuitem label="Copy" accesskey="c"/>
+      <menuitem label="Paste" accesskey="p" disabled="true"/>
+    </menupopup>
+  </menu>
+ </menubar>
+
+<toolbar id="findfiles-toolbar>
+
+
+ Image:menubar1.png
+

在此我们已经加入了两个菜单以及一些不同的菜单命令。注意菜单栏是如何放置在toolbox内的。在 打开搜索 和 保存搜索 后面的三个点通常提示用户本命令操作会打开一个对话框。每个菜单和菜单项已经加入了访问快捷键。在图中可以看到菜单标签内的字母已经被打上了下划线。而 粘贴 命令在此被禁止。我们假定没有什么可以用来粘贴。

+

Our Find files example so far : Source View

+
+

给菜单加入勾选(check)标记

+

许多应用程序的菜单项都有check标记。例如,许可特性在命令里面会有一个check,而禁止特征则没有check在里面。当用户选择菜单后,check状态就进行了切换。你也可以在菜单项上创建radio按钮。

+

check创建类似于checkbox元素和radio元素。包括了两个属性的使用:type标识check的类型,而name标识同在一起的组命令。下面的示例创建一个带有check项的菜单。

+

Example 2 : Source View

+
<toolbox>
+  <menubar id="options-menubar">
+    <menu id="options_menu" label="Options">
+      <menupopup>
+        <menuitem id="backups" label="Make Backups" type="checkbox"/>
+        <menuitem id="backups" label="Email Administrator" type="checkbox" checked="true"/>
+      </menupopup>
+    </menu>
+  </menubar>
+</toolbox>
+
+

加入的type属性用来标识菜单项是可以check的。通过设置checkbox的值,通过选择菜单项,使它被勾选或取消勾选。

+

带有radio标记的菜单

+

除标准check菜单外,还可以通过设置type的值为radio来创建radio风格的check型菜单。radio风格的check菜单用于在一组目录项中仅选择一项的时候。例如在一个菜单中每次只能选取一个生效的情况。当选取另外一项时,前面的选择项就会自动取消选择。

+

为了将一组菜单项放置在一起,需要将每一项的name属性设置为一样,就会形成一个菜单组。示例如下:

+

Example 3 : Source View

+
<toolbox>
+  <menubar id="planets-menubar">
+    <menu id="planet-menu" label="Planet">
+      <menupopup>
+        <menuitem id="jupiter" label="Jupiter" type="radio" name="ringed"/>
+        <menuitem id="saturn" label="Saturn" type="radio" name="ringed" checked="true"/>
+        <menuitem id="uranus" label="Uranus" type="radio" name="ringed"/>
+        <menuseparator/>
+        <menuitem id="earth" label="Earth" type="radio" name="inhabited" checked="true"/>
+        <menuitem id="moon" label="Moon" type="radio" name="inhabited"/>
+      </menupopup>
+    </menu>
+  </menubar>
+</toolbox>
+
+

试一下这个示例,可以发现前三个菜单项只有一个可以被勾选。它们被聚为一组,因为他们的name属性值相同。最后一个菜单项--Earth,一个radio按钮,由于拥有不同的name属性值,因此不是这个菜单组的一部分。

+

当然,聚集在一组中的项只能放置在相同的菜单中。虽然将它们相邻的放在一起比分开放要直观得多,但在菜单中并没有必要将它们放在一起。

+

下一回,我们将学习如何创建弹出菜单

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/more_wizards/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/more_wizards/index.html new file mode 100644 index 0000000000..48648bb971 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/more_wizards/index.html @@ -0,0 +1,64 @@ +--- +title: More Wizards +slug: Mozilla/Tech/XUL/Tutorial/More_Wizards +translation_of: Archive/Mozilla/XUL/Tutorial/More_Wizards +--- +
+
+

This section describes some additional features of wizards.

+

More Complex Wizard Navigation

+

Normally, a wizard displays each wizardpage in the order that you place them in the XUL file. In some cases however, you may want to have different pages of the wizard appear depending on what the user selects in earlier pages.

+

In this case, place a pageid attribute on each of the pages. This should be set to an identifier for each page. Then, to navigate to a page, use one of two methods:

+
    +
  1. Set the next attribute on each page to the page ID of the next page to go to. You can change these attributes as needed to navigate to different pages.
  2. +
  3. Call the wizard's goTo() method. It takes one argument, the page ID of a page to go to. You might call this method in the onpageadvanced or onwizardnext handlers. Remember to return false in this case, because you have already changed the page yourself. Note that the goTo() method, because it causes a page change, will fire the events again, so you'll have to make sure you handle that case.
  4. +
+

For example, here are a set of wizard pages (the inner content has been omitted):

+
<wizardpage pageid="type" next="font">
+<wizardpage pageid="font" next="done">
+<wizardpage pageid="color" next="done">
+<wizardpage pageid="done">
+ +

A script will adjust the next attributes as necessary to go to the page with the page ID color when needed.

+

Wizard Functions

+

The wizard works much like a tabbed panel, except that the tabs are not displayed and the user navigates between pages by using the buttons along the bottom. Because all of the pages are part of the same file, all of the values of the fields on all pages will be remembered. Thus, you do not have to load and save information between pages.

+

However, you may want to do some validation of each field on each page. For this, use the handlers described in the previous section. If a field is invalid, you might display an alert. In some cases, it would be more convenient to disable the Next button until valid input has been entered.

+

The wizard has a property canAdvance, which can be set to true to indicate that the Next button should be enabled. If set to false, the Next button is disabled. You can change the property when invalid or valid data has been entered.

+

In the following example, the user must enter a secret code into a textbox on the first page of the wizard. The function checkCode() is called whenever the first page is shown as indicated by the onpageshow attribute. It is also called whenever a key is pressed in the textbox, to determine whether the Next button should be enabled again.

+

Wizard example

+

Source

+
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<wizard id="theWizard" title="Secret Code Wizard"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script>
+function checkCode(){
+  document.getElementById('theWizard').canAdvance = (document.getElementById('secretCode').value == "cabbage");
+}
+</script>
+
+  <wizardpage onpageshow="checkCode(); return true;">
+       <label value="Enter the secret code:"/>
+       <textbox id="secretCode" onkeyup="checkCode();"/>
+  </wizardpage>
+
+  <wizardpage>
+       <label value="That is the correct secret code."/>
+  </wizardpage>
+
+</wizard>
+

There is also a corresponding canRewind property that you can use to enable or disable the Back button. Both properties are adjusted automatically as you switch pages. Thus, the Back button will be disabled on the first page so you don't have to set it yourself.

+

Another useful property of the wizard is currentPage, which holds a reference to the currently displayed wizardpage. You can also modify the current page by changing this property. If you do change it, the various page change events will still be fired.

+

Next, we'll see how to use overlays to handle common content.

+
+
diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/numeric_controls/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/numeric_controls/index.html new file mode 100644 index 0000000000..310abf97a4 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/numeric_controls/index.html @@ -0,0 +1,78 @@ +--- +title: 数值控件 +slug: Mozilla/Tech/XUL/Tutorial/Numeric_Controls +translation_of: Archive/Mozilla/XUL/Tutorial/Numeric_Controls +--- +

+

« 上一页下一页 »

+

+

+

XUL有两种输入数值或者范围的元素,两种输入日期和时间的元素。这些元素仅适用于Firefox 3以及后续版本。

+

XUL has two elements used for the entry of numeric values or ranges, and well as two elements for entering dates and times. These elements are only available in Firefox 3 and later.

+

数值域Number Fields

+

textbox元素也可以用于输入数值,只要设置type属性的值为number即可。这种类型的textbox可以仅用于输入数字而会忽略输入的其他类型字符。另外,textbox一侧添加了上下箭头,允许用户增减输入的值。

+

A textbox may be used for entering numbers by setting the value of the type attribute to the value number. This type of textbox may only be used to enter numbers. Other characters are not allowed and are just ignored if typed. In addition, arrow buttons appear beside the textbox to allow the user to cycle through the values.

+
+ Image:Controlguide-textbox-number.gif
+

和其他类型的textbox一样,可以通过value属性指定默认值。自然,这个值应该是一个数值。另外,可以通过min属性和max属性指定元素的最小和最大值。如果指定了最小和最大值,你就设定了textbox可以输入的值域。如果用户输入了一个超出上下界的值,它会自动取最大值或最小值代替。例如,下面的数值类型textbox的值域是1到20。

+

As with other textboxes, the default value can be specified with the value attribute. Naturally, this value should be a number. However, the minimum and maximum values can also be specified using the min and max attributes. If these are set, you can control the range of values that the textbox may be set to. If the user enters a value less or greater than this value, it will be reset to the minimum or maximum value as necessary. For instance, the following numeric textbox has a range between 1 and 20.

+
<textbox type="number" min="1" max="20"/>
+
+

由于没有指定默认值,元素默认取值1,即最小值。设置min属性为1表明元素的最小可能值是1,同时设置max属性为20表明最大可能值是20。如果没有设置最小值,那么默认是0。max属性默认是Infinity,即最大值没有限制。

+

As the default value isn't specified, it will default to 1, the minimum value. The min attribute is set to 1 to indicate a minimum possible value of 1 and the max attribute is set to 20 to indiciate a maximum possible value of 20. If the minimum value is not specified, it has a default value of 0. The maximum value defaults to the special value Infinity which means that there is no limit.

+

其他数值型textbox属性Other numeric textbox attributes

+

increment属性指定当点击箭头时数值的改变量。默认值是1,当然可以设置一个更大的值来加大改变量。例如,下面的例子设置为以10的倍数改变值。

+

The increment attribute may be used to specify by how much the value changes when the arrows are pressed. The default value is 1, but specifying a different value allows the number to change by a larger amount. For instance, the following example steps in multiples of 10.

+
<textbox type="number" increment="10" max="100"/>
+
+

这个textbox从0到100,依次取10的倍数。由于没有指定min属性,默认是0。注意,用户仍然可以直接输入其他值。increment属性只会影响到上下箭头。当textbox有焦点时,用户可以通过上箭头增加值,用下箭头减小值。

+

This textbox steps in multiples of 10 from 0 to 100. Since the min attribute was not specified, it defaults to 0. Note that the user can still enter other values if they are typed in. The increment attribute only affects the arrow buttons. The user may also increment or decrement the value using this increment by using the up and down cursor keys while the textbox is focused.

+

decimalplaces属性表明需要显示的小数位数。默认值是0,表明只显示整数部分。指定其他值则可用于显示小数。

+

The decimalplaces attribute indicates how many decimal places to show. The default value is 0, which means show integers only. However a different value may be used to show decimal values.

+
<textbox type="number" decimalplaces="2"/>
+
+

在这个例子中,textbox将显示小数点后两位数字。小数位数多于两位的数值会被舍入到两位小数。

+

In this example, two digits right of the decimal point are shown. Values with additional fractional digits are rounded to two digits.

+

滑块Scales

+

scale元素也可以用来从一个区间中选择值。和textbox不同的是滑轨代替了文本框。用户可以拖动滑轨上的滑块来调整值。

+

A scale element may also be used to select from a range of values. Instead of a textbox however, a sliding scale is used. The user may drag the thumb of the scale to adjust the value.

+
+ Image:Controlguide-scale.gif
+

Scale与textbox有很多相同的属性:value, min, max and increment,使用方法也类似。Scale并不实际显示数值,但这个值可能在脚本中用到。当值改变时,Scale将触发change事件。

+

Many of the same attributes as a numeric textbox may be used with a scale: value, min, max and increment may all be used in a similar fashion. The scale does not actually show the value as a number, but it may be used in a script. A scale will fire a change event whenever the scales's value is modified.

+
<scale value="40" min="1" max="50"/>
+
+

这个例子设置了一个默认值是40,值域是1到50的Scale元素。

+

This scale defaults to a value of 40 and has a range between 1 and 50.

+

数值型textbox一般应用于数值对用户而言很重要的情况,例如需要用户输入天数或者文件的最大大小。而Scale则应该用于实际值对用户不那么重要,只要用户能改变它就可以的情况。例如调整音量或者缩放。

+

A numeric textbox would normally be used when the value was important to the user, for instance, a field to enter a number of days, or the maximum size of a file. A scale would be used when the actual value isn't important, just that sliding the scale decreases or increases a state. For instance, a volume slider or a zoom level.

+

Scale元素的默认布局是小值在左,大值在右,水平放置。可以通过改变orient属性和dir属性修改。

+

The default arrangement of a scale is horizontal with lower values to the left and higher values to the right. However, you can change this orientation with the orient and dir attributes.

+
<scale orient="vertical" dir="reverse"/>
+
+

这个例子设置Scale垂直显示,且小值在下,大值在上。

+

This scale will be shown vertical with lower values at the bottom and higher values at the top.

+

日期时间输入域Date and Time Entry Fields

+

datepicker元素和timepicker元素用于用户输入日期和时间。他们会显示一组数值textbox用于输入日期和时间的各部分。

+

The datepicker and timepicker elements may be used to allow the user to enter dates and times. When used, they display a set of numeric textboxes to enter each of the components of the date or time.

+
<datepicker value="2004-03-24"/>
+<timepicker value="15:30:00"/>
+
+
+ Image:Controlguide-timepicker.gif
+

value属性用于设置默认值;如果没有显示指定,则初始化为当前日期或时间。属性值的格式严格按照例子所示,日期为YYYY-MM-DD,时间是HH:MM:SS(也可以省去秒以及前面的冒号)。

+

The value attribute is used to set the default value; if this attribute is omitted, the field will be initially set to the current date or time. The format of the attribute is exactly as above, that is dates are of the form YYYY/MM/DD and times are of the form HH:MM:SS (although the seconds and the accompanying colon may be omitted).

+

这两个元素保证用户输入一个有效的日期或者时间,因此你就不用再自己校验用户输入的日是不是大于当月的总天数以及闰年等等。

+

These two elements ensure that the user enters a value date or time. This way, you do not have to check for valid dates, ensure that the day isn't greater than the number of days in the month, handle leap years, and so forth.

+

timepicker元素只有一种样式,而datepicker元素有三种不同的样式。默认样式是显示三个输入域分别对应年月日。type属性用于选择另外两种样式。grid样式效果如下。

+

While the timepicker only comes is one style, the datepicker has three different variations. The default style shows three fields for entering the year, month and date. The type attribute may be used to select the other two. Using a value of grid uses a calendar grid, as shown in the image below.

+

Image:Controlsguide-datepicker-grid.png

+

你也可以使用popup样式,该样式结合了另两种,也有三个输入域用于输入年月日,同时提供一个下拉按钮,用于显示日历供用户选择一天。

+

You can also use the value popup which creates a combination of the two types. This type has three fields for entering the year, month and date, as well as a dropdown button for displaying a popup calendar grid for selecting a day.

+
<datepicker type="popup"/>
+
+

+

« 上一页下一页 »

+

+

 

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/popup_menus/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/popup_menus/index.html new file mode 100644 index 0000000000..026ec62f83 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/popup_menus/index.html @@ -0,0 +1,6 @@ +--- +title: 弹出菜单 +slug: Mozilla/Tech/XUL/Tutorial/Popup_Menus +translation_of: Archive/Mozilla/XUL/Tutorial/Popup_Menus +--- +

[fd]

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/progress_meters/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/progress_meters/index.html new file mode 100644 index 0000000000..bacf39b352 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/progress_meters/index.html @@ -0,0 +1,58 @@ +--- +title: XUL_教程/进度条 +slug: Mozilla/Tech/XUL/Tutorial/Progress_Meters +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/Progress_Meters +--- +

+

« 上一页下一页 »

+

+

 

+

添加一个进度条

+

进度条是条状的,它用来指示一个任务完成了多少。你通常可以在当下载文件或当执行一个很长的操作时看到它。XUL有一个progressmeter元素可以用来创建这些。有两种类型的进度条: 确定的和不确定的。

+

确定的进度条可以用在当你已经知道完成某个操作的时间长度时。进度条将会被往上填充,并且在充 满时,操作刚好完成。这会用在文件的长度已经知道的下载文件对话框。

+

不确定进度条会用于当你不知道一个操作的时间长度的情况。进度条是动态的就像一个不停循环移动的杆或一个可调整的框,发生在平台和外观被使用。

+

确定的进度条: Image:prog-det.png

+

不确定的进度条: Image:prog-udet.png

+

进度条的语法如下:

+
<progressmeter
+    id="identifier"
+    mode="determined"
+    value="50%"/>
+
+

属性如下:

+
+
+ id 
+
+ 进度条的唯一标识符。
+
+ mode
+
+ 进度条的类型。如果这里设置为determined,进度条就是确定型进行度,在任务完成时在填满。如果这里设置为undetermined,这个进度条就是不确定型进度条,用于当你不知道花费时间的长度时。如果不指定这个属性默认值为确定型。
+
+ value 
+
+ 当前进度条的尺度值。你只能在确定型进度条中使用这个属性。这个值可以设成从0%到100%的百分值。这个值可以在任务结束时由脚本来改变。
+
+
+
文件查找的例子
+

让我们添加一个进度条到我们文件查找的对话框吧。我们应该使用不确定的进度条因为我们不知道能搜索到多少文件或者要多久才能搜索完成。然而,现在我们将要增加一个普通的因为动态的可以避免在开发期间的困恼。 进度条仅显示在搜索过程中。我们将在后面的脚本中对它进行开合控制。

+
<hbox>
+
+  <progressmeter value="50%" style="margin: 4px;"/>
+
+  <spacer flex="1"/>
+</hbox>
+
+

值被设成50%因此我们能在窗口上看到尺度。边缘被设成4像素因此它会与窗口的边缘分开。最开始,我们只希望进度条被显示在搜索开始时。脚本会在需要时显示和隐藏它。

+

例子太长了。 Source View

+

Image:progress1.png

+

 

+
+

在下一节,我们将学习如何在窗口增加HTML的附加元素

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/property_files/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/property_files/index.html new file mode 100644 index 0000000000..a5800e69f9 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/property_files/index.html @@ -0,0 +1,97 @@ +--- +title: 属性文件 +slug: Mozilla/Tech/XUL/Tutorial/Property_Files +translation_of: Archive/Mozilla/XUL/Tutorial/Property_Files +--- +
+
+

 

+

    在脚本中,不能使用实体,用属性文件代替。

+

 

+
+

属性

+
+ Edit section
+

    当你在XUL文件中使用DTD文件是恰当的。然而,脚本不解析实体。也就是说,如果你希望在脚本中显示信息而且你不知道到底要显示什么,请使用属性文件

+

    一个属性文件包含一系列字符串。你可以在DTD文件旁边找到属性文件(.properties后缀)。属性按照以下语法定义 name=value。实例如下。

+
notFoundAlert=No files were found matching the criteria.
+deleteAlert=Click OK to have all your files deleted.
+resultMessage=%2$S files found in the %1$S directory.
+
+

    上例中,属性文件包含桑属性,可以由脚本读取显示给用户。

+
+
+

Stringbundles

+
+ Edit section
+

   你可以写一段代码手动来读取属性,而在XUL中有一个 stringbundle 元素来帮你做。这个元素有一系列函数有属性文件中获取属性并得到本地化信息。这个元素有属性文件读取内容并为你建立一个属性列表。你可以通过名字来查找属性。

+
<stringbundleset id="strbundles">
+<stringbundle id="strings" src="strings.properties"/>
+</stringbundleset>
+
+

    这个元素会从与该XUL文件系统的目录中读取名为 'strings.properties'的文件。像其他非显示元素一样你可以使用一个 stringbundleset 来包含所以的stringbundle

+
+

stringbundle获取字符串

+
+ Edit section
+

     stringbundle 元素有一系列方法。首先是 getString 用于脚本读取字符串。

+
var strbundle = document.getElementById("strings");
+var nofilesfound=strbundle.getString("notFoundAlert");
+
+alert(nofilesfound);
+
+
    +
  • 本例首先使用 id 获得字符串束的一个引用
  • +
  • 然后在属性文件中查找 'notFoundAlert' 字符串 getString() 函数返回字符串的值或 null (字符串不存在)。
  • +
  • 最后把职工文本显示在提示框里。
  • +
+
+
+

文本格式

+
+ Edit section
+

    getFormattedString()方法也根据名字从文本束中查找字符串,此外会按照格式控制代码 (如 %S) 将其后给出的数组内容替换入字符串。

+
var dir = "/usr/local/document";
+var count = 10;
+
+var strbundle = document.getElementById("strings");
+var result = strbundle.getFormattedString("resultMessage", [ dir, count ]);
+
+alert(result);
+
+

    本例显示如下。

+
10 files found in the /usr/local/document directory.
+

    你会注意到格式化代码 %1$S%2$S被使用,替换顺序也和在数组中的不同。格式化代码 %n$S 直接描述替换参数的位置。尽管在不同语言中词序可能不同通过 getFormattedString()描述的顺序可以被写入属性文件。

+
+
+
+

非ASCII码的换码符

+
+ Edit section
+

    (这可能不再正确:在 Localizing extension descriptions中说 “使用 UTF-8 编码(而非 BOM) 保证外文正确显示。” UTF-8 编码文本有效, 换码符同样有用。一些新想法的引入会更有用。)

+

    尽管大多数语言使用非ASCII字符集。属性文件只能使用ASCII字符集编制。然而,属性文件支持其他字符的换码形式: \uXXXX 这里的 XXXX 是字符码,因此,你的属性文件可以包含非ASCII字符,不过你需要把他们转换为换码形式。你可以使用 Sun's Java Development Kit (JDK)的 native2ascii 命令来完成它。

+

Gecko 1.8.x (or later) 支持属性文件以 UTF-8编码。你可以直接写入非ASCII字符。

+


+ 下一章,我们将讨论 XBL,它用于定义元素的行为( behavior of an element.)

+

 

+
+

« Previous Next »

+
+

  

+

 

+
+
+
+
+
+

Retrieved from "https://developer.mozilla.org/En/XUL_Tutorial/Property_Files"

+
+ +

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/rdf_datasources/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/rdf_datasources/index.html new file mode 100644 index 0000000000..b4d4c51238 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/rdf_datasources/index.html @@ -0,0 +1,267 @@ +--- +title: RDF Datasources +slug: Mozilla/Tech/XUL/Tutorial/RDF_Datasources +translation_of: Archive/Mozilla/XUL/Tutorial/RDF_Datasources +--- +

 

+

+

« 上一页下一页 »

+

+

Here, we'll look at additional datasources and how to use your own RDF files as datasources.

+

Other Mozilla Datasources

+

Mozilla provides a number of other built-in datasources. Some of them are listed here with a few examples. They work very similarly to the bookmarks, although the fields will be different in each case.

+

The History List

+

The history datasource provides access to the user's history list which is the list of URLs the user has visited recently. The resource can be referred to using rdf:history as the datasource. The table below shows the resources (or fields) that you can retrieve from the history datasource. Put the URL values below where you want the value of the resource to be used.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Datehttp://home.netscape.com/NC-rdf#DateDate of last visit
Namehttp://home.netscape.com/NC-rdf#NameTitle of the page
Pagehttp://home.netscape.com/NC-rdf#PagePage name
Referrerhttp://home.netscape.com/NC-rdf#ReferrerReferrer of the page
URLhttp://home.netscape.com/NC-rdf#URLURL of the page
Visit Counthttp://home.netscape.com/NC-rdf#VisitCountNumber of page visits
+

A typical history list will display a tree with a selection of these fields. To use them, just put the URL values above in the label attributes of the buttons or treecells. You can use NC:HistoryRoot as the value of the ref attribute. You can also use the value NC:HistoryByDate to get the history sorted into days.

+

Using The History List Example

+

Let's see an example of displaying the history list. We'll display the history in a tree with three columns, the Name, the URL and the Date.

+

Example 1 : Source

+
<tree flex="1" datasources="rdf:history" ref="NC:HistoryRoot">
+
+  <treecols>
+    <treecol id="name" label="Name" flex="1"/>
+    <treecol id="url" label="URL" flex="1"/>
+    <treecol id="date" label="Date" flex="1"/>
+  </treecols>
+
+  <template>
+
+    <rule>
+      <treechildren>
+       <treeitem uri="rdf:*">
+         <treerow>
+           <treecell label="rdf:http://home.netscape.com/NC-rdf#Name"/>
+           <treecell label="rdf:http://home.netscape.com/NC-rdf#URL"/>
+           <treecell label="rdf:http://home.netscape.com/NC-rdf#Date"/>
+         </treerow>
+       </treeitem>
+      </treechildren>
+    </rule>
+
+  </template>
+</tree>
+
+

Other Datasources

+

The tables below list some of the other datasources available with Mozilla. You can use any of the resources that you want.

+
+
+ Bookmarks (rdf:bookmarks)
+
+ The bookmarks are generated from the user's bookmark list.
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Resources
Added Datehttp://home.netscape.com/NC-rdf#BookmarkAddDateDate the bookmark was added
Descriptionhttp://home.netscape.com/NC-rdf#DescriptionBookmark description
Last Modifiedhttp://home.netscape.com/WEB-rdf#LastModifiedDateDate of last modification
Last Visitedhttp://home.netscape.com/WEB-rdf#LastVisitDateDate of last visit
Namehttp://home.netscape.com/NC-rdf#NameBookmark name
Shortcut URLhttp://home.netscape.com/NC-rdf#ShortcutURLCustom keywords field
URLhttp://home.netscape.com/NC-rdf#URLThe URL to link to
+ + + + + + + + + + + + + + + + + + +
Possible Bookmarks Roots
NC:BookmarksRootThe top level of the bookmarks hierarchy
NC:IEFavoritesRootThe bookmark folder that corresponds to the user's IE favorites.
NC:PersonalToolbarFolderThe bookmark folder that corresponds to the personal toolbar folder.
+
+
+ Files (rdf:files)
+
+ A view of the user's files.
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Resources
Namehttp://home.netscape.com/NC-rdf#NameName of the file
URLhttp://home.netscape.com/NC-rdf#URLURL of the file
Content-Lengthhttp://home.netscape.com/NC-rdf#Content-LengthThe length of the file.
LastModifiedDatehttp://home.netscape.com/NC-rdf#LastModifiedDateThe date that URL was last modified.
extensionhttp://home.netscape.com/NC-rdf#extensionThe extension of the file, including the period. This property is only available on platforms that use file extensions.
+ + + + + + + + + + + + + + +
Possible Files Roots
NC:FilesRootTop level of the filesystem (usually the list of drives)
A file URLBy using a file URL for the ref attribute, you can select a specific directory to be returned. For example, you might use file:///windows or files:///usr/local.
+

The files datasource is an example of a datasource that determines its resources only when necessary. We don't want every file in the filesystem to be determined before the data is displayed. Instead, only the files and directories that the tree element (or other elements) will need to display at a given time will be determined.

+

Composite Datasources

+

You can specify multiple datasources in the datasources attribute by separating them with whitespace as in the example below. This has the effect of reading the data from all the datasources mentioned.

+
<tree datasources="rdf:bookmarks rdf:history animals.rdf" ref="NC:BookmarksRoot">
+
+

This example reads the resources from the bookmarks, history and the animals.rdf file. They are combined into a single composite datasource and can be used as if they were one.

+

The special datasource rdf:null corresponds to nothing. You can use this datasource if you want to dynamically set the datasource using a script, but don't want one initially or don't know its exact URL.

+

Custom RDF Datasources

+

You can use any of the above internal datasources if you wish. There are several others for mail, address books and searching and so on. However, you might want to use your own RDF datasource stored in an RDF file. The file can be either a local file or a remote file. Just put the URL of the RDF file in the datasources attribute.

+

Using RDF files provides just as much functionality as any of the internal datasources. You can use rules to match specific types of content. The attributes on the rule element will match if they match the attributes on an RDF Description element. You can also create RDF files that are hierarchical.

+

Using RDF file Example

+

The following is an example of how an RDF file can be used as a datasource. The RDF file is fairly large and can be viewed separately: Source RDF

+

Example 2 : Source View

+
<tree flex="1" width="200" height="200"
+      datasources="animals.rdf" ref="http://www.some-fictitious-zoo.com/all-animals">
+
+  <treecols>
+    <treecol id="name" label="Name" primary="true" flex="1"/>
+    <treecol id="species" label="Species" flex="1"/>
+  </treecols>
+
+  <template>
+    <rule>
+      <treechildren>
+       <treeitem uri="rdf:*">
+         <treerow>
+           <treecell label="rdf:http://www.some-fictitious-zoo.com/rdf#name"/>
+           <treecell label="rdf:http://www.some-fictitious-zoo.com/rdf#species"/>
+         </treerow>
+       </treeitem>
+      </treechildren>
+    </rule>
+
+  </template>
+</tree>
+
+

Image:datasrc1.jpg

+

Here, the data has been generated from the file. The ref attribute has been set to the root element in the RDF file, which is the top-level Seq. This will give us a complete list of animals. If we wanted to, we could set the ref attribute to any of the other about attribute values to limit the set of data that is returned. For example, to display only the reptiles, use a value of http://www.some-fictitious-zoo.com/reptiles.

+

Setting the ref Attribute Example

+

The example below shows how to display a particular piece of an RDF datasource by setting the ref attribute.

+

Example 3 : Source View

+
<window
+  id="example-window"
+  title="History List"
+  xmlns:ANIMALS="http://www.some-fictitious-zoo.com/rdf#"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<button label="Click here to see the mammals the zoo has" type="menu"
+        datasources="animals.rdf" ref="http://www.some-fictitious-zoo.com/mammals">
+  <template>
+    <rule ANIMALS:specimens="0"></rule>
+    <rule>
+      <menupopup>
+        <menuitem uri="rdf:*" label="rdf:http://www.some-fictitious-zoo.com/rdf#name"/>
+      </menupopup>
+    </rule>
+  </template>
+</button>
+
+</window>
+
+

In this case only the mammals are desired, so we select the URI of the mammals list. You will notice that the value of the ref attribute in the example is http://www.some-fictitious-zoo.com/mammals which corresponds to one of the Seq elements in the RDF file. This causes only the descendants of this list to be returned.

+

Two rules have been used here. The first rule catches all the resources that have their ANIMALS:specimens attribute set to 0. You can see this attribute in the RDF file on each of the Description elements. Some of them have a value of 0. So in these cases, rule one will match. Because rule one has no content, nothing will be displayed for these ones. This is an effective way to hide data that we don't want to display.

+

The second rule applies to all other resources and creates a row in a popup menu. The end effect is that we get a popup menu containing all the mammals which have a specimen that is not 0.

+

Next, we'll look at the full rule syntax.

+

+

« 上一页下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/scroll_bars/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/scroll_bars/index.html new file mode 100644 index 0000000000..ea21fc9535 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/scroll_bars/index.html @@ -0,0 +1,9 @@ +--- +title: 滚动栏 +slug: Mozilla/Tech/XUL/Tutorial/Scroll_Bars +translation_of: Archive/Mozilla/XUL/Tutorial/Scroll_Bars +--- +

This page has no content. Enrich M

DC by contributing.cxz + +
   
   
   
+

 

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/scrolling_menus/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/scrolling_menus/index.html new file mode 100644 index 0000000000..e484aba178 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/scrolling_menus/index.html @@ -0,0 +1,45 @@ +--- +title: XUL_教程/滚动菜单 +slug: Mozilla/Tech/XUL/Tutorial/Scrolling_Menus +tags: + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial/Scrolling_Menus +--- +

 

+

+

« 上一页下一页 »

+

+

本节讲述滚动菜单并且将本机制运用到其它元素中。

+

创建一个大菜单

+

如果创建一个菜单,里面有很多的命令在里面,会发生什么呢?这样所有的项不会一次性在屏幕上显示完。Mozilla提供一种滚动机制允许滚动这些项。

+
+ Image:menuscroll1.png
+

如果可用空间太小,在每个菜单的末端会出现箭头。如果将鼠标移动到箭头上,菜单可以上翻或下翻。如果可用的空间足够大,箭头则不会显示。注意是否出现滚动行为完全依赖于当前的实际情况(theme)。

+

该行为是完全自动的。你不必特意的去为得到滚动菜单而做些工作。它会应用于菜单栏上的菜单,滚动菜单或菜单列表中。执行它使用arrowscrollbox元素。该元素用来创建带箭头的滚动框。

+

arrowscrollbox可以被用在任何使用规范框的地方。但不能用于菜单中。通常是用于垂直的框中,并且可能包括有很多元素在里面。可以将它用于下拉列表中,当你不想要它是一个下拉框的时候。

+

示例 - 按钮的滚动列表

+

下面的示例说明了如何创建多个按钮的一个滚动列表(需要改变窗口大小以查看箭头按钮):

+

Example 1 : Source View

+
<arrowscrollbox orient="vertical" flex="1">
+  <button label="Red"/>
+  <button label="Blue"/>
+  <button label="Green"/>
+  <button label="Yellow"/>
+  <button label="Orange"/>
+  <button label="Silver"/>
+  <button label="Lavender"/>
+  <button label="Gold"/>
+  <button label="Turquoise"/>
+  <button label="Peach"/>
+  <button label="Maroon"/>
+  <button label="Black"/>
+</arrowscrollbox>
+
+

试一下这个示例,首先它会以完全大小打开。但是,如果缩小窗口的高度,滚动箭头就会出现。将窗口拉大则箭头会消失。

+

可以设置CSS中arrowscrollboxmax-height属性来限制滚动框的大小,这样使箭头能够一直显示。

+

因此,arrowscrollbox在菜单和弹出菜单中相当有用。

+

下回,我们将学习如何添加一些XUL元素的事件句柄.

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/simple_menu_bars/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/simple_menu_bars/index.html new file mode 100644 index 0000000000..a9179852f7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/simple_menu_bars/index.html @@ -0,0 +1,159 @@ +--- +title: XUL_教程/简单菜单栏 +slug: Mozilla/Tech/XUL/Tutorial/Simple_Menu_Bars +tags: + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial/Simple_Menu_Bars +--- +

 

+ +

+

« 上一页下一页 »

+

+ +

在本节中,我们来看看如何创建菜单栏及菜单项。

+ +

创建菜单

+ +

XUL有几种不同的方式来创建菜单。最基本的方式当然是类似大多数程序拥有一个菜单栏并附有一排菜单项在上面。也可以创建弹出式菜单。XUL的菜单特性由几种不同的元素组成,它可以让你创建菜单栏和弹出式菜单。菜单上的项可以轻松的进行自定义。我们在part of how to make menus一文中已经学习过使用menulist了。本节我们就以此为基础。

+ +

菜单栏通常像toolbar一样创建。菜单栏也可以放置于toolbox中,则菜单就像在其它类型工具栏一样。XUL拥有一些特殊元素,可以提供一些特定功能的菜单。

+ +

有五种相关的元素用来创建菜单栏及其菜单,在此我们简单解释一下,在后面我们再详述:

+ +
+
menubar
+
一排菜单的窗口。
+
+ +
+
menu
+
尽管名字是菜单,但它实际上在菜单栏上仅仅体现其主题而已。该元素可以放置在菜单栏中或者独立放置。
+
+ +
+
menupopup
+
当点击菜单主题时,弹出框会显现。该框包括了菜单命令的列表。
+
+ +
+
menuitem
+
菜单上的独立命令。应放置于menupopup中。
+
+ +
+
menuseparator
+
菜单上的分割条。应放置于menupopup中。
+
+ +
+

你可以在除Macintosh之外的任何平台在菜单栏中自定义任何你想要的菜单。这是因为Macintosh自己特殊的菜单置于屏幕最顶端,由系统控制着。虽然你可以创建自定义菜单,但放置于菜单上的任何特殊样式的规则或非菜单元素均不能生效。在创建菜单时头脑中留意这一点。

+
+ +
简单菜单栏示例
+ +

Example 1 : Source View

+ +
Image:menubar-ex1.png
+ +
<toolbox flex="1">
+  <menubar id="sample-menubar">
+    <menu id="file-menu" label="File">
+      <menupopup id="file-popup">
+        <menuitem label="New"/>
+        <menuitem label="Open"/>
+        <menuitem label="Save"/>
+        <menuseparator/>
+        <menuitem label="Exit"/>
+      </menupopup>
+    </menu>
+    <menu id="edit-menu" label="Edit">
+      <menupopup id="edit-popup">
+        <menuitem label="Undo"/>
+        <menuitem label="Redo"/>
+      </menupopup>
+    </menu>
+  </menubar>
+</toolbox>
+
+ +

喏,使用menubar元素创建了一个简单的菜单栏。上面还会创建一排菜单。menu元素在菜单顶端创建菜单主题显示于菜单栏上。使用menupopup元素创建弹出菜单。用户点击父菜单主题时,会弹出显示。弹出菜单框的大小会足够的大,可以容纳里面所有的菜单命令显示。菜单命令本身使用menuitem元素进行创建。每一个都代表菜单弹出框上的一个单独命令。

+ +

你还可以使用menuseparator元素创建菜单上面的分割线。用于分割不同的菜单项组。

+ + + +

menubar是一个包括菜单的框。注意它已经被放置于一个固定的toolbox中。菜单栏没有特殊的属性一,仅仅是一种类型的框。这意味着可以创建一个垂直的工具栏,通过设置orient属性为vertical。

+ + + +

menu元素运行起来就像是button元素。可以接受与它相同的部分属性及额外的一些属性:

+ +
+
id
+
菜单主题按钮的唯一标识符。
+
+ +
+
label
+
显示在菜单上的文字,例如 文件 或 编辑。
+
+ +
+
disabled
+
该布尔属性决定菜单是否被禁用。虽然可以,但很少情况需要禁止整个菜单。该属性值可以被设置为true或者false。当然,后者是默认值。
+
+ +
+
accesskey
+
该属性值是用户可以按键盘激活菜单项的键值。该字母通常在菜单主题后面以下划线方式显示。Mozilla会视标签属性根据在此指定的字符给它加上下划线。因此,需要指定一个在文本中存在的字符(尽管指定的键不在文本中也能正常工作)。
+
+ +
Image:menubar-ex2.jpg
+ +

menu元素通常放置在菜单栏上,尽管这不是必需的。但是,这将出现不一样的显示结果。此处的图片展示了早期没有菜单栏的示例看起来的效果。

+ + + +

menupopup元素创建包括菜单命令的弹出窗口。它是一种类型的框,默认为垂直布局。如果你想要并且将menuitems放置在一排中,你可以将它改为水平布局。通常仅有menuitems元素和menuseparators放置在menupopup中。你可以放置任何元素在menupopup中,但是在Macintosh中它们都会被忽略。

+ + + +

menuitem元素与menu元素非常相似并且拥有部分相同属性。

+ +
+
id
+
菜单项的唯一标识符。
+
+ +
+
label
+
显示在菜单项上的文本,例如打开 或 保存。
+
+ +
+
disabled
+
该布尔属性值决定菜单项是否被禁止。该属性可以被设置为true或者false,但默认值是后者。
+
+ +
+
accesskey
+
该值是用户可以使用键盘激活菜单项的键值。该字母通常以下划线方式显示于菜单主题后面。Mozilla将视label属性值给指定的字母加上下划线。因此,你需要指定在文本中存在的字符。
+
+ +
+
acceltext
+
该值指定显示在菜单命令末尾的快捷键文本提示。但是它还没有与menuitem进行键的关联。我们在后面再研究如何do this later.
+
+ + + +

menuseparator没有特别的属性。它只是在两个相信的菜单元素之间创建一条水平的分割线。

+ +

下一节,我们会学习一些更多菜单特性.

+ +

+

« 上一页下一页 »

+

+ +

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/splitters/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/splitters/index.html new file mode 100644 index 0000000000..172190858c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/splitters/index.html @@ -0,0 +1,85 @@ +--- +title: 分割线 +slug: Mozilla/Tech/XUL/Tutorial/Splitters +translation_of: Archive/Mozilla/XUL/Tutorial/Splitters +--- +

我们来看看如何向一个窗口添加分隔线。

+

 分隔box

+

有时候你可能会想将一个窗口分成两节,而使用户可以改变这两节的尺寸。一个例子是mozilla的浏览器窗口,你可以通过拖动两个结构之间的小条来改变侧边栏的尺寸。你也可以点击旁边的标记隐藏这个侧边栏

+

元素splitter

+

这个特性是由一个叫做splitter的元素来实现的。它可以在两个节之间创建一个较小的条,可以让用户来改变两边的大小。你可以将splitter放在任何想要放置的地方,这样就可以改变在同一个格子里前后元素的大小了当在水平box中放置一个splitter的时候,将会水平的改变大小。当放在竖直的box中的时候,就可以改变竖直方向的大小了。

+

元素splitter的用法如下:

+ + + + + + +
+

<splitter

+

    id="identifier"

+

    state="open"

+

    collapse="before"

+

    resizebefore="closest"

+

    resizeafter="closest">

+
+

属性如下:

+

属性id  全局唯一标识

+

属性state 指出splitter的状态。默认设为open,将分割面板分开,否则设置为collapse,将其中一个隐藏,另一个占据整个空间

+

属性collapse 这表明当点击隐藏标记的时候隐藏哪一边。设置为before则隐藏前面的元素,如果设置为after则隐藏分割线后面的元素。如果设置为none,也是默认的值,当点击隐藏标记的时候都不会隐藏。

+

属性resizebefore 当分割线被拖动的时候。其左边或者上面的元素会改变大小。这一属性说明哪一个元素改变大小。设置为closest会使左边离分割线最近的立即改变大小,设置为farther则左边离分割线最远的元素将会最先改变大小。默认值为closest。

+

属性resizeafter当分割线被拖动的时候。其右边或者下面的元素会改变大小。这一属性说明哪一个元素改变大小。设置为closest会使右边离分割线最近的立即改变大小,设置为farther则右边离分割线最远的元素会改变大小。这个属性还可以设置为grow,这种情况下分割线右边的部分不会改变大小,相反的,整个格子会改变大小。默认值为closest。

+

如果设置了collapse属性,还可以添加一个grippy元素在splitter里面,这个元素可以用来销毁元素。

+

分割线旁边的元素的width和height属性会在splitter拖动的时候进行调整。准确的说是根据resizebefore和resizeafter属性来调整。

+

Splitter的例子

+

例子1:

+ + + + + + +
+

<hbox flex="1">

+

  <iframe id="content-1" width="60" height="20" src="w1.html"/>

+

  <splitter collapse="before" resizeafter="farthest">

+

    <grippy/>

+

  </splitter>

+

  <iframe id="content-2" width="60" height="20" src="w2.html"/>

+

  <iframe id="content-3" width="60" height="20" src="w3.html"/>

+

  <iframe id="content-4" width="60" height="20" src="w4.html"/>

+

</hbox>

+
+

+

这里创建了4个iframe以及一个分割线,分割线在第一个和第二个iframe之间。属性collapse设置为before,也就是当隐藏标记点击的时候,第一个frame会消失。

+

这个splitter的resizeafter属性设置为farther。也就是说当拖动splitter的时候,其后最远的元素会改变大小。也就是frame4会改变大小。

+

没有对resizebefore设置值,因此其默认值是closest。这里,分割线之前只有一个splitter,因此frame1会改变大小。

+

Frame2和frame3只有在frame4达到最小值时才会改变大小。

+

+

也可以在一个窗口上放置多个splitter。同样的也可以隐藏其他元素,而不仅仅是frame。

+

 查找文件对话框例子

+

让我们看看给查找文件对话框添加一个splitter之后是个什么样子。一个可能是在对话框中添加查找结果,在搜索选项和按钮之间。分割线可以让你隐藏或者查看搜索结果。

+ + + + + + +
+

</tabbox>

+

 

+

  <iframe src="results.html"/>

+

  <splitter collapse="before" resizeafter="grow">

+

   <grippy/>

+

  </splitter>

+

 

+

 <hbox>

+
+

这里添加了一个iframe和一个splitter。这里在tabbox之后不需要spacer了,可以将其移除。Frame的内容包含在一个'results.html'文件里面,现在创建这个文件并将其放在任何地方。以后我们会用一个结果列表来代替它。

+

这个splitter的collapse属性设置为before,就是说分割线之前的元素将会被隐藏。这里就是这个iframe。下面又一个隐藏标志点击之后的图。

+

属性resizeafter设置为grow,这样分割线之后的元素将会在分割线向下拖动的时候向下移动。Frame中的内容的大小可以变到任何尺寸。注意,窗口自己不会改变大小,你也会发现这是一个水平分割线,因为是放在竖直box里面的。

+

正常状态

+

+

隐藏后状态

+

+

接下来将会介绍如何创建工具条

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/stack_positioning/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/stack_positioning/index.html new file mode 100644 index 0000000000..40712df82e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/stack_positioning/index.html @@ -0,0 +1,30 @@ +--- +title: 定位层(stack堆) +slug: Mozilla/Tech/XUL/Tutorial/Stack_Positioning +translation_of: Archive/Mozilla/XUL/Tutorial/Stack_Positioning +--- +

这一节描述如何为堆中的元素进行定位

+

堆子元素的位置

+

通常,stack的子元素为与堆的大小匹配会自动扩展。然而,你也可以将其子元素放在指定的位置。例如,如果一个堆有两个按钮子元素,一个房子左边缘20像素,距顶部50像素。第二个可以房子距离左边缘100像素而距离顶部5像素。

+

可以通过设置两个属性来指定子元素的位置,水平方向上使用left属性,竖直方向上使用top属性。如果你在stack的子元素中不指定这些属性,就会扩展以匹配堆的尺寸。

+

例子1:

+

+ + + + + + +
+

<stack>

+

  <button label="Goblins" left="5" top="5"/>

+

  <button label="Trolls" left="60" top="20"/>

+

  <button label="Vampires" left="10" top="60"/>

+

</stack>

+
+

这个堆有三个子元素,每个元素都使用了left和top属性来定位。这里所有的子元素都是按钮,但是并不是所有的子元素必须是同一类型。可以是任意元素,包括格子或者其他堆。

+

堆的大小由所有紫云山的位置来决定,总会将大小调整到所有子元素都可见的大小。如果你将left属性设置为400,堆将会有一个400加上元素宽度的宽度。你也可以通过各种样式的不同属性如width。Max-width等来重写这个尺寸。

+

也可以通过脚本来调整left和top的值,这样就会使元素移动。堆的优点是当一个指定位置元素位置发生变化时,其他元素不会受到影响。如果在格子中移动子元素,其他元素可能会动态的改它们的位置。

+

你也可以将元素重叠起来。当绘制子元素的时候,元素会按照它们出现在堆中的顺序出现。就是说,第一个子元素在最后面。最后一个元素出现在顶部。你可以使用DOM函数来改变子元素的顺序。

+

在响应鼠标事件的时候,顶部的元素会最先获取这个事件。也就是说如果有两个按钮重叠起来了,最上面的那个按钮会捕获到鼠标点击的事件。

+

下一节描述标签格子(tabboxes),与面板相似但有自己的外观

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/stacks_and_decks/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/stacks_and_decks/index.html new file mode 100644 index 0000000000..39aa1762a1 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/stacks_and_decks/index.html @@ -0,0 +1,71 @@ +--- +title: 层和卡片 +slug: Mozilla/Tech/XUL/Tutorial/Stacks_and_Decks +translation_of: Archive/Mozilla/XUL/Tutorial/Stacks_and_Decks +--- +

有时候需要将元素按照一系列重叠的卡片一样进行显示。堆和面板元素可以达到这一目的。

+

 容器

+

每一个XUL格子元素都是一个可以容纳其他元素的容器。有很多具有特殊样式的格子,例如工具条和标签面板。标签box可以创建不带有任何特殊属性的最简单格子。然而,具有特殊样式的格子与常规的格子一样对其内部的元素进行排列,只是他们有附加特性而已。

+

事实上,很多组件可以容纳其他元素。我们已经看到了按钮可以容纳除了默认元素之外的其他元素。滚动条也是也是一种特殊的格子类型,如果你不提供元素的话,他们会自己创建自己的元素。它也会自己处理滑块的运动。

+

接下来的几节,我们会介绍一些用来容纳其他元素的元素。他们都是有特殊样式的格子,可以将格子的所有属性都用在这些元素上。

+

  堆

+

元素stack是一个简单的格子,与其他格子的工作模式一样,只是它的子元素将会处于所有其他元素的最上面。第一个子元素会在最下面。第二个紧接着第一个,接着是第三个,等等。在一个堆中可以堆上任意多的元素。

+

属性orient没有什么意义,因为堆中的子元素都是一个在一个的上面,而不是一个紧挨一个的。堆的大小由最大的子元素的大小决定。但你可以使用CSS属性的width,height,min-width和其他相关属性来控制堆和他的子元素。

+

元素stack可以在需要为已经存在的元素添加状态指示器时使用。例如,进度条可能会用一个直条和上面一个label来创建。

+

带有阴影的堆

+

为了方便的使用stack元素,可能需要为它仿制很多CSS属性。比如像下面这样为它创建一个文字阴影的效果:

+

例子1:

+ + + + + + +
+

<stack>

+

  <description value="Shadowed" style="padding-left: 1px; padding-top: 1px; font-size: 15pt"/>

+

  <description value="Shadowed" style="color: red; font-size: 15pt;"/>

+

</stack>

+
+

+

两个description元素都创建了一个大小为15点的文字。首先是通过在左边和顶部添加一个1像素的偏移。这样的结果是重复绘制文字'Shadowed'但会与另一个有一点点的偏移。

+

这种方法的比使用text-shadow有一些优势,因为你可以完全将主体文字与阴

+

影分开进行控制。它可以有自己的字体,下划线或者大小。(你甚至可以制作阴影闪烁的效果)。这在mozilla不支持CSS的文字阴影时也很有用。缺点是阴影的存在使得堆的尺寸变大了。。阴影效果对于创建禁用的按钮的外观很有用:

+

例子2:

+ + + + + + +
+

<stack style="background-color: #C0C0C0">

+

  <description value="Disabled" style="color: white; padding-left: 1px; padding-top: 1px;"/>

+

  <description value="Disabled" style="color: grey;"/>

+

</stack>

+
+

这样安排文字和阴影颜色在某些平台上会产生禁用的外观

+

注意,鼠标点击或者按键按下的事件是在堆上顶部元素,即堆中的最后一个元素。就意味着按钮只有是堆中最后一个元素的时候才能工作。

+

  面板

+

元素deck也是和stack一样只在顶部显示一个子元素,但是面板一次只显示一个子元素。这对向导接口非常有用,其中一系列相似的面板顺序显示。你可以通过使面板中的内容发生变化而只创建一个窗口,而不是创建多个独立的窗口和导航按钮。

+

与堆相似,deck元素的直接子元素组成ianb的页面。面板的显示页面可以通过改变设置selectedIndex属性来控制显示出来的子元素。索引是一个数字,可以指定哪一个页面将会显示。页面索引起始值为0.因此第一个子元素的page0,第二个是page1,等等。

+

例子3:

+ + + + + + +
+

<deck selectedIndex="2">

+

  <description value="This is the first page"/>

+

  <button label="This is the second page"/>

+

  <box>

+

    <description value="This is the third page"/>

+

    <button label="This is also the third page"/>

+

  </box>

+

</deck>

+
+

这里有三个页面,默认为显示第三个。第三个页面是一个格子,里面有两个元素。格子里面的元素和格子本身组成了一个页面。面板的大小是子元素中最大的大小这里就是第三个页面。

+

你可以在脚本中改变selectedIndex属性来对页面进行切换。更多关于这个方面的介绍在事件和DOM的章节

+

下一节将会描述如何定位堆中的元素

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/styling_a_tree/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/styling_a_tree/index.html new file mode 100644 index 0000000000..7574e792b7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/styling_a_tree/index.html @@ -0,0 +1,12 @@ +--- +title: 样式化树 +slug: Mozilla/Tech/XUL/Tutorial/Styling_a_Tree +translation_of: Archive/Mozilla/XUL/Tutorial/Styling_a_Tree +--- +

XUL:<treerow properties="makeItBlue">

+

css:
+ treechildren::-moz-tree-row(makeItBlue)
+ {
+   background-color: blue;
+ }

+

可以参考这里 点击这里

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/tabboxes/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/tabboxes/index.html new file mode 100644 index 0000000000..c8c3e527c7 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/tabboxes/index.html @@ -0,0 +1,125 @@ +--- +title: 分页组 +slug: Mozilla/Tech/XUL/Tutorial/Tabboxes +tags: + - tabbox +translation_of: Archive/Mozilla/XUL/Tutorial/Tabboxes +--- +

选择对话框中经常出现标签页,这里我们将会了解如何创建它们。

+

分页组

+

在应用程序的选择窗口中经常出现典型的标签页。在窗口的顶部会出现一系列的标签。用户可以通过点击相应的标签来查看不同的选项集合。当你有很多选项而无法在一个屏幕中完全显示的时候非常有用。

+

XUL也提供了一种方法来创建这样的对话框。包含五种新的元素,下面详细的介绍这几个元素。

+

tabbox 最外层的格子,含有顶部的标签和标签页。

+

tabs 含有独立标签页的内部格。即这是一排标签

+

tabpanels 页面的容器

+

tabpanel 一个单独的页面的主体。你可以将一个页面的内容放在里面。第一个tabpanel对应于第一个标签页,第二个对应第二个,等等。

+

元素tabbox含有两个子元素,一个tabs元素和一个tabpanels元素。用法如下:

+ + + + + + +
+

<tabbox id="tablist">

+

  <tabs>

+

    <!-- tab elements go here -->

+

  </tabs>

+

  <tabpanels>

+

    <!-- tabpanel elements go here -->

+

  </tabpanels>

+

</tabbox>

+
+

元素tab放在tabs里面,这与常规的box很像。元素tab与box其实没有什么不同的。Tab可以容纳任何类型的元素。不同的是,tab的面板一次只显示一个页面,与deck很相像。

+

每个标签页的内容应该放到每个tabpanel元素内部。他们不是在tab元素内部的。Tab元素的内容出现在顶部。

+

每个tabpanel元素成为显示时的一个页面。最大的页面的尺寸用作整个tabbox的尺寸。

+

分页组实例

+

例子1:

+

+ + + + + + +
+

<tabbox>

+

  <tabs>

+

    <tab label="Mail"/>

+

    <tab label="News"/>

+

  </tabs>

+

  <tabpanels>

+

    <tabpanel id="mailtab">

+

      <checkbox label="Automatically check for mail"/>

+

    </tabpanel>

+

    <tabpanel id="newstab">

+

      <button label="Clear News Buffer"/>

+

    </tabpanel>

+

  </tabpanels>

+

</tabbox>

+
+

这里有两个标签页,一个mail一个news。当点击news标签的时候,带有'Clear News Buffer'按钮的页面会出现。

+

当前选择的标签元素有一个selected属性值为true。这可以改变当前选择的标签页。一次只能有一个标签的selected属性为true。

+

标签页的位置

+

最后,你可以改变标签页的位置以使他们出现这个页面的任意位置。没有特殊的语法。你可以简单的使用orient和dir属性来实现。注意在布局的时候记住tab元素就像一般的格子,而tabbox元素更像是常规的竖直容器,tabs元素更像是默认为水平的容器格子。

+

例如,要将标签放到左边,可以将tabs元素的朝向改为竖直的。然后调整tabbox使其具有水平朝向。这会使得标签出现在左边而不是顶部。注意改变tabpanels元素的朝向没有影响,因为标签页是相互覆盖的。

+

也可以通过将tabs元素放在tabpanels元素后面来实现将标签放在右边或者下面。或者,也可以将tabbox的dir属性设置为reverse来实现。但是你最好将标签放在上面,否则在某些流行的主题下可能看起来不是很好。

+

为查找文件对话框添加标签页。

+

让我们为查找文件的对话框添加第二个panel。我们将会创建一个选项标签(并默认选择)来包含一些搜索选项。这可能不是最好的接口。但我们使用它来说明标签的使用。顶部的文字和搜索选择各种需要放在第一个标签中,我们将会添加一些选项在第二个标签中。进度条和按钮可以放在主窗口中,在标签外部。

+ + + + + + +
+

<vbox flex="1">

+

 

+

<tabbox selectedIndex="1">

+

  <tabs>

+

    <tab label="Search"/>

+

    <tab label="Options"/>

+

  </tabs>

+

  <tabpanels>

+

   <tabpanel id="searchpanel" orient="vertical">

+

 

+

    <description>

+

     Enter your search criteria below and select the Find button to begin

+

     the search.

+

    </description>

+

 

+

    <spacer style="height: 10px"/>

+

 

+

    <groupbox orient="horizontal">

+

      <caption label="Search Criteria"/>

+

 

+

      <menulist id="searchtype">

+

        <menupopup>

+

          <menuitem label="Name"/>

+

          <menuitem label="Size"/>

+

          <menuitem label="Date Modified"/>

+

        </menupopup>

+

      </menulist>

+

      <spacer style="width: 10px;"/>

+

      <menulist id="searchmode">

+

        <menupopup>

+

          <menuitem label="Is"/>

+

          <menuitem label="Is Not"/>

+

        </menupopup>

+

      </menulist>

+

 

+

      <spacer style="height: 10px"/>

+

      <textbox id="find-text" flex="1" style="min-width: 15em;"/>

+

 

+

    </groupbox>

+

   </tabpanel>

+

   <tabpanel id="optionspanel" orient="vertical">

+

    <checkbox id="casecheck" label="Case Sensitive Search"/>

+

    <checkbox id="wordscheck" label="Match Entire Filename"/>

+

   </tabpanel>

+

 </tabpanels>

+

</tabbox>

+
+

+

元素tab硬件放在了窗口的主要内容外面。你可以看到两标签,search和options。点击每一个都会将相应的标签页显示出来。如图中显示,两个选项出现在第二个标签上。第一个标签看起来与之前的更像,除了有顶部的标签之外。

+

下一节,我们来看看如何创建内容的网格(grid)

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/templates/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/templates/index.html new file mode 100644 index 0000000000..01b1eb0cf4 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/templates/index.html @@ -0,0 +1,77 @@ +--- +title: XUL_教程/模板(Templates) +slug: Mozilla/Tech/XUL/Tutorial/Templates +translation_of: Archive/Mozilla/XUL/Tutorial/Templates +--- +

 

+

在这一小节,我们将学习如果使用数据填充元素。

+

填充元素(Populating Elements)

+

XUL提供了通过RDF数据建立元素的方法,来源可以是一个RDF文件,也可以是一个内部数据源。Mozilla本身提供了很多数据源,比如书签、历史记录、邮件列表等。我们在下一小节会针对这部分进行更多的讨论。

+

我们通常会向treeitems和menuitems这类的元素填充数据。但你完全可以根据实际情况向其他元素填充数据。在这里,我们还是从这些其他元素入手开始讲解,因为实现树型和菜单需要的代码比较多。

+

为了使用RDF数据建立元素,首先要为这些元素提供一个复制用的模板。实际上,我们只是提供了第一个元素而已,剩下的元素都是在第一个元素的基础上构造出来的。

+

模板是通过template元素建立的。template元素里用于放置那些新构建元素的内容。template元素要置于包含新构建元素的容器中,比如说你要创建一个tree元素,那么就要把template元素置于tree元素中。

+

上面这些通过一个简单的例子来说明会很直观明了,在这个例子中,我们会为每个书签都建立 一个按钮。Mozilla提供了一个书签的数据源,我们可以直接拿来使用,为了简便,我们只取最顶层的书签(也可能是文件夹)来建立按钮。对于那些子标 签,我们可能会通过树型结构或者菜单等来显示这种层叠的结构。

+

这个例子和其他直接引用内部数据源的程序一样,只能通过chrome开头的地址来调用,处于安全考虑,Mozilla禁止从其他数据源间接调用内部数据源。

+

为了运行这个例子,你需要建立一个chrome包并把文件都置于包中,这时就可以通过在浏览器的地址栏输入chrome地址运行了。

+

示例 9.2.1: 下载

+
+
<vbox datasources="rdf:bookmarks" ref="NC:BookmarksRoot" flex="1">
+  <template>
+    <button uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name"/>
+  </template>
+</vbox>
+
+

在这个例子中,建立了一个vbox,vbox里面包含一列的按钮,每个按钮都对应一个顶级的书签。你可以注意到template元素内只有一个button元素。这个唯一的按钮元素是所有按钮元素建立的基础。旁边的图片就是最后的运行结果,每个按钮对应于一个书签。

+

你可以试着在保持这个例子打开的情况下,向浏览器添加一个书签,你会发现这个例子中会立刻添加一个按钮,对应于你刚刚添加的那个书签。(你可能需要重新激活这个窗口,这样才能看到结果)

+

模板本身被置于vbox中,而box容器有两个特性专门是为模板服务的,可以标识数据的来源。第一个是datasource特性,用来声明用来建立元素的RDF数据源。在这个例子中,对应的是rdf:bookmarks。你一定可以猜到这个RDF对应的就是书签数据源。这个数据源是由Mozilla提供的。如果要使用自己的数据源,只需要在datasources特性中指定自定义的RDF地址就可以,就像下面例子中的一样:

+
+
<box datasources="chrome://zoo/content/animals.rdf"
+     ref="http://www.some-fictitious-zoo.com/all-animals">
+
+

也还可以同时设置多个数据源,只要在不同的数据源地址间加上空格就可以。这通常用于显示多个来源的数据。

+

ref特性用于说明你想从数据源获取哪些数据。在这个书签的例子中,使用的是NC:BookmarksRoot,对应的是最顶级的书签。ref具体取什么值依赖于要使用的数据源。如果你使用自己的RDF文件作为数据源,ref的value值通常被设置为Bag、Seq或者Alt元素的about特性的值。

+

当向box容器添加了这两个特性以后,就可以使用模板来生成元素了。模板里的元素要使用不同的方式来声明。你应该注意到上面例子中,button元素设置了uri特性,同时为label特性设置了一个特殊含义的值。

+

模板里的特性值如果是以“rdf:”开头的,就表明这个值是要从数据源中读取的。在上面的例子中,label特性就是这种情况。value中除了“rdf:”的剩余部分由命名空间和属性名称组成,表明要使用数据源中的name属性。如果你对这部分感到迷糊,请重新阅读《XUL教程 - 9.1 - RDF概述》的最后一段。那个例子描述了RDF中的资源是怎样被指向的。在这里我们只使用name属性,当然其他属性在这里也是可以使用的。

+

我们为这些按钮的label特性设置了特定的URI,是因为我们需要用RDF数据源中的name属性来填充label。我们可以把URI放到按钮的 任何一个特性中,放到其他元素中也是可以的。不管放到哪个特性中,都会被数据源中相应的值替换。最后的结果,就是我们用按钮label显示出了每个书签的 名字。

+

下面的例子展示了我们如何为按钮的其他特性设置数据源。当然我们已经假设数据源中包含相应的资源。如果需要的资源在数据源中没有被找到,那么特性的value就会被设置为空字符串。

+
+
<button class="rdf:http://www.example.com/rdf#class"
+        uri="rdf:*"
+        label="rdf:http://www.example.com/rdf#name"/>
+        crop="rdf:http://www.example.com/rdf#crop"/>
+
+

如上面例子所示,你可以通过不同的数据源动态设置元素的每个特性。

+

uri特性用定义开始生成内容的元素。之前的内容只会生成一次,而之后的内容会每次都生成。在后面通过模板建立树型元素的例子中,我们将对这点进行更加详细的阐述。

+

当我们将这些特性添加进模板所在的容器后(在这个例子中是box),就可以使用外部数据来建立各种有趣的列表了。我们当然可以在模板中多放几个元素,也可以在任何元素的特性上添加RDF引用,下面就是一个例子:

+

实例 9.2.2: 下载

+
+
<vbox datasources="rdf:bookmarks" ref="NC:BookmarksRoot" flex="1">
+  <template>
+    <vbox uri="rdf:*">
+      <button label="rdf:http://home.netscape.com/NC-rdf#Name"/>
+      <label value="rdf:http://home.netscape.com/NC-rdf#URL"/>
+    </vbox>
+  </template>
+</vbox>
+
+

这个模板建立了一个vbox,容器中每个书签都对应于一个按钮和一个标签。按钮上显示的是书签的名字,标签上显示的是书签的地址。

+

新建立的元素从功能上来说,和直接向XUL中添加数据是没有差别的。每一个通过模板建立的元素都会被自动添加id特性,用来标识这个资源,你也可以使用这个特性对每个资源进行引用。

+

你还可以在同一个特性的值中,定义多个不同的资源,中间用空格分隔,下面就是一个例子。可以在这里查看更多关于资源定义的语法。

+

示例 9.2.3: 源代码

+
+
<vbox datasources="rdf:bookmarks" ref="NC:BookmarksRoot"
+     flex="1">
+  <template>
+    <label uri="rdf:*" value="rdf:http://home.netscape.com/NC-rdf#Name
+rdf:http://home.netscape.com/NC-rdf#URL"/>
+  </template>
+</vbox>
+
+

建立模板(How Templates are Built)

+

一旦为元素设置了datasources特性,就表明这个元素将会通过模板来生成。要明确这点,是否生成内容不是由template标 记决定的,而是由atasources特性来决定的。只要设置了这个特性,元素就会自动被添加一个叫做构造器的对象。这个对象的责任就是通过模板来构建内 容。在JavaSciprt中,你可以使用builder属性来访问这个构造器对象,但通常你只有在需要手动重新生成内容的时候才需要调用这个对象。

+

构造器有两种类型,最常用的是内容构造器(content builder),另外一种是树型构造器(tree builder),当然只有在构造树型元素的时候才用的到。

+

内容构造器从template元素中读取内容,并在每行都进行复制。比如在上面的例子中如果有十个书签,就会构建10个label元素,并都会添加到vbox元素下面。如果你使用DOM函数对树型结构进行遍历,你可以找到这些元素,并可以调用它们的属性。这些元素最终会在界面显示出来,但是template元素本身是不会显示的,虽然在DOM中是可以找到template元素的。另外,每个label的id特性将被设置为RDF资源中对应的值。

+

内容构造器总是从uri="rdf:*"定义的地方开始操作。如果uri特性所在的元素不是在第一行,那么之前的元素都值将被建立一次。下面的例子中会建立一个hbox,hbox内会用一组label来填充。

+

--------------------------------------------------------------------------------

+

本文完整内容请参见:

+

http://cuimingda.com/2008/10/xul-tutorial-templates.html

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/the_box_model/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/the_box_model/index.html new file mode 100644 index 0000000000..be0bf1832c --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/the_box_model/index.html @@ -0,0 +1,39 @@ +--- +title: XUL_教程/分组方式 +slug: Mozilla/Tech/XUL/Tutorial/The_Box_Model +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/The_Box_Model +--- +

+

« 上一页下一页 »

+

+

 

+

盒模型入门

+

在XUL里主要的布局叫做“盒模型”。这个模型允许你把窗口分割成连续的盒子。在盒子里面元素可以按水平或垂直方向排列。通过将一系列的盒子结合在一起,使用定位格和元素的flex属性,你可以控制窗口的布局。

+

虽然盒模型是XUL元素布局的基础部份,但原理并不复杂,只有几条简单的规则。一个盒子可以将它的子盒布置在两个方向之一,水平或垂直。水平盒子将它的元素进行水平排列,而垂直盒子将它的元素进行垂直排列。你可以把一个盒子想像HTML表格中的一行或一列。除了可以在子元素中放置不同的属性还可以使用一些样式表属性来控制子盒的精确定位和尺寸。

+

盒的例子

+

下面是定义盒子的基本语法:

+
<hbox>
+  <!-- horizontal elements -->
+</hbox>
+
+<vbox>
+  <!-- vertical elements -->
+</vbox>
+
+

hbox元素用来创建一个水平方向的盒子。每个放在hbox中的元素将被水平地排成一行。vbox 元素用来创建一个垂直方向的盒子。添加进来的元素将会被垂直地放在前一个的下面。

+

同样有一个普通的box元素默认是水平方向的,和hbox的意思相同。然而,你可以使用orient 属生去操作盒子的方向。你可以设置这个属性的值为horizontal 去创建一个水平的盒子和vertical去创建一个垂直的盒子。

+

因此,下面两行的效果是一样的:

+
<vbox></vbox>
+
+<box orient="vertical"></box>
+
+

下面例子展示怎么垂直放置三个按钮。

+

例1 : Source View

+
+ Image:boxes-ex1.png
+
<vbox>
+  <button id="yes" label="Yes"/>
+  <button id="no" label="No"/>
+  <
diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/the_chrome_url/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/the_chrome_url/index.html new file mode 100644 index 0000000000..817869f2d2 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/the_chrome_url/index.html @@ -0,0 +1,74 @@ +--- +title: 关于Chrome URL +slug: Mozilla/Tech/XUL/Tutorial/The_Chrome_URL +translation_of: Archive/Mozilla/XUL/Tutorial/The_Chrome_URL +--- +
+ << 前页 后页 >>
+

Chrome统一资源定位器(URL)

+

下面的部分将描述如何关联(引用)XUL文档和其他的chrome文件。

+

<big>Chrome统一资源定位器(URL)</big>

+

XUL文件可以像HTML文件一样被一个普通的HTTP URL(或者其他任何类型的URL)关联。尽管如此,用于Mozilla的chrome系统的软件包可以用特殊的chrome URL关联。Mozilla自带的软件包伴随Mozilla已经安装好,但你可以注册自己的包。

+

软件包安装过之后具有不受安全限制的优点——安全限制对于很多程序来说都是必须的。相对于其他类型的URL来说,另外一个好处是它们可以自动处理多个主题和语言选项。举例来说,一条chrome URL允许你关联(引用)某个主题当中的一个文件,比如说是图片,与此同时你不需要知道用户当前使用的是哪个主题。只要不同主题里面的对应文件名相同,你总是可以通过chrome URL来引用这个文件。Mozilla会找到文件的路径并返回正确的数据。这也就意味着,软件包安装的位置与是否能访问它没有关系。chrome URL与文件物理存放位置无关,这使得写含有很多文件的程序变得简单了,因为你无需关心文件位置的细节。

+

Chrome统一资源定位器(URL)的基本语法规则如下:

+ + + + + + +
+
+chrome://<package name>/<part>/<file.xul>
+
+

上面的<package name>是软件包的名字,比如是编辑器或聊天工具。<part>可以是'content','skin'或'locale',这取决于你的需要。'file.xul'是文件名。

+

示例chrome://messenger/content/messenger.xul

+

这个例子关联到的是'content'中的messenger窗口。将'content'替换为'skin'并改掉文件名,就可以指向皮肤中的某个文件。同样的,用'locale'替换'content'后,我们就能指向语言中的文件。

+

当你打开一个chrome URL,Mozilla在其已安装包列表中查找,尝试定位到与URL中包名相同的JAR文件和目录.chrome URL和JAR文件之间的对应关系由chrome目录中的'清单'(manifest)文件来指定。如果你把messenger.jar移动到别的地方,并相应地更新'清单'文件中的信息,Thunderbird(译者注:此处Thunderbird是上文中提到的messenger)仍然能够正确工作,因为它不依赖特定的安装位置。利用chrome URL我们可以脱离Mozilla中例如包的位置等细节信息。类似地,如果用户改变了主题,'skin'部分的chrome URL实际所指向的就是另外的一套文件,但XUL和脚本无需改变。

+

下面是更多的示例。注意例子中URL是如何避免指定使用某个特定的主题或者语言,以及如何避免指定特定目录的。

+ + + + + + +
+
+chrome://messenger/content/messenger.xul
+chrome://messenger/content/attach.js
+chrome://messenger/skin/icons/folder-inbox.png
+chrome://messenger/locale/messenger.dtd
+
+
+

要关联到子目录,你只要在chrome URL的最后加上目录名就可以。下面的这些URL关联到bookmarks窗口,这里列出来了适合Mozilla和Firefox的版本——因为两者软件包的名字有差异:

+ + + + + + +
+
+chrome://communicator/content/bookmarks/bookmarksManager.xul (Mozilla)
+chrome://browser/content/bookmarks/bookmarksManager.xul (Firefox)
+
+
+

chrome URL在任何普通URL可以使用地方一样能用,甚至你可以在Mozilla的浏览器窗口(译者注:地址栏)中直接输入。当在浏览器地址栏中输入上面提到的URL之一,你会发现窗口会像网页一样显示出来,而且大多数功能和在单独的窗口一样可以正常使用。但是,有些对话框可能工作不正常,那可能是因为需要由父窗口在打开他们的时候传递一些参数。

+

你还将会遇到不带文件名的chrome URL,比如:

+ + + + + + +
+
+chrome://browser/content/
+
+

这种情况只有给出了包名和模块名。这类的引用(关联)会自动从目录中选择一个合适的文件。对于content来说,与包同名并带有.xul后缀的文件会被选中。在上面的例子中,显示的会是'browser.xul'。对于messenger包,messenger.xul会被显示。当你创建自己的包时,你需要为你的主窗口创建一个和软件包同名的文件,这样它就能被上面这种短形式的URL关联。这样带来的便利是只要用户知道包的名字,他就能打这个应用程序。当然了,对于修改浏览器界面的扩展(extensions)来说,用户不需要知道URL,因为扩展通过用户界面来显示自身。

+

对于皮肤而言,包名.css被选中;对于语言,选中的是包名.dtd。

+

需要记住的是,chrome URL与它在磁盘上的位置无关。URL的第一部分两个元素是包名和模块(content,skin或locale)。将内容文件放在叫'content'的目录是很普遍的事情,这和惯例不符,这些文件会被放在一个完全不同的结构中。

+
+

(下一部分) 在接下来的部分,我们将看看如何创建'清单'(manifest)文件和包。

+
+ << 前页 后页 >>
diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/toolbars/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/toolbars/index.html new file mode 100644 index 0000000000..4ba0a4e2e3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/toolbars/index.html @@ -0,0 +1,101 @@ +--- +title: XUL_教程/工具栏 +slug: Mozilla/Tech/XUL/Tutorial/Toolbars +tags: + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial/Toolbars +--- +

 

+

+

« 上一页下一页 »

+

+

工具栏通常沿着窗口顶部放置,并包含许多完成普通功能的按钮。XUL有一个创建工具栏的方法。

+

A toolbar is usually placed along the top of a window and contains a number of buttons that perform common functions. XUL has a method to create toolbars.

+


+ 工具栏

+

Like a number of elements, XUL toolbars are a type of box.像许多的界面要素, XUL工具栏也是一种界面框。 Usually, a row of buttons would appear in the toolbar, but any element can be placed in a toolbar.通常,工具栏里会出现一排按钮,但任何界面要素都可以放到工具栏里。 For example, the Mozilla browser window contains a textbox that displays the page URL.举例来说, mozilla浏览器窗口包含一个文本框 ,显示了该网页的url 。

+

Toolbars may be placed on any side of the window, either horizontally or vertically.工具栏可被水平或垂直地放置在窗口的任一边。 Of course you wouldn't normally put a textbox in a vertical toolbar.当然,通常你不会把文本框放在一个垂直工具栏里。 Actually, because toolbars are just boxes they can actually go anywhere you want, even in the middle of a window.事实上,因为工具栏只是个界面框,它们能去你想要它们去的任何地方,即使是窗口的中间。 Typically however, a set of toolbars would appear along the top of a window.通常,一组工具栏会出现在窗口的顶部。 When more than one toolbar is placed next to each other, they are typically grouped together in something called a 'toolbox'.当多个工具栏一个接一个放置时,他们通常被一个叫做'工具箱'的东西集合在一起。 [ edit ] A simple toolbar inside a toolbox [编辑] 一个简单的工具栏里面一个工具箱

+

Source View 来源 查看 形象: toolbar1.jpg

+
<toolbox>   <toolbar id="nav-toolbar">     <toolbarbutton label="Back"/>     <toolbarbutton label="Forward"/>   </toolbar> </toolbox> <工具箱> <toolbar id="nav-toolbar"> <toolbarbutton label="back"/> <toolbarbutton label="forward"/> < /工具栏> < /工具箱>
+
+

This has created a toolbar containing two buttons, a Back button and a Forward button.这就造成了一种工具列载有两个按钮,有一个备份(后退)按钮和前进按钮。 The one toolbar has been placed inside the toolbox.在一个工具栏已被置于内工具箱。 This has involved four new tags, which are described here.这涉及到4个新的标签,这是形容这里。

+

toolbox 工具箱

+
   A box that contains toolbars.一个方框,其中包含工具栏。
+
+

toolbar 工具栏

+
   A single toolbar that contains toolbar items such as buttons.一个单一的工具栏包含了工具栏的项目,如按钮。
+
+

toolbarbutton toolbarbutton

+
   A button on a toolbar, which has all the same features of a regular button but is usually drawn differently.一个按钮,一个工具条,其中已全部一样的特点,定期按钮,但通常是取用不同。
+
+

The toolbar is the main element that creates the actual toolbar. 该工具是主要因素,造成了实际的工具栏。 Inside it are placed the individual toolbar items, usually buttons, but they can be other elements.它里面放置了个人工具栏的项目,通常是按钮,但是它们可以被其他元素。

+

In the example above, only one toolbar was created.在上面的例子中,只有一个工具栏被创建。 Multiple toolbars can be created just as easily by adding more toolbar elements after the first one.更多工具栏的创建就想在第一个工具栏中添加元素一样容易。

+

The toolbox is a container for toolbars. 工具箱是一个容器工具栏。 In some applications, you will have several toolbars along the top of the window.在某些应用中,你将有几个工具栏沿顶部的窗口。 You can put them all inside a toolbox .你可以把它们都内一个工具箱。

+

You do not have to put toolbar elements inside a toolbox .你不须要把工具栏的内容里面一个工具箱。 [ edit ] Our find files example [编辑] 我们找到档案为例

+

Let's add a toolbar to the find files dialog.让我们添加一个工具栏,向找到的文件对话框。 We don't really need one but we'll add one anyway to demonstrate its use.我们并不真的需要一个,但我们将增加一个无论如何,以证明其使用。 Two buttons will be added, an Open button and a Save button.两个按钮将被增加,一个打开按钮和一个储存按钮。 Presumably, they would allow the user to save search results and re-open them later.据推测,它们将使用户能够保存搜寻结果,或重新打开。

+
<vbox flex="1"> <toolbox>     <toolbar id="findfiles-toolbar">       <toolbarbutton id="opensearch" label="Open"/>       <toolbarbutton id="savesearch" label="Save"/>     </toolbar>   </toolbox> <tabbox> < vbox挠性= " 1 " > <toolbox> <toolbar id="findfiles-toolbar"> <toolbarbutton id="opensearch" label="open"/> <toolbarbutton id="savesearch" label="save"/> < /工具栏> < /工具箱> <tabbox>
+
+

形象: toolbar5.png

+

A toolbar with two buttons has been added here.工具栏上有两个按钮已被添加在这里。 In the image, you can see them appear horizontally along the top.在图像,你可以看到他们出现横向沿顶部。 Notice that the toolbar has been placed inside the vertical box just above the tabbox.公告说,该工具已被置于内垂直票房略高于tabbox 。 This is because we need the vertical orientation so that the toolbar will appear above everything else.这是因为,我们需要的垂直方向,使该工具栏将出现高于一切。

+

The find files example so far: Source View这一发现的档案为例,目前为止:源观

+

Next, we'll find out how to add a menu bar to a window .明年,我们将看看如何添加一个菜单栏,以一个窗口 。

+

 

+

Adding a Toolbar

+

Like a number of elements, XUL toolbars are a type of box. Usually, a row of buttons would appear in the toolbar, but any element can be placed in a toolbar. For example, the Mozilla browser window contains a textbox that displays the page URL.

+

Toolbars may be placed on any side of the window, either horizontally or vertically. Of course you wouldn't normally put a textbox in a vertical toolbar. Actually, because toolbars are just boxes they can actually go anywhere you want, even in the middle of a window. Typically however, a set of toolbars would appear along the top of a window. When more than one toolbar is placed next to each other, they are typically grouped together in something called a 'toolbox'.

+
A simple toolbar inside a toolbox
+

Source View

+
+ Image:toolbar1.jpg
+
<toolbox>
+  <toolbar id="nav-toolbar">
+    <toolbarbutton label="Back"/>
+    <toolbarbutton label="Forward"/>
+  </toolbar>
+</toolbox>
+
+

This has created a toolbar containing two buttons, a Back button and a Forward button. The one toolbar has been placed inside the toolbox. This has involved four new tags, which are described here.

+
+
+ toolbox
+
+ A box that contains toolbars.
+
+
+
+ toolbar
+
+ A single toolbar that contains toolbar items such as buttons.
+
+
+
+ toolbarbutton
+
+ A button on a toolbar, which has all the same features of a regular button but is usually drawn differently.
+
+

The toolbar is the main element that creates the actual toolbar. Inside it are placed the individual toolbar items, usually buttons, but they can be other elements.

+

In the example above, only one toolbar was created. Multiple toolbars can be created just as easily by adding more toolbar elements after the first one.

+

The toolbox is a container for toolbars. In some applications, you will have several toolbars along the top of the window. You can put them all inside a toolbox.

+

You do not have to put toolbar elements inside a toolbox.

+
+

Our find files example

+

Let's add a toolbar to the find files dialog. We don't really need one but we'll add one anyway to demonstrate its use. Two buttons will be added, an Open button and a Save button. Presumably, they would allow the user to save search results and re-open them later.

+
<vbox flex="1">
+  <toolbox>
+    <toolbar id="findfiles-toolbar">
+      <toolbarbutton id="opensearch" label="Open"/>
+      <toolbarbutton id="savesearch" label="Save"/>
+    </toolbar>
+  </toolbox>
+  <tabbox>
+
+

 

+
+ Image:toolbar5.png
+

A toolbar with two buttons has been added here. In the image, you can see them appear horizontally along the top. Notice that the toolbar has been placed inside the vertical box just above the tabbox. This is because we need the vertical orientation so that the toolbar will appear above everything else.

+

The find files example so far: Source View

+
+

Next, we'll find out how to add a menu bar to a window.

+

+

« 上一页下一页 »

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/trees/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/trees/index.html new file mode 100644 index 0000000000..6162b31e6a --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/trees/index.html @@ -0,0 +1,8 @@ +--- +title: 树结构 +slug: Mozilla/Tech/XUL/Tutorial/Trees +translation_of: Archive/Mozilla/XUL/Tutorial/Trees +--- +

XUL提一种供用树的形式而创建表格或是分层结构的列表。

+

+

在XUL中树是个很复杂的元素。它用于有层次需求的结构来显示行列中的文本。树允许用户对某行进行排序、调整、隐藏等操作。比如火狐中的书签项和雷鸟邮箱结构都是用树做成的。

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/using_spacers/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/using_spacers/index.html new file mode 100644 index 0000000000..7501f87216 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/using_spacers/index.html @@ -0,0 +1,111 @@ +--- +title: XUL_教程/使用定位格 +slug: Mozilla/Tech/XUL/Tutorial/Using_Spacers +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/Using_Spacers +--- +

+

« 上一页下一页 »

+

+

 

+

添加定位格

+

开发用户界面的问题之一是每个用户都有不同的显示器。一些用户使用较高分辨率的较大显示器而另外一些用户使用的是较低分辨率的。另外,不同的平台对用户界面的也不同。如果加上多语言支持,每种语言之间用到的文字的需要的显示空间也不一样。

+

应用程序的窗口通常需要考虑支持多平台和多语言。某些平台和用户接口工具提供组件让用户可以轻易地去调整适合他们自己的大小和位置。(例如Java平台使用布局管理器。)

+

XUL为元素提供能力自动调整位置和大小。 就像我们看到的文件查找窗口的尺寸是刚好能将元素放在它里面。每次我们增中一些东西,窗口就会变得更大。

+

XUL使用一个叫做“箱状模型”(Box Model)的布局系统。我们将在下一节中讲到。它允许你将一个窗口划分成连续的盒子存放元素。盒子可以基于你定义的规格调整位置和大小。到现在,可以知道 window 元素是属于盒子的类型。

+

在了解什么是盒子之前,我们将引入其他用于布局的XUL元素,spacer。定位格很简单,它只需要一个属性,稍后将会说明。一个简单的定位格看起来就像下面:

+
<spacer flex="1"/>
+
+

spacer用于在窗口中放置一片空白。它多数用于用户调整窗口大小时它可以拉伸或者收缩。 这将决定是将按钮放置在一个窗口的左边或底边还是放在右边或底边 。将要看到,你可以使用一连串的空格去创建许多布局效果。

+

上面这个语法中,定位格有一个属性,叫做flex。这用于定义定位格的弹性。在上面的例子中,定位格为1的弹性。这会创建一个有弹力的定位格。如果你直接将它放在窗口里,这个定位格会在窗口的大小被改变时自动伸缩。

+

马上我们将会把一个定位格添加到我们的文件查找例子中。首先,让我们看一下当调整当前对话框时会发生什么。

+

Image:springs1.jpg

+

如果你改变文件查找窗口的尺寸,你会看到所有的元素都保持着它们原来的位置。它们中没有一个移动或调整了大小虽然窗口里有更多的空间。让我们再看一下当增加了一个定位格后在文本输入框和查找按钮之间发生了什么。

+

Image:springs2.jpg

+

在添加了定位格后再调整窗口的大小时,你可以看到定位格填充了空白。按钮被推到了最后面。

+
+
我们文件查找的例子
+

下面的代码增加一个定位格。把它插入到查找按钮的前面。

+
<spacer flex="1"/>
+
+<button id="find-button" label="Find"/>
+
+
+

关于弹性的更多信息

+

XUL在窗口中放置有弹性元素是通过计算元素合适的宽度和高度然后再添加空间。除非你指定元素的宽度和高度信息,元素的内容就决定了它的默认大小。你需要注意在对话框中的取消按钮总是设置了宽度因此它能在它里面放文字。如果你创建一个具有非常长的标签的按钮,按钮的默认大小将会很大使得有足够的空间可以放下标签。其它的元素,像是文本输入框会选择一个合适的默认大小。

+

flex属性用于指定元素可以改变自身的尺寸去填充它所在的盒子 (在这个例子中的窗口)。我们已经看到了应用于定位格的弹性属性,但它是可以应用于所有的元素的。例如,你可以改成能自动调整大小的查找按钮。

+

Image:springs3.jpg

+

如图所示,在查找按钮上增中了弹性属性,在窗口进行大小调整时它也会跟着调整。定位格实际上是没有指定任何东西。它实际上就是一个隐藏的按钮。它除了不会在屏幕上显示外大部分的使用方法就是和按钮一样的。

+

你可以从上面的图片得到更多的提示。不仅是在查找按钮的尺寸增大了,而且在主标签和按钮之间显示了更多的空间。当然,这是我们之前放进去的定位格。它也调整了自己的尺寸。如果你更深入地观察,你会注意到在定位格和按钮之间分到的尺寸改变值是相等的。定位格拿到了一半的空余空间,按钮拿到了另外一半。

+

我们看到这个效果是因为定位格和查找按钮都使用了 flex 属性。因为都是可伸缩的,按钮和定位格的尺寸调整是相等的。

+

如果你想设置一个元素是另一个的两倍大小要怎么做呢?你可以给flex属性设一个更高的值。弹性元素的值是一个概率。如果一个元素的弹性值为1而另一个的弹性值是2,第二个比第一个大多少倍。在效果上,一个弹性为2说的是这个元素有一个弹性是二次的元素弹性增长。

+

flex属性不能用来指定一个真实的尺寸。作为替换,它说明在一个盒容器的子容器中填入多少的空白空间。我们将在下节看到盒子。一旦子盒的默认尺寸被指定,弹性值就被用于在对盒子中剩余的空白空间进行分割。例如,如果一个盒子有200像素宽并且包括2个可伸缩的按钮,第一个是50像素和另外一个是90像素,在它们的外面将还会有60像素的空白空间。如果两个按钮都有弹性的值为1,空白空间将会被分配给每个按钮伸缩长度为30像素。如果第二个按钮的弹性增加到2,第一个按钮将得到20像素的扩展空间,而第二个按钮将得到40像素的扩展空间。

+

flex属性可以被放在任何元素,但是当它直接放在XUL元素里面时就只有一个意思。意思是说即使你可以把flex放在HTML元素中,如果元素不是一个非盒元素它就得不到效果。

+
弹性例子
+
例1:
+  <button label="Find" flex="1"/>
+  <button label="Cancel" flex="1"/>
+
+例2:
+  <button label="Find" flex="1"/>
+  <button label="Cancel" flex="10"/>
+
+例3:
+  <button label="Find" flex="2"/>
+  <button label="Replace"/>
+  <button label="Cancel" flex="4"/>
+
+例4:
+  <button label="Find" flex="2"/>
+  <button label="Replace" flex="2"/>
+  <button label="Cancel" flex="3"/>
+
+例5:
+  <html:div>
+    <button label="Find" flex="2"/>
+    <button label="Replace" flex="2"/>
+  </html:div>
+
+例6:
+  <button label="Find" flex="145"/>
+  <button label="Replace" flex="145"/>
+
+
+
+ 例1 
+
+ 在这个例子中两个按钮平均分配弹性值。两个按钮的将会被平均地改变大小。
+
+ 例2 
+
+ 这,两个按钮都是可伸缩的,但查找按钮的伸展率是取消按钮的十分之一,因为取消按钮的弹性值为10,可用的空间被分割成查找按钮的一份和取消按钮的十分。
+
+ 例3 
+
+ 这里只有其中的两个按钮设置为可弹性。替换按钮将不会改变它的尺寸而另外两个会。 取消按钮将会比查找按钮大一倍因为它的弹性值是查找按钮的弹性值的二倍。
+
+ 例4 
+
+ 在这个例子,三个按钮都具有可弹性。查找和替换按钮的尺寸将是相同的,但取消按钮会更大一些(多50%的扩展)。
+
+ 例5 
+
+ 这里,两个按钮都放在div元素里面。按钮不是放在盒子里所以可申缩性在这里是无意义的。效果和没有使用flex属性是相同的。
+
+ 例6 
+
+ 因为两个按钮的弹性值是一样的,他们将得到相同的弹性。这样还不如用1来代替145。在这个例子中没有什么不同。建议你使用可读性更好的低数值。
+
+

注意像按钮的标签和按钮的最小尺寸等其他的因素会影响到按钮的尺寸。事实上,按钮不会收缩到比它的标签还小。

+

将弹性值设为0与没有设置flex属性的效果是一样的。它的意思是元素不使用弹性。你有时可以看到弹性值会指定为一个百分率。这没有特殊的意义,这已经是处理过的就算没有百分号在那里。

+

你也许注意到在你垂直改变查找对话框的尺寸时,按钮也会调整它自己的尺寸去适应窗口的高度。这是因为所有在窗口中的按钮都有隐含的垂直弹性。在下一节我们将会学习如何去改变这个值。

+
+
到目前为止的文件查找例子
+

Source View

+
+

接下来,我们将要学习 按钮的更多特性

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/using_xbl_from_stylesheets/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/using_xbl_from_stylesheets/index.html new file mode 100644 index 0000000000..04c8ab7123 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/using_xbl_from_stylesheets/index.html @@ -0,0 +1,223 @@ +--- +title: 通过CSS和XBL创建可复用的内容 +slug: Mozilla/Tech/XUL/Tutorial/Using_XBL_from_stylesheets +translation_of: Archive/Beginner_tutorials/Using_XBL_from_stylesheets +--- +

+ +

本页面介绍了如何在Mozilla中使用CSS来提升在复杂应用结构中的代码与资源的复用。

+ +
+

提示:XBL不能通过HTTP来加载,所以XBL只能使用file:///scheme或者通过附加代码的方式进行本地访问。

+
+ +

你可以应用这项技术于一个简单的示例。

+ +

Information: XBL bindings

+ +

由标记语言和CSS提供的这个结构并不适用于组件需要自包含和复用的复杂应用。你可以将样式表(stylesheet)和脚本(script)放置在独立的文件中。但是你必须将这些文件加载到文档(html)中,最后形成一个整体。

+ +

另一个结构上的限制则与内容有关。你可以使用CSS为选中的元素提供内容,但是内容限定在文本和图片,并且内容的位置只能是选中的元素前或者后。

+ +

Mozilla provides a mechanism that overcomes these limitations: XBL (XML Bindings Language). You can use XBL to link selected elements to their own:

+ +

Mozilla提供了一个机制来克服上述限制:XBL(XML Bindings Language)。

+ + + +

因此你可以避免在文档中链接每一个组件,你可以使用自包含的组件来方便维护和复用。

+ + + + + + + + +
More details
For more information about XBL bindings, see the XBL page in this wiki.
+ +

Action: An XBL demonstration

+ +

创建一个新的html文档,doc6.html。将下面的内容拷贝到文件中:

+ +
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<HEAD>
+<TITLE>Mozilla CSS Getting Started - XBL demonstration</TITLE>
+<LINK rel="stylesheet" type="text/css" href="style6.css">
+</HEAD>
+
+<BODY>
+<H1>XBL demonstration</H1>
+<DIV id="square">Click Me</DIV>
+</BODY>
+
+</HTML>
+
+
+ +

创建一个新的CSS文件,style6.css。这个样式表包含了文档的样式。将下面的内容拷贝到CSS文件中:

+ +
+
/*** XBL demonstration ***/
+#square {
+  -moz-binding: url("square.xbl#square");
+  }
+
+
+ +

Make a new text file, square.xbl. This file contains the XBL binding. Copy and paste the content from here:

+ +

创建一个新的文本文件,square.xbl。这个文件包含了XBL的绑定关系。将下面的内容拷贝到文件中。

+ +
+
<?xml version="1.0"?>
+<!DOCTYPE bindings>
+<bindings xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:html="http://www.w3.org/1999/xhtml">
+
+<binding id="square">
+
+  <resources>
+    <stylesheet src="bind6.css"/>
+    </resources>
+
+  <content>
+    <html:div anonid="square"/>
+    <xul:button anonid="button" type="button">
+      <children/>
+      </xul:button>
+    </content>
+
+  <implementation>
+
+    <field name="square"><![CDATA[
+      document.getAnonymousElementByAttribute(this, "anonid", "square")
+      ]]></field>
+
+    <field name="button"><![CDATA[
+      document.getAnonymousElementByAttribute(this, "anonid", "button")
+      ]]></field>
+
+    <method name="doDemo">
+      <body><![CDATA[
+        this.square.style.backgroundColor = "#cf4"
+        this.square.style.marginLeft = "20em"
+        this.button.setAttribute("disabled", "true")
+        setTimeout(this.clearDemo, 2000, this)
+        ]]></body>
+      </method>
+
+    <method name="clearDemo">
+      <parameter name="me"/>
+      <body><![CDATA[
+        me.square.style.backgroundColor = "transparent"
+        me.square.style.marginLeft = "0"
+        me.button.removeAttribute("disabled")
+        ]]></body>
+      </method>
+
+    </implementation>
+
+  <handlers>
+    <handler event="click" button="0"><![CDATA[
+     if (event.originalTarget == this.button) this.doDemo()
+     ]]></handler>
+    </handlers>
+
+  </binding>
+
+</bindings>
+
+
+ +

Make a new CSS file, bind6.css. This separate stylesheet contains style for the binding. Copy and paste the content from here:

+ +

创建一个新的CSS文件,bind6.css。这个独立的样式表包含了

+ +
+
/*** XBL demonstration ***/
+[anonid="square"] {
+  width: 20em;
+  height: 20em;
+  border: 2px inset gray;
+  }
+
+[anonid="button"] {
+  margin-top: 1em;
+  padding: .5em 2em;
+  }
+
+
+ +

在你的浏览器中打开文档然后按下按钮。

+ +

这个维基页面并不支持JavaScript,所以无法再这里展示示例。示例看上去就如下面所示,分别是按下按钮之前和之后的效果。

+ + + + + + + + +
xbldemo0.pngxbldemo1.png
+ +

关于这个示例的提示:

+ + + +

挑战

+ + + + + + + + +
 
Change the XBL file so that the square doubles in width when it changes color, instead of jumping to the right. +

Use the DOM Inspector tool to inspect the document, revealing the added content.

+ +

 

+
+ +

What next?

+ +

If you had difficulty understanding this page, or if you have other comments about it, please contribute to its Discussion page.

+ +

In this demonstration, the square and the button make a self-contained widget that functions within an HTML document. Mozilla has a specialized markup language for creating user interfaces. The next page demonstrates it: XUL user interfaces.

diff --git "a/files/zh-cn/mozilla/tech/xul/tutorial/xbl\344\273\213\347\273\215/index.html" "b/files/zh-cn/mozilla/tech/xul/tutorial/xbl\344\273\213\347\273\215/index.html" new file mode 100644 index 0000000000..6b6ef8288e --- /dev/null +++ "b/files/zh-cn/mozilla/tech/xul/tutorial/xbl\344\273\213\347\273\215/index.html" @@ -0,0 +1,104 @@ +--- +title: XUL 教程 +slug: Mozilla/Tech/XUL/Tutorial/XBL介绍 +tags: + - XBL +translation_of: Archive/Mozilla/XUL/Tutorial/Introduction_to_XBL +--- +

 

+ +

+

« 上一页下一页 »

+

+ +

 

+ +

XUL有一个姐妹语言,XBL(可扩展绑定语言)。这种语言被用于声明 XUL 窗口控件的行为。

+ +

Bindings

+ +

你可以用 XUL 来为应用程序定义用户界面的外观。你可以通过 应用样式自定义元素的外观。你也可以通过改变样式以 创建新皮肤。所有元素的基础外观,比如 滚动条复选框,都可以通过调整样式或设置元素参数来进行修改。然而,XUL 没有提供改变元素的工作方式(或添加一个可重用的新元素)的方法。例如,您可能想改变滚动条的运行方式,就需要用到 XBL

+ +

一个 XBL 文件包含一组绑定(binding)。每个绑定描述一个 XUL 控件的行为。例如,一个绑定可以和一个滚动条相关联。这个行为除却描述滚动条的属性于方法之外,还描述了组成滚动条的 XUL 元素。

+ +

类似 XUL,XBL 是一种 XML 语言,所以它有与之相似的语法规范。下述例子展示了 XBL 文件的基础结构:

+ +
<?xml version="1.0"?>
+<bindings xmlns="http://www.mozilla.org/xbl">
+  <binding id="binding1">
+    <!-- content, property, method and event descriptions go here -->
+  </binding>
+  <binding id="binding2">
+    <!-- content, property, method and event descriptions go here -->
+  </binding>
+</bindings>
+
+ +

bindings 元素是 XBL 文件的根元素,包含了一个或多个 bindings 元素。每个 bindings 元素都声明一个单独的 binding,id 属性可以用来确定 binding,就像上述的例子一样。模板有两个 binding,分别叫做 binding1binding2。一个可与滚动条关联,另一个则与菜单关联。一个 binding 可以和任意 XUL 元素相关联。如果你使用 CSS 类,就能按需使用各种不同的 binding。注意上面模板中的 bindings 元素的命名空间。它声明了我们所使用的 XBL 语法。

+ +

将绑定文件的链接正确设为 CSS 中 -moz-binding 的值,就可以把一个 binding 绑定到元素上。例如:

+ +
scrollbar {
+    -moz-binding: url('chrome://findfile/content/findfile.xml#binding1');
+}
+
+ +

URL 指向了 “chrome://findfile/content/findfile.xml” 文件中的 ID“binding1”。“#binding1”语法用于指向特定的 binding,很像指向 HTML 文件中的 anchor 标签的语法。通常你会(借助此语法)把所有的 binding 放进一个单独的文件里。例中结果是“binding1”将会描述所有的滚动条元素。如果您没用-moz-binding URL中的标签,就会用到XBL文件中的第一个binding。

+ +

binding 声明了五种类型:

+ +
    +
  1. 内容:添加到 binding 绑定到的元素的子元素
  2. +
  3. 属性:添加到 binding 绑定到的元素的属性。它们能通过脚本存取。
  4. +
  5. 方法:添加到 binding 绑定到的元素的方法。它们能从脚本调用。
  6. +
  7. 事件:元素将响应的例如鼠标单击和按键这类事件。 binding能添加脚本,来提供默认操作。另外,能够定义新事件。
  8. +
  9. 样式:被 XBL 定义的 binding 绑定到的元素所拥有的自定义样式的属性
  10. +
+ +

Binding 示例

+ +

box 很通用,您能用它来创建自定义的窗口控件(虽然您能用任何元素,甚至自己构造的)。给一个 box 标签分配一个 class 属性,您就可以将 binding 连接到只属于该类的 box。比如下面的例子:

+ +

XUL (example.xul):

+ +
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://example/skin/example.css" type="text/css"?>
+
+<window
+     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <box class="okcancelbuttons"/>
+</window>
+ +

CSS (example.css):

+ +
box.okcancelbuttons {
+    -moz-binding: url('chrome://example/skin/example.xml#okcancel');
+}
+ +

XBL (example.xml):

+ +
<?xml version="1.0"?>
+<bindings xmlns="http://www.mozilla.org/xbl"
+         xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <binding id="okcancel">
+    <content>
+      <xul:button label="OK"/>
+      <xul:button label="Cancel"/>
+    </content>
+  </binding>
+</bindings>
+ +

这个例子创建了一个有单个 box 的窗口,这个 box 已经声明过含有一个 okcancelbuttons 类。与文件相关的样式表阐述了含类 okcancelbuttons 的box有在XBL文件中定义的特定的binding。除 box 之外,可用其它元素,甚至自定义的标签。

+ +

部分 XBL 的细节将在下一章描述。不过呢,总结来说,它使得在box里自动增加了两个按钮。一个 OK 按钮,一个 Cancel 按钮。

+ +

在下一节中,我们将看看该如何 使用 XBL 创建内容

+ +

+

« 上一页下一页 »

+

+ +

/*以下疑似是历史残余链接…*/

+ +

 

diff --git "a/files/zh-cn/mozilla/tech/xul/tutorial/xpcom_\346\216\245\345\217\243/index.html" "b/files/zh-cn/mozilla/tech/xul/tutorial/xpcom_\346\216\245\345\217\243/index.html" new file mode 100644 index 0000000000..fb2dbb3699 --- /dev/null +++ "b/files/zh-cn/mozilla/tech/xul/tutorial/xpcom_\346\216\245\345\217\243/index.html" @@ -0,0 +1,179 @@ +--- +title: XPCOM 接口 +slug: Mozilla/Tech/XUL/Tutorial/XPCOM_接口 +translation_of: Archive/Mozilla/XUL/Tutorial/XPCOM_Interfaces +--- +

 

+ +

+

« 上一页下一页 »

+

+ +

    本章简单的看看 XPCOM (跨平台组件对象模型)——Mozilla 使用的对象系统。

+ +

调用本地对象

+ +

    通过XUL我们可以建立一个复杂的用户界面,我们可以通过脚本来修改界面及处理任务。然而有很多事件是不能有JavaScript直接完成的,比如,我们像创建一个邮件程序,我们需要写一个脚本来连接到服务器发送好接收邮件,而JavaScript没有这个能力。

+ +

    处理这种事情的唯一手段就是用本地代码写一个获得邮件的模块,同时也需要一个用脚本调用本地对象的简单方法。 Mozilla 通过了这样的模型—— XPCOM (Cross-platform Component Object Model)。

+ +
Mozilla 提供了不少XPCOM 组件及接口,并且大多数情况下,你不需要自己完成他们。通过学习本章,你可以在 XULPlanet XPCOM Reference 寻找合适的。
+ +

关于XPCOM

+ +

    Mozilla 是有一系列组件构成的。每一个组件都处理特定的任务。比如,有一个处理菜单,按钮及元素的组件。组件又建立在一系列定义(接口)上。

+ +

    Mozilla 中的接口定义了在一个组件中需要实现的功能,组件是它的代码实现,每一个组件都要实现接口描述的功能。一个组件可以时多个接口,多个组件也可以实现同一个接口。

+ +

    让我们来以‘文件’组件为例,需要创建一个描述‘文件’属性及功能的接口文件。文件需要有文件名、数据、大小等属性;删除、移动、复制等方法。

+ +

    文件接口用字符文件描述而无需实现。实现的工作留给组件来完成,组件需要返回文件名、数据、大小的代码,以及复制、删除等代码。

+ +

    我们不关心组件如何实现,只要它实现了接口。当然我们有不同的实现方法,并且对于不同的平台也会不同。然而,他们必须实现同样的接口,这样我们就可以利用从接口中得到的信息使用组件。

+ +

    Mozilla中接口通常以'nsI'或 'mozI'开头,这样就很容易找出接口。比如 nsIAddressBook 用于地址表, nsISound 用于声音文件 , nsILocalFile 用于本地文件,Mozilla中的接口参见 Interfaces.

+ +

    XPCOM 组件是一种本地实现,也就是说他们可以做 JavaScript 不能做的事情。我们可以调用接口定义的由组件属性的任意方法,比如,如果我们有一个组件,它实现了 nsISound 接口我们就可以用它来放声音。

+ +

创建XPCOM 对象

+ +

调用 XPCOM 组件分三步

+ +
    +
  1. 获取组件
  2. +
  3. 获取组件实现的接口
  4. +
  5. 调用所需函数
  6. +
+ +

    如果我们做了前两步,最后一步可以无限制的使用,例如,我们想要重命名文件,这个方法定义在nsILocalFile 接口中。第一步得到文件组件。第二步,我们获取它实现了的nsILocalFile 接口,最后,调用接口通过的方法。这个接口用于代表单个文件。

+ +

    我们知道接口长椅 'nsI' 或 'mozI'开头。组件通常像使用URI一样来引用,Mozilla 储存了当前注册的组件列表。像插件一样,用户可以添加新的组件。

+ +

    Mozilla 通过了一个文件组件,它实现了 nsILocalFile。可以通过'@mozilla.org/file/local;1'引用,这个字符串称作协议ID,语法如下:

+ +
@<internetdomain>/module[/submodule[...]];<version>[?<name>=<value>[&<name>=<value>[...]]]
+
+ +

    其他组件也按相似的方法引用。

+ +

    组件的协议 ID 用于获取组件,可以用下面的脚本得到组件。

+ +
var aFile = Components.classes["@mozilla.org/file/local;1"].createInstance();
+
+ +

    一个文件组件返回并储存在变量 aFile 中,上例中的 Components 引用一个提供相关功能的全局对象。 这里,使用 classes 方法获得组件组,classes 方法返回可用组件的数组。得到不同的组件只需把双引号中的需要ID换成你需要的,最后用createInstance()方法创建实例。

+ +

    你需要检查 createInstance() 的返回值以确保非空,如果为空则表示所需组件不存在。

+ +

    当然,到此为止,我们只引用了文件组件本身,为了使用它的函数,我们需要得到它的接口,本例为 nsILocalFile。我们再加一行。

+ +
var aFile = Components.classes["@mozilla.org/file/local;1"].createInstance();
+if (aFile) aFile.QueryInterface(Components.interfaces.nsILocalFile);
+
+ +

     QueryInterface() 是一个所以组件都通过的函数来返回特定的接口。函数有一个参数,你想得到的接口Componentsinterfaces 方法包含一个可用接口的数组,这里把 nsILocalFile 作为参数传给 QueryInterface()。结果是aFile会引用它所实现了 nsILocalFile 接口的那部分。

+ +

    上面的两行脚本可以用于获取任何组件及接口,只需更换组件名及接口名。下例,获得一个 sound 接口。

+ +
var sound = Components.classes["@mozilla.org/sound;1"].createInstance();
+if (sound) sound.QueryInterface(Components.interfaces.nsISound);
+
+ +

    XPCOM 接口可以继承其它的接口。这种接口拥有它自己的功能及它所继承的接口的功能所有的接口都继承自顶级接口nsISupports,它有一个函数由于支持JavaScript—— QueryInterface()。因为所以的组件都实现 nsISupports 接口所以QueryInterface()对每个组件都有效。

+ +

    一些组件可能会实现相同的接口。他们可能是原件的子类但不是必须的。组件可能都会实现 nsILocalFile接口,另外一个组件可能会实现多个接口。因为这个原因我们在调用函数之前需要得到定义函数的接口。

+ +

    这里有一个简写形式,不过一般的我们把它分成多行。

+ +
var aLocalFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
+
+ +

    这一行代码完成了上面两行所做的事。

+ +

    如果你使用 QueryInterface() 引用一个本组件没有实现的接口,会抛出一个异常。如果不确定组件支持哪个接口请使用 instanceof 操作符检查。

+ +
var aFile = Components.classes["@mozilla.org/file/local;1"].createInstance();
+if (aFile instanceof Components.interfaces.nsILocalFile){
+  // do something
+}
+
+ +

    如果aFile实现nsILocalFile 接口 instanceof返回真,在块中就可以调用 QueryInterface()

+ +

调用接口函数

+ +

    现在你有了一个关联到 nsILocalFile 接口组件的一个引用,你就可以调用nsILocalFile通过的函数。下面列出了 nsILocalFile提供的属性及方法。

+ +
+
initWithPath 
+
此方法用于初始化文件名及路径,第一个参数是文件路径如 '/usr/local/mozilla'.
+
leafName 
+
除去文件路径的文件名。
+
fileSize 
+
文件尺寸。
+
isDirectory() 
+
 nsILocalFile 代表目录返回真。
+
remove(recursive) 
+
删除一个文件。如果recursive 参数为true,一个目录及其中的所以文件包括子目录均被删除。
+
copyTo(directory,newname) 
+
把文件复制到新目录,并随意更改文件名。目录应保存在 nsILocalFile对象中。
+
moveTo(directory,newname) 
+
把文件移到新目录或重命名。 目录应保存在 nsILocalFile对象中。
+
+ +

    为了删除文件,需要将其赋值给 nsILocalFile。我们可以使用initWithPath() 方法指明所需文件,然后调用 remove() 函数,它带一个参数;是否递归删除,如下例。

+ +
var aFile = Components.classes["@mozilla.org/file/local;1"].createInstance();
+if (aFile instanceof Components.interfaces.nsILocalFile){
+  aFile.initWithPath("/mozilla/testfile.txt");
+  aFile.remove(false);
+}
+
+ +

    以上代码会定位 /mozilla/testfile.txt 并删除它。试着把它与事件处理相连。你可以把文件名改为一个需要删除的文件并把它删除。

+ +

    上面的函数中 copyTo() 及moveTo()可以用于复制及移动文件。注意他们移动的目标目录不是保存在字符串中而是nsILocalFile,也就是说你需要两个文件字节,下面是一个复制文件的例子。

+ +
function copyFile(sourcefile,destdir)
+{
+  // get a component for the file to copy
+  var aFile = Components.classes["@mozilla.org/file/local;1"]
+    .createInstance(Components.interfaces.nsILocalFile);
+  if (!aFile) return false;
+
+  // get a component for the directory to copy to
+  var aDir = Components.classes["@mozilla.org/file/local;1"]
+    .createInstance(Components.interfaces.nsILocalFile);
+  if (!aDir) return false;
+
+  // next, assign URLs to the file components
+  aFile.initWithPath(sourcefile);
+  aDir.initWithPath(destdir);
+
+  // finally, copy the file, without renaming it
+  aFile.copyTo(aDir,null);
+}
+
+copyFile("/mozilla/testfile.txt","/etc");
+
+ +

XPCOM 服务器

+ +

    一些 XPCOM 组件是被称为服务器的特殊组件,你无需创建他们因为他们只能存在一个副本。服务器提供了类似于读取,设置全局数据或操作其他对象的方法。我们使用getService()代替 createInstance()方法来获取服务器组件,除此以外,服务器并没有与其他组件相异之处。

+ +

    如Mozilla通过了一个书签服务器,它允许你向当前用户的书签列表中添加书签。如下例。

+ +
var bmarks = Components.classes["@mozilla.org/browser/bookmarks-service;1"].getService();
+bmarks.QueryInterface(Components.interfaces.nsIBookmarksService);
+bmarks.addBookmarkImmediately("http://www.mozilla.org","Mozilla",0,null);
+
+ +

    首先组件 "@mozilla.org/browser/bookmarks-service;1"被返回,并保存在变量 bmarks中,我们使用 QueryInterface() 得到 nsIBookmarksService 接口。这个接口通过的addBookmarkImmediately() 函数用于添加书签。函数的前两个参数是书签的 URL 和标题。第三个参数是书签类型通常是 0 ,最后一个参数是书签页的字符集,可为空。

+ +

    下一章看看Mozilla为我们通过的接口。 interfaces provided with Mozilla that we can use.

+ +

+

« 上一页下一页 »

+

+ +

diff --git a/files/zh-cn/mozilla/tech/xul/tutorial/xul_structure/index.html b/files/zh-cn/mozilla/tech/xul/tutorial/xul_structure/index.html new file mode 100644 index 0000000000..5983802be3 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/tutorial/xul_structure/index.html @@ -0,0 +1,43 @@ +--- +title: XUL_教程/XUL的结构 +slug: Mozilla/Tech/XUL/Tutorial/XUL_Structure +tags: + - XUL_Tutorial +translation_of: Archive/Mozilla/XUL/Tutorial/XUL_Structure +--- +

+

下一页 »

+

+

 

+

XUL是怎么被处理的?

+

XUL与HTML的处理方式一样,先读出内容,然后解析为一棵对象树,再对每个对象作处理,使其显示出来。因为XUL是用来定义用户界面的,因此它与HTML用来做显示的功能一样。实际上,在Mozilla中,HTML和XUL,甚至SVG都是使用同样的底层代码来处理的。这样意味着一些CSS属性(注意是属性,不是CSS的全部)可以用在HTML和XUL。XUL同HTML一样可以从本地文件系统或web页面读取(不过这样多少有些功能上的限制)。另外就是打成一个包,可以让别人下载和安装。安装后的包就可以有一些更强的权限,象读文本文件,读用户参数和bookmark,以及访问其它系统特性。

+

包注册就是Firefox扩展的安装方式。包是由XUL、Javascript、CSS、HTML和图片等构成。文件名后缀为.xpi,它其实是一个zip格式的压缩包。象Firefox的扩展一般是通过overlay的方式,对Firefox进行扩展的,如增加菜单、工具条等。但这些功能的代码其实是与浏览器分离的,而且卸载也很容易(就象NewEdit中的插件一样)。

+

注册的包不一定要使用overlay的扩展方式(overlay是对已经存在的应用的扩展)。但这样,你就不能直接通过浏览器来使用这些功能。但你仍然可以使用称为chrome(增色) URL的方式来调用注册包。这种chrome URL的形式为"chrome://"。它用来指示安装的包和扩展。

+

通过chrome方式来访问可以获得比http方式更多的权限,而通过这种方式,你就可以做访问本地文件等操作。这一点非常重要,权限的区分是通过URL的类型来实现的。通过http方式访问HTML和XUL,没有这些特别的权限,而通过chrome方式访问,HTML和XUL都具有这样的权力。

+

Mozilla浏览器本身就是由许多的包构成的。而这些文件就是通过chrome URL来访问的,以获得特别的权限。

+

Mozilla中有三种主要的文档类型:HTML, XUL和XML。它们之间有些是可能共享的特性,有些是不能共享的,使用时要注意。

+

小结:

+

Mozilla使用同样的引擎来渲染HTML和XUL,使用CSS来指明它们的外观。 XUL可以从web站点、本地文件系统,或作为包被安装并通过chrome URL来访问(这就是浏览器扩展所做的方式)。 Chrome URL可以用来访问安装的包,并且使用特别的权限来打开它们。 HTML、XUL、XML有不同的文档类型。一些特性是互通的,然而另一些特性是各自的。

+

包的组织

+

由Mozilla提供的包可以在Mozilla的安装目录下的chrome子目录中找到。但仅仅把文件拷贝到chrome目录下是不会赋给它任何的权限,也不可以通过chrome URL来访问的,还需要配置才可以。需要按照chrome包格式的要求来组织才可以。

+

一个包的文件通常被组织为一个JAR文件。注意,很象Java中的Jar包,都是Zip格式的。但里面可不是Java程序。这也造成了某些人认为开发扩展需要懂Java,其实不是的。只是后缀与Java一样。(不清楚为什么用这个后缀)同时,也可以不打成一个JAR包,就是展开的目录也可以(如果你看到另一个教程XUL App Tutorial,你会看到就没有打成一个JAR包)。

+

通常一个chrome包有三个目录,但它们都是可选的,分别为:content、skin和locale。

+ +

用户界面的定义都放在XUL文件中,这些文件都以.xul为后缀。一个content目录下可以有多个XUL文件,但主窗体文件名必须与包名相同。例如editor包必须有一个叫做editor.xul的文件。其它的脚本文件(一般是.js文件,Javascript)也放在这个目录下。

+ +

样式表用来描述窗口显示的外观。它们与XUL分离,可以灵活地修改程序的外观。

+ +

所有界面中用到的文本都放在这里。如果支持多国语言,它们将按语言种类进行组织。只要在这里进行翻译即可实现多语言。 同时在每个目录下还应该有一个名为:contents.rdf的文件,它用来描述相关目录的信息清单。Mozilla将读取它,并使用它的内容来注册包,并给这个包分配一个chrome URL,这样这些文件就可以通过这个chrome URL来访问了。如果没有contents.rdf文件,这个包就不能被分配一个chrome URL,因此也就不能通过chrome来访问了。同时要注意,只有你需要通过chrome URL来访问的目录才需要contents.rdf文件,不需要访问的目录可能不要。再有,如果一个目录下还有子目录,但子目录通过与父目录相同的chrome URL来访问,子目录也可以不要contents.rdf文件。

+

在locale目录中,语言化文件有两种形式:DTD和属性(properties)文件。DTD(Document Type Definition,文档类型定义)是XML中常用的文件,它一般是用来定义XML中的元素规则,还可以用来定义XML中出现的实体(entity)元素。XUL要使用DTD中的实体声明,用来显示文本信息。因此如果想实现多语言,就要按语种创建子目录,生成多个DTD文件。属性文件是给脚本使用的。

+

Mozilla中的包通常是放在chrome目录下,但是你也可以不放在这个目录下,而是放在磁盘任意的地方。在chrome目录下的chrome.rdf文件保存了安装了的包、skin、locale的列表及它们的位置。放在chrome下是最常见的。对于存在多种skin和locale的情况,chrome.rdf中保存了激活的配置。

+

 

+

+

下一页 »

+

+

diff --git "a/files/zh-cn/mozilla/tech/xul/tutorial/\346\233\264\345\244\232\347\232\204\346\214\211\351\222\256\347\211\271\346\200\247/index.html" "b/files/zh-cn/mozilla/tech/xul/tutorial/\346\233\264\345\244\232\347\232\204\346\214\211\351\222\256\347\211\271\346\200\247/index.html" new file mode 100644 index 0000000000..4a72667660 --- /dev/null +++ "b/files/zh-cn/mozilla/tech/xul/tutorial/\346\233\264\345\244\232\347\232\204\346\214\211\351\222\256\347\211\271\346\200\247/index.html" @@ -0,0 +1,68 @@ +--- +title: XUL_教程/更多的按钮特性 +slug: Mozilla/Tech/XUL/Tutorial/更多的按钮特性 +tags: + - XUL_教程 +translation_of: Archive/Mozilla/XUL/Tutorial/More_Button_Features +--- +

+

« 上一页下一页 »

+

+

 

+

添加图像

+

你可以使用image属性通过指定URL为按钮添加一个图像。图像从URL进行加载,可以是一个相对或绝对的URL路径,然后在按钮上显示图像。 下面的按钮有labelimage 'happy.png'。图像显示在标签的左边。你可以使用其它两个属性去改变这个位置。这将会在后面进行解释。

+

例1 : Source View

+
<button label="help" image="happy.png"/>
+
+

使用CSS图像的按钮

+

在按钮上指定图像的另一个方法是使用样式表(CSS list-style-image )属性。这将计划允许不改变XUL文件去改变"外观"(在这个例子,外观指按钮的图片)。

+

例2 : Source View

+
<button id="find-button"
+  label="Find" style="list-style-image: url('happy.png')"/>
+
+

在这个例子,在按钮上显示图像 'happy.png'。 style属性的功能类似于在HTML中一样。通常,它可以使用在所有的XUL元素。注意你确实应该在一个分离的样式表里定义样式。

+

图像定位

+

默认情况下,按钮上的图像会放置在文本标签的左边。有两个属性可以用来控制定位。

+

dir属性控制图像和文本的方向。设置这个属性的值为reverse,图像将会放在文本的右边。使用normal值,或者删除这个属性,图像将会放在文本的左边。

+

orient属性用于在将图片放在文本的上面或下面。默认值是horizontal用于将用于将图像放在文本的左或右。你也可以使用值vertical将图像放在上方或下方。在这个例子,dir属性控制放置在上方或下方。相同的值被使用时,如果用在normal的意思是将图像放在文本的上方,而用在reverse的意思是将图像放在文本的下方。

+

例3 : Source View

+
+ Image:advbtns1.png
+
<button label="Left" image="happy.png"/>
+<button label="Right" image="happy.png" dir="reverse"/>
+<button label="Above" image="happy.png" orient="vertical"/>
+<button label="Below" image="happy.png" orient="vertical" dir="reverse"/>
+
+


+ 这个例子展示了四个连续的不同类型的按钮。注意两个属性都没有指定说明使用的是默认值。

+

特殊内容按钮

+

按钮可以在内部包含任意的标记元素,这些元素将会被渲染在按钮内部。你或许不会经常使用这个,但你可以在创建自定义元素时使用它。

+

例如,下面将创建一个有两个红字的按钮:

+

例4 : Source View

+
<button>
+  <description value="This is a"/>
+  <description value="rather strange" style="color: red;"/>
+  <description value="button"/>
+</button>
+
+

任何XUL元素都可以放在button里面。HTML元素将被忽略,因此你需要使用description元素来包装它来达到换行的目的。如果你在按钮上指定label属性,它将会覆盖按钮内的所有内容。

+

弹出菜单按钮

+

你可以在按钮里面放置一个menupopup去促使在按钮被按下时向下弹出一个菜单,就像使用 menulist。然而,在这个例子你必须设置type 属性的值为menu

+

例5 : Source View

+
+ Image:advbtns2.png
+
<button type="menu" label="Device">
+  <menupopup>
+    <menuitem label="Printer"/>
+    <menuitem label="Mouse"/>
+    <menuitem label="Keyboard"/>
+  </menupopup>
+</button>
+
+

在这个例子中,用户可以点击按钮去弹出一个包括三个项目的菜单。注意在选择这些菜单项之中的一个时不会改变按钮的标签,不像menulist那样。这种按钮类型是有意做成类似于菜单的,在每个项目上附上脚本去执行任务。我们将会在后面看到更多的菜单。

+

你也可以设置 type 属性的值为menu-button。这也可以创建一个像菜单的按钮,但显示会有所不同,右边的图像显示它们的区别。左边是一个'menu'而第二个是'menu-button'。 它有一个箭头标记菜单的存在。 在'menu'上,用户可以点击按钮的任何地方去显示菜单。在 'menu-button'上,用户点击箭头去显示菜单。

+

接下来,我们将要学习更多关于 在窗口中放置元素.

+

+

« 上一页下一页 »

+

+

diff --git a/files/zh-cn/mozilla/tech/xul/vbox/index.html b/files/zh-cn/mozilla/tech/xul/vbox/index.html new file mode 100644 index 0000000000..eb23c89d10 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/vbox/index.html @@ -0,0 +1,130 @@ +--- +title: vbox +slug: Mozilla/Tech/XUL/vbox +tags: + - XUL Elements + - XUL Reference +translation_of: Archive/Mozilla/XUL/vbox +--- +
+ « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+ +

A container element which can contain any number of child elements. This is equivalent to the box element, except it defaults to vertical orientation.
+ 一个可以包含任何子元素的容器元素。这相当于默认为垂直方向的box 元素。

+ +

More information is available in the XUL tutorial.
+ 更多信息参考XUL tutorial

+ +

Example

+ +

示例

+ +

vbox example

+ +
<!-- Two labels at bottom -->
+<vbox>
+  <spacer flex="1"/>
+  <label value="One"/>
+  <label value="Two"/>
+</vbox>
+
+ +

Attributes

+ +

属性

+ +

+ + + + + +

Inherited from XUL element
+align, +allowevents, +allownegativeassertions, +class, +coalesceduplicatearcs, +collapsed, +container, +containment, +context, +contextmenu, +datasources, +dir, +empty, +equalsize, +flags, +flex, +height, +hidden, +id, +insertafter, +insertbefore, +left, +maxheight, +maxwidth, +menu, +minheight, +minwidth, +mousethrough, +observes, +ordinal, +orient, +pack, +persist, +popup, +position, +preference-editable, +querytype, +ref, +removeelement, +sortDirection, +sortResource, +sortResource2, +statustext, +style, +template, +tooltip, +tooltiptext, +top, +uri, +wait-cursor, +width

+

+ +

Properties

+ +

特性

+ +

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+ +

Methods

+ +

方法

+ +

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ + + +

相关

+ +
+
Elements
+ 元素
+
box, hbox
+
+ +

 

+ +
 
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/window/index.html b/files/zh-cn/mozilla/tech/xul/window/index.html new file mode 100644 index 0000000000..f748259648 --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/window/index.html @@ -0,0 +1,281 @@ +--- +title: window +slug: Mozilla/Tech/XUL/window +translation_of: Archive/Mozilla/XUL/window +--- +
+ « XUL Reference home [ + 示例 | + 属性 | + 特性 | + 方法 | + 相关 ] +
+ +

window标签用来描述一个窗口的顶级结构,在 XUL文档中,他是一个根节点。默认情况下,它里面的控件是水平排列的。作为一个box容器, box的属性都可以被使用. 默认的, 窗口将有一个特定于平台的框架围绕着他。

+ +

如果需要给窗口添加一个图标,你需要首先创建一个 icon 文件,也就是例如 <windowid>.ico<windowid>.xpm ,然后将他们放置到 项目文件夹的/chrome/icons/default/ 目录下. 这里所说的的 <windowid> 是此窗口内window标签的id. 这样,您就能为每个窗口设置不同的图标了。

+ +

如果没有将 "chrome://global/skin/"下的指定css文件引用进来, 此窗口将不能正常加载 ,有可能看不见 或者被打开的时候出现漏洞.

+ +
+

注意: 通过Gecko 1.9.2标记, 当一个窗口通过查看动作引起的“激活”或“失活”事件被“激活”或“失活”时,你可以侦测到。这方面的信息,请查看  窗口激活事件.

+
+ +

更多的信息请查看 XUL tutorial.

+ +
+
标记属性
+
accelerated, chromemargin, disablechrome, disablefastfind, drawintitlebar, fullscreenbutton, height, hidechrome, id, lightweightthemes, lightweightthemesfooter, screenX, screenY, sizemode, title, width, windowtype
+
+ +

实例

+ +
<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<!-- Extremely recommended to keep this css include!! -->
+<window id="rootWnd" title="Register Online!"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <vbox>
+    <hbox>
+      <image src="application_form.png"/>
+      <description>Register Online!</description>
+    </hbox>
+    <groupbox align="start">
+      <caption label="Your Information"/>
+      <radiogroup>
+        <vbox>
+          <hbox>
+            <label control="your-fname" value="Enter first name:"/>
+            <textbox id="your-fname" value="Johan"/>
+          </hbox>
+          <hbox>
+            <label control="your-lname" value="Enter last name:"/>
+            <textbox id="your-lname" value="Hernandez"/>
+          </hbox>
+          <hbox>
+            <button oncommand="alert('save!')">
+              <description>Save</description>
+            </button>
+          </hbox>
+        </vbox>
+      </radiogroup>
+    </groupbox>
+  </vbox>
+</window>
+
+ +

标记属性

+ +

+
accelerated
Type: boolean
Set this attribute to true to allow hardware layer managers to accelerate the window.
+
+ +
+
+ activetitlebarcolor
+
+ Type: color string
+
+ Specify background color of the window's titlebar when it is active (foreground). Moreover this hides separator between titlebar and window contents. This only affects Mac OS X.
+
+ +

 

+
+ +
chromemargin
Type: margin string
Controls the amount of chrome that should be visible on each side of the window. The specified string should contain four numbers, separated by commas, indicating the margin in pixels for the top, right, bottom, and left edges of the window, respectively. This value may be -1 to use the default margin for that side on the current platform, 0 to have no system border (that is, to extend the client area to the edge of the window), or a value greater than zero to indicate how much less than the default default width you wish the margin on that side to be. If this value turns out to be less than 0, 0 is used.
+
+
+ +
disablechrome
Type: boolean
Set this attribute to true to disable chrome in the window. This is used to hide chrome when showing in-browser UI such as the about:addons page, and causes the toolbars to be hidden, with only the tab strip (and, if currently displayed, the add-on bar) left showing.
Note: This has no effect if the tabs on top preference is turned off.
+
+
+
disablefastfind
Type: boolean
Put disablefastfind="true" on the root element of a XUL document, which is intended to be loaded in a tab, to disable the find bar for the tab with this document. This is used to prevent the find bar from being displayed when it's not supported by the content (such as in the Add-ons manager tab).
+
+ +
drawintitlebar
Type: boolean
If this attribute is true, the top of the window's content area will begin at the top edge of the title bar, instead of below the title bar. This allows the window to draw in the title bar. This is supported only from window elements, and is ignored on platforms that don't support drawing into the title bar.
+
+
+ +
fullscreenbutton
Type: boolean
Set this attribute to true to display a button in the window chrome to allow the user to switch the window into full screen mode. Supported on Mac OS X 10.7 Lion and later and on Windows. The window receives a "fullscreen" event once the change has been made.
+
+
+ + +
+
height
+
Type: string (representing an integer)
+
The preferred height of the element in pixels. The actual displayed height may be different if the element or its contents have a minimum or maximum height. The CSS height property may also be used.
+
+
+ + +
+
hidechrome
+
Type: boolean
+
Set this attribute to true to have the chrome including the titlebar hidden.
+
+
+ +
+
+ id
+
+ 类型: 元素的ID,在主窗口中必须唯一
+
+ 一个唯一的标识一边开发者能够定义. 你可以使用方法 getElementById() 或者其他 DOM 的函数并在样式表中添加对元素的引用。
+
+ +

+
+ + +
+
inactivetitlebarcolor
+
Type: color string
+
Specify background color of the window's titlebar when it is inactive (background). Moreover this hides separator between titlebar and window contents. This affects only on Mac OS X.
+
+
+ +
lightweightthemes
Type: boolean
true if the window supports lightweight themes, otherwise false.
+
+
+ +
lightweightthemesfooter
Type: id
Specifies the ID of an element to which a lightweight theme's footer image will be applied.
+
+
+ + +
+
screenX
+
Type: integer
+
The horizontal position at which the window appears on the screen.
+
+
+ + +
+
screenY
+
Type: integer
+
The vertical position at which the window appears on the screen.
+
+
+ + +
+
sizemode
+
Type: one of the values below
+
The state of the window. It can have one of the following values:
+
+
+
maximized
+
The window is maximized, and occupies the full size of the screen.
+
normal
+
The window appears in a normal state at the desired size.
+
+
+
+ +

This attribute is used to save and restore the state of a window (together with the persist attribute) and for CSS styles (e.g. to hide the resizer grippy on maximized windows).

+ +
Note: When a window is minimized, the sizemode attribute is not updated. This is done so that if a window is closed while minimized, its persisted sizemode attribute wouldn't be minimized.
+ +

Setting this attribute does not change the window state. Use window.maximize(), window.restore(), or window.minimize() to change the window state.

+ +

To get the window state from JavaScript code, use window.windowState. Listen to the sizemodechange event dispatched to the DOM window to get notified when the window state changes.

+ + +
+ + +
+
title
+
Type: string
+
The text to appear in the title bar of the window.
+
+
+ + +
+
width
+
Type: string (representing an integer)
+
The preferred width of the element. The value should not include a unit as all values are in pixels. The actual displayed width may be different if the element or its contents have a minimum or maximum width, or the size is adjusted by the flexibility or alignment of its parent. The CSS width property may also be used.
+
+ + +
+ +
+
+ windowtype
+
+ Type: string
+
+ Set to a string which can be used to identify the type of window. This might be used, for example, to distinguish between a browser window and an editor window. Some of Mozilla's window handling functions use this attribute to group windows of the same type together.
+
+
+

Values for window type as found on MXR: http://mxr.mozilla.org/mozilla-release/search?string=windowtype

+

navigator:browser - Looks like if window has gBrowser it has this window type

+

devtools:scratchpad - Scratchpad windows

+

navigator:view-source - The view source windows

+
+ +

 

+

+ +

属性

+ +

+

Inherited Properties
align, , allowEvents, , boxObject, builder, , , , className, , , , , collapsed, contextMenu, controllers, database, datasources, dir, , , flex, height, hidden, id, , , left, , maxHeight, maxWidth, menu, minHeight, minWidth, , , , , , , observes, ordinal, orient, , pack, , persist, , , , ref, resource, , , , , statusText, style, ,, tooltip, tooltipText, top, width

+ +

方法

+ +

+

Inherited from XUL element
blur, click, doCommand, focus, getElementsByAttribute

Inherited from DOM element
addEventListener(), appendChild(), dispatchEvent(), getAttribute(), getAttributeNode(), getAttributeNodeNS(), getAttributeNS(), getElementsByTagName(), getElementsByTagNameNS(), hasAttribute(), hasAttributeNS(), hasAttributes(), hasChildNodes(), insertBefore(), isSupported(), normalize(), removeAttribute(), removeAttributeNode(), removeAttributeNS(), removeChild(), removeEventListener(), replaceChild(), setAttribute(), setAttributeNode(), setAttributeNodeNS(), setAttributeNS()

+ +

另请参阅: DOM window object methods 

+ +

请注意

+ +

DTD文件如果丢失或者不可访问,而XUL文件中却引用了其中的内容,将会引起 "XML Parsing Error: undefined entity...<window" 的错误。DOCTYPE声明中系统关键字后如果含有文件名,将会引起没有提示的加载失败, 而唯一的错误提示将会是在下一个XUL元素加载时出现未定义实体的错误。

+ + + +
+
prefwindow, dialog, dialogheader
+
+ +

相关的话题

+ +
+
+ +

用户注意事项

+ +

如果要更改窗口标题栏中的图标, 请参考这里: Window icons.

+ +

如果要将小图标添加到地址栏和浏览器选项卡(即对话框不是弹出),请使用下面的代码片段来使用html名称空间和链接。

+ +
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	xmlns:html="http://www.w3.org/1999/xhtml">
+
+<!-- Icon from chrome -->
+<html:link rel="icon" href="chrome://myExtension/content/path/to/favicon.png"/>
+
+<!-- From a remote site -->
+<html:link rel="icon" href="http://www.mozilla.org/favicon.ico"/>
+
+ +

由于Firefox3.6之前的代码不能正常工作 ——会出现以下提示: "Warning: XUL box for box element contained an inline link child, forcing all its children to be wrapped in a block". 如果这段代码放在window标签之间, 它将会使窗口内的所有其他控件都变得乱七八糟.而如果放在 box 标签之间, 窗口控件呈现反而很不错, 但是依然会引起错误。 这一问题可以如下解决:

+ +
<html:link rel="icon" href="chrome://myExtension/content/path/to/favicon.png" style="display:none"/>
+
+ +

or

+ +
<html:head>
+  <html:link rel="icon" href="chrome://myExtension/content/path/to/favicon.png"/>
+</html:head>
+
+ +

diff --git a/files/zh-cn/mozilla/tech/xul/xul_reference/index.html b/files/zh-cn/mozilla/tech/xul/xul_reference/index.html new file mode 100644 index 0000000000..829a2a260e --- /dev/null +++ b/files/zh-cn/mozilla/tech/xul/xul_reference/index.html @@ -0,0 +1,20 @@ +--- +title: XUL Reference +slug: Mozilla/Tech/XUL/XUL_Reference +tags: + - XUL + - XUL Reference +translation_of: Archive/Mozilla/XUL/XUL_Reference +--- +

« XUL Reference «

+ +
全部 XUL 元素 (按英文字母顺序排列)

action
arrowscrollbox
assign
bbox
binding
bindings
box
broadcaster
broadcasterset
button
browser
checkbox
caption
colorpicker
column
columns
commandset
command
conditions
content
datepicker
deck
description
dialog
dialogheader
dropmarker
editor
grid
grippy
groupbox
hbox
iframe
image
key
keyset
label
listbox
listcell
listcol
listcols
listhead
listheader
listitem

member
menu
menubar
menuitem
menulist
menupopup
menuseparator
notification
notificationbox
observes
overlay
page
panel
param
popupset
preference
preferences
prefpane
prefwindow
progressmeter
query
queryset
radio
radiogroup
resizer
richlistbox
richlistitem
row
rows
rule
scale
script
scrollbar
scrollbox
scrollcorner
separator
spacer
spinbuttons
splitter
stack
statusbar

statusbarpanel
stringbundle
stringbundleset
tab
tabbrowser (Firefox 3/Gecko 1.9 开始只用于Firefox本身)
tabbox
tabpanel
tabpanels
tabs
template
textnode
textbox
textbox (Firefox autocomplete)
textbox (Mozilla autocomplete)
timepicker
titlebar
toolbar
toolbarbutton
toolbargrippy
toolbaritem
toolbarpalette
toolbarseparator
toolbarset
toolbarspacer
toolbarspring
toolbox
tooltip
tree
treecell
treechildren
treecol
treecols
treeitem
treerow
treeseparator
triple
vbox
where
window
wizard
wizardpage

+

XUL 参考

+

« XUL Reference «

+ +
XUL 要素 (按类别排序)

WINDOWS

dialog
overlay
page
window
wizard
wizardpage
preference
preferences
prefpane
prefwindow

WINDOW STRUCTURE

browser
tabbrowser
editor
iframe
titlebar
resizer
statusbar
statusbarpanel
dialogheader
notification
notificationbox

MENUS AND POPUPS

menubar
menu
menuitem
menuseparator
menupopup
panel
tooltip
popupset

TOOLBARS

toolbar
toolbarbutton
toolbargrippy
toolbaritem
toolbarpalette
toolbarseparator
toolbarset
toolbarspacer
toolbarspring
toolbox

TABS AND GROUPING

tabbox
tabs
tab
tabpanels
tabpanel
groupbox
caption
separator
spacer

CONTROLS

button
checkbox
colorpicker
datepicker
menulist
progressmeter
radio
radiogroup
scale
splitter
textbox
textbox (Firefox autocomplete)
textbox (Mozilla autocomplete)
timepicker

TEXT AND IMAGES

description
label
image

LISTS

listbox
listitem
listcell
listcol
listcols
listhead
listheader
richlistbox
richlistitem

TREES

tree
treecell
treechildren
treecol
treecols
treeitem
treerow
treeseparator

 

LAYOUT

box
hbox
vbox
bbox
deck
stack
grid
columns
column
rows
row
scrollbox

TEMPLATES

action
assign
binding
bindings
conditions
content
member
param
query
queryset
rule
template
textnode
triple
where

SCRIPTING

script
commandset
command
broadcaster
broadcasterset
observes
key
keyset
stringbundle
stringbundleset

HELPER ELEMENTS

arrowscrollbox
dropmarker
grippy
scrollbar
scrollcorner
spinbuttons

+

更多XUL相关列表

+ +

+
diff --git a/files/zh-cn/mozilla/thunderbird/index.html b/files/zh-cn/mozilla/thunderbird/index.html new file mode 100644 index 0000000000..58129cc9e5 --- /dev/null +++ b/files/zh-cn/mozilla/thunderbird/index.html @@ -0,0 +1,75 @@ +--- +title: Thunderbird +slug: Mozilla/Thunderbird +translation_of: Mozilla/Thunderbird +--- +

Thunderbird 是Mozilla的电子邮件/消息应用程序。These pages document Thunderbird and also provide links to documentation about the MailNews backend which is also used in other projects such as Eudora/Penelope, Seamonkey, Correo, etc.

+

Thunderbird is Firefox's kid sibling, and is built on the same technical platform as the web browser. In development for many years, and currently one of the most popular open source email clients, it is used by millions of people around the world to bring together all their email accounts, newsgroup and feed reading in a familiar high-productivity environment.  (From early 2007 to early 2011 Thunderbird was developed by Mozilla Messaging, a subsidiary that was owned by Mozilla.)

+ + + + + + + +
+

文档

+
+
+ Building Thunderbird
+
+ Information about building Thunderbird with the comm-central repository. There's also information about how comm-central works, how the review process works and how to use the Mozilla symbol server to help with debugging.
+
+ MailNews Protocols
+
+ Rough documentation about mail protocols..
+
+ Database views
+
+ Backend information about {{ Interface("nsIMsgDBView") }} and related interfaces..
+
+ Thunderbird API documentation
+
+ Thunderbird API documentation
+
+ Extension documentation
+
+ Tutorials and tips for building Thunderbird extensions
+
+ Automated Testing
+
+ Details of Thunderbird's automated testing facilities
+
+ Thunderbird in the Enterprise
+
+ Help with deploying Thunderbird in large organizations
+
+

View All...

+
+

社区

+ +

工具

+ + + +
+

 

diff --git a/files/zh-cn/mozilla/thunderbird/mail_client_architecture_overview/index.html b/files/zh-cn/mozilla/thunderbird/mail_client_architecture_overview/index.html new file mode 100644 index 0000000000..b289702d64 --- /dev/null +++ b/files/zh-cn/mozilla/thunderbird/mail_client_architecture_overview/index.html @@ -0,0 +1,94 @@ +--- +title: Mail client architecture overview +slug: Mozilla/Thunderbird/Mail_client_architecture_overview +translation_of: Mozilla/Thunderbird/Mail_client_architecture_overview +--- +

{{ outdated("It was imported from mozilla.org and last updated in 2002. All of the links seem to be broken.") }}

+ +

The mail reader

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Gecko (XUL and HTML rendering)
+
+
RDF(dynamic widgets)
+
+
JS(menus, events)
+
+
libmime
+
+
Mail Datasources
+
+
Mail JavaScript
+
+
Folder/Message management
+
msgdb +
 
+
+
IMAP/NNTP/POP3
+
+
Necko(networking)
+
+ +

 灰色 带黑框的表示mail/news之外的模块。

+ +

 

+ +

The base Module

+ +

 

+ +

基础模块提供了一个协议无关的消息服务接口。包括帐户、文件夹和消息管理。

+ +

The base module consists of the following basic building blocks

+ + + +

There are also a number of protocol independant subsystems that have a symbiotic relationship with base:

+ + + +

Finally, there are larger modules outside of the mail client that are mail-oriented. Most of these modules have little dependancy on the mail reader itself:

+ + diff --git a/files/zh-cn/mozilla/thunderbird/mailnews_protocols/index.html b/files/zh-cn/mozilla/thunderbird/mailnews_protocols/index.html new file mode 100644 index 0000000000..b6b0c4873f --- /dev/null +++ b/files/zh-cn/mozilla/thunderbird/mailnews_protocols/index.html @@ -0,0 +1,31 @@ +--- +title: MailNews Protocols +slug: Mozilla/Thunderbird/MailNews_protocols +translation_of: Mozilla/Thunderbird/MailNews_protocols +--- + + +

除了RSS,这些协议以C++实现。 RSS以JS 实现,而且实现模式和其他以C++实现的协议不同。

+ +

IMAP、POP3和NNTP 是 "incoming" 协议,即从服务器获取消息, 并以文件夹的形式展现给用户。这些协议在mailnews相应的协议子目录中定义(即 mailnews/imap, mailnews/local (for pop3), mailnews/news),均有如下的类组成:

+ +

An incoming server class, which implements nsIMsgIncomingServer and inherits from mailnews/base/util/nsMsgIncomingServer, i.e.., nsPop3IncomingServer, nsImapIncomingServer, nsNNTPIncomingServer.

+ +

A folder class, which implements nsIMsgFolder, and inherits from nsMsgDBFolder. Most commands/operations go through the folder object. nsImapMailFolder, nsNewsFolder, nsLocalMailFolder (for POP3)

+ +

A service class, which generally sits between the folder object or the server object, and the protocol object. The service class creates and initializes the url object for the operation, and hands that off to a protocol object to run. The service classes usually have their own interface, but they also implement nsIMsgMessageService.

+ +

A url object. These implement nsIMsgMailNewsUrl, inherit from base/util/nsMsgMailNewsUrl, and implement their own protocol-specific interface (nsIImapUrl, nsINntpUrl, nsIPop3Url).

+ +

A protocol object that takes a url and handles the network communications with the actual server required to run that url. These implement nsIMsgProtocol, inherit from nsMsgProtocol, and implement their own protocol-specific interface (nsIImapProtocol, nsIPop3Protocol, nsINntpProtocol)

+ +

In addition, in mailnews/db/msgdb/public, we have protocol-specific msg db classes (and in the case of news, a nsINewsDatabase interface), so that we can use polymorphism when msg db operations need to be specialized for different kinds of folders.

+ +

The message search code also has protocol-specific code to handle searching on the server, or local mailbox. The search code also knows what the different search capabilities of the various protocols are.

diff --git a/files/zh-cn/mozilla/toolkit_version_format/index.html b/files/zh-cn/mozilla/toolkit_version_format/index.html new file mode 100644 index 0000000000..ce6e5b2399 --- /dev/null +++ b/files/zh-cn/mozilla/toolkit_version_format/index.html @@ -0,0 +1,88 @@ +--- +title: 版本格式说明 +slug: Mozilla/Toolkit_version_format +tags: + - Toolkit API +translation_of: Mozilla/Toolkit_version_format +--- +

本文档是 Firefox 1.5(XULRunner 1.8)及更高版本中使用的版本格式的参考。此格式由扩展管理器,软件更新和平台其他部分的使用。至少以下位置的版本必须符合以下格式:

+ + + +

您可以使用 {{ interface("nsIVersionComparator") }} 来比较应用程序的版本。

+ +

有关 Firefox / Thunderbird 1.0 中使用的旧版本格式的说明,请参阅 {{ Anch("Older version formats") }}.

+ +

版本格式

+ +

版本字符串由一个或多个版本部分组成,用点分隔。

+ +

每个版本的一部分本身解析为四个部分组成一个序列:<number-a><string-b><number-c><string-d>. 每个部分都是可选的。数字是 10 进制的整数(可以是负数),字符串是非数字的ASCII字符。

+ +

有效版本部分的几个例子:

+ + + +

应用一些特殊的解析规则来实现向后兼容性和可读性:

+ + + +

当比较版本时,将版本分解为字符串部分和数字部分对应起来一一比较, 例如 '1.0pre1' < '1.0pre10'。有关如何比较版本的详细信息,请参阅下一节。

+ +

比较版本

+ +

当比较两个版本字符串时,它们的版本部分将从左到右进行比较。空的或缺少的版本部分等于 0 。

+ +

当一个版本字符串的版本部分大于另一个版本字符串的相应版本部分时,第一个版本字符串大于另一个版本字符串。

+ +

否则,版本字符串相等。请注意,由于缺少的版本部分被视为 0,所以以下版本字符串相等: 1, 1.0, 1.0., 1.0.0, 还有 1.0...

+ +

比较版本部分

+ +

版本部分也从左到右进行比较,将 <number-a> 和 <number-c> 作为数字进行比较,而 <string-b> 和 <string-b> 按字节比较。 存在的字符串部分始终小于不存在的字符串部分(如 1.6a 小于1.6)。

+ +

一些例子

+ +
1.-1
+< 1 == 1. == 1.0 == 1.0.0
+< 1.1a < 1.1aa < 1.1ab < 1.1b < 1.1c
+< 1.1whatever
+< 1.1pre == 1.1pre0 == 1.0+
+< 1.1pre1a < 1.1pre1aa < 1.1pre1b < 1.1pre1
+< 1.1pre2
+< 1.1pre10
+< 1.1.-1
+< 1.1 == 1.1.0 == 1.1.00
+< 1.10
+< 1.* < 1.*.1
+< 2.0
+
+ +

技术参考

+ +

如果你有兴趣看 toolkit 版本比较的实现, 请参考 nsVersionComparator.cpp.

+ +

旧版本的格式

+ +

Firefox 和 Thunderbird 1.0 使用简单的版本格式,即

+ +
major[.minor[.release[.build]]][+]
+
+ +

其中 {{ mediawiki.external('..') }} 表示可选部分, majorminorrelease 和 build 都是非负整数。

diff --git a/files/zh-cn/mozilla/webidl_bindings/index.html b/files/zh-cn/mozilla/webidl_bindings/index.html new file mode 100644 index 0000000000..27b670ceea --- /dev/null +++ b/files/zh-cn/mozilla/webidl_bindings/index.html @@ -0,0 +1,920 @@ +--- +title: WebIDL绑定 +slug: Mozilla/WebIDL_bindings +translation_of: Mozilla/WebIDL_bindings +--- +
+

注意:需要记录索引和命名的setter / creator / deleter的设置。

+
+ +

在构建时生成 WebIDL binding 需要两个东西:一个实实在在的WebIDL文件,以及另一个描述了 WebIDL 如何映射为 Gecko 内部代码的元数据配置文件。

+ +

所有的 WebIDL文件应该放置在 dom/webidl 中并将文件名添加到该目录下的 moz.build 文件的列表中。

+ +

注意如果你添加了新的接口,关于 dom/tests/mochitest/general/test_interfaces.html 很可能会失效。这就表示你需要让你的 DOM peer review 一下。不要急于在没有 review 的情况下将你的接口添加到moz.build 列表中;这样只会惹恼你的 DOM peers,最后无论如何你的改动都得被重新review。

+ +

dom/bindings/Bindings.conf配置文件是一个简单的Python dict(字典)类型数据。它会将接口名称与接口信息相映射,这被称为descriptor(python描述符)。会有各种可能的方式来处理每种边缘情况,然而大多数描述符通常都非常简单。

+ +

所有生成的代码都放置在 mozilla::dom namespace 中。对于每个接口,将创建一个名称以Binding为后缀的namespace ,与该接口的 binding 相关的所有内容都放在该namespace中。

+ +

有许多放在 dom/bindings 目录中的助手对象和工具方法同样也在 mozilla::dom 命名空间中,其头文件也被导出到了 mozilla/dom 中(在编译时会放到 $OBJDIR/dist/include 目录).。

+ +

向一个类添加 WebIDL 绑定

+ +

要将MyInterface 接口的WebIDL binding 添加到应该实现该接口的类 mozilla::dom::MyInterface中,你需要执行以下操作:

+ +
    +
  1. 如果你的接口没有继承自其他任何接口,你应当继承 nsWrapperCache,并把该类Hook到生命周期收集器(cycle collector),以便它可以正确地跟踪 wrapper 缓存。请注意,如果您的对象只能创建,而不能从其他对象获取,则可能不需要执行此操作。如果你也继承了 nsISupports接口,请确保 nsISupports 在父类列表中位于 nsWrapperCache 之前。如果您的接口 确实 继承了别的接口,则只需继承另一个接口对应的C++类型即可。
  2. +
+ +

如果确实需要Hook 生命周期收集器(cycle collector),在同样也继承了nsISupports的常见情况下,它将如下所示:

+ +
// Add strong pointers your class holds here. If you do, change to using
+// NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE.
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(MyClass)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(MyClass)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(MyClass)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MyClass)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+ +

       2. 如果你的类不是继承自实现了 GetParentObject接口的类,则添加一个同名函数。对于您的类的给定实例,该函数每次都返回相同的对象(除非您编写显式代码,通过重新设置JS wrapper来处理父对象的更改,就像节点所做的那样)。其思想是遍历 GetParentObject 链最终会将您得到 Window。这样,每个WebIDL对象都与一个特定的窗口相关联。

+ +

例如,nsINode::GetParentObject  返回节点的所有者文档。GetParentObject的返回类型并不重要,只是它必须单独从nsISupports继承,或者具有可以从中生成nsISupports的相应ToSupports方法。(这允许编译器通过该类的一个非显式构造函数将返回值隐式转换为 ParentObject实例.)

+ +

如果希望快速创建许多 MyInterface 实例,则 GetParentObject 的返回值本身应从nsWrapperCache 继承以获得最佳性能。在出于安全目的将结果对象与随机全局对象相关联的情况下,允许从GetParentObject返回null ;对于将其暴露于Web content,这通常是不合适的。同样,如果您不需要wrapper 缓存,则不需要执行此操作。从GetParentObject返回的实际类型必须在你实现的头文件中的头部 include 中导入,以便此类型的定义对绑定代码可见。

+ +

      3. 在 dom/webidl目录下添加 MyInterface 的WebIDL 定义, 并将该文件添加到 dom/webidl/moz.build 的列表中.

+ +

      4. 在dom/bindings/Bindings.conf中添加一个条目,用于设置有关接口实现的一些基本信息。如果C++类型不是 mozilla::dom::MyInterface,则需要将 'nativeType'设置为正确的类型。如果通过将“::”替换为“/”并附加“.h”路径 的该类型头文件中不存在,则将其相应的位置添加至相应的“headerFile”注释中 (或向.webidl文件添加 HeaderFile annotation 注释)。如果您不需要设置任何注释,那么您也不需要添加条目,代码生成器将简单地采用此处的默认值。请注意,通常不建议使用“headerFile”注释。如果您确实使用了它,您将需要确保您的头文件 include 了 Func 注释所需的所有头文件。

+ +

    5. 将外部接口条目添加到Bindings.conf中,用于新接口的任何 作为 非webidl接口的参数或返回值。

+ +

    6.  在mozilla::dom::MyInterface上实现WrapObject 重载,它只调用 mozilla::dom::MyInterface_Binding::Wrap。请注意,如果您的C++类型正在实现多个不同的Web IDL接口,则需要选择在此处调用哪个mozilla::dom::MyInterface_Binding::Wrap。例如,参见AudioContext::WrapObject

+ +

    7.  在mozilla::dom::MyInterface上公开接口需要的任何方法。它们可以是inline、virtual、具有任何调用约定的,等等,只要它们具有正确的参数类型和返回类型。通过运行mach webidl-example MyInterface,您可以看到函数声明应该是什么样子的示例。这将在objdir中的 dom/bindings 中生成两个文件:MyInterface-example.hMyInterface-example.cpp,这两个文件显示了使用从nsISupports继承并具有包装器缓存的类的接口的基本实现。

+ +

参见  sample patch that migrates window.performance.* to WebIDL bindings(这是一个往window添加接口的提交。译者注).

+ +
注意: 如果您的对象只能通过创建来被JS调用,而不是通过从某个地方获取它,那么您可以跳过上面的步骤1和2,而且向您的descriptor中添加 'wrapperCache': False。您需要在WebIDL中将返回对象的函数标记为[NewObject] 。如果您的对象没有使用引用计数,则返回它的函数的返回值应返回 nsAutoPtr
+ +

创建WebIDL 之  C++反射

+ +

WebIDL操作之C++反射(方法)

+ +

WebIDL操作被转换为对底层C++对象的方法调用。如何确定返回类型和参数类型的方法 如下所述。除此之外,所有 允许抛出的方法 都将获得一个附加到其参数列表中的 ErrorResult& 参数。使用特定WebIDL类型( 如 any 或者object )的非静态方法将获得参数列表之前的JSContext*参数。静态方法将被传递一个 const GlobalObject& 用作相关的全局变量,并且可以通过对其调用 Context()来获取JSContext* 。

+ +

C++方法的名称只是WebIDL操作的名称,第一个字母转换为大写。

+ +

WebIDL重载被转换为C++重载:它们只是调用具有相同名称和不同签名的C++方法。

+ +

例如如下所示的 webidl:

+ +
interface MyInterface
+{
+  void doSomething(long number);
+  double doSomething(MyInterface? otherInstance);
+
+  [Throws]
+  MyInterface doSomethingElse(optional long maybeNumber);
+  [Throws]
+  void doSomethingElse(MyInterface otherInstance);
+
+  void doTheOther(any something);
+
+  void doYetAnotherThing(optional boolean actuallyDoIt = false);
+
+  static void staticOperation(any arg);
+};
+ +

会需要这些方法声明:

+ +
class MyClass
+{
+  void DoSomething(int32_t aNumber);
+  double DoSomething(MyClass* aOtherInstance);
+
+  already_AddRefed<MyInterface> DoSomethingElse(Optional<int32_t> aMaybeNumber,
+                                                ErrorResult& rv);
+  void DoSomethingElse(MyClass& aOtherInstance, ErrorResult& rv);
+
+  void DoTheOther(JSContext* cx, JS::Value aSomething);
+
+  void DoYetAnotherThing(bool aActuallyDoIt);
+
+  static void StaticOperation(const GlobalObject& aGlobal, JS::Value aSomething);
+}
+ +

WebIDL属性的C++反射

+ +

WebIDL属性被转换为底层C++对象上getter和setter的一对方法调用。只读属性只有getter而没有setter。

+ +

getter的名称是将第一个字母转换为大写的属性的名称。如果满足以下任一条件,则将Get 前置:

+ +
    +
  1. 属性的类型可以为空。
  2. +
  3. getter 可以 throw。
  4. +
  5. 属性的返回值通过C++ 中的 out parameter 返回。
  6. +
+ +

getter的方法签名看起来就像没有参数的操作,并且属性的类型作为返回类型。

+ +

 setter 的名称是Set ,后跟属性的名称,第一个字母转换为大写。方法签名看起来就像一个具有void返回值和单个参数的操作,该参数的类型是属性的类型。

+ +

WebIDL构造函数的 C++反射

+ +

WebIDL构造函数被转换为名为Constructor的静态类方法。此方法的参数将是WebIDL构造函数的参数,带有 const GlobalObject& 用于相关的全局前缀。对于非Worker情况,全局通常是构造函数附加到的 DOM Window 的 内部 Window 。如果由于某些参数类型也需要JSContext*,则它将位于全局变量之后。MyInterface的构造函数的返回值与返回MyInterface实例的方法的返回值完全相同。始终允许构造函数 throw。

+ +

如下 IDL所示:

+ +
[Constructor,
+ Constructor(unsigned long someNumber)]
+interface MyInterface
+{
+};
+ +

需要在 MyClass中进行如下声明:

+ +
class MyClass {
+  // Various nsISupports stuff or whatnot
+  static
+  already_AddRefed<MyClass> Constructor(const GlobalObject& aGlobal,
+                                        ErrorResult& rv);
+  static
+  already_AddRefed<MyClass> Constructor(const GlobalObject& aGlobal,
+                                        uint32_t aSomeNumber,
+                                        ErrorResult& rv);
+};
+ +

C++ reflections of WebIDL types

+ +

The exact C++ representation for WebIDL types can depend on the precise way that they're being used: e.g. return values, arguments, and sequence or dictionary members might all have different representations.

+ +

Unless stated otherwise, a type only has one representation.  Also, unless stated otherwise, nullable types are represented by wrapping Nullable<> around the base type.

+ +

In all cases, optional arguments which do not have a default value are represented by wrappingconst Optional<>& around the representation of the argument type.  If the argument type is a C++ reference, it will also become a NonNull<> around the actual type of the object in the process.  Optional arguments which do have a default value are just represented by the argument type itself, set to the default value if the argument was not in fact passed in.

+ +

Variadic WebIDL arguments are treated as a const Sequence<>& around the actual argument type.

+ +

any

+ +

any is represented in three different ways, depending on use:

+ + + +

Methods using any always get a JSContext* argument.

+ +

For example, this WebIDL:

+ +
interface Test { attribute any myAttr; any myMethod(any arg1, sequence<any> arg2, optional any arg3); };
+ +

will correspond to these C++ function declarations:

+ +
void MyAttr(JSContext* cx, JS::MutableHandle<JS::Value> retval);
+void SetMyAttr(JSContext* cx, JS::Handle<JS::Value> value);
+void MyMethod(JSContext* cx, JS::Handle<JS::Value> arg1,
+              const Sequence<JS::Value>& arg2,
+              const Optional<JS::Handle<JS::Value> >& arg3,
+              JS::MutableHandle<JS::Value> retval);
+ +

boolean

+ +

The boolean WebIDL type is represented as a C++ bool.

+ +

For example, this WebIDL:

+ +
interface Test { attribute boolean myAttr; boolean myMethod(optional boolean arg); };
+ +

will correspond to these C++ function declarations:

+ +
bool MyAttr();
+void SetMyAttr(bool value);
+JS::Value MyMethod(const Optional<bool>& arg);
+ +

Integer types

+ +

Integer WebIDL types are mapped to the corresponding C99 stdint types.

+ +

For example, this WebIDL:

+ +
interface Test { attribute short myAttr; long long myMethod(unsigned long? arg); };
+ +

will correspond to these C++ function declarations:

+ +
int16_t MyAttr();
+void SetMyAttr(int16_t value);
+int64_t MyMethod(const Nullable<uint32_t>& arg);
+ +

Floating point types

+ +

Floating point WebIDL types are mapped to the C++ type of the same name.  So float andunrestricted float become a C++ float, while double and unrestricted doublebecome a C++ double.

+ +

For example, this WebIDL:

+ +
interface Test { float myAttr; double myMethod(unrestricted double? arg); };
+ +

will correspond to these C++ function declarations:

+ +
float MyAttr();
+void SetMyAttr(float value);
+double MyMethod(const Nullable<double>& arg);
+ +

DOMString

+ +

Strings are reflected in three different ways, depending on use:

+ + + +

Nullable strings are represented by the same types as non-nullable ones, but the string will return true for DOMStringIsNull().  Returning null as a string value can be done usingSetDOMStringToNull on the out param if it's an nsAString or calling SetNull() on aDOMString.

+ +

For example, this WebIDL:

+ +
interface Test { DOMString myAttr; [Throws] DOMString myMethod(sequence<DOMString> arg1, DOMString? arg2, optional DOMString arg3); };
+ +

will correspond to these C++ function declarations:

+ +
void GetMyAttr(nsString& retval);
+void SetMyAttr(const nsAString& value);
+void MyMethod(const Sequence<nsString>& arg1, const nsAString& arg2,
+              const Optional<nsAString>& arg3, nsString& retval, ErrorResult& rv);
+ +

ByteString

+ +

ByteString is reflected in three different ways, depending on use:

+ + + +

Nullable ByteString are represented by the same types as non-nullable ones, but the string will return true for IsVoid().  Returning null as a string value can be done using SetIsVoid()on the out param.

+ +

object

+ +

object is represented in three different ways, depending on use:

+ + + +

Methods using object always get a JSContext* argument.

+ +

For example, this WebIDL:

+ +
interface Test { object myAttr; object myMethod(object arg1, object? arg2, sequence<object> arg3, optional object arg4, optional object? arg5); };
+ +

will correspond to these C++ function declarations:

+ +
void GetMyAttr(JSContext* cx, JS::MutableHandle<JSObject*> retval);
+void SetMyAttr(JSContext* cx, JS::Handle<JSObject*> value);
+void MyMethod(JSContext* cx, JS::Handle<JSObject*> arg1, JS::Handle<JSObject*> arg2,
+              const Sequence<JSObject*>& arg3,
+              const Optional<JS::Handle<JSObject*> >& arg4,
+              const Optional<JS::Handle<JSObject*> >& arg5,
+              JS::MutableHandle<JSObject*> retval);
+ +

Interface types

+ +

There are four kinds of interface types in the WebIDL bindings.  Callback interfaces are used to represent script objects that browser code can call into.  External interfaces are used to represent objects that have not been converted to the WebIDL bindings yet.  WebIDL interfaces are used to represent WebIDL binding objects.  "SpiderMonkey" interfaces are used to represent objects that are implemented natively by the JavaScript engine (e.g. typed arrays).

+ +
Callback interfaces
+ +

Callback interfaces are represented in C++ as objects inheriting frommozilla::dom::CallbackInterface, whose name, in the mozilla::dom namespace, matches the name of the callback interface in the WebIDL.  The exact representation depends on how the type is being used.

+ + + +

If the interface is a single-opertion interface, the object exposes two methods that both invoke the same underlying JS callable.  The first of these methods allows the caller to pass in a thisobject, while the second defaults to undefined as the this value.  In either case, the thisvalue is only used if the callback interface is implemented by a JS callable.  If it's implemented by an object with a property whose name matches the operation, the object itself is always used as this.

+ +

If the interface is not a single-operation interface, it just exposes a single method for every IDL method/getter/setter.

+ +

The signatures of the methods correspond to the signatures for throwing IDL methods/getters/setters with an additional trailing "mozilla::dom::CallbackObject::ExceptionHandling aExceptionHandling" argument, defaulting to eReportExceptions.  If aReportExceptions is set toeReportExceptions, the methods will report JS exceptions before returning.  IfaReportExceptions is set to eRethrowExceptions, JS exceptions will be stashed in theErrorResult and will be reported when the stack unwinds to wherever the ErrorResult was set up.

+ +

For example, this WebIDL:

+ +
callback interface MyCallback { attribute long someNumber; short someMethod(DOMString someString); }; callback interface MyOtherCallback { // single-operation interface short doSomething(Node someNode); }; interface MyInterface { attribute MyCallback foo; attribute MyCallback? bar; };
+ +

will lead to these C++ class declarations, in the mozilla::dom namespace:

+ +
class MyCallback : public CallbackInterface
+{
+  int32_t GetSomeNumber(ErrorResult& rv, ExceptionHandling aExceptionHandling = eReportExceptions);
+  void SetSomeNumber(int32_t arg, ErrorResult& rv,
+                     ExceptionHandling aExceptionHandling = eReportExceptions);
+  int16_t SomeMethod(const nsAString& someString, ErrorResult& rv,
+                     ExceptionHandling aExceptionHandling = eReportExceptions);
+};
+
+class MyOtherCallback : public CallbackInterface
+{
+public:
+  int16_t
+  DoSomething(nsINode& someNode, ErrorResult& rv,
+              ExceptionHandling aExceptionHandling = eReportExceptions);
+
+  template<typename T>
+  int16_t
+  DoSomething(const T& thisObj, nsINode& someNode, ErrorResult& rv,
+              ExceptionHandling aExceptionHandling = eReportExceptions);
+};
+ +

and these C++ function declarations on the implementation of MyInterface:

+ +
already_AddRefed<MyCallback> GetFoo(); void SetFoo(MyCallback&); already_AddRefed<MyCallback> GetBar(); void SetBar(MyCallback*);
+ +
External interfaces
+ +

External interfaces are represented in C++ as objects that XPConnect knows how to unwrap to.  This can mean XPCOM interfaces (whether declared in XPIDL or not) or it can mean some type that there's a castable native unwrapping function for.  The C++ type to be used should be thenativeType listed for the external interface in the Bindings.conf file.  The exact representation depends on how the type is being used.

+ + + +
WebIDL interfaces
+ +

WebIDL interfaces are represented in C++ as C++ classes.  The class involved must either be refcounted or must be explicitly annotated in Bindings.conf as being directly owned by the JS object.  If the class inherits from nsISupports, then the canonical nsISupports must be on the primary inheritance chain of the object.  If the interface has a parent interface, the C++ class corresponding to the parent must be on the primary inheritance chain of the object.  This guarantees that a void* can be stored in the JSObject which can then be reinterpret_castto any of the classes that correspond to interfaces the object implements.  The C++ type to be used should be the nativeType listed for the interface in the Bindings.conf file, ormozilla::dom::InterfaceName if none is listed.  The exact representation depends on how the type is being used.

+ + + +

For example, this WebIDL:

+ +
interface MyInterface { attribute MyInterface myAttr; void passNullable(MyInterface? arg); MyInterface? doSomething(sequence<MyInterface> arg); MyInterface doTheOther(sequence<MyInterface?> arg); readonly attribute MyInterface? nullableAttr; readonly attribute MyInterface someOtherAttr; // Marked as resultNotAddRefed readonly attribute MyInterface someYetOtherAttr; };
+ +

Would correspond to these C++ function declarations:

+ +
already_AddRefed<MyClass> MyAttr();
+void SetMyAttr(MyClass& value);
+void PassNullable(MyClass* arg);
+already_AddRefed<MyClass> doSomething(const Sequence<OwningNonNull<MyClass> >& arg);
+already_AddRefed<MyClass> doTheOther(const Sequence<nsRefPtr<MyClass> >& arg);
+already_Addrefed<MyClass> GetMyAttr();
+MyClass* SomeOtherAttr();
+MyClass* SomeYetOtherAttr(); // Don't have to return already_AddRefed!
+ +
"SpiderMonkey" interfaces
+ +

Typed array, array buffer, and array buffer view arguments are represented by the objects inTypedArray.h.  For example, this WebIDL:

+ +
interface Test { void passTypedArrayBuffer(ArrayBuffer arg); void passTypedArray(ArrayBufferView arg); void passInt16Array(Int16Array? arg); }
+ +

will correspond to these C++ function declarations:

+ +
void PassTypedArrayBuffer(const ArrayBuffer& arg);
+void PassTypedArray(const ArrayBufferView& arg);
+void PassInt16Array(const Nullable<Int16Array>& arg);
+ +

Typed array return values are represented by JSObject*.

+ +

Typed arrays store a JSObject* and hence need to be rooted properly.  On-stack typed arrays can be declared as RootedTypedArray<TypedArrayType> (e.g.RootedTypedArray<Int16Array>).  Typed arrays on the heap need to be traced.

+ +

Dictionary types

+ +

A dictionary argument is represented by a const reference to a struct whose name is the dictionary name in the mozilla::dom namespace.  The struct has one member for each of the dictionary's members with the same name except the first letter uppercased and prefixed with "m". The members that have default values have types as described under the corresponding WebIDL type in this document.  The members that don't have default values have those types wrapped in Optional<>.

+ +

Dictionary return values are represented by an out parameter whose type is a non-const reference to the struct described above, with all the members that have default values preinitialized to those default values.

+ +

Note that optional dictionary arguments are always considered to have a default value of nullso dictionary arguments are never wrapped in Optional<>.

+ +

If necessary, dictionaries can be directly initialized from a JS::Value in C++ code by invoking their Init() method.  Consumers doing this should declare their dictionary asRootedDictionary<DictionaryName>.  When this is done, passing in a null scope object and even a null JSContext* is allowed if the passed-in JS::Value is JS::NullValue().  Likewise, a dictionary struct can be converted to a JS::Value in C++ by calling ToJSValuewith the dictionary as the second argument.  If Init() or ToJSValue() return false, they will generally set a pending exception on the JSContext; reporting those is the responsibility of the caller.

+ +

For example, this WebIDL:

+ +
dictionary Dict { long foo = 5; DOMString bar; }; interface Test { void initSomething(optional Dict arg); };
+ +

will correspond to this C++ function declaration:

+ +
void InitSomething(const Dict& arg);
+ +

and the Dict struct will look like this:

+ +
struct Dict {
+  bool Init(JSContext* aCx, JS::Handle<JS::Value> aVal, const char* aSourceDescription = "value");
+
+  Optional<nsString> mBar;
+  int32_t mFoo;
+}
+ +

Note that the dictionary members are sorted in the struct in alphabetical order.

+ +

Enumeration types

+ +

WebIDL enumeration types are represented as C++ enums.  The values of the C++ enum are named by taking the strings in the WebIDL enumeration, replacing all non-alphanumerics with underscores, and uppercasing the first letter, with a special case for the empty string, which becomes the value _empty.

+ +

For a WebIDL enum named MyEnum, the C++ enum is named MyEnum and placed in themozilla::dom namespace, while the values are placed in the mozilla::dom::MyEnumnamespace.  There is also a mozilla::dom::MyEnumValues::strings which is an array ofmozilla::dom::EnumEntry structs that gives access to the string representations of the values.

+ +

For example, this WebIDL:

+ +
enum MyEnum { "something", "something-else", "", "another" };
+ +

would lead to this C++ enum declaration:

+ +
MOZ_BEGIN_ENUM_CLASS(MyEnum, uint32_t)
+  Something,
+  Something_else,
+  _empty,
+  Another
+MOZ_END_ENUM_CLASS(MyEnum)
+
+namespace MyEnumValues {
+extern const EnumEntry strings[10];
+} // namespace MyEnumValues
+ +

Callback function types

+ +

Callback functions are represented as an object, inheriting frommozilla::dom::CallbackFunction, whose name, in the mozilla::dom namespace, matches the name of the callback function in the WebIDL.  If the type is nullable, a pointer is passed in; otherwise a reference is passed in.

+ +

The object exposes two Call methods, which both invoke the underlying JS callable.  The firstCall method has the same signature as a throwing method declared just like the callback function, with an additional trailing "mozilla::dom::CallbackObject::ExceptionHandling aExceptionHandling" argument, defaulting to eReportExceptions, and calling it will invoke the callable withundefined as the this value.  The second Call method allows passing in an explicit thisvalue as the first argument.  This second call method is a template on the type of the first argument, so the this value can be passed in in whatever form is most convenient, as long as it's either a type that can be wrapped by XPConnect or a WebIDL interface type.

+ +

If aReportExceptions is set to eReportExceptions, the Call methods will report JS exceptions before returning.  If aReportExceptions is set to eRethrowExceptions, JS exceptions will be stashed in the ErrorResult and will be reported when the stack unwinds to wherever the ErrorResult was set up.

+ +

For example, this WebIDL:

+ +
callback MyCallback = long (MyInterface arg1, boolean arg2); interface MyInterface { attribute MyCallback foo; attribute MyCallback? bar; };
+ +

will lead to this C++ class declaration, in the mozilla::dom namespace:

+ +
class MyCallback : public CallbackFunction
+{
+public:
+  int32_t
+  Call(MyInterface& arg1, bool arg2, ErrorResult& rv,
+       ExceptionHandling aExceptionHandling = eReportExceptions);
+
+  template<typename T>
+  int32_t
+  Call(const T& thisObj, MyInterface& arg1, bool arg2, ErrorResult& rv,
+       ExceptionHandling aExceptionHandling = eReportExceptions);
+};
+ +

and these C++ function declarations in the MyInterface class:

+ +
already_AddRefed<MyCallback> GetFoo(); void SetFoo(MyCallback&); already_AddRefed<MyCallback> GetBar(); void SetBar(MyCallback*);
+ +

Sequences

+ +

Sequence arguments are represented by const Sequence<T>&, where T depends on the type of elements in the WebIDL sequence.

+ +

Sequence return values are represented by an nsTArray<T> out param appended to the argument list, where T is the return type for the elements of the WebIDL sequence.  This comes after all IDL arguments, but before the ErrorResult&, if any, for the method.

+ +

Arrays

+ +

IDL array objects are not supported yet.  The spec on these is likely to change drastically anyway.

+ +

Union types

+ +

Union types are reflected as a struct in the mozilla::dom namespace.  There are two kinds of union structs: one kind does not keep its members alive (is "non-owning"), and the other does (is "owning").  Const references to non-owning unions are used for plain arguments.  Owning unions are used in dictionaries, sequences, and for variadic arguments.  Union return values become a non-const owning union out param.  The name of the struct is the concatenation of the names of the types in the union, with "Or" inserted between them, and for an owning struct "Owning" prepended.  So for example, this IDL:

+ +
void passUnion((object or long) arg); (object or long) receiveUnion(); void passSequenceOfUnions(sequence<(object or long)> arg); void passOtherUnion((HTMLDivElement or ArrayBuffer or EventInit) arg);
+ +

would correspond to these C++ function declarations:

+ +
void PassUnion(const ObjectOrLong& aArg);
+void ReceiveUnion(OwningObjectObjectOrLong& aArg);
+void PassSequenceOfUnions(const Sequence<OwningObjectOrLong>& aArg);
+void PassOtherUnion(const HTMLDivElementOrArrayBufferOrEventInit& aArg);
+ +

Union structs expose accessors to test whether they're of a given type and to get hold of the data of that type.  They also expose setters that set the union as being of a particular type and return a reference to the union's internal storage where that type could be stored.  The one exception is the object type, which uses a somewhat different form of setter where theJSObject* is passed in directly. For example, ObjectOrLong would have the following methods:

+ +
bool IsObject() const;
+JSObject* GetAsObject() const;
+void SetToObject(JSContext*, JSObject*);
+bool IsLong() const;
+int32_t GetAsLong() const;
+int32_t& SetAsLong()
+ +

Owning unions used on the stack should be declared as a RootedUnion<UnionType>.  For example, RootedUnion<OwningObjectOrLong>.

+ +

Date

+ +

WebIDL Date types are represented by a mozilla::dom::Date struct.

+ +

Stringifiers

+ +

Named stringifiers operations in WebIDL will just invoke the corresponding C++ method.

+ +

Anonymous stringifiers in WebIDL will invoke the C++ method called Stringify.  So for example given this IDL:

+ +
interface FirstInterface { stringifier; }; interface SecondInterface { stringifier DOMString getStringRepresentation(); };
+ +

the corresponding C++ would be:

+ +
class FirstInterface { public: void Stringify(nsAString& aResult); }; class SecondInterface { public: void GetStringRepresentation(nsAString& aResult); };
+ +

Legacy Callers

+ +

Only anonymous legacy callers are supported, and will invoke the C++ method calledLegacyCall.  This will be passed the JS "this" value as the first argument, then the arguments to the actual operation.  A JSContext will be passed if any of the operation arguments need it.  So for example given this IDL:

+ +
interface InterfaceWithCall { legacycaller long (float arg); };
+ +

the corresponding C++ would be:

+ +
class InterfaceWithCall {
+public:
+  int32_t LegacyCall(JS::Handle<JS::Value> aThisVal, float aArgument);
+};
+ +

Named getters

+ +

If the interface has a named getter, the binding will expect several methods on the C++ implementation:

+ + + +

The NameIsEnumerable and GetSupportedNames methods need to agree on which names are and are not enumerable.  The NamedGetter and GetSupportedNames methods need to agree on which names are supported.

+ +

So for example, given this IDL:

+ +
interface InterfaceWithNamedGetter { getter long(DOMString arg); };
+ +

the corresponding C++ would be:

+ +
class InterfaceWithNamedGetter
+{
+public:
+  int32_t NamedGetter(const nsAString& aName, bool& aFound);
+  bool NameIsEnumerable(const nsAString& aName);
+  void GetSupportedNames(unsigned aFlags, nsTArray<nsString>& aNames);
+};
+ +

Throwing exceptions from WebIDL methods, getters, and setters

+ +

WebIDL methods, getters, and setters that are explicitly marked as allowed to throw have anErrorResult& argument as their last argument.  To throw an exception, simply call Throw()on the ErrorResult& and return from your C++ back into the binding code.

+ +

In cases when the specification calls for throwing a TypeError, you should useErrorResult::ThrowTypeError() instead of calling Throw().

+ +

Custom extended attributes

+ +

Our WebIDL parser and code generator recognize several extended attributes that are not present in the WebIDL spec.

+ +

[ChromeOnly]

+ +

This extended attribute can be specified on any method, attribute, or constant on an interface or on an interface as a whole.

+ +

Interface members flagged as [ChromeOnly] are only exposed in chrome Windows (and in particular, are not exposed to webpages).  From the point of view of web content, it's as if the interface member were not there at all.  These members are exposed to chrome script working with a content object via Xrays.

+ +

If specified on an interface as a whole, this functions like [Func] except that the binding code will automatically check whether the caller script has the system principal (is chrome or a worker started from a chrome page) instead of calling into the C++ implementation to determine whether to expose the interface object on the global.   This means that accessing a  content global via Xrays will show [ChromeOnly] interface objects on it.

+ +

This extended attibute can be specified together with [AvailableIn][CheckPermissions],[Func],  and [Pref].  If more than one of these is specified, all conditions will need to test true for the interface or interface member to be exposed.

+ +

[Pref=prefname]

+ +

This extended attribute can be specified on any method, attribute, or constant on an interface or on an interface as a whole. It takes a value, which must be the name of a boolean preference.

+ +

If specified on an interface member, the interface member involved is only exposed if the preference is set to true. An example of how this can be used:

+ +
interface MyInterface { attribute long alwaysHere; [Pref="my.pref.name"] attribute long onlyHereIfEnabled; };
+ +

If specifed on an interface as a whole, this functions like [Func] except that the binding will check the value of the preference directly without calling into the C++ implementation of the interface at all. This is useful when the enable check is simple and it's desirable to keep the prefname with the WebIDL declaration. The implementation can callMyInterfaceBinding::PrefEnabled() to check whether it is enabled or not.  An example of how this can be used:

+ +
[Pref="my.pref.name"] interface MyConditionalInterface { };
+ +

This extended attibute can be specified together with [AvailableIn][CheckPermissions],[ChromeOnly], and[Func].  If more than one of these is specified, all conditions will need to test true for the interface or interface member to be exposed.

+ +

[Func="funcname"]

+ +

This extended attribute can be specified on any method, attribute, or constant on an interface or on an interface as a whole.  It takes a value, which must be the name of a static function. 

+ +

If specified on an interface member, the interface member involved is only exposed if the specified function returns true.   An example of how this can be used:

+ +
interface MyInterface { attribute long alwaysHere; [Func="MyClass::StuffEnabled"] attribute long onlyHereIfEnabled; };
+ +

The function is invoked with two arguments: the JSContext that the operation is happening on and the JSObject for the global of the object that the property will be defined on if the function returns true.  In particular, in the Xray case the JSContext is in the caller compartment (typically chrome) but the JSObject is in the target compartment (typically content).  This allows the method implementation to select which compartment it cares about in its checks.

+ +

The above IDL would also require the following C++:

+ +
class MyClass {
+  static bool StuffEnabled(JSContext* cx, JSObject* obj);
+};
+ +

If specified on an interface as a whole, then lookups for the interface object for this interface on a DOM Window will only find it if the specified function returns true.  For objects that can only be created via a constructor, this allows disabling the functionality altogether and making it look like the feature is not implemented at all.

+ +

An example of how [Func] can be used:

+ +
[Func="MyClass::MyConditionalInterfaceEnabled"] interface MyConditionalInterface { };
+ +

In this case, the C++ function is passed a JS::Handle<JSObject*>.  So the C++ in this case would look like this:

+ +
class MyClass {
+  static bool MyConditionalInterfaceEnabled(JSContext* cx, JS::Handle<JSObject*> obj);
+};
+ +

Just like in the interface member case, the JSContext is in the caller compartment but theJSObject is the actual object the property would be defined on.  In the Xray case that mean obj is in the target compartment (typically content) and cx is typically chrome.

+ +

This extended attibute can be specified together with [AvailableIn][CheckPermissions],[ChromeOnly], and [Pref].  If more than one of these is specified, all conditions will need to test true for the interface or interface member to be exposed.

+ +

[AvailableIn=Where]

+ +

This extended attribute can be specified on any method, attribute, or constant on an interface or on an interface as a whole. It takes a value, which must be either PrivilegedApps orCertifiedApps.  This will make the interface or interface member only visible in privileged and certified apps respectively on Firefox OS.

+ +

This extended attibute can be specified together with [ChromeOnly][CheckPermissions],[Func], and  [Pref].  If more than one of these is specified, all conditions will need to test true for the interface or interface member to be exposed.

+ +

[CheckPermissions="list of permissions"]

+ +

This extended attribute can be specified on any method, attribute, or constant on an interface or on an interface as a whole. It takes a whitespace-separated list of permissions to be checked before making the interface or interface member visible to a page or app. When multiple permission names are specified, at least one of them will need to be set to nsIPermissionManager::ALLOW_ACTION for the interface or interface member to be exposed.

+ +

This extended attribute can be specified together with [AvailableIn][ChromeOnly],[Func] and [Pref]. If more than one of these is specified, all conditions will need to test true for the interface or interface member to be exposed.

+ +

[Throws][GetterThrows][SetterThrows]

+ +

Used to flag methods or attributes as allowing the C++ callee to throw.  This causes the binding generator, and in many cases the JIT, to generate extra code to handle possible exceptions.  Possibly-throwing methods and attributes get an ErrorResult& argument.

+ +

[Throws] applies to both methods and attributes; for attributes it means both the getter and the setter can throw.  [GetterThrows] applies only to attributes.  [SetterThrows] applies only to non-readonly attributes.

+ +

For bindings that involve workers, the above can all be specified with MainThread or Workersas a value.  When doing this, if [Throws] is specified on an attribute, no matter what its value, then [GetterThrows] and [SetterThrows] will be ignored.  So to have an attribute which can throw both when getting and setting on main thread but can only throw from the setter in workers, use [SetterThrows, GetterThrows=MainThread].

+ +

For interfaces flagged with [JSImplementation], all methods and properties are assumed to be able to throw and do not need to be flagged as throwing.

+ +

[Pure]

+ +

Used to flag attributes whose getter has no side-effects or methods that have no side-effects in the DOM.  Attributes/methods flagged in this way promise that they will keep returning the same value as long as no DOM setters or non-[Pure] DOM methods executed.  This allows the JIT to perform loop-hoisting and common subexpression elimination on the return values of these attributes/methods in some cases.  [Pure] things are allowed to throw exceptions as long as they do so deterministically.  This extended attribute can be used on writable attributes as long as the getter obeys the above rules.

+ +

[Constant]

+ +

Used to flag readonly attributes that could have been annotated with [Pure] and also always return the same value.  This allows the JIT to do even more aggressive optimization of getters for such attributes.  This should only be used when it's absolutely guaranteed that the return value of the attribute getter will always be the same from the JS engine's point of view.  This extended attribute implies [Pure] as far as the JIT is concerned.

+ +

[NeedNewResolve]

+ +

Used to flag interfaces which have a custom resolve hook.  This annotation will cause theDoNewResolve method to be called on the underlying C++ class when a property lookup happens on the object.  The signature of this method is: bool DoNewResolve(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>).  Here the passed-in object is the object the property lookup is happening on (which may be an Xray for the actual DOM object) and the jsid is the property name.  The value that the property should have is returned in the MutableHandle<Value>, with UndefinedValue() indicating that the property does not exist.

+ +

If this extended attribute is used, then the underlying C++ class must also implement a method called GetOwnPropertyNames with the signature void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames, ErrorResult& aRv).  This method wil be called by the JS engine's enumerate hook and must provide a superset of all the property names that DoNewResolve might resolve.  Providing names that DoNewResolve won't actually resolve is OK.

+ +

[HeaderFile="path/to/headerfile.h"]

+ +

Indicates where the implementation can be found. Similar to the headerFile annotation in Bindings.conf.

+ +

[JSImplementation="@mozilla.org/some-contractid;1"]

+ +

Used on an interface to provide the contractid of the JavaScript component implementing the interface.

+ + + +

Setting this extended attribute to propName on an interface causeswindow.navigator.propName to be an instance of the interface.

+ +

[StoreInSlot]

+ +

Used to flag attributes that can be gotten very quickly from the JS object by the JIT.  Such attributes will have their getter called immediately when the JS wrapper for the DOM object is created, and the returned value will be stored directly on the JS object.  Later gets of the attribute will not call the C++ getter and instead use the cached value.  If the value returned by the attribute needs to change, the C++ code should call the ClearCachedFooValue method in the namespace of the relevant binding, where foo is the name of the attribute.  This will immediately call the C++ getter and cache the value it returns, so it needs a JSContext to work on.  This extended attribute can only be used in on attributes whose getters are [Pure] or[Constant] and which are not [Throws] or [GetterThrows].

+ +

So for example, given this IDL:

+ +
interface MyInterface { [Pure, StoreInSlot] attribute long myAttribute; };
+ +

the C++ implementation of MyInterface would clear the cached value by callingmozilla::dom::MyInterfaceBinding::ClearCachedMyAttributeValue(cx, this).

+ +

If the attribute is not readonly, setting it will automatically clear the cached value and reget it again before the setter returns.

+ +

[Cached]

+ +

Used to flag attributes that, when their getter is called, will cache the returned value on the JS object.  This can be used to implement attributes whose value is a sequence or dictionary (which would otherwise end up returning a new object each time and hence not be allowed in WebIDL).

+ +

Unlike [StoreInSlot] this does not cause the getter to be eagerly called at JS wrapper creation time; the caching is lazy.  [Cached] attributes must be [Pure] or [Constant], because otherwise not calling the C++ getter would be observable, but are allowed to have throwing getters.  Their cached value can be cleared by calling the ClearCachedFooValue method in the namespace of the relevant binding, where foo is the name of the attribute.  Unlike [StoreInSlot] attributes, doing so will not immediately invoke the getter, so does not need a JSContext.

+ +

So for example, given this IDL:

+ +
interface MyInterface { [Pure, StoreInSlot] attribute long myAttribute; };
+ +

the C++ implementation of MyInterface would clear the cached value by callingmozilla::dom::MyInterfaceBinding::ClearCachedMyAttributeValue(this).

+ +

If the attribute is not readonly, setting it will automatically clear the cached value.

+ +

[Frozen]

+ +

Used to flag attributes that, when their getter is called, will call Object.freeze on the return value before returning it.  This extended attribute is only allowed on attributes that return sequences, and corresponds to returning a frozen Array.

+ +

[ChromeConstructor]

+ +

[ChromeConstructor] has the same behaviour as [Constructor], but the constructor will throw if it's not called from chrome code. The usage rules and restrictions as those for[Constructor] apply. Note that [Constructor] and [ChromeConstructor] are mutually exclusive, while there can be multiple of either, there can never be both on the same interface.

+ +

Helper objects

+ +

The C++ side of the bindings uses a number of helper objects.

+ +

Nullable<T>

+ +

Nullable<> is a struct declared in Nullable.h and exported tomozilla/dom/Nullable.h that is used to represent nullable values of types that don't have a natural way to represent null.

+ +

Nullable<T> has an IsNull() getter that returns whether null is represented and a Value()getter that returns a const T& and can be used to get the value when it's not null.

+ +

Nullable<T> has a SetNull() setter that sets it as representing null and two setters that can be used to set it to a value: "void SetValue(T)" (for setting it to a given value) and "T& SetValue()" for directly modifying the underlying T&.

+ +

Optional<T>

+ +

Optional<> is a struct declared in BindingDeclarations.h and exported tomozilla/dom/BindingDeclarations.h that is used to represent optional arguments and dictionary members, but only those that have no default value.

+ +

Optional<T> has a WasPassed() getter that returns true if a value is available.  In that case, the Value() getter can be used to get a const T& for the value.

+ +

NonNull<T>

+ +

NonNull<T> is a struct declared in BindingUtils.h and exported tomozilla/dom/BindingUtils.h that is used to represent non-null C++ objects.  It has a conversion operator that produces T&.

+ +

OwningNonNull<T>

+ +

OwningNonNull<T> is a struct declared in BindingUtils.h and exported tomozilla/dom/BindingUtils.h that is used to represent non-null C++ objects and holds a strong reference to them.  It has a conversion operator that produces T&.

+ +

Typed arrays, arraybuffers, array buffer views

+ +

TypedArray.h is exported to mozilla/dom/TypedArray.h and exposes structs that correspond to the various typed array types, as well as ArrayBuffer and ArrayBufferView, all in the mozilla::dom namespace.  Each struct has an Data() method that returns a pointer to the relevant type (uint8_t for ArrayBuffer and ArrayBufferView) and a Length()method that returns the length in units of *Data().  So for example, Int32Array has aData() returning int32_t* and a Length() that returns the number of 32-bit ints in the array..

+ +

Sequence<T>

+ +

Sequence<> is a type declared in BindingDeclarations.h and exported tomozilla/dom/BindingDeclarations.h that is used to represent sequence arguments.  It's some kind of typed array, but which exact kind is opaque to consumers.  This allows the binding code to change the exact definition (e.g. to use auto arrays of different sizes and so forth) without having to update all the callees.

+ +

CallbackFunction

+ +

CallbackFunction is a type declared in CallbackFunction.h and exported tomozilla/dom/CallbackFunction.h that is used as a common base class for all the generated callback function representations.  This class inherits from nsISupports, and consumers must make sure to cycle-collect it, since it keeps JS objects alive.

+ +

CallbackInterface

+ +

CallbackInterface is a type declared in CallbackInterface.h and exported tomozilla/dom/CallbackInterface.h that is used as a common base class for all the generated callback interface representations.  This class inherits from nsISupports, and consumers must make sure to cycle-collect it, since it keeps JS objects alive.

+ +

DOMString

+ +

DOMString is a class declared in BindingDeclarations.h and exported tomozilla/dom/BindingDeclarations.h that is used for WebIDL DOMString return values.  It has a conversion operator to nsString& so that it can be passed to methods that take that type or nsAString&, but callees that care about performance, have an nsStringBufferavailable, and promise to hold on to the nsStringBuffer at least until the binding code comes off the stack can also take a DOMString directly for their string return value and call itsSetStringBuffer method with the nsStringBuffer and its length.  This allows the binding code to avoid extra reference-counting of the string buffer in many cases, and allows it to take a faster codepath even if it does end up having to addref the nsStringBuffer.

+ +

GlobalObject

+ +

GlobalObject is a class declared in BindingDeclarations.h and exported tomozilla/dom/BindingDeclarations.h that is used to represent the global object for static attributes and operations (including constructors).  It has a Get() method that returns theJSObject*  for the global and a GetAsSupports() method that returns an nsISupports*for the global on the main thread, if such is available. It also has a GetContext() method that returns the JSContext* the call is happening on.  A caveat: the compartment of theJSContext may not match the compartment of the global!

+ +

Date

+ +

Date is a class declared in BindingDeclarations.h and exported tomozilla/dom/BindingDeclarations.h that is used to represent WebIDL Dates.  It has aTimeStamp() method returning a double which represents a number of milliseconds since the epoch, as well as SetTimeStamp() methods that can be used to initialize it with a double timestamp or a JS Date object.  It also has a ToDateObject() method that can be used to create a new JS Date.

+ +

ErrorResult

+ +

ErrorResult is a class declared in ErrorResult.h and exported to mozilla/ErrorResult.hthat is used to represent exceptions in WebIDL bindings.  This has the following methods:

+ + + +

Bindings.conf details

+ +

XXXbz write me.  In particular, need to describe at least use of concreteprefable, andaddExternalInterface

+ +

How to get a JSContext passed to a given method

+ +

In some rare cases you may need a JSContext* argument to be passed to a C++ method that wouldn't otherwise get such an argument. To see how to achieve this, search forimplicitJSContext in dom/bindings/Bindings.conf.

+ +

Implementing WebIDL using Javascript

+ +

There is support for implementing WebIDL interfaces in JavaScript.  When this is done, there are actually two objects created: the implementation object (running as a chrome-privileged script) and the content-exposed object (which is what the web page sees).  This allows the implementation object to have various APIs that the content-exposed object does not.  It also means that consumers have to be careful about which object they are creating.

+ +

Creating JS-implemented WebIDL objects

+ +

To create a JS-implemented WebIDL object, one must create both the chrome-side implementation object and the content-side page-exposed object. There are three ways to do this.

+ +

Using the WebIDL constructor

+ +

If the interface has a constructor, a content-side object can be created by getting that constructor from the relevant content window and invoking it. For example:

+ +
var contentObject = new contentWin.RTCPeerConnection();
+ +

The returned object will be an Xray wrapper for the content-side object. Creating the object this way will automatically create the chrome-side object using its contractID.

+ +

This method is limited to the constructor signatures exposed to webpages. Any additional configuration of the object needs to be done via [ChromeOnly] methods on the interface. 

+ +

Creating many objects this way can be slow due to the createInstance overhead involved. 

+ +

Using a _create method  

+ +

 A content-side object can be created for a given chrome-side object by invoking the static_create method on the interface. This method takes two arguments: the content window in which to create the object and the chrome-side object to use. For example:

+ +
var contentObject = RTCPeerConnection._create(contentWin,
+                                              new MyPeerConnectionImpl());
+ +

However, if you are in a JS component, you may only be able to get to the correct interface object via some window object. In this case, the code would look more like:

+ +
var contentObject = contentWin.RTCPeerConnection._create(contentWin,
+                                                         new MyPeerConnectionImpl());
+ +

Creating the object this way will not invoke its __init method or init method.

+ +

By returning a chrome-side object from a JS-implemented WebIDL method

+ +

If a JS-implemented WebIDL method is declared as returning a JS-implemented interface, then a non-WebIDL object returned from that method will be treated as the chrome-side part of a JS-implemented WebIdL object and the content-side part will be automatically created.

+ +

Creating the object this way will not invoke its __init method or init method.

+ +

Implementing a WebIDL object in JavaScript

+ +

To implement a WebIDL interface in JavaScript, first add a WebIDL file, in the same way as you would for a C++-implemented interface.  To support implementation in JS, you must add an extended attribute JSImplementation="CONTRACT_ID_STRING" on your interface, where CONTRACT_ID_STRING is the XPCOM component contract ID of the JS implementation.  Here's an example:

+ +
[Constructor(optional long firstNumber), JSImplementation="@mozilla.org/my-number;1"] interface MyNumber { attribute long value; readonly attribute long otherValue; void doNothing(); };
+ +

Next, create an XPCOM component that implements this interface.  Basic directions for how to do this can be found elsewhere on MDN.  Use the same contract ID as you specified in the WebIDL file.  The class ID doesn't matter, except that it should be a newly generated one.  ForQueryInterface, you only need to implement nsISupports, not anything corresponding to the WebIDL interface.  The name you use for the XPCOM component should be distinct from the name of the interface, to avoid confusing error messages.

+ +

WebIDL attributes are implemented as properties on the JS object or its prototype chain, whereas WebIDL methods are implemented as methods on the object or prototype.  Note that any other instances of the interface that you are passed in as arguments are the full web-facing version of the object, and not the JS implementation, so you currently cannot access any private data.

+ +

The WebIDL constructor invocation will first create your object.  If the XPCOM component implements nsIDOMGlobalPropertyInitializer, then the object's init method will be invoked with a single argument: the content window the constructor came from.  This allows the JS implementation to know which content window it's associated with.  The init method should not return anything.  After this, the content-side object will be created. Then, if there are any constructor arguments, the object's __init method will be invoked, with the constructor arguments as its arguments.

+ +

If you want an instance of the class to be added to window.navigator, add an extended attribute NavigatorProperty="PropertyName" which will make the instance available aswindow.navigator.PropertyName.

+ +

Checking for Permissions or Preferences

+ +

When implementing an XPIDL interface using Javascript, the init method may check if the caller has the proper permissions, or if the appropriate preference is set. If this check fails, then it will return null to indicate that the object should not be created.  JS-implemented WebIDL does NOT work like that.  In JS-implemented WebIDL, the init method should only return undefined.  If any other value, such as null, is returned, the bindings code will assert or crash.  In other words, it acts like it has a "void" return type.

+ +

Instead, preference or permission checking should be implemented by adding an extended attribute to the WebIDL interface. This has the advantage that if the check fails, the constructor or object will not show up at all.

+ +

For preference checking, add an extended attribute Pref="myPref.enabled" wheremyPref.enabled is the preference that should be checked.  SettingsLock is an example of this.

+ +

For permissions or other kinds of checking, add an extended attributeFunc="MyPermissionChecker" where MyPermissionChecker is a function implemented in C++ that returns true if the interface should be enabled.  This function can do whatever checking is needed.  One example of this is PushManager.

+ +

Example

+ +

Here's an example JS implementation of the above interface. The invisibleValue field will not be accessible to web content, but is usable by the doNothing() method.

+ +
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); function MyNumberInner() { this.value = 111; this.invisibleValue = 12345; } MyNumberInner.prototype = { classDescription: "Get my number XPCOM Component", classID: Components.ID("{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"), // dummy UUID contractID: "@mozilla.org/my-number;1", QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports]), doNothing: function() {}, get otherValue() { return this.invisibleValue - 4; }, __init: function(firstNumber) { if (arguments.length > 0) { this.value = firstNumber; } } } var components = [MyNumberInner]; var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
+ +

Finally, add a component and a contract and whatever other manifest stuff you need to implement an XPCOM component.

+ +

Guarantees provided by bindings

+ +

When implementing a WebIDL interface in JavaScript, certain guarantees will be provided by the binding implementation.  For example, string or numeric arguments will actually be primitive strings or numbers.  Dictionaries will contain only the properties that they are declared to have, and they will have the right types.  Interface arguments will actually be objects implementing that interface.

+ +

What the bindings will NOT guarantee is much of anything about object and any arguments.  They will get cross-compartment wrappers that make touching them from chrome code not be an immediate security bug, but otherwise they can have quite surprising behavior if the page is trying to be malicious.  Try to avoid using these types if possible.

+ +

Accessing the content object from the implementation

+ +

If the JS implementation of the WebIDL interface needs to access the content object, it is available as a property called __DOM_IMPL__ on the chrome implementation object.  This property only appears after the content-side object has been created. So it is available in__init but not in init.

+ +

Determining the principal of the caller that invoked the WebIDL API

+ +

This can be done by calling Component.utils.getWebIDLCallerPrincipal().

+ +

Throwing exceptions from JS-implemented APIs

+ +

There are two reasons a JS implemented API might throw.  The first reason is that some unforeseen condition occurred and the second is that a specification requires an exception to be thrown.

+ +

When throwing for an unforeseen condition, the exception will be reported to the console, and a sanitized NS_ERROR_UNEXPECTED exception will be thrown to the calling content script, with the file/line of the content code that invoked your API.  This will avoid exposing chrome URIs and other implementation details to the content code.

+ +

When throwing because a specification requires an exception, you need to communicate to the binding code that this is what you're doing.  Right now this is done by throwing a DOMErrorfrom the window your WebIDL object is associated with (the one that was passed to your initmethod).  The binding code will then rethrow just the message string of that DOMError to the web page, as a plain JS Error.  This does not allow implementing exceptions per spec (e.g. there is no way to explicitly throw a TypeError or other Error subclass), unfortunately; we're still working on that.  Since you know for this case the exception is being thrown because a spec requires it, you know you need to create the DOMError.  An example of how this could work:

+ +
if (!isValid(passedInObject)) {
+  throw new this.contentWindow.DOMError("Error", "Object is invalid");
+}
+ +

In some cases you may need to perform operations whose exception message you just want to propagate to the content caller.  This can be done like so:

+ +
try {
+  someOperationThatCanThrow();
+} catch (e) {
+  throw new this.contentWindow.DOMError(e.name, e.message);
+}
+ +

Inheriting from interfaces implemented in C++

+ +

It's possible to have an interface implemented in JavaScript inherit from an interface implemented in C++.  To do so, simply have one interface inherit from the other and the bindings code will auto-generate a C++ object inheriting from the implementation of the parent interface.  The class implementing the parent interface will need a constructor that takes annsPIDOMWindow* (though it doesn't have to do anything with that argument).

+ +

If the class implementing the parent interface is abstract and you want to use a specific concrete class as the implementation to inherit from, you will need to add a defaultImpl annotation to the descriptor for the parent interface in Bindings.conf.  The value of the annotation is the C++ class to use as the parent for JS-implemented descendants; if defaultImpl is not specified, the nativeType will be used.

+ +

For example, consider this interface that we wish to implement in JavaScript:

+ +
[JSImplementation
+ +

="some-contract"] interface MyEventTarget : EventTarget { attribute EventHandler onmyevent; void dispatchTheEvent(); // Sends a "myevent" event to this EventTarget }

+ +

The implementation would look something like this, ignoring the XPCOM boilerplate:

+ +
function MyEventTargetImpl() { } MyEventTargetImpl.prototype = { init: function(contentWindow) { // XXXbz need to document how to get this called on you! this.contentWindow = contentWindow; } get onmyevent() { return this.__DOM_IMPL__.getEventHandler("onmyevent"); } set onmyevent(handler) { this.__DOM_IMPL__.setEventHandler("onmyevent", handler); } dispatchTheEvent: function() { var event = new this.contentWindow.Event("myevent"); this.__DOM_IMPL__.dispatchEvent(event); } };
+ +

The implementation would automatically support the API exposed on EventTarget (so for example addEventListener).  Calling the dispatchTheEvent method would cause dispatch of an event that content script can see via listeners it has added.

+ +

Note that in this case the chrome implementation is relying on some [ChromeOnly] methods on EventTarget that were added specifically to make it possible to easily implement event handlers.  Other cases can do similar things as needed

+ +

+ +

+ +

+ +

diff --git a/files/zh-cn/mozilla/xmlhttprequest_changes_for_gecko_1.8/index.html b/files/zh-cn/mozilla/xmlhttprequest_changes_for_gecko_1.8/index.html new file mode 100644 index 0000000000..cd7607f36c --- /dev/null +++ b/files/zh-cn/mozilla/xmlhttprequest_changes_for_gecko_1.8/index.html @@ -0,0 +1,19 @@ +--- +title: XMLHttpRequest 在 Gecko1.8 发生的变化 +slug: Mozilla/XMLHttpRequest_changes_for_Gecko_1.8 +tags: + - AJAX + - Add-ons + - Extensions + - XMLHttpRequest +translation_of: Mozilla/XMLHttpRequest_changes_for_Gecko_1.8 +--- +

此文档描述了 Gecko's XMLHttpRequest 的实现自1.7版本 (i.e., Firefox 1.0附带的Gecko版本)。发生的一些改变,这些变化仅仅作用于XUL扩展以及XUL程序,将不会作用于web程序。

+ +

 XMLHttpRequest.send的改变

+ +

如果你将一个 nsIInputStream 实例传递给 send 方法, 那么流的起始部分将不再包含 Content-Length 和 Content-Type 头部信息. 并且 Content-Length 将由流的长度推断得出,  Content-Type 将必须通过调用 setRequestHeader 方法来手动指定. 更多关于这些要求的详细信息请查阅 nsIXMLHttpRequest.idl.

+ +

XMLHttpRequest.onreadystatechange 的改变

+ +

此属性现在的类型为 nsIOnReadystatechangeHandler 而不是 nsIOnReadyStateChangeHandler  。 (类型的名称中的 "S" 和 "C" 已变更为小写.)

diff --git "a/files/zh-cn/mozilla/\345\220\214\346\227\266\344\275\277\347\224\250\345\244\232\344\270\252\347\233\270\344\272\222\347\213\254\347\253\213\347\232\204\347\201\253\347\213\220\346\265\217\350\247\210\345\231\250/index.html" "b/files/zh-cn/mozilla/\345\220\214\346\227\266\344\275\277\347\224\250\345\244\232\344\270\252\347\233\270\344\272\222\347\213\254\347\253\213\347\232\204\347\201\253\347\213\220\346\265\217\350\247\210\345\231\250/index.html" new file mode 100644 index 0000000000..ab77b18752 --- /dev/null +++ "b/files/zh-cn/mozilla/\345\220\214\346\227\266\344\275\277\347\224\250\345\244\232\344\270\252\347\233\270\344\272\222\347\213\254\347\253\213\347\232\204\347\201\253\347\213\220\346\265\217\350\247\210\345\231\250/index.html" @@ -0,0 +1,123 @@ +--- +title: 同时使用多个相互独立的火狐浏览器 +slug: Mozilla/同时使用多个相互独立的火狐浏览器 +translation_of: Mozilla/Firefox/Multiple_profiles +--- +

{{ draft() }}

+

火狐浏览器的配置文件是用户在浏览器中的设置、自定义、个性化内容的集合。你可以在这个连接中看到它的详细内容: Profiles on Mozilla's end-user support site.

+

为什么要拥有多个配置文件

+

不同的家庭成员可能希望使用不同的配置文件。这样他们的书签设置和插件就可以区分开来。

+

Web developers might want a secondary profile for testing websites, apps, or other projects on different Firefox channels. For example, you might want to have the Firebug add-on installed for Web development, but not for general-purpose Web browsing. While using the Nightly channel, you may encounter some add-ons that have become temporarily incompatible with new API changes, until the add-on developer has a chance to update them. You can remove such add-ons from your profile for Nightly use, while keeping them for use with other profiles.

+

For QA, testing, and bug triaging contributors, you may want to have multiple development versions of Firefox installed, each with its own profile. Creating new profiles for testing can keep you from losing your preferences, bookmarks, and history. It takes some time to set up a new profile, but once it is complete, all of your Firefox versions will update separately and can be run simultanesouly.

+

可用的浏览器开发通道

+

There are four available browser channels, each at a different level of stability and development. The four channels are Release, Beta, Aurora, and Nightly. The Release channel is recommended for most users, as it is the "official release" channel. However, for those more adventurous, you can try one of the other three channels to see what is coming in Firefox and play around with emerging features. The Beta channel contains the features that are expected to be in the next release of Firefox and are in final stages of testing. Aurora contains experimental features, which are not yet at beta quality. Nightly contains the latest code from Firefox developers and is the least stable channel.

+

第三方工具

+

In addition to the built-in Profile Manager and the external Profile Manager, there are a few third-party tools that make working with multiple profiles easy:

+

Mac OSX

+ +

配置文件管理器

+

{{ Note("On all operating systems, before you can start the Profile Manager, Firefox must be completely closed.") }}

+

These instructions are tentatively going away in favor of a new profile manager. You can find more details at Profile Manager

+

在Windows中启动配置文件管理器

+

Windows XP

+
    +
  1. Click the Start button
  2. +
  3. Click "Run"
  4. +
  5. Type "firefox -ProfileManager"
  6. +
+

Windows Vista/7

+
    +
  1. Click the Start button
  2. +
  3. Click the search bar at the bottom.
  4. +
  5. Type "firefox -ProfileManager"
  6. +
+

Windows 8/8.1

+
    +
  1. Press "Windows + R" on your keyboard.
  2. +
  3. Type "firefox -ProfileManager".
  4. +
+

If the Profile Manager window does not open, Firefox may have been running in the background, even though it was not visible. Close all instances of Firefox or restart the computer and then try again.

+

在Linux中启动配置文件管理器

+

If Firefox is already included in your Linux distribution or if you have installed Firefox with the package manager of your Linux distribution:

+
    +
  1. At the top of the Firefox window, click on the File menu and select Quit.
  2. +
  3. In Terminal run:
    + firefox --ProfileManager
  4. +
+

If the Profile Manager window does not open, Firefox may have been running in the background, even though it was not visible. Close all instances of Firefox or restart the computer and then try again.

+

在Mac OSX中启动配置文件管理器

+

Use the following tutorial until someone can test and step-by-step on a mac directly. Easily Run Multiple Firefox Instances on a Mac.

+

创建配置文件

+

These instructions should be the same for all operating systems.

+
    +
  1. To start the Create Profile Wizard, click "Create Profile..." in the Profile Manager.
  2. +
  3. Click Next and enter the name of the profile. Use a profile name that is descriptive, such as your personal name. This name is not exposed on the Internet.
  4. +
  5. You can also choose where to store the profile on your computer. To select storage location, click Choose Folder....
  6. +
  7. {{ Note("If you choose your own folder location for the profile, select a new or empty folder. If you choose a folder that isn't empty and you later remove the profile and choose the \"Delete Files\" option, everything inside that folder will be deleted.") }}
  8. +
  9. To create the new profile, click Finish.
  10. +
+

删除配置文件

+
    +
  1. In the Profile Manager, select the profile to remove, and click Delete Profile....
  2. +
  3. Confirm that you wish to delete the profile: +
      +
    • Don't Delete Files removes the profile from the Profile Manager yet retains the profile data files on your computer in the storage folder, so that your information is not lost. "Don't Delete Files" is the preferred option because it saves the old profile's folder and allows you to recover the files to a new profile.
    • +
    • Delete Files removes the profile and its files, including the profile bookmarks, settings, passwords, etc. {{ warning("If you use the \"Delete Files\" option, the profile folder and files will be deleted. This action cannot be undone.") }}
    • +
    • Cancel interrupts the profile deletion.
    • +
    +
  4. +
+

重命名配置文件

+
    +
  1. In the Profile Manager, select the profile you want to rename, and then click "Rename Profile".
  2. +
  3. Enter a new name for the profile and click on OK.
  4. +
  5. {{ Note("The folder containing the files for the profile is not renamed. ") }}
  6. +
+

可用选项

+

Work Offline

+

Choosing this option loads the selected profile and starts Firefox offline. You can view previously viewed web pages and experiment with your profile.

+

Don't ask at startup

+

If you have multiple profiles, Firefox prompts you for the profile to use each time you start Firefox. Select this option to allow Firefox to load the selected profile without prompting at startup.

+

{{ Note("To access other profiles after selecting this option, you must start the Profile Manager first.") }}

+

Using the profiles

+

Windows

+

If you want to have the profile manager to pop up each time you start Firefox, so you can choose a profile, you will need to edit the "Target" of the launch icon. To do this:

+
    +
  1. Right click the icon and choose "Properties".
  2. +
  3. When the properties dialog box pops up, you should see a "Target" text field that you can edit, and it should show the current file path.
  4. +
  5. After the closing quote, add "-ProfileManager"
  6. +
  7. Click Ok.
  8. +
+

Now whenever you double click that icon, the profile manager should appear, allowing you to choose which profile you'd like to use.

+

If you want individual icons to launch specific profiles, you will need to edit the "Target" of each icon. To do this:

+
    +
  1. Right click the icon and choose "Properties".
  2. +
  3. When the properties dialog box pops up, you should see a "Target" text field that you can edit, and it should show the current file path.
  4. +
  5. To permanently set a specific profile, add "-p PROFILE_NAME" to the target path, but outside of the quotes, replacing "PROFILE_NAME" with the actual profile name you chose.
  6. +
  7. If you would like to also allow multiple instances of Firefox to run at the same time, add "-no-remote" after the profile name.
  8. +
+

Once you are all done, click Ok. Do this for each icon you'd like to have a specific profile for. Once done, each one should automatically start with the specified profile.

+

Linux

+

There is no extremely straightforward way to create custom application launchers in Gnome 3 like there was in Gnome 2. The following tutorial will help get you going overall: Gnome 3 Custom application launcher. Once you get to the point of adding a new item, you can have the profile dialog show up every time or set the launcher to launch a specific profile.

+

If you want to have the profile manager to pop up each time you start Firefox, so you can choose a profile, you will need to set the command line for your new launcher.

+
    +
  1. Set the "command" text field to target the executable file, likely "/usr/bin/firefox", and add the "-p" parameter.
  2. +
+

If you want individual icons to launch specific profiles, you will need to set the command line for your new launcher. To do this:

+
    +
  1. Set the "command" text field to target the executable file, likely "/usr/bin/firefox", and add the "-p PROFILE_NAME" parameter, replacing "PROFILE_NAME" with the specific profile.
  2. +
  3. Repeat as necessary for each profile you want to set.
  4. +
  5. If you would like to also allow multiple instances of Firefox to run at the same time, add "-no-remote" after the profile name.
  6. +
+

Mac OSX

+

You can find a useful tutorial to set up custom launchers here: Managing Multiple Firefox Profiles in OSX. Do note it's best to follow all steps in the "Creating the scripts" section, including the "edit Info.plist" step. Leave off the profile name if you want the profile selector to show up every time you launch.

+

Setting up multiple profiles for different Firefox Channels

+

This section will be especially helpful if you are a developer wanting to work with multiple channels and each having their own separate launcher.

+

Windows

+

In Windows, the Aurora and Nightly builds get their own directory in the "Programs" folder, so you don't have to worry about where to store the downloaded files. However, all three will attempt to use the same profile by default, and you'll want to not keep this because the different channels have different levels of features. To set each launcher, follow the Windows instructions at Windows Launcher

+

Linux

+

In Linux, things aren't as automatically set up, and you will likely get a prompt to download a tar.bz2 file to extract from. Extract the files to a new directory and use the new launcher instructions from here. The only change you will need to make is the command path. You will want to set it to the directory you extracted the Firefox channel's tar.bz2 file into, and the executable "firefox" file located within. The remaining profile assignment methods will remain the same. You will want to, for sure, add the "-no-remote" part to the end of the command field, so that you could run multiple instances at the same time.

+

Mac OSX

+

You can find a useful tutorial to set up custom launchers here: Managing Multiple Firefox Profiles in OSX. Do note it's best to follow all steps in the "Creating the scripts" section, including the "edit Info.plist" step. Also you'll want to change the path in the do shell script to point to the correct .app file for the Firefox channel you want to target.

diff --git "a/files/zh-cn/mozilla/\346\227\245\345\216\206/index.html" "b/files/zh-cn/mozilla/\346\227\245\345\216\206/index.html" new file mode 100644 index 0000000000..876073f871 --- /dev/null +++ "b/files/zh-cn/mozilla/\346\227\245\345\216\206/index.html" @@ -0,0 +1,75 @@ +--- +title: Mozilla 日历 +slug: Mozilla/日历 +translation_of: Mozilla/Calendar +--- + + + + + + + +
Sunbird-Logo-148x155.png +

Mozillar日历项目是一个基于Mozilla应用程序架构的社区驱动的项目,其核心是基于libical的日历后端。Lightning附加组件是在该平台上构建的,它为Mozilla的邮件客户端Thunderbird提供集成化的日历功能。

+

Mozilla Calendar emphasizes free and open source technology and supports standardized technology like the ical/ics (rfc2445) format and the CalDAV (rfc4791) protocol, which is implemented by many freely available servers and also some commercial providers.

+
+ + + + + + + +
+

开发相关的主题

+
+
+ Building Calendar
+
+ Information about building Calendar with the new comm-central repository. There is also a simple build page for Thunderbird including Lightning and information about how comm-central works.
+
+
+
+ Creating a Calendar extension
+
+ Tutorial on creating a Calendar extension for Sunbird and Lightning.
+
+
+
+ Localization
+
+ How to get started with translating Calendar into your language and how to build Lightning in your Language. 
+
+ Testing Calendar
+
+ CalendarUtils reference for writing Mozmill tests, which can automatically test the UI so that regressions can be easily found.
+
+ Calendar Versions
+
+ This page will tell you which Calendar version fits with which Mozilla Platform and where current development is being done.
+
+
+

工具

+
+
+ Bugzilla
+
+ The Bugzilla database used to track issues for Mozilla projects.
+
+  
+
+ MXR
+
+ Browse and search the Calendar source code repository on the Web.
+
+  
+
+ Calendar Servers
+
+ Setup your own calendar server, or check to see how well commercial products are supported.
+
+  
+
+
+

 

-- cgit v1.2.3-54-g00ecf