Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

merge development to stabilization

  • Loading branch information...
commit 48839700cc5ad883660f84ac683444ae54f348cf 2 parents 4cd0c39 + 3b08b3b
@mykmelez mykmelez authored
Showing with 2,145 additions and 1,381 deletions.
  1. +5 −1 .gitignore
  2. +1 −1  bin/cfx
  3. +1 −1  bin/cfx.bat
  4. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/about.md
  5. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/annotator.md
  6. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/creating.md
  7. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/displaying.md
  8. +1 −1  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/overview.md
  9. +1 −1  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/storing.md
  10. +3 −3 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/annotator/widget.md
  11. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/api-idioms.md
  12. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/api-intro.md
  13. +7 −7 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/api-modules.md
  14. +56 −40 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/cfx-tool.md
  15. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/commonjs.md
  16. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/console.md
  17. +175 −0 doc/dev-guide-source/addon-development/content-scripts/access.md
  18. +60 −0 doc/dev-guide-source/addon-development/content-scripts/loading.md
  19. +67 −0 doc/dev-guide-source/addon-development/content-scripts/reddit-example.md
  20. +179 −0 doc/dev-guide-source/addon-development/content-scripts/using-port.md
  21. +136 −0 doc/dev-guide-source/addon-development/content-scripts/using-postmessage.md
  22. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/events.md
  23. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/getting-started.md
  24. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/guides.md
  25. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/implementing-reusable-module.md
  26. +2 −2 {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/implementing-simple-addon.md
  27. +1 −1  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/installation.md
  28. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/module-search.md
  29. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/package-spec.md
  30. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/program-id.md
  31. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/reference.md
  32. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/troubleshooting.md
  33. 0  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/tutorials.md
  34. +1 −1  {static-files/md/dev-guide → doc/dev-guide-source}/addon-development/two-types-of-scripts.md
  35. +87 −0 doc/dev-guide-source/addon-development/web-content.md
  36. 0  {static-files/md/dev-guide → doc/dev-guide-source}/appendices/credits.md
  37. 0  {static-files/md/dev-guide → doc/dev-guide-source}/appendices/glossary.md
  38. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/about.md
  39. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/best-practices.md
  40. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/chrome.md
  41. +1 −1  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/e10s.md
  42. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/globals.md
  43. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/guides.md
  44. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/reference.md
  45. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/tutorials.md
  46. 0  {static-files/md/dev-guide → doc/dev-guide-source}/module-development/xpi.md
  47. 0  {static-files/md/dev-guide → doc/dev-guide-source}/welcome.md
  48. +23 −16 { → doc}/static-files/base.html
  49. 0  { → doc}/static-files/css/api-reference.css
  50. 0  { → doc}/static-files/css/base.css
  51. 0  { → doc}/static-files/css/footer.css
  52. 0  { → doc}/static-files/css/header.css
  53. 0  { → doc}/static-files/css/sdk-docs.css
  54. 0  { → doc}/static-files/js/jquery.js
  55. +0 −24 { → doc}/static-files/js/main.js
  56. +175 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/access.md
  57. +60 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/loading.md
  58. +67 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/reddit-example.md
  59. +179 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/using-port.md
  60. +136 −0 doc/static-files/md/dev-guide/addon-development/content-scripts/using-postmessage.md
  61. 0  { → doc}/static-files/media/annotator/annotation-list.png
  62. 0  { → doc}/static-files/media/annotator/annotation-panel.png
  63. 0  { → doc}/static-files/media/annotator/annotator-design.png
  64. 0  { → doc}/static-files/media/annotator/editor-panel.png
  65. 0  { → doc}/static-files/media/annotator/highlight.png
  66. 0  { → doc}/static-files/media/annotator/matcher.png
  67. 0  { → doc}/static-files/media/annotator/pencil-off.png
  68. 0  { → doc}/static-files/media/annotator/pencil-on.png
  69. 0  { → doc}/static-files/media/annotator/widget-icon.png
  70. 0  { → doc}/static-files/media/bg-footer.png
  71. 0  { → doc}/static-files/media/bg-header.png
  72. 0  { → doc}/static-files/media/commonjs-modules.jpg
  73. 0  { → doc}/static-files/media/commonjs-translator.jpg
  74. 0  { → doc}/static-files/media/content-scripting-events.png
  75. 0  { → doc}/static-files/media/content-scripting-overview.png
  76. 0  { → doc}/static-files/media/favicon.png
  77. 0  { → doc}/static-files/media/firefox-32.png
  78. 0  { → doc}/static-files/media/firefox-logo.png
  79. 0  { → doc}/static-files/media/footer-logo-med.png
  80. 0  { → doc}/static-files/media/mozilla-tab.png
  81. 0  { → doc}/static-files/media/multiple-workers.jpg
  82. 0  { → doc}/static-files/media/screenshots/default-panel-osx.png
  83. 0  { → doc}/static-files/media/screenshots/default-panel-ubuntu.png
  84. 0  { → doc}/static-files/media/screenshots/default-panel-windows.png
  85. 0  { → doc}/static-files/media/screenshots/modules/context-menu-image-osx.png
  86. 0  { → doc}/static-files/media/screenshots/modules/notification-growl-osx.png
  87. 0  { → doc}/static-files/media/screenshots/modules/panel-tabs-osx.png
  88. 0  { → doc}/static-files/media/screenshots/modules/widget-content-osx.png
  89. 0  { → doc}/static-files/media/screenshots/modules/widget-icon-osx.png
  90. 0  { → doc}/static-files/media/screenshots/modules/widget-panel-osx.png
  91. 0  { → doc}/static-files/media/screenshots/translator/context-menu-osx.png
  92. 0  { → doc}/static-files/media/screenshots/translator/translated-osx.png
  93. BIN  doc/static-files/media/screenshots/widget-panel-clock.png
  94. 0  { → doc}/static-files/media/twitter-widget.png
  95. 0  { → doc}/static-files/syntaxhighlighter/MIT-LICENSE
  96. 0  { → doc}/static-files/syntaxhighlighter/scripts/shBrushCss.js
  97. 0  { → doc}/static-files/syntaxhighlighter/scripts/shBrushJScript.js
  98. 0  { → doc}/static-files/syntaxhighlighter/scripts/shBrushXml.js
  99. 0  { → doc}/static-files/syntaxhighlighter/scripts/shCore.js
  100. 0  { → doc}/static-files/syntaxhighlighter/styles/shCore.css
  101. 0  { → doc}/static-files/syntaxhighlighter/styles/shThemeDefault.css
  102. +2 −2 packages/addon-kit/docs/context-menu.md
  103. +2 −2 packages/addon-kit/docs/page-mod.md
  104. +4 −4 packages/addon-kit/docs/page-worker.md
  105. +7 −7 packages/addon-kit/docs/panel.md
  106. +31 −1 packages/addon-kit/docs/request.md
  107. +13 −1 packages/addon-kit/docs/self.md
  108. +5 −0 packages/addon-kit/docs/tabs.md
  109. +11 −11 packages/addon-kit/docs/widget.md
  110. +1 −1  packages/addon-kit/lib/context-menu.js
  111. +1 −1  packages/addon-kit/lib/page-mod.js
  112. +1 −1  packages/addon-kit/lib/tabs.js
  113. +7 −1 packages/addon-kit/tests/test-private-browsing.js
  114. +33 −0 packages/addon-kit/tests/test-tabs.js
  115. +2 −2 packages/api-utils/docs/content/worker.md
  116. +30 −0 packages/api-utils/docs/unit-test.md
  117. +5 −0 packages/api-utils/lib/content/content-proxy.js
  118. +1 −1  packages/api-utils/lib/content/symbiont.js
  119. +18 −9 packages/api-utils/lib/content/worker.js
  120. +0 −2  packages/api-utils/lib/cuddlefish.js
  121. +1 −1  packages/api-utils/lib/e10s.js
  122. +3 −5 packages/api-utils/lib/preferences-service.js
  123. +12 −3 packages/api-utils/lib/securable-module.js
  124. +2 −0  packages/api-utils/lib/self-maker.js
  125. +7 −1 packages/api-utils/lib/tabs/tab.js
  126. +2 −2 packages/api-utils/lib/unit-test-finder.js
  127. +2 −2 packages/api-utils/lib/windows/tabs.js
  128. +4 −1 packages/api-utils/tests/test-content-proxy.js
  129. +21 −11 packages/api-utils/tests/test-content-worker.js
  130. +1 −1  packages/api-utils/tests/test-preferences-service.js
  131. +25 −0 packages/api-utils/tests/test-require.js
  132. +11 −1 packages/api-utils/tests/test-self.js
  133. +24 −69 python-lib/cuddlefish/__init__.py
  134. +1 −1  python-lib/cuddlefish/app-extension/install.rdf
  135. 0  python-lib/cuddlefish/docs/__init__.py
  136. 0  python-lib/cuddlefish/{ → docs}/apiparser.py
  137. 0  python-lib/cuddlefish/{ → docs}/apirenderer.py
  138. +224 −0 python-lib/cuddlefish/docs/generate.py
  139. +3 −3 python-lib/cuddlefish/{ → docs}/webdocs.py
  140. +39 −40 python-lib/cuddlefish/manifest.py
  141. +0 −463 python-lib/cuddlefish/server.py
  142. +1 −1  python-lib/cuddlefish/tests/__init__.py
  143. 0  python-lib/cuddlefish/tests/static-files/{static-files/md/dev-guide → doc/dev-guide-source}/no_h1.md
  144. 0  python-lib/cuddlefish/tests/static-files/{static-files/md/dev-guide → doc/dev-guide-source}/welcome.md
  145. 0  python-lib/cuddlefish/tests/static-files/{ → doc}/static-files/base.html
  146. 0  python-lib/cuddlefish/tests/static-files/{ → doc}/static-files/index.html
  147. +1 −0  python-lib/cuddlefish/tests/static-files/doc/status.md5
  148. +1 −1  python-lib/cuddlefish/tests/test_apiparser.py
  149. +2 −2 python-lib/cuddlefish/tests/test_apirenderer.py
  150. +87 −0 python-lib/cuddlefish/tests/test_generate.py
  151. +22 −6 python-lib/cuddlefish/tests/test_manifest.py
  152. +0 −71 python-lib/cuddlefish/tests/test_server.py
  153. +18 −0 python-lib/cuddlefish/tests/test_util.py
  154. +3 −3 python-lib/cuddlefish/tests/test_webdocs.py
  155. +19 −0 python-lib/cuddlefish/util.py
  156. +5 −18 python-lib/cuddlefish/xpi.py
  157. +0 −523 static-files/md/dev-guide/addon-development/web-content.md
View
6 .gitignore
@@ -3,7 +3,11 @@ python-lib/cuddlefish/app-extension/components/jetpack.xpt
testdocs.tgz
jetpack-sdk-docs.tgz
.test_tmp/
-jetpack-sdk-docs/
+doc/dev-guide/
+doc/index.html
+doc/packages/
+doc/status.md5
+
# If you want to add other files here, like *.pyc and *.DS_Store,
# please add them to a global git ignore file.
View
2  bin/cfx
@@ -5,7 +5,7 @@ import sys
# set the cuddlefish "root directory" for this process if it's not already
# set in the environment
-cuddlefish_root = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
+cuddlefish_root = os.path.dirname(os.path.dirname(os.path.realpath(sys.argv[0])))
if 'CUDDLEFISH_ROOT' not in os.environ:
os.environ['CUDDLEFISH_ROOT'] = cuddlefish_root
View
2  bin/cfx.bat
@@ -1,3 +1,3 @@
@echo off
-python "%VIRTUAL_ENV%\bin\cfx" %1 %2 %3 %4 %5 %6 %7 %8 %9
+python "%VIRTUAL_ENV%\bin\cfx" %*
View
0  static-files/md/dev-guide/addon-development/about.md → doc/dev-guide-source/addon-development/about.md
File renamed without changes
View
0  ...ev-guide/addon-development/annotator/annotator.md → ...e-source/addon-development/annotator/annotator.md
File renamed without changes
View
4 ...dev-guide/addon-development/annotator/creating.md → ...de-source/addon-development/annotator/creating.md
@@ -170,7 +170,7 @@ overview-amo-review-process/](http://blog.mozilla.com/addons/2011/02/04/overview
You should see the highlight appearing when you move the mouse over certain elements:
<img class="image-center"
-src="media/annotator/highlight.png" alt="Annotator Highlighting">
+src="static-files/media/annotator/highlight.png" alt="Annotator Highlighting">
Click on the highlight and you should see something like this in the console
output:
@@ -323,7 +323,7 @@ element and click the element when it is highlighted. You should see a panel
with a text area for a note:
<img class="image-center"
-src="media/annotator/editor-panel.png" alt="Annotator Editor Panel">
+src="static-files/media/annotator/editor-panel.png" alt="Annotator Editor Panel">
<br>
Enter the note and press the return key: you should see console output like
View
4 ...v-guide/addon-development/annotator/displaying.md → ...-source/addon-development/annotator/displaying.md
@@ -191,13 +191,13 @@ Execute `cfx run` one last time. Activate the annotator and enter an
annotation. You should see a yellow border around the item you annotated:
<img class="image-center"
-src="media/annotator/matcher.png" alt="Annotator Matcher">
+src="static-files/media/annotator/matcher.png" alt="Annotator Matcher">
<br>
When you move your mouse over the item, the annotation should appear:
<img class="image-center"
-src="media/annotator/annotation-panel.png" alt="Annotation Panel">
+src="static-files/media/annotator/annotation-panel.png" alt="Annotation Panel">
<br>
Obviously this add-on isn't complete yet. It could do with more beautiful
View
2  ...dev-guide/addon-development/annotator/overview.md → ...de-source/addon-development/annotator/overview.md
@@ -10,7 +10,7 @@ We could represent the basic interactions between the `main` module and the
various content scripts like this:
<img class="image-center"
-src="media/annotator/annotator-design.png" alt="Annotator Design">
+src="static-files/media/annotator/annotator-design.png" alt="Annotator Design">
## User Interface ##
View
2  .../dev-guide/addon-development/annotator/storing.md → ...ide-source/addon-development/annotator/storing.md
@@ -233,7 +233,7 @@ Firefox. Activate the add-on, add an annotation, and then right-click the
widget. You should see something like this:
<img class="image-center"
-src="media/annotator/annotation-list.png" alt="Annotation List">
+src="static-files/media/annotator/annotation-list.png" alt="Annotation List">
<br>
<span class="aside">
View
6 ...d/dev-guide/addon-development/annotator/widget.md → ...uide-source/addon-development/annotator/widget.md
@@ -46,8 +46,8 @@ Save this in your `data/widget` directory as `widget.js`.
You can copy the widget's icons from here:
-<img style="margin-left:40px; margin-right:20px;" src="media/annotator/pencil-on.png" alt="Active Annotator">
-<img style="margin-left:20px; margin-right:20px;" src="media/annotator/pencil-off.png" alt="Inactive Annotator">
+<img style="margin-left:40px; margin-right:20px;" src="static-files/media/annotator/pencil-on.png" alt="Active Annotator">
+<img style="margin-left:20px; margin-right:20px;" src="static-files/media/annotator/pencil-off.png" alt="Inactive Annotator">
(Or make your own if you're feeling creative.) Save them in your `data/widget` directory.
@@ -100,7 +100,7 @@ Now from the `annotator` directory type `cfx run`. You should see the widget
in the add-on bar:
<div align="center">
-<img src="media/annotator/widget-icon.png" alt="Widget Icon">
+<img src="static-files/media/annotator/widget-icon.png" alt="Widget Icon">
</div>
<br>
View
0  ...iles/md/dev-guide/addon-development/api-idioms.md → doc/dev-guide-source/addon-development/api-idioms.md
File renamed without changes
View
0  ...files/md/dev-guide/addon-development/api-intro.md → doc/dev-guide-source/addon-development/api-intro.md
File renamed without changes
View
14 ...les/md/dev-guide/addon-development/api-modules.md → ...dev-guide-source/addon-development/api-modules.md
@@ -22,7 +22,7 @@ You can build or load the content locally or load it from a remote server.
The screenshot below shows a panel whose content is built from the list of
currently open tabs:
-<img class="image-center" src="media/screenshots/modules/panel-tabs-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/panel-tabs-osx.png"
alt="List open tabs panel">
<br>
@@ -40,7 +40,7 @@ Widgets are generally used in one of two different contexts:
the time in a selected time zone or the weather. The screenshot below shows a
widget that displays the time in the selected city:
-<img class="image-center" src="media/screenshots/modules/widget-content-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/widget-content-osx.png"
alt="Mozilla widget content">
<br>
@@ -49,7 +49,7 @@ interface. For example, a widget might display only an icon, but open a
settings dialog when the user clicks it. The widget below displays only the
Mozilla icon:
-<img class="image-center" src="media/screenshots/modules/widget-icon-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/widget-icon-osx.png"
alt="Mozilla widget icon">
<br>
@@ -57,7 +57,7 @@ To simplify your code in the latter case, you can assign a panel object to
your widget. Then when the user clicks the widget, the widget will display
the panel anchored to the widget:
-<img class="image-center" src="media/screenshots/modules/widget-panel-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/widget-panel-osx.png"
alt="Panel anchored to widget">
<br>
@@ -73,7 +73,7 @@ is selected) or define your own contexts using scripts.
In the screenshot below an add-on has added a new submenu to the context menu
associated with `img` elements:
-<img class="image-center" src="media/screenshots/modules/context-menu-image-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/context-menu-image-osx.png"
alt="Context-menu">
<br>
@@ -86,7 +86,7 @@ OS X and Windows, libnotify on Linux), so the notification will look slightly
different on different platforms. On Mac OS X a notification will look
something like this:
-<img class="image-center" src="media/screenshots/modules/notification-growl-osx.png"
+<img class="image-center" src="static-files/media/screenshots/modules/notification-growl-osx.png"
alt="Growl notification">
<br>
@@ -196,4 +196,4 @@ ID](dev-guide/addon-development/program-id.html).
Note that the `self` module is completely different from the global `self`
object accessible to content scripts, which is used by a content script to
-[communicate with the add-on code](dev-guide/addon-development/web-content#content_script_events).
+[communicate with the add-on code](dev-guide/addon-development/content-scripts/using-port.html).
View
96 ...-files/md/dev-guide/addon-development/cfx-tool.md → doc/dev-guide-source/addon-development/cfx-tool.md
@@ -23,8 +23,24 @@ applicable to a subset of the commands.
### cfx docs ###
-This command launches an HTTP server on the localhost to view web-based
-documentation in a new Firefox window.
+This command displays the documentation for the SDK. The documentation is
+shipped with the SDK in [Markdown](http://daringfireball.net/projects/markdown/)
+format. The first time this command is executed, and any time after the
+Markdown files on disk have changed, `cfx docs` will generate a set of HTML
+pages from them and launch a web browser to display them. If the Markdown files
+haven't changed, `cfx docs` just launches a browser initialized to the set of
+generated pages.
+
+To regenerate the documentation associated with a single file, you can
+specify the file as an argument. For example:
+
+<pre>
+ cfx docs doc/dev-guide-source/addon-development/cfx-tool.md
+</pre>
+
+This command will regenerate only the HTML page you're reading.
+This is useful if you're iteratively editing a single file, and don't want to wait for cfx to
+regenerate the complete documentation tree.
### cfx init ####
Create a new directory, change into it, and run `cfx init`.
@@ -87,6 +103,25 @@ your add-on alongside debuggers like [Firebug](http://getfirebug.com/).
<tr>
<td>
+ <code>--binary-args=CMDARGS</code>
+ </td>
+ <td>
+ <p>Pass <a href="http://kb.mozillazine.org/Command_line_arguments">extra
+ arguments</a> to the binary being executed (for example, Firefox).</p>
+ <p>For example, to pass the
+ <code>-jsconsole</code> argument to Firefox, which will launch the
+ <a href="https://developer.mozilla.org/en/Error_Console">JavaScript
+ Error Console</a>, try the following:</p<>
+ <pre>
+ cfx run --binary-args -jsconsole</pre>
+ <p>To pass multiple arguments, or arguments containing spaces, quote them:</p>
+ <pre>
+ cfx run --binary-args '-url "www.mozilla.org" -jsconsole'</pre>
+ </td>
+</tr>
+
+<tr>
+ <td>
<code>--extra-packages=EXTRA_PACKAGES</code>
</td>
<td>
@@ -218,25 +253,6 @@ To launch the application, enter the following command:
<tr>
<td>
- <code>--binary-args=CMDARGS</code>
- </td>
- <td>
- <p>Pass <a href="http://kb.mozillazine.org/Command_line_arguments">extra
- arguments</a> to the binary being executed (for example, Firefox).</p>
- <p>For example, to pass the
- <code>-jsconsole</code> argument to Firefox, which will launch the
- <a href="https://developer.mozilla.org/en/Error_Console">JavaScript
- Error Console</a>, try the following:</p<>
- <pre>
- cfx run --binary-args -jsconsole</pre>
- <p>To pass multiple arguments, or arguments containing spaces, quote them:</p>
- <pre>
- cfx run --binary-args '-url "www.mozilla.org" -jsconsole'</pre>
- </td>
-</tr>
-
-<tr>
- <td>
<code>--e10s</code>
</td>
<td>
@@ -298,6 +314,25 @@ times.
<tr>
<td>
+ <code>--binary-args=CMDARGS</code>
+ </td>
+ <td>
+ <p>Pass <a href="http://kb.mozillazine.org/Command_line_arguments">extra
+ arguments</a> to the binary being executed (for example, Firefox).</p>
+ <p>For example, to pass the
+ <code>-jsconsole</code> argument to Firefox, which will launch the
+ <a href="https://developer.mozilla.org/en/Error_Console">JavaScript
+ Error Console</a>, try the following:</p<>
+ <pre>
+ cfx run --binary-args -jsconsole</pre>
+ <p>To pass multiple arguments, or arguments containing spaces, quote them:</p>
+ <pre>
+ cfx run --binary-args '-url "www.mozilla.org" -jsconsole'</pre>
+ </td>
+</tr>
+
+<tr>
+ <td>
<code>--dependencies</code>
</td>
<td>
@@ -432,25 +467,6 @@ To launch the application, enter the following command:
<tr>
<td>
- <code>--binary-args=CMDARGS</code>
- </td>
- <td>
- <p>Pass <a href="http://kb.mozillazine.org/Command_line_arguments">extra
- arguments</a> to the binary being executed (for example, Firefox).</p>
- <p>For example, to pass the
- <code>-jsconsole</code> argument to Firefox, which will launch the
- <a href="https://developer.mozilla.org/en/Error_Console">JavaScript
- Error Console</a>, try the following:</p<>
- <pre>
- cfx run --binary-args -jsconsole</pre>
- <p>To pass multiple arguments, or arguments containing spaces, quote them:</p>
- <pre>
- cfx run --binary-args '-url "www.mozilla.org" -jsconsole'</pre>
- </td>
-</tr>
-
-<tr>
- <td>
<code>--e10s</code>
</td>
<td>
View
4 ...-files/md/dev-guide/addon-development/commonjs.md → doc/dev-guide-source/addon-development/commonjs.md
@@ -19,7 +19,7 @@ module wants to make available to other modules
object of another module. Your translator add-on uses `require` to import the
SDK modules it uses.
-![CommonJS modules](media/commonjs-modules.jpg)
+![CommonJS modules](static-files/media/commonjs-modules.jpg)
The SDK
[freezes](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze)
@@ -62,7 +62,7 @@ soon as Firefox has enabled the add-on.
So in terms of CommonJS objects the translator consists of a package that
contains a single module called `main`, and which imports three SDK modules:
-![CommonJS translator](media/commonjs-translator.jpg)
+![CommonJS translator](static-files/media/commonjs-translator.jpg)
Because an add-on is a CommonJS package it's possible to include more than one
module in an add-on, and to make your modules available to any code that want
View
0  ...c-files/md/dev-guide/addon-development/console.md → doc/dev-guide-source/addon-development/console.md
File renamed without changes
View
175 doc/dev-guide-source/addon-development/content-scripts/access.md
@@ -0,0 +1,175 @@
+# Content Script Access #
+
+This page talks about the access content scripts have to:
+
+* DOM objects in the pages they are attached to
+* other content scripts
+* other scripts loaded by the page they are attached to
+
+## Access to the DOM ##
+
+Content scripts need to be able to access DOM objects in arbitrary web
+pages, but this could cause two potential security problems:
+
+1. JavaScript values from the content script could be accessed by the page,
+enabling a malicious page to steal data or call privileged methods.
+2. a malicious page could redefine standard functions and properties of DOM
+objects so they don't do what the add-on expects.
+
+To deal with this, content scripts access DOM objects via a proxy.
+Any changes they make are made to the proxy, and so are not visible to
+page content.
+
+The proxy is based on `XRayWrapper`, (also known as
+[`XPCNativeWrapper`](https://developer.mozilla.oreg/en/XPCNativeWrapper)).
+These wrappers give the user access to the native values of DOM functions
+and properties, even if they have been redefined by a script.
+
+For example: the page below redefines `window.confirm()` to return
+`true` without showing a confirmation dialog:
+
+<script type="syntaxhighlighter" class="brush: html"><![CDATA[
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang='en' xml:lang='en' xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <script>
+ window.confirm = function(message) {
+ return true;
+ }
+ &lt;/script>
+ </head>
+</html>
+
+</script>
+
+But thanks to the content proxy, a content script which calls
+`window.confirm()` will get the native implementation:
+
+ var widgets = require("widget");
+ var tabs = require("tabs");
+ var data = require("self").data;
+
+ var widget = widgets.Widget({
+ id: "transfer",
+ label: "Transfer",
+ content: "Transfer",
+ width: 100,
+ onClick: function() {
+ tabs.activeTab.attach({
+ // native implementation of window.confirm will be used
+ contentScript: "console.log(window.confirm('Transfer all my money?'));"
+ });
+ }
+ });
+
+ tabs.open(data.url("xray.html"));
+
+You can try out this example [using the builder](https://builder.addons.mozilla.org/addon/1013777/revision/4/).
+
+The proxy is transparent to content scripts: as far as the content script
+is concerned, it is accessing the DOM directly. But because it's not, some
+things that you might expect to work, won't. For example, if the page includes
+a library like [jQuery](http://www.jquery.com), or any other page script
+adds other objects to any DOM nodes, they won't be visible to the content
+script. So to use jQuery you'll typically have to add it as a content script,
+as in [this example](dev-guide/addon-development/content-scripts/reddit-example.html).
+
+### unsafeWindow ###
+
+If you really need direct access to the underlying DOM, you can use the
+global `unsafeWindow` object.
+
+To see the difference, try editing the
+[example in the builder](https://builder.addons.mozilla.org/addon/1013777/revision/4/)
+so the content script uses `unsafeWindow.confirm()` instead of
+`window.confirm()` (to edit the example, you'll need to create an account
+with the Add-on Builder and clone the original add-on). Alternatively, try out
+[the example here](https://builder.addons.mozilla.org/addon/1015979/revision/3/).
+
+Avoid using `unsafeWindow` if possible: it is the same concept as
+Greasemonkey's unsafeWindow, and the
+[warnings for that](http://wiki.greasespot.net/UnsafeWindow) apply equally
+here. Also, `unsafeWindow` isn't a supported API, so it could be removed or
+changed in a future version of the SDK.
+
+
+## Access to Other Content Scripts ##
+
+Content scripts loaded into the same document can interact
+with each other directly as well as with the web content itself. However,
+content scripts which have been loaded into different documents
+cannot interact with each other.
+
+For example:
+
+* if an add-on creates a single `panel` object and loads several content
+scripts into the panel, then they can interact with each other
+
+* if an add-on creates two `panel` objects and loads a script into each
+one, they can't interact with each other.
+
+* if an add-on creates a single `page-mod` object and loads several content
+scripts into the page mod, then only content scripts associated with the
+same page can interact with each other: if two different matching pages are
+loaded, content scripts attached to page A cannot interact with those attached
+to page B.
+
+The web content has no access to objects created by the content script, unless
+the content script explicitly makes them available.
+
+## Access to Page Scripts ##
+
+You can communicate between the content script and page scripts using
+[`postMessage()`](https://developer.mozilla.org/en/DOM/window.postMessage),
+but there's a twist: in early versions of the SDK, the global `postMessage()`
+function in content scripts was used for communicating between the content
+script and the main add-on code. Although this has been
+[deprecated in favor of `self.postMessage`](https://wiki.mozilla.org/Labs/Jetpack/Release_Notes/1.0b5#Major_Changes),
+the old globals are still supported, so you can't currently use
+`window.postMessage()`. You must use `document.defaultView.postMessage()`
+instead.
+
+The following page script uses
+[`window.addEventListener`](https://developer.mozilla.org/en/DOM/element.addEventListener)
+to listen for messages:
+
+<script type="syntaxhighlighter" class="brush: html"><![CDATA[
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang='en' xml:lang='en' xmlns="http://www.w3.org/1999/xhtml">
+
+ <head>
+ <script>
+ window.addEventListener("message", function(event) {
+ window.alert(event.data);
+ }, false);
+ &lt;/script>
+
+ </head>
+
+</html>
+
+</script>
+
+Content scripts can send it messages using `document.defaultView.postMessage()`:
+
+ var widgets = require("widget");
+ var tabs = require("tabs");
+ var data = require("self").data;
+
+ var widget = widgets.Widget({
+ id: "postMessage",
+ label: "demonstrate document.defaultView.postMessage",
+ contentURL: "http://www.mozilla.org/favicon.ico",
+ onClick: function() {
+ tabs.activeTab.attach({
+ contentScript: "document.defaultView.postMessage('hi there!', '*');"
+ });
+ }
+ });
+
+ tabs.open(data.url("listener.html"));
+
+You can see this add-on at
+[https://builder.addons.mozilla.org/addon/1013849/revision/8/](https://builder.addons.mozilla.org/addon/1013849/revision/8/).
View
60 doc/dev-guide-source/addon-development/content-scripts/loading.md
@@ -0,0 +1,60 @@
+
+# Loading Content Scripts #
+
+The constructors for content-script-using objects such as panel and page-mod
+define a group of options for loading content scripts:
+
+<pre>
+ contentScript string, array
+ contentScriptFile string, array
+ contentScriptWhen string
+</pre>
+
+We have already seen the `contentScript` option, which enables you to pass
+in the text of the script itself as a string literal. This version of the API
+avoids the need to maintain a separate file for the content script.
+
+The `contentScriptFile` option enables you to pass in the local file URL from
+which the content script will be loaded. To supply the file
+"my-content-script.js", located in the /data subdirectory under your package's
+root directory, use a line like:
+
+ // "data" is supplied by the "self" module
+ var data = require("self").data;
+ ...
+ contentScriptFile: data.url("my-content-script.js")
+
+Both `contentScript` and `contentScriptFile` accept an array of strings, so you
+can load multiple scripts, which can also interact directly with each other in
+the content process:
+
+ // "data" is supplied by the "self" module
+ var data = require("self").data;
+ ...
+ contentScriptFile:
+ [data.url("jquery-1.4.2.min.js"), data.url("my-content-script.js")]
+
+Scripts specified using contentScriptFile are loaded before those specified
+using contentScript. This enables you to load a JavaScript library like jQuery
+by URL, then pass in a simple script inline that can use jQuery.
+
+The `contentScriptWhen` option specifies when the content script(s) should be
+loaded. It takes one of three possible values:
+
+* "start" loads the scripts immediately after the document element for the
+page is inserted into the DOM. At this point the DOM content hasn't been
+loaded yet, so the script won't be able to interact with it.
+
+* "ready" loads the scripts after the DOM for the page has been loaded: that
+is, at the point the
+[DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events)
+event fires. At this point, content scripts are able to interact with the DOM
+content, but externally-referenced stylesheets and images may not have finished
+loading.
+
+* "end" loads the scripts after all content (DOM, JS, CSS, images) for the page
+has been loaded, at the time the
+[window.onload event](https://developer.mozilla.org/en/DOM/window.onload)
+fires.
+
+The default value is "end".
View
67 doc/dev-guide-source/addon-development/content-scripts/reddit-example.md
@@ -0,0 +1,67 @@
+# Reddit Example #
+
+This example add-on creates a panel containing the mobile version of Reddit.
+When the user clicks on the title of a story in the panel, the add-on opens
+the linked story in a new tab in the main browser window.
+
+To accomplish this the add-on needs to run a content script in the context of
+the Reddit page which intercepts mouse clicks on each title link and fetches the
+link's target URL. The content script then needs to send the URL to the add-on
+script.
+
+This is the complete add-on script:
+
+ var data = require("self").data;
+
+ var reddit_panel = require("panel").Panel({
+ width: 240,
+ height: 320,
+ contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
+ contentScriptFile: [data.url("jquery-1.4.4.min.js"),
+ data.url("panel.js")]
+ });
+
+ reddit_panel.port.on("click", function(url) {
+ require("tabs").open(url);
+ });
+
+ require("widget").Widget({
+ id: "open-reddit-btn",
+ label: "Reddit",
+ contentURL: "http://www.reddit.com/static/favicon.ico",
+ panel: reddit_panel
+ });
+
+This code supplies two content scripts to the panel's constructor in the
+`contentScriptFile` option: the jQuery library and the script that intercepts
+link clicks.
+
+Finally, it registers a listener to the user-defined `click` event which in
+turn passes the URL into the `open` function of the
+[tabs](packages/addon-kit/docs/tabs.html) module.
+
+This is the `panel.js` content script that intercepts link clicks:
+
+ $(window).click(function (event) {
+ var t = event.target;
+
+ // Don't intercept the click if it isn't on a link.
+ if (t.nodeName != "A")
+ return;
+
+ // Don't intercept the click if it was on one of the links in the header
+ // or next/previous footer, since those links should load in the panel itself.
+ if ($(t).parents('#header').length || $(t).parents('.nextprev').length)
+ return;
+
+ // Intercept the click, passing it to the addon, which will load it in a tab.
+ event.stopPropagation();
+ event.preventDefault();
+ self.port.emit('click', t.toString());
+ });
+
+This script uses jQuery to interact with the DOM of the page and the
+`self.port.emit` function to pass URLs back to the add-on script.
+
+See the `examples/reddit-panel` directory for the complete example (including
+the content script containing jQuery).
View
179 doc/dev-guide-source/addon-development/content-scripts/using-port.md
@@ -0,0 +1,179 @@
+
+# Communicating using "port" #
+
+To enable add-on scripts and content scripts to communicate with each other,
+each end of the conversation has access to a `port` object which defines two
+functions:
+
+**`emit()`** is used to emit an event. It may be called with any number of
+parameters, but is most likely to be called with a name for the event and
+an optional payload. The payload can be any value that is
+<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">serializable to JSON</a>
+
+ port.emit("myEvent", myEventPayload);
+
+**`on()`** takes two parameters: the name of the event and a function to handle it:
+
+ port.on("myEvent", function handleMyEvent(myEventPayload) {
+ // Handle the event
+ });
+
+Here's simple add-on that sends a message to a content script using `port`:
+
+ var tabs = require("tabs");
+
+ var alertContentScript = "self.port.on('alert', function(message) {" +
+ " window.alert(message);" +
+ "})";
+
+ tabs.on("ready", function(tab) {
+ worker = tab.attach({
+ contentScript: alertContentScript
+ });
+ worker.port.emit("alert", "Message from the add-on");
+ });
+
+ tabs.open("http://www.mozilla.org");
+
+We could depict the interface between add-on code and content script code like
+this:
+
+<img class="image-center" src="static-files/media/content-scripting-events.png"
+alt="Content script events">
+
+Events are asynchronous: that is, the sender does not wait for a reply from
+the recipient but just emits the event and continues processing.
+
+## Accessing `port` in the Content Script ##
+
+<span class="aside">Note that the global `self` object is completely
+different from the [`self` module](packages/addon-kit/docs/self.html), which
+provides an API for an add-on to access its data files and ID.</span>
+
+In the content script the `port` object is available as a property of the
+global `self` object. Thus, to emit an event from a content script:
+
+ self.port.emit("myContentScriptEvent", myContentScriptEventPayload);
+
+To receive an event from the add-on code:
+
+ self.port.on("myAddonEvent", function(myAddonEventPayload) {
+ // Handle the event
+ });
+
+Compare this to the technique used to receive _built-in_ events in the
+content script. For example, to receive the `context` event in a content script
+associated with a [context menu](packages/addon-kit/docs/context-menu.html)
+object, you would call the `on` function attached to the global `self` object:
+
+ self.on("context", function() {
+ // Handle the event
+ });
+
+So the `port` property is essentially used here as a namespace for
+user-defined events.
+
+## Accessing `port` in the Add-on Script ##
+
+In the add-on code, the channel of communication between the add-on and a
+particular content script context is encapsulated by the `worker` object. Thus
+the `port` object for communicating with a content script is a property of the
+corresponding `worker` object.
+
+However, the worker is not exposed to add-on code in quite the same way
+in all modules. The `panel` and `page-worker` objects integrate the
+worker API directly. So to receive events from a content script associated
+with a panel you use `panel.port.on()`:
+
+ var panel = require("panel").Panel({
+ contentScript: "self.port.emit('showing', 'panel is showing');"
+ });
+
+ panel.port.on("showing", function(text) {
+ console.log(text);
+ });
+
+ panel.show();
+
+Conversely, to emit user-defined events from your add-on you can just call
+`panel.port.emit()`:
+
+ var panel = require("panel").Panel({
+ contentScript: "self.port.on('alert', function(text) {" +
+ " console.log(text);" +
+ "});"
+ });
+
+ panel.show();
+ panel.port.emit("alert", "panel is showing");
+
+The `panel` and `page-worker` objects only host a single page at a time,
+so each distinct page object only needs a single channel of communication
+to its content scripts. But some modules, such as `page-mod`, might need to
+handle multiple pages, each with its own context in which the content scripts
+are executing, so it needs a separate channel (worker) for each page.
+
+So `page-mod` does not integrate the worker API directly: instead, each time a
+content script is attached to a page, the worker associated with the page is
+supplied to the page-mod in its `onAttach` function. By supplying a target for
+this function in the page-mod's constructor you can register to receive
+events from the content script, and take a reference to the worker so as to
+emit events to it.
+
+ var pageModScript = "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);" +
+ "});"
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('click', function(html) {
+ worker.port.emit('warning', 'Do not click this again');
+ });
+ }
+ });
+
+In the add-on above there are two user-defined events:
+
+* `click` is sent from the page-mod to the add-on, when the user clicks an
+element in the page
+* `warning` sends a silly string back to the page-mod
+
+## <a name="json_serializable">JSON-Serializable Values</a> ##
+
+The payload for an event can be any JSON-serializable value. When events are
+sent their payloads are automatically serialized, and when events are received
+their payloads are automatically deserialized, so you don't need to worry
+about serialization.
+
+However, you _do_ have to ensure that the payload can be serialized to JSON.
+This means that it needs to be a string, number, boolean, null, array of
+JSON-serializable values, or an object whose property values are themselves
+JSON-serializable. This means you can't send functions, and if the object
+contains methods they won't be encoded.
+
+For example, to include an array of strings in the payload:
+
+ var pageModScript = "self.port.emit('loaded'," +
+ " [" +
+ " document.location.toString()," +
+ " document.title" +
+ " ]" +
+ ");"
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('loaded', function(pageInfo) {
+ console.log(pageInfo[0]);
+ console.log(pageInfo[1]);
+ });
+ }
+ });
View
136 doc/dev-guide-source/addon-development/content-scripts/using-postmessage.md
@@ -0,0 +1,136 @@
+# Communicating using "postMessage()" #
+
+As an alternative to user-defined events content modules support the built-in
+`message` event. In most cases user-defined events are preferable to message
+events. However, the `context-menu` module does not support user-defined
+events, so to send messages from a content script to the add-on via a context
+menu object, you must use message events.
+
+## Handling Message Events in the Content Script ##
+
+To send a message from a content script, you use the `postMessage` function of
+the global `self` object:
+
+ self.postMessage(contentScriptMessage);
+
+This takes a single parameter, the message payload, which may be any
+<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>.
+
+To receive a message from the add-on script, use `self`'s `on` function:
+
+ self.on("message", function(addonMessage) {
+ // Handle the message
+ });
+
+Like all event-registration functions, this takes two parameters: the name
+of the event, and the handler function. The handler function is passed the
+message payload.
+
+## Handling Message Events in the Add-on Script ##
+
+To send a message to a content script, use the worker's `postMessage`
+function. Again, `panel` and `page` integrate `worker` directly:
+
+ // Post a message to the panel's content scripts
+ panel.postMessage(addonMessage);
+
+However, for `page-mod` objects you need to listen to the `onAttach` event
+and use the worker supplied to that:
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.postMessage(addonMessage);
+ }
+ });
+
+To receive messages from a content script, use the worker's `on` function.
+To simplify this most content modules provide an `onMessage` property as an
+argument to the constructor:
+
+ panel = require("panel").Panel({
+ onMessage: function(contentScriptMessage) {
+ // Handle message from the content script
+ }
+ });
+
+## Message Events Versus User-Defined Events ##
+
+You can use message events as an alternative to user-defined events:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.postMessage(event.target.toString());" +
+ "}, false);";
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.on('message', function(message) {
+ console.log('mouseover: ' + message);
+ });
+ }
+ });
+
+The reason to prefer user-defined events is that as soon as you need to send
+more than one type of message, then both sending and receiving messages gets
+more complex.
+
+Suppose the content script wants to send `mouseout` events as well as
+`mouseover`. Now we have to embed the event type in the message payload, and
+implement a switch function in the receiver to dispatch the message:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.postMessage({" +
+ " kind: 'mouseover'," +
+ " element: event.target.toString()" +
+ " });" +
+ "}, false);" +
+ "window.addEventListener('mouseout', function(event) {" +
+ " self.postMessage({" +
+ " kind: 'mouseout'," +
+ " element: event.target.toString()" +
+ " });" +
+ " }, false);"
+
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.on('message', function(message) {
+ switch(message.kind) {
+ case 'mouseover':
+ console.log('mouseover: ' + message.element);
+ break;
+ case 'mouseout':
+ console.log('mouseout: ' + message.element);
+ break;
+ }
+ });
+ }
+ });
+
+Implementing the same add-on with user-defined events is shorter and more
+readable:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.port.emit('mouseover', event.target.toString());" +
+ "}, false);" +
+ "window.addEventListener('mouseout', function(event) {" +
+ " self.port.emit('mouseout', event.target.toString());" +
+ "}, false);";
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('mouseover', function(message) {
+ console.log('mouseover :' + message);
+ });
+ worker.port.on('mouseout', function(message) {
+ console.log('mouseout :' + message);
+ });
+ }
+ });
View
0  ...ic-files/md/dev-guide/addon-development/events.md → doc/dev-guide-source/addon-development/events.md
File renamed without changes
View
0  ...md/dev-guide/addon-development/getting-started.md → ...guide-source/addon-development/getting-started.md
File renamed without changes
View
0  ...ic-files/md/dev-guide/addon-development/guides.md → doc/dev-guide-source/addon-development/guides.md
File renamed without changes
View
0  ...addon-development/implementing-reusable-module.md → ...addon-development/implementing-reusable-module.md
File renamed without changes
View
4 ...de/addon-development/implementing-simple-addon.md → ...ce/addon-development/implementing-simple-addon.md
@@ -250,12 +250,12 @@ page containing some text that is not in English, for example:
Select some text on that page and right-click to activate the context menu.
You should see a new item labeled "Translate Selection":
-![translator context-menu](media/screenshots/translator/context-menu-osx.png)
+![translator context-menu](static-files/media/screenshots/translator/context-menu-osx.png)
Select that item and the text you selected should be replaced with its English
translation:
-![translator context-menu](media/screenshots/translator/translated-osx.png)
+![translator context-menu](static-files/media/screenshots/translator/translated-osx.png)
You will also see output like this appear in your command shell:
View
2  ...es/md/dev-guide/addon-development/installation.md → ...ev-guide-source/addon-development/installation.md
@@ -114,7 +114,7 @@ add-on for distribution, view documentation, and run unit tests.
## cfx docs ##
If you're reading these documents online, try running `cfx docs`. This will
-run a self-hosted documentation server and open it in your web browser.
+build the documentation for the SDK and display it in a browser.
## Problems? ##
View
0  ...s/md/dev-guide/addon-development/module-search.md → ...v-guide-source/addon-development/module-search.md
File renamed without changes
View
0  ...es/md/dev-guide/addon-development/package-spec.md → ...ev-guide-source/addon-development/package-spec.md
File renamed without changes
View
0  ...iles/md/dev-guide/addon-development/program-id.md → doc/dev-guide-source/addon-development/program-id.md
File renamed without changes
View
0  ...files/md/dev-guide/addon-development/reference.md → doc/dev-guide-source/addon-development/reference.md
File renamed without changes
View
0  ...md/dev-guide/addon-development/troubleshooting.md → ...guide-source/addon-development/troubleshooting.md
File renamed without changes
View
0  ...files/md/dev-guide/addon-development/tutorials.md → doc/dev-guide-source/addon-development/tutorials.md
File renamed without changes
View
2  ...v-guide/addon-development/two-types-of-scripts.md → ...-source/addon-development/two-types-of-scripts.md
@@ -107,7 +107,7 @@ such as <code>window</code>, <code>document</code>, and
<tr>
<td>The <code>self</code> global, used for communicating between content
scripts and add-on code. See the guide to
-<a href="dev-guide/addon-development/web-content.html#content_script_events">communicating with content scripts</a>
+<a href="dev-guide/addon-development/content-scripts/using-port.html">communicating with content scripts</a>
for more details.
</td>
<td class="cross">✘</td>
View
87 doc/dev-guide-source/addon-development/web-content.md
@@ -0,0 +1,87 @@
+# Content Scripts #
+
+Almost all interesting add-ons will need to interact with web content or the
+browser's user interface. For example, they may need to access and modify the
+content of web pages or be notified when the user clicks a link.
+
+The SDK provides several core modules to support this:
+
+**[panel](packages/addon-kit/docs/panel.html)**<br>
+Create a dialog that can host web content.
+
+**[page-worker](packages/addon-kit/docs/page-worker.html)**<br>
+Retrieve a page and access its content, without displaying it to the user.
+
+**[page-mod](packages/addon-kit/docs/page-mod.html)**<br>
+Execute scripts in the context of selected web pages.
+
+**[widget](packages/addon-kit/docs/widget.html)**<br>
+Host an add-on's user interface, including web content.
+
+**[context-menu](packages/addon-kit/docs/context-menu.html)**<br>
+Add items to the browser's context menu.
+
+Firefox is moving towards a model in which it uses separate
+processes to display the UI, handle web content, and execute add-ons. The main
+add-on code will run in the add-on process and will not have direct access to
+any web content.
+
+This means that an add-on which needs to interact with web content needs to be
+structured in two parts:
+
+* the main script runs in the add-on process
+* any code that needs to interact with web content is loaded into the web
+content process as a separate script. These separate scripts are called
+_content scripts_.
+
+A single add-on may use multiple content scripts, and content scripts loaded
+into the same context can interact directly with each other as well as with
+the web content itself. See the chapter on
+<a href="dev-guide/addon-development/content-scripts/access.html">
+content script access</a>.
+
+The add-on script and content script can't directly access each other's state.
+Instead, you can define your own events which each side can emit, and the
+other side can register listeners to handle them. The interfaces are similar
+to the event-handling interfaces described in the
+[Working with Events](dev-guide/addon-development/events.html) guide.
+
+The diagram below shows an overview of the main components and their
+relationships. The gray fill represents code written by the add-on developer.
+
+<img class="image-center" src="static-files/media/content-scripting-overview.png"
+alt="Content script events">
+
+This might sound complicated but it doesn't need to be. The following add-on
+uses the [page-mod](packages/addon-kit/docs/page-mod.html) module to replace the
+content of any web page in the `.co.uk` domain by executing a content script
+in the context of that page:
+
+ var pageMod = require("page-mod");
+
+ pageMod.add(new pageMod.PageMod({
+ include: ["*.co.uk"],
+ contentScript: 'document.body.innerHTML = ' +
+ '"<h1>this page has been eaten</h1>";'
+ }));
+
+In this example the content script is supplied directly to the page mod via
+the `contentScript` option in its constructor, and does not need to be
+maintained as a separate file at all.
+
+The next few chapters explain content scripts in detail:
+
+* [Loading Content Scripts](dev-guide/addon-development/content-scripts/loading.html):
+how to attach content scripts to web pages, and how to control the point at
+which they are executed
+* [Content Script Access](dev-guide/addon-development/content-scripts/access.html):
+detail about the access content scripts get to the DOM, to other content scripts,
+and to scripts loaded by the page itself
+* [Communicating Using <code>port</code>](dev-guide/addon-development/content-scripts/using-port.html):
+how to communicate between your add-on and its content scripts using the
+<code>port</code> object
+* [Communicating using <code>postMessage()</code>](dev-guide/addon-development/content-scripts/using-postmessage.html):
+how to communicate between your add-on and its content scripts using the
+<code>postMessage()</code> API
+* [Example](dev-guide/addon-development/content-scripts/reddit-example.html):
+a simple example add-on using content scripts
View
0  static-files/md/dev-guide/appendices/credits.md → doc/dev-guide-source/appendices/credits.md
File renamed without changes
View
0  static-files/md/dev-guide/appendices/glossary.md → doc/dev-guide-source/appendices/glossary.md
File renamed without changes
View
0  ...ic-files/md/dev-guide/module-development/about.md → doc/dev-guide-source/module-development/about.md
File renamed without changes
View
0  ...md/dev-guide/module-development/best-practices.md → ...guide-source/module-development/best-practices.md
File renamed without changes
View
0  ...c-files/md/dev-guide/module-development/chrome.md → doc/dev-guide-source/module-development/chrome.md
File renamed without changes
View
2  static-files/md/dev-guide/module-development/e10s.md → doc/dev-guide-source/module-development/e10s.md
@@ -16,7 +16,7 @@ parent chrome process.
## The Big Picture ##
-![Multi-Process Architecture](media/twitter-widget.png)
+![Multi-Process Architecture](static-files/media/twitter-widget.png)
The above diagram is a simplified depiction of what happens when a hypothetical
add-on using the `widget` module is loaded.
View
0  ...-files/md/dev-guide/module-development/globals.md → doc/dev-guide-source/module-development/globals.md
File renamed without changes
View
0  ...c-files/md/dev-guide/module-development/guides.md → doc/dev-guide-source/module-development/guides.md
File renamed without changes
View
0  ...iles/md/dev-guide/module-development/reference.md → doc/dev-guide-source/module-development/reference.md
File renamed without changes
View
0  ...iles/md/dev-guide/module-development/tutorials.md → doc/dev-guide-source/module-development/tutorials.md
File renamed without changes
View
0  static-files/md/dev-guide/module-development/xpi.md → doc/dev-guide-source/module-development/xpi.md
File renamed without changes
View
0  static-files/md/dev-guide/welcome.md → doc/dev-guide-source/welcome.md
File renamed without changes
View
39 static-files/base.html → doc/static-files/base.html
@@ -4,17 +4,17 @@
<head>
<base >
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
- <script type="text/javascript" src="syntaxhighlighter/scripts/shCore.js"></script>
- <script type="text/javascript" src="syntaxhighlighter/scripts/shBrushCss.js"></script>
- <script type="text/javascript" src="syntaxhighlighter/scripts/shBrushXml.js"></script>
- <script type="text/javascript" src="syntaxhighlighter/scripts/shBrushJScript.js"></script>
- <link rel="stylesheet" type="text/css" media="all" href="css/base.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/header.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/footer.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/sdk-docs.css">
- <link rel="stylesheet" type="text/css" media="all" href="css/api-reference.css">
- <link rel="stylesheet" type="text/css" href="syntaxhighlighter/styles/shCore.css">
- <link rel="stylesheet" type="text/css" href="syntaxhighlighter/styles/shThemeDefault.css">
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shCore.js"></script>
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shBrushCss.js"></script>
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shBrushXml.js"></script>
+ <script type="text/javascript" src="static-files/syntaxhighlighter/scripts/shBrushJScript.js"></script>
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/base.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/header.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/footer.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/sdk-docs.css">
+ <link rel="stylesheet" type="text/css" media="all" href="static-files/css/api-reference.css">
+ <link rel="stylesheet" type="text/css" href="static-files/syntaxhighlighter/styles/shCore.css">
+ <link rel="stylesheet" type="text/css" href="static-files/syntaxhighlighter/styles/shThemeDefault.css">
<!--[if IE]>
<style type="text/css">
.package-summary .module,
@@ -25,7 +25,7 @@
</style>
<![endif]-->
- <link rel="shortcut icon" type="image/x-icon" href="media/favicon.png">
+ <link rel="shortcut icon" type="image/x-icon" href="static-files/media/favicon.png">
<title></title>
</head>
<body>
@@ -100,7 +100,14 @@ <h3 class="sidebar-subsection-header"><a href="dev-guide/addon-development/guide
<ul>
<li><h4><a href="dev-guide/addon-development/two-types-of-scripts.html">Two Types of Scripts</a></h4></li>
<li><h4><a href="dev-guide/addon-development/events.html">Working with Events</a></h4></li>
- <li><h4><a href="dev-guide/addon-development/web-content.html">Working with Content Scripts</a></h4></li>
+ <li><h4><a href="dev-guide/addon-development/web-content.html">Content Scripts</a></h4>
+ <ul>
+ <li><a href="dev-guide/addon-development/content-scripts/loading.html">Loading Content Scripts</a></li>
+ <li><a href="dev-guide/addon-development/content-scripts/access.html">Content Script Access</a></li>
+ <li><a href="dev-guide/addon-development/content-scripts/using-port.html">Using <code>port</code></a></li>
+ <li><a href="dev-guide/addon-development/content-scripts/using-postmessage.html">Using <code>postMessage</code></a></li>
+ <li><a href="dev-guide/addon-development/content-scripts/reddit-example.html">Example</a></li>
+ </ul></li>
<li><h4><a href="dev-guide/addon-development/program-id.html">The Program ID</a></h4></li>
<li><h4><a href="dev-guide/addon-development/module-search.html">Module Search</a></h4></li>
</ul>
@@ -171,7 +178,7 @@ <h3 class="sidebar-subsection-header"><a href="dev-guide/module-development/refe
<div role="contentinfo" id="footer">
<div class="section">
- <img alt="" src="media/footer-logo-med.png" class="footerlogo">
+ <img alt="" src="static-files/media/footer-logo-med.png" class="footerlogo">
<div id="social-footer">
<ul>
<li>get to know <b>add-ons</b></li>
@@ -197,8 +204,8 @@ <h3 class="sidebar-subsection-header"><a href="dev-guide/module-development/refe
</div>
</div>
-<script type="text/javascript" src="js/jquery.js"></script>
-<script type="text/javascript" src="js/main.js"></script>
+<script type="text/javascript" src="static-files/js/jquery.js"></script>
+<script type="text/javascript" src="static-files/js/main.js"></script>
</body>
View
0  static-files/css/api-reference.css → doc/static-files/css/api-reference.css
File renamed without changes
View
0  static-files/css/base.css → doc/static-files/css/base.css
File renamed without changes
View
0  static-files/css/footer.css → doc/static-files/css/footer.css
File renamed without changes
View
0  static-files/css/header.css → doc/static-files/css/header.css
File renamed without changes
View
0  static-files/css/sdk-docs.css → doc/static-files/css/sdk-docs.css
File renamed without changes
View
0  static-files/js/jquery.js → doc/static-files/js/jquery.js
File renamed without changes
View
24 static-files/js/main.js → doc/static-files/js/main.js
@@ -1,5 +1,4 @@
function run(jQuery) {
- var IDLE_PING_DELAY = 5000;
function highlightCode() {
$("code").parent("pre").addClass("brush: js");
@@ -95,29 +94,6 @@ function run(jQuery) {
}
}
- var serverNeedsKeepalive = true;
-
- function sendIdlePing() {
- jQuery.ajax({url:"/api/idle",
- cache: false,
- error: function(req) {
- if (req.status == 501 || req.status == 404) {
- // The server either isn't implementing idle, or
- // we're being served from static files; just bail
- // and stop pinging this API endpoint.
- serverNeedsKeepalive = false;
- }
- }});
- scheduleNextIdlePing();
- }
-
- function scheduleNextIdlePing() {
- if (serverNeedsKeepalive)
- window.setTimeout(sendIdlePing, IDLE_PING_DELAY);
- }
-
- if (window.location.protocol != "file:")
- scheduleNextIdlePing();
highlightCurrentPage();
highlightCode();
$(".syntaxhighlighter").width("auto");
View
175 doc/static-files/md/dev-guide/addon-development/content-scripts/access.md
@@ -0,0 +1,175 @@
+# Content Script Access #
+
+This page talks about the access content scripts have to:
+
+* DOM objects in the pages they are attached to
+* other content scripts
+* other scripts loaded by the page they are attached to
+
+## Access to the DOM ##
+
+Content scripts need to be able to access DOM objects in arbitrary web
+pages, but this could cause two potential security problems:
+
+1. JavaScript values from the content script could be accessed by the page,
+enabling a malicious page to steal data or call privileged methods.
+2. a malicious page could redefine standard functions and properties of DOM
+objects so they don't do what the add-on expects.
+
+To deal with this, content scripts access DOM objects via a proxy.
+Any changes they make are made to the proxy, and so are not visible to
+page content.
+
+The proxy is based on `XRayWrapper`, (also known as
+[`XPCNativeWrapper`](https://developer.mozilla.oreg/en/XPCNativeWrapper)).
+These wrappers give the user access to the native values of DOM functions
+and properties, even if they have been redefined by a script.
+
+For example: the page below redefines `window.confirm()` to return
+`true` without showing a confirmation dialog:
+
+<script type="syntaxhighlighter" class="brush: html"><![CDATA[
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang='en' xml:lang='en' xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <script>
+ window.confirm = function(message) {
+ return true;
+ }
+ &lt;/script>
+ </head>
+</html>
+
+</script>
+
+But thanks to the content proxy, a content script which calls
+`window.confirm()` will get the native implementation:
+
+ var widgets = require("widget");
+ var tabs = require("tabs");
+ var data = require("self").data;
+
+ var widget = widgets.Widget({
+ id: "transfer",
+ label: "Transfer",
+ content: "Transfer",
+ width: 100,
+ onClick: function() {
+ tabs.activeTab.attach({
+ // native implementation of window.confirm will be used
+ contentScript: "console.log(window.confirm('Transfer all my money?'));"
+ });
+ }
+ });
+
+ tabs.open(data.url("xray.html"));
+
+You can try out this example [using the builder](https://builder.addons.mozilla.org/addon/1013777/revision/4/).
+
+The proxy is transparent to content scripts: as far as the content script
+is concerned, it is accessing the DOM directly. But because it's not, some
+things that you might expect to work, won't. For example, if the page includes
+a library like [jQuery](http://www.jquery.com), or any other page script
+adds other objects to any DOM nodes, they won't be visible to the content
+script. So to use jQuery you'll typically have to add it as a content script,
+as in [this example](dev-guide/addon-development/content-scripts/reddit-example.html).
+
+### unsafeWindow ###
+
+If you really need direct access to the underlying DOM, you can use the
+global `unsafeWindow` object.
+
+To see the difference, try editing the
+[example in the builder](https://builder.addons.mozilla.org/addon/1013777/revision/4/)
+so the content script uses `unsafeWindow.confirm()` instead of
+`window.confirm()` (to edit the example, you'll need to create an account
+with the Add-on Builder and clone the original add-on). Alternatively, try out
+[the example here](https://builder.addons.mozilla.org/addon/1015979/revision/3/).
+
+Avoid using `unsafeWindow` if possible: it is the same concept as
+Greasemonkey's unsafeWindow, and the
+[warnings for that](http://wiki.greasespot.net/UnsafeWindow) apply equally
+here. Also, `unsafeWindow` isn't a supported API, so it could be removed or
+changed in a future version of the SDK.
+
+
+## Access to Other Content Scripts ##
+
+Content scripts loaded into the same document can interact
+with each other directly as well as with the web content itself. However,
+content scripts which have been loaded into different documents
+cannot interact with each other.
+
+For example:
+
+* if an add-on creates a single `panel` object and loads several content
+scripts into the panel, then they can interact with each other
+
+* if an add-on creates two `panel` objects and loads a script into each
+one, they can't interact with each other.
+
+* if an add-on creates a single `page-mod` object and loads several content
+scripts into the page mod, then only content scripts associated with the
+same page can interact with each other: if two different matching pages are
+loaded, content scripts attached to page A cannot interact with those attached
+to page B.
+
+The web content has no access to objects created by the content script, unless
+the content script explicitly makes them available.
+
+## Access to Page Scripts ##
+
+You can communicate between the content script and page scripts using
+[`postMessage()`](https://developer.mozilla.org/en/DOM/window.postMessage),
+but there's a twist: in early versions of the SDK, the global `postMessage()`
+function in content scripts was used for communicating between the content
+script and the main add-on code. Although this has been
+[deprecated in favor of `self.postMessage`](https://wiki.mozilla.org/Labs/Jetpack/Release_Notes/1.0b5#Major_Changes),
+the old globals are still supported, so you can't currently use
+`window.postMessage()`. You must use `document.defaultView.postMessage()`
+instead.
+
+The following page script uses
+[`window.addEventListener`](https://developer.mozilla.org/en/DOM/element.addEventListener)
+to listen for messages:
+
+<script type="syntaxhighlighter" class="brush: html"><![CDATA[
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html lang='en' xml:lang='en' xmlns="http://www.w3.org/1999/xhtml">
+
+ <head>
+ <script>
+ window.addEventListener("message", function(event) {
+ window.alert(event.data);
+ }, false);
+ &lt;/script>
+
+ </head>
+
+</html>
+
+</script>
+
+Content scripts can send it messages using `document.defaultView.postMessage()`:
+
+ var widgets = require("widget");
+ var tabs = require("tabs");
+ var data = require("self").data;
+
+ var widget = widgets.Widget({
+ id: "postMessage",
+ label: "demonstrate document.defaultView.postMessage",
+ contentURL: "http://www.mozilla.org/favicon.ico",
+ onClick: function() {
+ tabs.activeTab.attach({
+ contentScript: "document.defaultView.postMessage('hi there!', '*');"
+ });
+ }
+ });
+
+ tabs.open(data.url("listener.html"));
+
+You can see this add-on at
+[https://builder.addons.mozilla.org/addon/1013849/revision/8/](https://builder.addons.mozilla.org/addon/1013849/revision/8/).
View
60 doc/static-files/md/dev-guide/addon-development/content-scripts/loading.md
@@ -0,0 +1,60 @@
+
+# Loading Content Scripts #
+
+The constructors for content-script-using objects such as panel and page-mod
+define a group of options for loading content scripts:
+
+<pre>
+ contentScript string, array
+ contentScriptFile string, array
+ contentScriptWhen string
+</pre>
+
+We have already seen the `contentScript` option, which enables you to pass
+in the text of the script itself as a string literal. This version of the API
+avoids the need to maintain a separate file for the content script.
+
+The `contentScriptFile` option enables you to pass in the local file URL from
+which the content script will be loaded. To supply the file
+"my-content-script.js", located in the /data subdirectory under your package's
+root directory, use a line like:
+
+ // "data" is supplied by the "self" module
+ var data = require("self").data;
+ ...
+ contentScriptFile: data.url("my-content-script.js")
+
+Both `contentScript` and `contentScriptFile` accept an array of strings, so you
+can load multiple scripts, which can also interact directly with each other in
+the content process:
+
+ // "data" is supplied by the "self" module
+ var data = require("self").data;
+ ...
+ contentScriptFile:
+ [data.url("jquery-1.4.2.min.js"), data.url("my-content-script.js")]
+
+Scripts specified using contentScriptFile are loaded before those specified
+using contentScript. This enables you to load a JavaScript library like jQuery
+by URL, then pass in a simple script inline that can use jQuery.
+
+The `contentScriptWhen` option specifies when the content script(s) should be
+loaded. It takes one of three possible values:
+
+* "start" loads the scripts immediately after the document element for the
+page is inserted into the DOM. At this point the DOM content hasn't been
+loaded yet, so the script won't be able to interact with it.
+
+* "ready" loads the scripts after the DOM for the page has been loaded: that
+is, at the point the
+[DOMContentLoaded](https://developer.mozilla.org/en/Gecko-Specific_DOM_Events)
+event fires. At this point, content scripts are able to interact with the DOM
+content, but externally-referenced stylesheets and images may not have finished
+loading.
+
+* "end" loads the scripts after all content (DOM, JS, CSS, images) for the page
+has been loaded, at the time the
+[window.onload event](https://developer.mozilla.org/en/DOM/window.onload)
+fires.
+
+The default value is "end".
View
67 doc/static-files/md/dev-guide/addon-development/content-scripts/reddit-example.md
@@ -0,0 +1,67 @@
+# Reddit Example #
+
+This example add-on creates a panel containing the mobile version of Reddit.
+When the user clicks on the title of a story in the panel, the add-on opens
+the linked story in a new tab in the main browser window.
+
+To accomplish this the add-on needs to run a content script in the context of
+the Reddit page which intercepts mouse clicks on each title link and fetches the
+link's target URL. The content script then needs to send the URL to the add-on
+script.
+
+This is the complete add-on script:
+
+ var data = require("self").data;
+
+ var reddit_panel = require("panel").Panel({
+ width: 240,
+ height: 320,
+ contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
+ contentScriptFile: [data.url("jquery-1.4.4.min.js"),
+ data.url("panel.js")]
+ });
+
+ reddit_panel.port.on("click", function(url) {
+ require("tabs").open(url);
+ });
+
+ require("widget").Widget({
+ id: "open-reddit-btn",
+ label: "Reddit",
+ contentURL: "http://www.reddit.com/static/favicon.ico",
+ panel: reddit_panel
+ });
+
+This code supplies two content scripts to the panel's constructor in the
+`contentScriptFile` option: the jQuery library and the script that intercepts
+link clicks.
+
+Finally, it registers a listener to the user-defined `click` event which in
+turn passes the URL into the `open` function of the
+[tabs](packages/addon-kit/docs/tabs.html) module.
+
+This is the `panel.js` content script that intercepts link clicks:
+
+ $(window).click(function (event) {
+ var t = event.target;
+
+ // Don't intercept the click if it isn't on a link.
+ if (t.nodeName != "A")
+ return;
+
+ // Don't intercept the click if it was on one of the links in the header
+ // or next/previous footer, since those links should load in the panel itself.
+ if ($(t).parents('#header').length || $(t).parents('.nextprev').length)
+ return;
+
+ // Intercept the click, passing it to the addon, which will load it in a tab.
+ event.stopPropagation();
+ event.preventDefault();
+ self.port.emit('click', t.toString());
+ });
+
+This script uses jQuery to interact with the DOM of the page and the
+`self.port.emit` function to pass URLs back to the add-on script.
+
+See the `examples/reddit-panel` directory for the complete example (including
+the content script containing jQuery).
View
179 doc/static-files/md/dev-guide/addon-development/content-scripts/using-port.md
@@ -0,0 +1,179 @@
+
+# Communicating using "port" #
+
+To enable add-on scripts and content scripts to communicate with each other,
+each end of the conversation has access to a `port` object which defines two
+functions:
+
+**`emit()`** is used to emit an event. It may be called with any number of
+parameters, but is most likely to be called with a name for the event and
+an optional payload. The payload can be any value that is
+<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">serializable to JSON</a>
+
+ port.emit("myEvent", myEventPayload);
+
+**`on()`** takes two parameters: the name of the event and a function to handle it:
+
+ port.on("myEvent", function handleMyEvent(myEventPayload) {
+ // Handle the event
+ });
+
+Here's simple add-on that sends a message to a content script using `port`:
+
+ var tabs = require("tabs");
+
+ var alertContentScript = "self.port.on('alert', function(message) {" +
+ " window.alert(message);" +
+ "})";
+
+ tabs.on("ready", function(tab) {
+ worker = tab.attach({
+ contentScript: alertContentScript
+ });
+ worker.port.emit("alert", "Message from the add-on");
+ });
+
+ tabs.open("http://www.mozilla.org");
+
+We could depict the interface between add-on code and content script code like
+this:
+
+<img class="image-center" src="media/content-scripting-events.png"
+alt="Content script events">
+
+Events are asynchronous: that is, the sender does not wait for a reply from
+the recipient but just emits the event and continues processing.
+
+## Accessing `port` in the Content Script ##
+
+<span class="aside">Note that the global `self` object is completely
+different from the [`self` module](packages/addon-kit/docs/self.html), which
+provides an API for an add-on to access its data files and ID.</span>
+
+In the content script the `port` object is available as a property of the
+global `self` object. Thus, to emit an event from a content script:
+
+ self.port.emit("myContentScriptEvent", myContentScriptEventPayload);
+
+To receive an event from the add-on code:
+
+ self.port.on("myAddonEvent", function(myAddonEventPayload) {
+ // Handle the event
+ });
+
+Compare this to the technique used to receive _built-in_ events in the
+content script. For example, to receive the `context` event in a content script
+associated with a [context menu](packages/addon-kit/docs/context-menu.html)
+object, you would call the `on` function attached to the global `self` object:
+
+ self.on("context", function() {
+ // Handle the event
+ });
+
+So the `port` property is essentially used here as a namespace for
+user-defined events.
+
+## Accessing `port` in the Add-on Script ##
+
+In the add-on code, the channel of communication between the add-on and a
+particular content script context is encapsulated by the `worker` object. Thus
+the `port` object for communicating with a content script is a property of the
+corresponding `worker` object.
+
+However, the worker is not exposed to add-on code in quite the same way
+in all modules. The `panel` and `page-worker` objects integrate the
+worker API directly. So to receive events from a content script associated
+with a panel you use `panel.port.on()`:
+
+ var panel = require("panel").Panel({
+ contentScript: "self.port.emit('showing', 'panel is showing');"
+ });
+
+ panel.port.on("showing", function(text) {
+ console.log(text);
+ });
+
+ panel.show();
+
+Conversely, to emit user-defined events from your add-on you can just call
+`panel.port.emit()`:
+
+ var panel = require("panel").Panel({
+ contentScript: "self.port.on('alert', function(text) {" +
+ " console.log(text);" +
+ "});"
+ });
+
+ panel.show();
+ panel.port.emit("alert", "panel is showing");
+
+The `panel` and `page-worker` objects only host a single page at a time,
+so each distinct page object only needs a single channel of communication
+to its content scripts. But some modules, such as `page-mod`, might need to
+handle multiple pages, each with its own context in which the content scripts
+are executing, so it needs a separate channel (worker) for each page.
+
+So `page-mod` does not integrate the worker API directly: instead, each time a
+content script is attached to a page, the worker associated with the page is
+supplied to the page-mod in its `onAttach` function. By supplying a target for
+this function in the page-mod's constructor you can register to receive
+events from the content script, and take a reference to the worker so as to
+emit events to it.
+
+ var pageModScript = "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);" +
+ "});"
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('click', function(html) {
+ worker.port.emit('warning', 'Do not click this again');
+ });
+ }
+ });
+
+In the add-on above there are two user-defined events:
+
+* `click` is sent from the page-mod to the add-on, when the user clicks an
+element in the page
+* `warning` sends a silly string back to the page-mod
+
+## <a name="json_serializable">JSON-Serializable Values</a> ##
+
+The payload for an event can be any JSON-serializable value. When events are
+sent their payloads are automatically serialized, and when events are received
+their payloads are automatically deserialized, so you don't need to worry
+about serialization.
+
+However, you _do_ have to ensure that the payload can be serialized to JSON.
+This means that it needs to be a string, number, boolean, null, array of
+JSON-serializable values, or an object whose property values are themselves
+JSON-serializable. This means you can't send functions, and if the object
+contains methods they won't be encoded.
+
+For example, to include an array of strings in the payload:
+
+ var pageModScript = "self.port.emit('loaded'," +
+ " [" +
+ " document.location.toString()," +
+ " document.title" +
+ " ]" +
+ ");"
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('loaded', function(pageInfo) {
+ console.log(pageInfo[0]);
+ console.log(pageInfo[1]);
+ });
+ }
+ });
View
136 doc/static-files/md/dev-guide/addon-development/content-scripts/using-postmessage.md
@@ -0,0 +1,136 @@
+# Communicating using "postMessage()" #
+
+As an alternative to user-defined events content modules support the built-in
+`message` event. In most cases user-defined events are preferable to message
+events. However, the `context-menu` module does not support user-defined
+events, so to send messages from a content script to the add-on via a context
+menu object, you must use message events.
+
+## Handling Message Events in the Content Script ##
+
+To send a message from a content script, you use the `postMessage` function of
+the global `self` object:
+
+ self.postMessage(contentScriptMessage);
+
+This takes a single parameter, the message payload, which may be any
+<a href = "dev-guide/addon-development/content-scripts/using-port.html#json_serializable">JSON-serializable value</a>.
+
+To receive a message from the add-on script, use `self`'s `on` function:
+
+ self.on("message", function(addonMessage) {
+ // Handle the message
+ });
+
+Like all event-registration functions, this takes two parameters: the name
+of the event, and the handler function. The handler function is passed the
+message payload.
+
+## Handling Message Events in the Add-on Script ##
+
+To send a message to a content script, use the worker's `postMessage`
+function. Again, `panel` and `page` integrate `worker` directly:
+
+ // Post a message to the panel's content scripts
+ panel.postMessage(addonMessage);
+
+However, for `page-mod` objects you need to listen to the `onAttach` event
+and use the worker supplied to that:
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.postMessage(addonMessage);
+ }
+ });
+
+To receive messages from a content script, use the worker's `on` function.
+To simplify this most content modules provide an `onMessage` property as an
+argument to the constructor:
+
+ panel = require("panel").Panel({
+ onMessage: function(contentScriptMessage) {
+ // Handle message from the content script
+ }
+ });
+
+## Message Events Versus User-Defined Events ##
+
+You can use message events as an alternative to user-defined events:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.postMessage(event.target.toString());" +
+ "}, false);";
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.on('message', function(message) {
+ console.log('mouseover: ' + message);
+ });
+ }
+ });
+
+The reason to prefer user-defined events is that as soon as you need to send
+more than one type of message, then both sending and receiving messages gets
+more complex.
+
+Suppose the content script wants to send `mouseout` events as well as
+`mouseover`. Now we have to embed the event type in the message payload, and
+implement a switch function in the receiver to dispatch the message:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.postMessage({" +
+ " kind: 'mouseover'," +
+ " element: event.target.toString()" +
+ " });" +
+ "}, false);" +
+ "window.addEventListener('mouseout', function(event) {" +
+ " self.postMessage({" +
+ " kind: 'mouseout'," +
+ " element: event.target.toString()" +
+ " });" +
+ " }, false);"
+
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.on('message', function(message) {
+ switch(message.kind) {
+ case 'mouseover':
+ console.log('mouseover: ' + message.element);
+ break;
+ case 'mouseout':
+ console.log('mouseout: ' + message.element);
+ break;
+ }
+ });
+ }
+ });
+
+Implementing the same add-on with user-defined events is shorter and more
+readable:
+
+ var pageModScript = "window.addEventListener('mouseover', function(event) {" +
+ " self.port.emit('mouseover', event.target.toString());" +
+ "}, false);" +
+ "window.addEventListener('mouseout', function(event) {" +
+ " self.port.emit('mouseout', event.target.toString());" +
+ "}, false);";
+
+ var pageMod = require('page-mod').PageMod({
+ include: ['*'],
+ contentScript: pageModScript,
+ onAttach: function(worker) {
+ worker.port.on('mouseover', function(message) {
+ console.log('mouseover :' + message);
+ });
+ worker.port.on('mouseout', function(message) {
+ console.log('mouseout :' + message);
+ });
+ }
+ });
View
0  static-files/media/annotator/annotation-list.png → doc/static-files/media/annotator/annotation-list.png
File renamed without changes
View
0  static-files/media/annotator/annotation-panel.png → ...static-files/media/annotator/annotation-panel.png
File renamed without changes
View
0  static-files/media/annotator/annotator-design.png → ...static-files/media/annotator/annotator-design.png
File renamed without changes
View
0  static-files/media/annotator/editor-panel.png → doc/static-files/media/annotator/editor-panel.png
File renamed without changes
View
0  static-files/media/annotator/highlight.png → doc/static-files/media/annotator/highlight.png
File renamed without changes
View
0  static-files/media/annotator/matcher.png → doc/static-files/media/annotator/matcher.png
File renamed without changes
View
0  static-files/media/annotator/pencil-off.png → doc/static-files/media/annotator/pencil-off.png
File renamed without changes
View
0  static-files/media/annotator/pencil-on.png → doc/static-files/media/annotator/pencil-on.png
File renamed without changes
View
0  static-files/media/annotator/widget-icon.png → doc/static-files/media/annotator/widget-icon.png
File renamed without changes
View
0  static-files/media/bg-footer.png → doc/static-files/media/bg-footer.png
File renamed without changes
View
0  static-files/media/bg-header.png → doc/static-files/media/bg-header.png
File renamed without changes
View
0  static-files/media/commonjs-modules.jpg → doc/static-files/media/commonjs-modules.jpg
File renamed without changes
View
0  static-files/media/commonjs-translator.jpg → doc/static-files/media/commonjs-translator.jpg
File renamed without changes
View
0  static-files/media/content-scripting-events.png → doc/static-files/media/content-scripting-events.png
File renamed without changes
View
0  static-files/media/content-scripting-overview.png → ...static-files/media/content-scripting-overview.png
File renamed without changes
View
0  static-files/media/favicon.png → doc/static-files/media/favicon.png
File renamed without changes
View
0  static-files/media/firefox-32.png → doc/static-files/media/firefox-32.png
File renamed without changes
View
0  static-files/media/firefox-logo.png → doc/static-files/media/firefox-logo.png
File renamed without changes
View
0  static-files/media/footer-logo-med.png → doc/static-files/media/footer-logo-med.png
File renamed without changes
View
0  static-files/media/mozilla-tab.png → doc/static-files/media/mozilla-tab.png
File renamed without changes
View
0  static-files/media/multiple-workers.jpg → doc/static-files/media/multiple-workers.jpg
File renamed without changes
View
0  static-files/media/screenshots/default-panel-osx.png → ...tic-files/media/screenshots/default-panel-osx.png
File renamed without changes
View
0  ...-files/media/screenshots/default-panel-ubuntu.png → ...-files/media/screenshots/default-panel-ubuntu.png
File renamed without changes
View
0  ...files/media/screenshots/default-panel-windows.png → ...files/media/screenshots/default-panel-windows.png
File renamed without changes
View
0  ...ia/screenshots/modules/context-menu-image-osx.png → ...ia/screenshots/modules/context-menu-image-osx.png
File renamed without changes
View
0  ...ia/screenshots/modules/notification-growl-osx.png → ...ia/screenshots/modules/notification-growl-osx.png
Diff not rendered