From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- testing/marionette/accessibility.js | 441 ++ testing/marionette/action.js | 1348 +++++ testing/marionette/addon.js | 104 + testing/marionette/assert.js | 322 ++ testing/marionette/atom.js | 192 + testing/marionette/browser.js | 436 ++ testing/marionette/capture.js | 193 + testing/marionette/cert.js | 140 + testing/marionette/chrome/test.xul | 25 + testing/marionette/chrome/test2.xul | 19 + .../marionette/chrome/test_anonymous_content.xul | 37 + testing/marionette/chrome/test_dialog.dtd | 7 + testing/marionette/chrome/test_dialog.properties | 7 + testing/marionette/chrome/test_dialog.xul | 36 + testing/marionette/chrome/test_nested_iframe.xul | 9 + testing/marionette/client/.flake8 | 3 + testing/marionette/client/MANIFEST.in | 2 + testing/marionette/client/docs/Makefile | 153 + .../marionette/client/docs/advanced/actions.rst | 46 + testing/marionette/client/docs/advanced/debug.rst | 54 + .../client/docs/advanced/findelement.rst | 126 + .../marionette/client/docs/advanced/landing.rst | 13 + testing/marionette/client/docs/advanced/stale.rst | 71 + testing/marionette/client/docs/basics.rst | 185 + testing/marionette/client/docs/conf.py | 259 + testing/marionette/client/docs/index.rst | 16 + testing/marionette/client/docs/interactive.rst | 55 + testing/marionette/client/docs/make.bat | 190 + testing/marionette/client/docs/reference.rst | 51 + .../client/marionette_driver/__init__.py | 26 + .../marionette/client/marionette_driver/addons.py | 70 + testing/marionette/client/marionette_driver/by.py | 27 + .../client/marionette_driver/date_time_value.py | 49 + .../client/marionette_driver/decorators.py | 69 + .../marionette/client/marionette_driver/errors.py | 179 + .../client/marionette_driver/expected.py | 311 ++ .../client/marionette_driver/geckoinstance.py | 467 ++ .../client/marionette_driver/gestures.py | 93 + .../marionette/client/marionette_driver/keys.py | 84 + .../client/marionette_driver/localization.py | 54 + .../client/marionette_driver/marionette.py | 2153 ++++++++ .../client/marionette_driver/selection.py | 227 + .../marionette/client/marionette_driver/timeout.py | 98 + .../client/marionette_driver/transport.py | 300 ++ .../marionette/client/marionette_driver/wait.py | 167 + testing/marionette/client/requirements.txt | 2 + testing/marionette/client/setup.py | 49 + testing/marionette/components/marionette.js | 237 + testing/marionette/components/marionette.manifest | 4 + testing/marionette/components/moz.build | 9 + testing/marionette/cookies.js | 131 + testing/marionette/dispatcher.js | 228 + testing/marionette/driver.js | 2907 +++++++++++ testing/marionette/element.js | 1159 +++++ testing/marionette/error.js | 487 ++ testing/marionette/evaluate.js | 494 ++ testing/marionette/event.js | 1365 +++++ testing/marionette/frame.js | 260 + testing/marionette/harness/.flake8 | 3 + testing/marionette/harness/MANIFEST.in | 3 + testing/marionette/harness/README.rst | 30 + .../harness/marionette_harness/__init__.py | 35 + .../marionette_harness/marionette_test/__init__.py | 31 + .../marionette_test/decorators.py | 239 + .../marionette_test/testcases.py | 504 ++ .../harness/marionette_harness/runner/__init__.py | 22 + .../harness/marionette_harness/runner/base.py | 1076 ++++ .../harness/marionette_harness/runner/httpd.py | 142 + .../marionette_harness/runner/mixins/__init__.py | 13 + .../runner/mixins/browsermob-proxy-py/History.md | 57 + .../browsermobproxy/__init__.py | 6 + .../browsermob-proxy-py/browsermobproxy/client.py | 326 ++ .../browsermob-proxy-py/browsermobproxy/server.py | 106 + .../browsermobproxy/webdriver_event_listener.py | 34 + .../mixins/browsermob-proxy-py/docs/Makefile | 153 + .../docs/_build/html/.buildinfo | 4 + .../docs/_build/html/_modules/browsermobproxy.html | 98 + .../docs/_build/html/_modules/index.html | 90 + .../docs/_build/html/_sources/client.txt | 8 + .../docs/_build/html/_sources/index.txt | 72 + .../docs/_build/html/_sources/server.txt | 8 + .../docs/_build/html/_static/basic.css | 537 ++ .../docs/_build/html/_static/default.css | 256 + .../docs/_build/html/_static/doctools.js | 238 + .../docs/_build/html/_static/jquery.js | 2 + .../docs/_build/html/_static/pygments.css | 62 + .../docs/_build/html/_static/searchtools.js | 622 +++ .../docs/_build/html/_static/sidebar.js | 159 + .../docs/_build/html/_static/underscore.js | 31 + .../docs/_build/html/_static/websupport.js | 808 +++ .../docs/_build/html/client.html | 404 ++ .../docs/_build/html/genindex.html | 297 ++ .../docs/_build/html/index.html | 174 + .../docs/_build/html/objects.inv | 6 + .../docs/_build/html/py-modindex.html | 112 + .../docs/_build/html/search.html | 105 + .../docs/_build/html/searchindex.js | 1 + .../docs/_build/html/server.html | 157 + .../mixins/browsermob-proxy-py/docs/client.rst | 8 + .../runner/mixins/browsermob-proxy-py/docs/conf.py | 243 + .../mixins/browsermob-proxy-py/docs/index.rst | 72 + .../mixins/browsermob-proxy-py/docs/make.bat | 190 + .../mixins/browsermob-proxy-py/docs/server.rst | 8 + .../runner/mixins/browsermob-proxy-py/readme.md | 88 + .../runner/mixins/browsermob-proxy-py/setup.py | 20 + .../mixins/browsermob-proxy-py/test/test_client.py | 247 + .../mixins/browsermob-proxy-py/test/test_remote.py | 31 + .../browsermob-proxy-py/test/test_webdriver.py | 60 + .../marionette_harness/runner/mixins/browsermob.py | 80 + .../runner/mixins/window_manager.py | 129 + .../harness/marionette_harness/runner/serve.py | 227 + .../harness/marionette_harness/runner/test.cert | 86 + .../harness/marionette_harness/runner/test.key | 28 + .../harness/marionette_harness/runtests.py | 98 + .../tests/harness_unit/conftest.py | 100 + .../tests/harness_unit/test_httpd.py | 90 + .../harness_unit/test_marionette_arguments.py | 32 + .../tests/harness_unit/test_marionette_harness.py | 108 + .../tests/harness_unit/test_marionette_runner.py | 442 ++ .../harness_unit/test_marionette_test_result.py | 54 + .../tests/harness_unit/test_serve.py | 67 + .../marionette_harness/tests/unit-tests.ini | 11 + .../tests/unit/importanotherscript.js | 1 + .../marionette_harness/tests/unit/importscript.js | 1 + .../tests/unit/mn-restartless-unsigned.xpi | Bin 0 -> 1552 bytes .../tests/unit/single_finger_functions.py | 131 + .../tests/unit/test_about_pages.py | 134 + .../tests/unit/test_accessibility.py | 210 + .../marionette_harness/tests/unit/test_addons.py | 58 + .../tests/unit/test_anonymous_content.py | 90 + .../tests/unit/test_browsermobproxy.py | 34 + .../tests/unit/test_capabilities.py | 253 + .../marionette_harness/tests/unit/test_checkbox.py | 17 + .../tests/unit/test_checkbox_chrome.py | 36 + .../marionette_harness/tests/unit/test_chrome.py | 51 + .../tests/unit/test_chrome_async_finish.js | 6 + .../tests/unit/test_chrome_element_css.py | 23 + .../marionette_harness/tests/unit/test_clearing.py | 72 + .../marionette_harness/tests/unit/test_click.py | 254 + .../tests/unit/test_click_chrome.py | 35 + .../tests/unit/test_click_scrolling.py | 117 + .../marionette_harness/tests/unit/test_cookies.py | 115 + .../marionette_harness/tests/unit/test_crash.py | 155 + .../tests/unit/test_data_driven.py | 67 + .../tests/unit/test_date_time_value.py | 29 + .../tests/unit/test_element_retrieval.py | 483 ++ .../tests/unit/test_element_state.py | 162 + .../tests/unit/test_element_state_chrome.py | 85 + .../tests/unit/test_elementsize.py | 17 + .../tests/unit/test_elementsize_chrome.py | 34 + .../marionette_harness/tests/unit/test_errors.py | 77 + .../tests/unit/test_execute_async_script.py | 156 + .../tests/unit/test_execute_isolate.py | 37 + .../tests/unit/test_execute_sandboxes.py | 79 + .../tests/unit/test_execute_script.py | 402 ++ .../marionette_harness/tests/unit/test_expected.py | 228 + .../tests/unit/test_expectedfail.py | 11 + .../tests/unit/test_file_upload.py | 152 + .../tests/unit/test_findelement_chrome.py | 82 + .../tests/unit/test_geckoinstance.py | 25 + .../tests/unit/test_getactiveframe_oop.py | 93 + .../tests/unit/test_implicit_waits.py | 26 + .../tests/unit/test_import_script.py | 138 + .../tests/unit/test_key_actions.py | 91 + .../tests/unit/test_localization.py | 56 + .../marionette_harness/tests/unit/test_log.py | 64 + .../tests/unit/test_marionette.py | 67 + .../tests/unit/test_modal_dialogs.py | 198 + .../tests/unit/test_mouse_action.py | 114 + .../tests/unit/test_navigation.py | 447 ++ .../tests/unit/test_pagesource.py | 33 + .../tests/unit/test_pagesource_chrome.py | 29 + .../marionette_harness/tests/unit/test_position.py | 19 + .../marionette_harness/tests/unit/test_prefs.py | 167 + .../tests/unit/test_profile_management.py | 34 + .../marionette_harness/tests/unit/test_proxy.py | 252 + .../tests/unit/test_quit_restart.py | 173 + .../tests/unit/test_rendered_element.py | 34 + .../marionette_harness/tests/unit/test_report.py | 29 + .../tests/unit/test_run_js_test.py | 10 + .../tests/unit/test_screen_orientation.py | 86 + .../tests/unit/test_screenshot.py | 428 ++ .../marionette_harness/tests/unit/test_select.py | 164 + .../marionette_harness/tests/unit/test_session.py | 56 + .../tests/unit/test_set_window_size.py | 84 + .../tests/unit/test_shadow_dom.py | 80 + .../tests/unit/test_simpletest_chrome.js | 12 + .../tests/unit/test_simpletest_fail.js | 16 + .../tests/unit/test_simpletest_pass.js | 12 + .../tests/unit/test_simpletest_sanity.py | 107 + .../tests/unit/test_simpletest_timeout.js | 16 + .../tests/unit/test_single_finger_desktop.py | 123 + .../tests/unit/test_skip_setup.py | 35 + .../tests/unit/test_switch_frame.py | 183 + .../tests/unit/test_switch_frame_chrome.py | 56 + .../tests/unit/test_switch_remote_frame.py | 118 + .../tests/unit/test_switch_window_chrome.py | 124 + .../tests/unit/test_switch_window_content.py | 171 + .../tests/unit/test_teardown_context_preserved.py | 21 + .../marionette_harness/tests/unit/test_text.py | 224 + .../tests/unit/test_text_chrome.py | 44 + .../marionette_harness/tests/unit/test_timeouts.py | 115 + .../tests/unit/test_transport.py | 172 + .../marionette_harness/tests/unit/test_typing.py | 332 ++ .../tests/unit/test_using_permissions.py | 46 + .../tests/unit/test_visibility.py | 121 + .../marionette_harness/tests/unit/test_wait.py | 347 ++ .../tests/unit/test_window_close_chrome.py | 80 + .../tests/unit/test_window_close_content.py | 81 + .../tests/unit/test_window_handles_chrome.py | 207 + .../tests/unit/test_window_handles_content.py | 96 + .../tests/unit/test_window_position.py | 42 + .../tests/unit/test_window_title.py | 12 + .../tests/unit/test_window_title_chrome.py | 26 + .../tests/unit/test_window_type.py | 27 + .../tests/unit/test_with_using_context.py | 66 + .../marionette_harness/tests/unit/unit-tests.ini | 132 + .../marionette_harness/tests/webapi-tests.ini | 8 + .../harness/marionette_harness/www/black.png | Bin 0 -> 150 bytes .../harness/marionette_harness/www/bug814037.html | 55 + .../www/click_out_of_bounds_overflow.html | 90 + .../harness/marionette_harness/www/clicks.html | 39 + .../marionette_harness/www/cssTransform.html | 61 + .../marionette_harness/www/cssTransform2.html | 20 + .../marionette_harness/www/datetimePage.html | 15 + .../marionette_harness/www/deletingFrame.html | 29 + .../marionette_harness/www/double_click.html | 18 + .../marionette_harness/www/element_bottom.html | 12 + .../marionette_harness/www/element_left.html | 12 + .../www/element_outside_viewport.html | 41 + .../marionette_harness/www/element_right.html | 12 + .../marionette_harness/www/element_top.html | 12 + .../harness/marionette_harness/www/empty.html | 12 + .../harness/marionette_harness/www/formPage.html | 116 + .../harness/marionette_harness/www/frameset.html | 14 + .../marionette_harness/www/framesetPage2.html | 7 + .../harness/marionette_harness/www/hidden.html | 5 + .../harness/marionette_harness/www/html5/blue.jpg | Bin 0 -> 92 bytes .../www/html5/boolean_attributes.html | 2 + .../marionette_harness/www/html5/geolocation.js | 18 + .../harness/marionette_harness/www/html5/green.jpg | Bin 0 -> 92 bytes .../marionette_harness/www/html5/offline.html | 1 + .../harness/marionette_harness/www/html5/red.jpg | Bin 0 -> 92 bytes .../marionette_harness/www/html5/status.html | 1 + .../marionette_harness/www/html5/test.appcache | 11 + .../www/html5/test_html_inputs.html | 2 + .../marionette_harness/www/html5/yellow.jpg | Bin 0 -> 92 bytes .../harness/marionette_harness/www/html5Page.html | 45 + .../marionette_harness/www/javascriptPage.html | 278 ++ .../harness/marionette_harness/www/macbeth.html | 5254 ++++++++++++++++++++ .../marionette_harness/www/modal_dialogs.html | 39 + .../marionette_harness/www/nestedElements.html | 9 + .../harness/marionette_harness/www/rectangles.html | 40 + .../harness/marionette_harness/www/resultPage.html | 17 + .../harness/marionette_harness/www/scroll.html | 30 + .../harness/marionette_harness/www/scroll2.html | 24 + .../harness/marionette_harness/www/scroll3.html | 18 + .../harness/marionette_harness/www/scroll4.html | 15 + .../harness/marionette_harness/www/scroll5.html | 20 + .../harness/marionette_harness/www/shim.js | 282 ++ .../harness/marionette_harness/www/test.html | 38 + .../harness/marionette_harness/www/testAction.html | 94 + .../marionette_harness/www/testPageSource.html | 14 + .../marionette_harness/www/testPageSource.xml | 5 + .../www/testPageSourceWithUnicodeChars.html | 11 + .../harness/marionette_harness/www/testSize.html | 9 + .../marionette_harness/www/test_accessibility.html | 57 + .../www/test_carets_columns.html | 31 + .../marionette_harness/www/test_carets_cursor.html | 31 + .../www/test_carets_display_none.html | 10 + .../marionette_harness/www/test_carets_iframe.html | 20 + .../www/test_carets_longtext.html | 9 + .../www/test_carets_multipleline.html | 24 + .../www/test_carets_multiplerange.html | 19 + .../www/test_carets_selection.html | 38 + .../marionette_harness/www/test_clearing.html | 24 + .../marionette_harness/www/test_dynamic.html | 38 + .../marionette_harness/www/test_iframe.html | 16 + .../marionette_harness/www/test_inner_iframe.html | 13 + .../marionette_harness/www/test_nested_iframe.html | 13 + .../harness/marionette_harness/www/test_oop_1.html | 15 + .../harness/marionette_harness/www/test_oop_2.html | 15 + .../marionette_harness/www/test_shadow_dom.html | 26 + .../marionette_harness/www/test_windows.html | 14 + .../harness/marionette_harness/www/white.png | Bin 0 -> 150 bytes .../marionette_harness/www/windowHandles.html | 16 + .../harness/marionette_harness/www/xhtmlTest.html | 79 + testing/marionette/harness/requirements.txt | 14 + testing/marionette/harness/setup.py | 59 + testing/marionette/interaction.js | 455 ++ testing/marionette/jar.mn | 43 + testing/marionette/l10n.js | 95 + testing/marionette/legacyaction.js | 477 ++ testing/marionette/listener.js | 1812 +++++++ testing/marionette/logging.js | 75 + testing/marionette/mach_commands.py | 81 + testing/marionette/mach_test_package_commands.py | 67 + testing/marionette/marionette.eslintrc.js | 8 + testing/marionette/message.js | 285 ++ testing/marionette/modal.js | 113 + testing/marionette/moz.build | 13 + testing/marionette/navigate.js | 119 + testing/marionette/proxy.js | 376 ++ testing/marionette/puppeteer/.flake8 | 3 + testing/marionette/puppeteer/firefox/MANIFEST.in | 2 + testing/marionette/puppeteer/firefox/docs/Makefile | 177 + .../puppeteer/firefox/docs/api/appinfo.rst | 15 + .../marionette/puppeteer/firefox/docs/api/keys.rst | 12 + .../marionette/puppeteer/firefox/docs/api/l10n.rst | 11 + .../puppeteer/firefox/docs/api/places.rst | 13 + .../puppeteer/firefox/docs/api/security.rst | 13 + .../puppeteer/firefox/docs/api/software_update.rst | 30 + .../puppeteer/firefox/docs/api/utils.rst | 12 + testing/marionette/puppeteer/firefox/docs/conf.py | 270 + .../marionette/puppeteer/firefox/docs/index.rst | 85 + testing/marionette/puppeteer/firefox/docs/make.bat | 242 + .../firefox/docs/ui/about_window/window.rst | 59 + .../firefox/docs/ui/browser/notifications.rst | 44 + .../puppeteer/firefox/docs/ui/browser/tabbar.rst | 22 + .../puppeteer/firefox/docs/ui/browser/toolbars.rst | 28 + .../puppeteer/firefox/docs/ui/browser/window.rst | 11 + .../marionette/puppeteer/firefox/docs/ui/deck.rst | 9 + .../marionette/puppeteer/firefox/docs/ui/menu.rst | 10 + .../puppeteer/firefox/docs/ui/pageinfo/window.rst | 30 + .../firefox/docs/ui/update_wizard/dialog.rst | 128 + .../puppeteer/firefox/docs/ui/windows.rst | 16 + .../firefox/firefox_puppeteer/__init__.py | 9 + .../firefox/firefox_puppeteer/api/__init__.py | 0 .../firefox/firefox_puppeteer/api/appinfo.py | 45 + .../firefox/firefox_puppeteer/api/keys.py | 17 + .../firefox/firefox_puppeteer/api/l10n.py | 125 + .../firefox/firefox_puppeteer/api/places.py | 150 + .../firefox/firefox_puppeteer/api/security.py | 68 + .../firefox_puppeteer/api/software_update.py | 411 ++ .../firefox/firefox_puppeteer/api/utils.py | 140 + .../puppeteer/firefox/firefox_puppeteer/base.py | 14 + .../firefox/firefox_puppeteer/decorators.py | 35 + .../puppeteer/firefox/firefox_puppeteer/errors.py | 21 + .../puppeteer/firefox/firefox_puppeteer/mixins.py | 101 + .../firefox/firefox_puppeteer/puppeteer.py | 84 + .../firefox/firefox_puppeteer/ui/__init__.py | 0 .../firefox_puppeteer/ui/about_window/__init__.py | 0 .../firefox_puppeteer/ui/about_window/deck.py | 174 + .../firefox_puppeteer/ui/about_window/window.py | 32 + .../puppeteer/firefox/firefox_puppeteer/ui/base.py | 54 + .../firefox_puppeteer/ui/browser/__init__.py | 3 + .../firefox_puppeteer/ui/browser/notifications.py | 116 + .../firefox/firefox_puppeteer/ui/browser/tabbar.py | 388 ++ .../firefox_puppeteer/ui/browser/toolbars.py | 641 +++ .../firefox/firefox_puppeteer/ui/browser/window.py | 260 + .../puppeteer/firefox/firefox_puppeteer/ui/deck.py | 17 + .../puppeteer/firefox/firefox_puppeteer/ui/menu.py | 110 + .../firefox_puppeteer/ui/pageinfo/__init__.py | 0 .../firefox/firefox_puppeteer/ui/pageinfo/deck.py | 204 + .../firefox_puppeteer/ui/pageinfo/window.py | 61 + .../firefox_puppeteer/ui/update_wizard/__init__.py | 5 + .../firefox_puppeteer/ui/update_wizard/dialog.py | 46 + .../firefox_puppeteer/ui/update_wizard/wizard.py | 291 ++ .../firefox/firefox_puppeteer/ui/windows.py | 435 ++ .../puppeteer/firefox/requirements-docs.txt | 5 + .../marionette/puppeteer/firefox/requirements.txt | 2 + testing/marionette/puppeteer/firefox/setup.py | 36 + testing/marionette/server.js | 144 + testing/marionette/session.js | 457 ++ testing/marionette/simpletest.js | 208 + testing/marionette/test_action.js | 627 +++ testing/marionette/test_assert.js | 126 + testing/marionette/test_element.js | 55 + testing/marionette/test_error.js | 421 ++ testing/marionette/test_message.js | 204 + testing/marionette/test_navigate.js | 67 + testing/marionette/test_session.js | 370 ++ testing/marionette/unit.ini | 16 + 373 files changed, 55343 insertions(+) create mode 100644 testing/marionette/accessibility.js create mode 100644 testing/marionette/action.js create mode 100644 testing/marionette/addon.js create mode 100644 testing/marionette/assert.js create mode 100644 testing/marionette/atom.js create mode 100644 testing/marionette/browser.js create mode 100644 testing/marionette/capture.js create mode 100644 testing/marionette/cert.js create mode 100644 testing/marionette/chrome/test.xul create mode 100644 testing/marionette/chrome/test2.xul create mode 100644 testing/marionette/chrome/test_anonymous_content.xul create mode 100644 testing/marionette/chrome/test_dialog.dtd create mode 100644 testing/marionette/chrome/test_dialog.properties create mode 100644 testing/marionette/chrome/test_dialog.xul create mode 100644 testing/marionette/chrome/test_nested_iframe.xul create mode 100644 testing/marionette/client/.flake8 create mode 100644 testing/marionette/client/MANIFEST.in create mode 100644 testing/marionette/client/docs/Makefile create mode 100644 testing/marionette/client/docs/advanced/actions.rst create mode 100644 testing/marionette/client/docs/advanced/debug.rst create mode 100644 testing/marionette/client/docs/advanced/findelement.rst create mode 100644 testing/marionette/client/docs/advanced/landing.rst create mode 100644 testing/marionette/client/docs/advanced/stale.rst create mode 100644 testing/marionette/client/docs/basics.rst create mode 100644 testing/marionette/client/docs/conf.py create mode 100644 testing/marionette/client/docs/index.rst create mode 100644 testing/marionette/client/docs/interactive.rst create mode 100644 testing/marionette/client/docs/make.bat create mode 100644 testing/marionette/client/docs/reference.rst create mode 100644 testing/marionette/client/marionette_driver/__init__.py create mode 100644 testing/marionette/client/marionette_driver/addons.py create mode 100644 testing/marionette/client/marionette_driver/by.py create mode 100644 testing/marionette/client/marionette_driver/date_time_value.py create mode 100644 testing/marionette/client/marionette_driver/decorators.py create mode 100644 testing/marionette/client/marionette_driver/errors.py create mode 100644 testing/marionette/client/marionette_driver/expected.py create mode 100644 testing/marionette/client/marionette_driver/geckoinstance.py create mode 100644 testing/marionette/client/marionette_driver/gestures.py create mode 100644 testing/marionette/client/marionette_driver/keys.py create mode 100644 testing/marionette/client/marionette_driver/localization.py create mode 100644 testing/marionette/client/marionette_driver/marionette.py create mode 100644 testing/marionette/client/marionette_driver/selection.py create mode 100644 testing/marionette/client/marionette_driver/timeout.py create mode 100644 testing/marionette/client/marionette_driver/transport.py create mode 100644 testing/marionette/client/marionette_driver/wait.py create mode 100644 testing/marionette/client/requirements.txt create mode 100644 testing/marionette/client/setup.py create mode 100644 testing/marionette/components/marionette.js create mode 100644 testing/marionette/components/marionette.manifest create mode 100644 testing/marionette/components/moz.build create mode 100644 testing/marionette/cookies.js create mode 100644 testing/marionette/dispatcher.js create mode 100644 testing/marionette/driver.js create mode 100644 testing/marionette/element.js create mode 100644 testing/marionette/error.js create mode 100644 testing/marionette/evaluate.js create mode 100644 testing/marionette/event.js create mode 100644 testing/marionette/frame.js create mode 100644 testing/marionette/harness/.flake8 create mode 100644 testing/marionette/harness/MANIFEST.in create mode 100644 testing/marionette/harness/README.rst create mode 100644 testing/marionette/harness/marionette_harness/__init__.py create mode 100644 testing/marionette/harness/marionette_harness/marionette_test/__init__.py create mode 100644 testing/marionette/harness/marionette_harness/marionette_test/decorators.py create mode 100644 testing/marionette/harness/marionette_harness/marionette_test/testcases.py create mode 100644 testing/marionette/harness/marionette_harness/runner/__init__.py create mode 100644 testing/marionette/harness/marionette_harness/runner/base.py create mode 100644 testing/marionette/harness/marionette_harness/runner/httpd.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/__init__.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/History.md create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/browsermobproxy/__init__.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/browsermobproxy/client.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/browsermobproxy/server.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/browsermobproxy/webdriver_event_listener.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/Makefile create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/.buildinfo create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_modules/browsermobproxy.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_modules/index.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_sources/client.txt create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_sources/index.txt create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_sources/server.txt create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/basic.css create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/default.css create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/doctools.js create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/jquery.js create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/pygments.css create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/searchtools.js create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/sidebar.js create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/underscore.js create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/_static/websupport.js create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/client.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/genindex.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/index.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/objects.inv create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/py-modindex.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/search.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/searchindex.js create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/_build/html/server.html create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/client.rst create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/conf.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/index.rst create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/make.bat create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/docs/server.rst create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/readme.md create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/setup.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/test/test_client.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/test/test_remote.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob-proxy-py/test/test_webdriver.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/browsermob.py create mode 100644 testing/marionette/harness/marionette_harness/runner/mixins/window_manager.py create mode 100755 testing/marionette/harness/marionette_harness/runner/serve.py create mode 100644 testing/marionette/harness/marionette_harness/runner/test.cert create mode 100644 testing/marionette/harness/marionette_harness/runner/test.key create mode 100644 testing/marionette/harness/marionette_harness/runtests.py create mode 100644 testing/marionette/harness/marionette_harness/tests/harness_unit/conftest.py create mode 100644 testing/marionette/harness/marionette_harness/tests/harness_unit/test_httpd.py create mode 100644 testing/marionette/harness/marionette_harness/tests/harness_unit/test_marionette_arguments.py create mode 100644 testing/marionette/harness/marionette_harness/tests/harness_unit/test_marionette_harness.py create mode 100644 testing/marionette/harness/marionette_harness/tests/harness_unit/test_marionette_runner.py create mode 100644 testing/marionette/harness/marionette_harness/tests/harness_unit/test_marionette_test_result.py create mode 100644 testing/marionette/harness/marionette_harness/tests/harness_unit/test_serve.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit-tests.ini create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/importanotherscript.js create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/importscript.js create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/mn-restartless-unsigned.xpi create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/single_finger_functions.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_about_pages.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_accessibility.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_addons.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_anonymous_content.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_browsermobproxy.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_capabilities.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_checkbox.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_checkbox_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_chrome_async_finish.js create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_chrome_element_css.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_clearing.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_click.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_click_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_click_scrolling.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_cookies.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_crash.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_data_driven.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_date_time_value.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_element_retrieval.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_element_state.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_element_state_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_elementsize.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_elementsize_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_errors.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_execute_async_script.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_execute_isolate.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_execute_sandboxes.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_execute_script.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_expected.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_expectedfail.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_file_upload.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_findelement_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_geckoinstance.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_getactiveframe_oop.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_implicit_waits.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_import_script.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_key_actions.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_localization.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_log.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_mouse_action.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_navigation.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_pagesource.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_pagesource_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_position.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_prefs.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_profile_management.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_proxy.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_quit_restart.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_rendered_element.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_report.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_run_js_test.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_screen_orientation.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_screenshot.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_select.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_session.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_set_window_size.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_shadow_dom.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_simpletest_chrome.js create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_simpletest_fail.js create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_simpletest_pass.js create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_simpletest_sanity.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_simpletest_timeout.js create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_single_finger_desktop.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_skip_setup.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_switch_frame.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_switch_frame_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_switch_remote_frame.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_switch_window_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_switch_window_content.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_teardown_context_preserved.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_text.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_text_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_timeouts.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_transport.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_typing.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_using_permissions.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_visibility.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_wait.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_close_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_close_content.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_handles_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_handles_content.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_position.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_title.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_title_chrome.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_window_type.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/test_with_using_context.py create mode 100644 testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini create mode 100644 testing/marionette/harness/marionette_harness/tests/webapi-tests.ini create mode 100644 testing/marionette/harness/marionette_harness/www/black.png create mode 100644 testing/marionette/harness/marionette_harness/www/bug814037.html create mode 100644 testing/marionette/harness/marionette_harness/www/click_out_of_bounds_overflow.html create mode 100644 testing/marionette/harness/marionette_harness/www/clicks.html create mode 100644 testing/marionette/harness/marionette_harness/www/cssTransform.html create mode 100644 testing/marionette/harness/marionette_harness/www/cssTransform2.html create mode 100644 testing/marionette/harness/marionette_harness/www/datetimePage.html create mode 100644 testing/marionette/harness/marionette_harness/www/deletingFrame.html create mode 100644 testing/marionette/harness/marionette_harness/www/double_click.html create mode 100644 testing/marionette/harness/marionette_harness/www/element_bottom.html create mode 100644 testing/marionette/harness/marionette_harness/www/element_left.html create mode 100644 testing/marionette/harness/marionette_harness/www/element_outside_viewport.html create mode 100644 testing/marionette/harness/marionette_harness/www/element_right.html create mode 100644 testing/marionette/harness/marionette_harness/www/element_top.html create mode 100644 testing/marionette/harness/marionette_harness/www/empty.html create mode 100644 testing/marionette/harness/marionette_harness/www/formPage.html create mode 100644 testing/marionette/harness/marionette_harness/www/frameset.html create mode 100644 testing/marionette/harness/marionette_harness/www/framesetPage2.html create mode 100644 testing/marionette/harness/marionette_harness/www/hidden.html create mode 100644 testing/marionette/harness/marionette_harness/www/html5/blue.jpg create mode 100644 testing/marionette/harness/marionette_harness/www/html5/boolean_attributes.html create mode 100644 testing/marionette/harness/marionette_harness/www/html5/geolocation.js create mode 100644 testing/marionette/harness/marionette_harness/www/html5/green.jpg create mode 100644 testing/marionette/harness/marionette_harness/www/html5/offline.html create mode 100644 testing/marionette/harness/marionette_harness/www/html5/red.jpg create mode 100644 testing/marionette/harness/marionette_harness/www/html5/status.html create mode 100644 testing/marionette/harness/marionette_harness/www/html5/test.appcache create mode 100644 testing/marionette/harness/marionette_harness/www/html5/test_html_inputs.html create mode 100644 testing/marionette/harness/marionette_harness/www/html5/yellow.jpg create mode 100644 testing/marionette/harness/marionette_harness/www/html5Page.html create mode 100644 testing/marionette/harness/marionette_harness/www/javascriptPage.html create mode 100644 testing/marionette/harness/marionette_harness/www/macbeth.html create mode 100644 testing/marionette/harness/marionette_harness/www/modal_dialogs.html create mode 100644 testing/marionette/harness/marionette_harness/www/nestedElements.html create mode 100644 testing/marionette/harness/marionette_harness/www/rectangles.html create mode 100644 testing/marionette/harness/marionette_harness/www/resultPage.html create mode 100644 testing/marionette/harness/marionette_harness/www/scroll.html create mode 100644 testing/marionette/harness/marionette_harness/www/scroll2.html create mode 100644 testing/marionette/harness/marionette_harness/www/scroll3.html create mode 100644 testing/marionette/harness/marionette_harness/www/scroll4.html create mode 100644 testing/marionette/harness/marionette_harness/www/scroll5.html create mode 100644 testing/marionette/harness/marionette_harness/www/shim.js create mode 100644 testing/marionette/harness/marionette_harness/www/test.html create mode 100644 testing/marionette/harness/marionette_harness/www/testAction.html create mode 100644 testing/marionette/harness/marionette_harness/www/testPageSource.html create mode 100644 testing/marionette/harness/marionette_harness/www/testPageSource.xml create mode 100644 testing/marionette/harness/marionette_harness/www/testPageSourceWithUnicodeChars.html create mode 100644 testing/marionette/harness/marionette_harness/www/testSize.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_accessibility.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_columns.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_cursor.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_display_none.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_iframe.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_longtext.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_multipleline.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_multiplerange.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_carets_selection.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_clearing.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_dynamic.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_iframe.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_inner_iframe.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_nested_iframe.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_oop_1.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_oop_2.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_shadow_dom.html create mode 100644 testing/marionette/harness/marionette_harness/www/test_windows.html create mode 100644 testing/marionette/harness/marionette_harness/www/white.png create mode 100644 testing/marionette/harness/marionette_harness/www/windowHandles.html create mode 100644 testing/marionette/harness/marionette_harness/www/xhtmlTest.html create mode 100644 testing/marionette/harness/requirements.txt create mode 100644 testing/marionette/harness/setup.py create mode 100644 testing/marionette/interaction.js create mode 100644 testing/marionette/jar.mn create mode 100644 testing/marionette/l10n.js create mode 100644 testing/marionette/legacyaction.js create mode 100644 testing/marionette/listener.js create mode 100644 testing/marionette/logging.js create mode 100644 testing/marionette/mach_commands.py create mode 100644 testing/marionette/mach_test_package_commands.py create mode 100644 testing/marionette/marionette.eslintrc.js create mode 100644 testing/marionette/message.js create mode 100644 testing/marionette/modal.js create mode 100644 testing/marionette/moz.build create mode 100644 testing/marionette/navigate.js create mode 100644 testing/marionette/proxy.js create mode 100644 testing/marionette/puppeteer/.flake8 create mode 100644 testing/marionette/puppeteer/firefox/MANIFEST.in create mode 100644 testing/marionette/puppeteer/firefox/docs/Makefile create mode 100644 testing/marionette/puppeteer/firefox/docs/api/appinfo.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/api/keys.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/api/l10n.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/api/places.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/api/security.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/api/software_update.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/api/utils.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/conf.py create mode 100644 testing/marionette/puppeteer/firefox/docs/index.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/make.bat create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/about_window/window.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/browser/notifications.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/browser/tabbar.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/browser/toolbars.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/browser/window.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/deck.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/menu.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/pageinfo/window.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/update_wizard/dialog.rst create mode 100644 testing/marionette/puppeteer/firefox/docs/ui/windows.rst create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/__init__.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/__init__.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/appinfo.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/keys.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/l10n.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/places.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/security.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/software_update.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/api/utils.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/base.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/decorators.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/errors.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/mixins.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/puppeteer.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/__init__.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/about_window/__init__.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/about_window/deck.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/about_window/window.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/base.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/__init__.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/notifications.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/tabbar.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/browser/window.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/deck.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/menu.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/__init__.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/deck.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/window.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/__init__.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/dialog.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py create mode 100644 testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/windows.py create mode 100644 testing/marionette/puppeteer/firefox/requirements-docs.txt create mode 100644 testing/marionette/puppeteer/firefox/requirements.txt create mode 100644 testing/marionette/puppeteer/firefox/setup.py create mode 100644 testing/marionette/server.js create mode 100644 testing/marionette/session.js create mode 100644 testing/marionette/simpletest.js create mode 100644 testing/marionette/test_action.js create mode 100644 testing/marionette/test_assert.js create mode 100644 testing/marionette/test_element.js create mode 100644 testing/marionette/test_error.js create mode 100644 testing/marionette/test_message.js create mode 100644 testing/marionette/test_navigate.js create mode 100644 testing/marionette/test_session.js create mode 100644 testing/marionette/unit.ini (limited to 'testing/marionette') diff --git a/testing/marionette/accessibility.js b/testing/marionette/accessibility.js new file mode 100644 index 000000000..4ada0b88d --- /dev/null +++ b/testing/marionette/accessibility.js @@ -0,0 +1,441 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Log.jsm"); + +const logger = Log.repository.getLogger("Marionette"); + +Cu.import("chrome://marionette/content/error.js"); + +XPCOMUtils.defineLazyModuleGetter( + this, "setInterval", "resource://gre/modules/Timer.jsm"); +XPCOMUtils.defineLazyModuleGetter( + this, "clearInterval", "resource://gre/modules/Timer.jsm"); + +XPCOMUtils.defineLazyGetter(this, "service", () => { + let service; + try { + service = Cc["@mozilla.org/accessibilityService;1"].getService( + Ci.nsIAccessibilityService); + } catch (e) { + logger.warn("Accessibility module is not present"); + } finally { + return service; + } +}); + +this.EXPORTED_SYMBOLS = ["accessibility"]; + +/** + * Number of attempts to get an accessible object for an element. + * We attempt more than once because accessible tree can be out of sync + * with the DOM tree for a short period of time. + */ +const GET_ACCESSIBLE_ATTEMPTS = 100; + +/** + * An interval between attempts to retrieve an accessible object for an + * element. + */ +const GET_ACCESSIBLE_ATTEMPT_INTERVAL = 10; + +this.accessibility = { + get service() { + return service; + } +}; + +/** + * Accessible states used to check element"s state from the accessiblity API + * perspective. + * Note: if gecko is built with --disable-accessibility, the interfaces are not + * defined. This is why we use getters instead to be able to use these + * statically. + */ +accessibility.State = { + get Unavailable() { + return Ci.nsIAccessibleStates.STATE_UNAVAILABLE; + }, + get Focusable() { + return Ci.nsIAccessibleStates.STATE_FOCUSABLE; + }, + get Selectable() { + return Ci.nsIAccessibleStates.STATE_SELECTABLE; + }, + get Selected() { + return Ci.nsIAccessibleStates.STATE_SELECTED; + } +}; + +/** + * Accessible object roles that support some action. + */ +accessibility.ActionableRoles = new Set([ + "checkbutton", + "check menu item", + "check rich option", + "combobox", + "combobox option", + "entry", + "key", + "link", + "listbox option", + "listbox rich option", + "menuitem", + "option", + "outlineitem", + "pagetab", + "pushbutton", + "radiobutton", + "radio menu item", + "rowheader", + "slider", + "spinbutton", + "switch", +]); + + +/** + * Factory function that constructs a new {@code accessibility.Checks} + * object with enforced strictness or not. + */ +accessibility.get = function (strict = false) { + return new accessibility.Checks(!!strict); +}; + +/** + * Component responsible for interacting with platform accessibility + * API. + * + * Its methods serve as wrappers for testing content and chrome + * accessibility as well as accessibility of user interactions. + */ +accessibility.Checks = class { + + /** + * @param {boolean} strict + * Flag indicating whether the accessibility issue should be logged + * or cause an error to be thrown. Default is to log to stdout. + */ + constructor(strict) { + this.strict = strict; + } + + /** + * Get an accessible object for an element. + * + * @param {DOMElement|XULElement} element + * Element to get the accessible object for. + * @param {boolean=} mustHaveAccessible + * Flag indicating that the element must have an accessible object. + * Defaults to not require this. + * + * @return {Promise: nsIAccessible} + * Promise with an accessibility object for the given element. + */ + getAccessible(element, mustHaveAccessible = false) { + if (!this.strict) { + return Promise.resolve(); + } + + return new Promise((resolve, reject) => { + if (!accessibility.service) { + reject(); + return; + } + + let acc = accessibility.service.getAccessibleFor(element); + if (acc || !mustHaveAccessible) { + // if accessible object is found, return it; + // if it is not required, also resolve + resolve(acc); + } else { + // if we require an accessible object, we need to poll for it + // because accessible tree might be + // out of sync with DOM tree for a short time + let attempts = GET_ACCESSIBLE_ATTEMPTS; + let intervalId = setInterval(() => { + let acc = accessibility.service.getAccessibleFor(element); + if (acc || --attempts <= 0) { + clearInterval(intervalId); + if (acc) { + resolve(acc); + } else { + reject(); + } + } + }, GET_ACCESSIBLE_ATTEMPT_INTERVAL); + } + }).catch(() => this.error( + "Element does not have an accessible object", element)); + }; + + /** + * Test if the accessible has a role that supports some arbitrary + * action. + * + * @param {nsIAccessible} accessible + * Accessible object. + * + * @return {boolean} + * True if an actionable role is found on the accessible, false + * otherwise. + */ + isActionableRole(accessible) { + return accessibility.ActionableRoles.has( + accessibility.service.getStringRole(accessible.role)); + } + + /** + * Test if an accessible has at least one action that it supports. + * + * @param {nsIAccessible} accessible + * Accessible object. + * + * @return {boolean} + * True if the accessible has at least one supported action, + * false otherwise. + */ + hasActionCount(accessible) { + return accessible.actionCount > 0; + } + + /** + * Test if an accessible has a valid name. + * + * @param {nsIAccessible} accessible + * Accessible object. + * + * @return {boolean} + * True if the accessible has a non-empty valid name, or false if + * this is not the case. + */ + hasValidName(accessible) { + return accessible.name && accessible.name.trim(); + } + + /** + * Test if an accessible has a {@code hidden} attribute. + * + * @param {nsIAccessible} accessible + * Accessible object. + * + * @return {boolean} + * True if the accesible object has a {@code hidden} attribute, + * false otherwise. + */ + hasHiddenAttribute(accessible) { + let hidden = false; + try { + hidden = accessible.attributes.getStringProperty("hidden"); + } finally { + // if the property is missing, error will be thrown + return hidden && hidden === "true"; + } + } + + /** + * Verify if an accessible has a given state. + * Test if an accessible has a given state. + * + * @param {nsIAccessible} accessible + * Accessible object to test. + * @param {number} stateToMatch + * State to match. + * + * @return {boolean} + * True if |accessible| has |stateToMatch|, false otherwise. + */ + matchState(accessible, stateToMatch) { + let state = {}; + accessible.getState(state, {}); + return !!(state.value & stateToMatch); + } + + /** + * Test if an accessible is hidden from the user. + * + * @param {nsIAccessible} accessible + * Accessible object. + * + * @return {boolean} + * True if element is hidden from user, false otherwise. + */ + isHidden(accessible) { + while (accessible) { + if (this.hasHiddenAttribute(accessible)) { + return true; + } + accessible = accessible.parent; + } + return false; + } + + /** + * Test if the element's visible state corresponds to its accessibility + * API visibility. + * + * @param {nsIAccessible} accessible + * Accessible object. + * @param {DOMElement|XULElement} element + * Element associated with |accessible|. + * @param {boolean} visible + * Visibility state of |element|. + * + * @throws ElementNotAccessibleError + * If |element|'s visibility state does not correspond to + * |accessible|'s. + */ + assertVisible(accessible, element, visible) { + if (!accessible) { + return; + } + + let hiddenAccessibility = this.isHidden(accessible); + + let message; + if (visible && hiddenAccessibility) { + message = "Element is not currently visible via the accessibility API " + + "and may not be manipulated by it"; + } else if (!visible && !hiddenAccessibility) { + message = "Element is currently only visible via the accessibility API " + + "and can be manipulated by it"; + } + this.error(message, element); + } + + /** + * Test if the element's unavailable accessibility state matches the + * enabled state. + * + * @param {nsIAccessible} accessible + * Accessible object. + * @param {DOMElement|XULElement} element + * Element associated with |accessible|. + * @param {boolean} enabled + * Enabled state of |element|. + * + * @throws ElementNotAccessibleError + * If |element|'s enabled state does not match |accessible|'s. + */ + assertEnabled(accessible, element, enabled) { + if (!accessible) { + return; + } + + let win = element.ownerDocument.defaultView; + let disabledAccessibility = this.matchState( + accessible, accessibility.State.Unavailable); + let explorable = win.getComputedStyle(element) + .getPropertyValue("pointer-events") !== "none"; + + let message; + if (!explorable && !disabledAccessibility) { + message = "Element is enabled but is not explorable via the " + + "accessibility API"; + } else if (enabled && disabledAccessibility) { + message = "Element is enabled but disabled via the accessibility API"; + } else if (!enabled && !disabledAccessibility) { + message = "Element is disabled but enabled via the accessibility API"; + } + this.error(message, element); + } + + /** + * Test if it is possible to activate an element with the accessibility + * API. + * + * @param {nsIAccessible} accessible + * Accessible object. + * @param {DOMElement|XULElement} element + * Element associated with |accessible|. + * + * @throws ElementNotAccessibleError + * If it is impossible to activate |element| with |accessible|. + */ + assertActionable(accessible, element) { + if (!accessible) { + return; + } + + let message; + if (!this.hasActionCount(accessible)) { + message = "Element does not support any accessible actions"; + } else if (!this.isActionableRole(accessible)) { + message = "Element does not have a correct accessibility role " + + "and may not be manipulated via the accessibility API"; + } else if (!this.hasValidName(accessible)) { + message = "Element is missing an accessible name"; + } else if (!this.matchState(accessible, accessibility.State.Focusable)) { + message = "Element is not focusable via the accessibility API"; + } + + this.error(message, element); + } + + /** + * Test that an element's selected state corresponds to its + * accessibility API selected state. + * + * @param {nsIAccessible} accessible + * Accessible object. + * @param {DOMElement|XULElement} + * Element associated with |accessible|. + * @param {boolean} selected + * The |element|s selected state. + * + * @throws ElementNotAccessibleError + * If |element|'s selected state does not correspond to + * |accessible|'s. + */ + assertSelected(accessible, element, selected) { + if (!accessible) { + return; + } + + // element is not selectable via the accessibility API + if (!this.matchState(accessible, accessibility.State.Selectable)) { + return; + } + + let selectedAccessibility = this.matchState(accessible, accessibility.State.Selected); + + let message; + if (selected && !selectedAccessibility) { + message = "Element is selected but not selected via the accessibility API"; + } else if (!selected && selectedAccessibility) { + message = "Element is not selected but selected via the accessibility API"; + } + this.error(message, element); + } + + /** + * Throw an error if strict accessibility checks are enforced and log + * the error to the log. + * + * @param {string} message + * @param {DOMElement|XULElement} element + * Element that caused an error. + * + * @throws ElementNotAccessibleError + * If |strict| is true. + */ + error(message, element) { + if (!message || !this.strict) { + return; + } + if (element) { + let {id, tagName, className} = element; + message += `: id: ${id}, tagName: ${tagName}, className: ${className}`; + } + + throw new ElementNotAccessibleError(message); + } + +}; diff --git a/testing/marionette/action.js b/testing/marionette/action.js new file mode 100644 index 000000000..2eb39810b --- /dev/null +++ b/testing/marionette/action.js @@ -0,0 +1,1348 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/Task.jsm"); + +Cu.import("chrome://marionette/content/assert.js"); +Cu.import("chrome://marionette/content/element.js"); +Cu.import("chrome://marionette/content/error.js"); +Cu.import("chrome://marionette/content/event.js"); + +this.EXPORTED_SYMBOLS = ["action"]; + +// TODO? With ES 2016 and Symbol you can make a safer approximation +// to an enum e.g. https://gist.github.com/xmlking/e86e4f15ec32b12c4689 +/** + * Implements WebDriver Actions API: a low-level interface for providing + * virtualised device input to the web browser. + */ +this.action = { + Pause: "pause", + KeyDown: "keyDown", + KeyUp: "keyUp", + PointerDown: "pointerDown", + PointerUp: "pointerUp", + PointerMove: "pointerMove", + PointerCancel: "pointerCancel", +}; + +const ACTIONS = { + none: new Set([action.Pause]), + key: new Set([action.Pause, action.KeyDown, action.KeyUp]), + pointer: new Set([ + action.Pause, + action.PointerDown, + action.PointerUp, + action.PointerMove, + action.PointerCancel, + ]), +}; + +/** Map from normalized key value to UI Events modifier key name */ +const MODIFIER_NAME_LOOKUP = { + "Alt": "alt", + "Shift": "shift", + "Control": "ctrl", + "Meta": "meta", +}; + +/** Map from raw key (codepoint) to normalized key value */ +const NORMALIZED_KEY_LOOKUP = { + "\uE000": "Unidentified", + "\uE001": "Cancel", + "\uE002": "Help", + "\uE003": "Backspace", + "\uE004": "Tab", + "\uE005": "Clear", + "\uE006": "Return", + "\uE007": "Enter", + "\uE008": "Shift", + "\uE009": "Control", + "\uE00A": "Alt", + "\uE00B": "Pause", + "\uE00C": "Escape", + "\uE00D": " ", + "\uE00E": "PageUp", + "\uE00F": "PageDown", + "\uE010": "End", + "\uE011": "Home", + "\uE012": "ArrowLeft", + "\uE013": "ArrowUp", + "\uE014": "ArrowRight", + "\uE015": "ArrowDown", + "\uE016": "Insert", + "\uE017": "Delete", + "\uE018": ";", + "\uE019": "=", + "\uE01A": "0", + "\uE01B": "1", + "\uE01C": "2", + "\uE01D": "3", + "\uE01E": "4", + "\uE01F": "5", + "\uE020": "6", + "\uE021": "7", + "\uE022": "8", + "\uE023": "9", + "\uE024": "*", + "\uE025": "+", + "\uE026": ",", + "\uE027": "-", + "\uE028": ".", + "\uE029": "/", + "\uE031": "F1", + "\uE032": "F2", + "\uE033": "F3", + "\uE034": "F4", + "\uE035": "F5", + "\uE036": "F6", + "\uE037": "F7", + "\uE038": "F8", + "\uE039": "F9", + "\uE03A": "F10", + "\uE03B": "F11", + "\uE03C": "F12", + "\uE03D": "Meta", + "\uE040": "ZenkakuHankaku", + "\uE050": "Shift", + "\uE051": "Control", + "\uE052": "Alt", + "\uE053": "Meta", + "\uE054": "PageUp", + "\uE055": "PageDown", + "\uE056": "End", + "\uE057": "Home", + "\uE058": "ArrowLeft", + "\uE059": "ArrowUp", + "\uE05A": "ArrowRight", + "\uE05B": "ArrowDown", + "\uE05C": "Insert", + "\uE05D": "Delete", +}; + +/** Map from raw key (codepoint) to key location */ +const KEY_LOCATION_LOOKUP = { + "\uE007": 1, + "\uE008": 1, + "\uE009": 1, + "\uE00A": 1, + "\uE01A": 3, + "\uE01B": 3, + "\uE01C": 3, + "\uE01D": 3, + "\uE01E": 3, + "\uE01F": 3, + "\uE020": 3, + "\uE021": 3, + "\uE022": 3, + "\uE023": 3, + "\uE024": 3, + "\uE025": 3, + "\uE026": 3, + "\uE027": 3, + "\uE028": 3, + "\uE029": 3, + "\uE03D": 1, + "\uE050": 2, + "\uE051": 2, + "\uE052": 2, + "\uE053": 2, + "\uE054": 3, + "\uE055": 3, + "\uE056": 3, + "\uE057": 3, + "\uE058": 3, + "\uE059": 3, + "\uE05A": 3, + "\uE05B": 3, + "\uE05C": 3, + "\uE05D": 3, +}; + +const KEY_CODE_LOOKUP = { + "\uE00A": "AltLeft", + "\uE052": "AltRight", + "\uE015": "ArrowDown", + "\uE012": "ArrowLeft", + "\uE014": "ArrowRight", + "\uE013": "ArrowUp", + "`": "Backquote", + "~": "Backquote", + "\\": "Backslash", + "|": "Backslash", + "\uE003": "Backspace", + "[": "BracketLeft", + "{": "BracketLeft", + "]": "BracketRight", + "}": "BracketRight", + ",": "Comma", + "<": "Comma", + "\uE009": "ControlLeft", + "\uE051": "ControlRight", + "\uE017": "Delete", + ")": "Digit0", + "0": "Digit0", + "!": "Digit1", + "1": "Digit1", + "2": "Digit2", + "@": "Digit2", + "#": "Digit3", + "3": "Digit3", + "$": "Digit4", + "4": "Digit4", + "%": "Digit5", + "5": "Digit5", + "6": "Digit6", + "^": "Digit6", + "&": "Digit7", + "7": "Digit7", + "*": "Digit8", + "8": "Digit8", + "(": "Digit9", + "9": "Digit9", + "\uE010": "End", + "\uE006": "Enter", + "+": "Equal", + "=": "Equal", + "\uE00C": "Escape", + "\uE031": "F1", + "\uE03A": "F10", + "\uE03B": "F11", + "\uE03C": "F12", + "\uE032": "F2", + "\uE033": "F3", + "\uE034": "F4", + "\uE035": "F5", + "\uE036": "F6", + "\uE037": "F7", + "\uE038": "F8", + "\uE039": "F9", + "\uE002": "Help", + "\uE011": "Home", + "\uE016": "Insert", + "<": "IntlBackslash", + ">": "IntlBackslash", + "A": "KeyA", + "a": "KeyA", + "B": "KeyB", + "b": "KeyB", + "C": "KeyC", + "c": "KeyC", + "D": "KeyD", + "d": "KeyD", + "E": "KeyE", + "e": "KeyE", + "F": "KeyF", + "f": "KeyF", + "G": "KeyG", + "g": "KeyG", + "H": "KeyH", + "h": "KeyH", + "I": "KeyI", + "i": "KeyI", + "J": "KeyJ", + "j": "KeyJ", + "K": "KeyK", + "k": "KeyK", + "L": "KeyL", + "l": "KeyL", + "M": "KeyM", + "m": "KeyM", + "N": "KeyN", + "n": "KeyN", + "O": "KeyO", + "o": "KeyO", + "P": "KeyP", + "p": "KeyP", + "Q": "KeyQ", + "q": "KeyQ", + "R": "KeyR", + "r": "KeyR", + "S": "KeyS", + "s": "KeyS", + "T": "KeyT", + "t": "KeyT", + "U": "KeyU", + "u": "KeyU", + "V": "KeyV", + "v": "KeyV", + "W": "KeyW", + "w": "KeyW", + "X": "KeyX", + "x": "KeyX", + "Y": "KeyY", + "y": "KeyY", + "Z": "KeyZ", + "z": "KeyZ", + "-": "Minus", + "_": "Minus", + "\uE01A": "Numpad0", + "\uE05C": "Numpad0", + "\uE01B": "Numpad1", + "\uE056": "Numpad1", + "\uE01C": "Numpad2", + "\uE05B": "Numpad2", + "\uE01D": "Numpad3", + "\uE055": "Numpad3", + "\uE01E": "Numpad4", + "\uE058": "Numpad4", + "\uE01F": "Numpad5", + "\uE020": "Numpad6", + "\uE05A": "Numpad6", + "\uE021": "Numpad7", + "\uE057": "Numpad7", + "\uE022": "Numpad8", + "\uE059": "Numpad8", + "\uE023": "Numpad9", + "\uE054": "Numpad9", + "\uE024": "NumpadAdd", + "\uE026": "NumpadComma", + "\uE028": "NumpadDecimal", + "\uE05D": "NumpadDecimal", + "\uE029": "NumpadDivide", + "\uE007": "NumpadEnter", + "\uE024": "NumpadMultiply", + "\uE026": "NumpadSubtract", + "\uE03D": "OSLeft", + "\uE053": "OSRight", + "\uE01E": "PageDown", + "\uE01F": "PageUp", + ".": "Period", + ">": "Period", + "\"": "Quote", + "'": "Quote", + ":": "Semicolon", + ";": "Semicolon", + "\uE008": "ShiftLeft", + "\uE050": "ShiftRight", + "/": "Slash", + "?": "Slash", + "\uE00D": "Space", + " ": "Space", + "\uE004": "Tab", +}; + +/** Represents possible values for a pointer-move origin. */ +action.PointerOrigin = { + Viewport: "viewport", + Pointer: "pointer", +}; + +/** + * Look up a PointerOrigin. + * + * @param {?} obj + * Origin for a pointerMove action. + * + * @return {?} + * A pointer origin that is either "viewport" (default), "pointer", or a + * web-element reference. + * + * @throws {InvalidArgumentError} + * If |obj| is not a valid origin. + */ +action.PointerOrigin.get = function(obj) { + let origin = obj; + if (typeof obj == "undefined") { + origin = this.Viewport; + } else if (typeof obj == "string") { + let name = capitalize(obj); + assert.in(name, this, error.pprint`Unknown pointer-move origin: ${obj}`); + origin = this[name]; + } else if (!element.isWebElementReference(obj)) { + throw new InvalidArgumentError("Expected 'origin' to be a string or a " + + `web element reference, got: ${obj}`); + } + return origin; +}; + +/** Represents possible subtypes for a pointer input source. */ +action.PointerType = { + Mouse: "mouse", + // TODO For now, only mouse is supported + //Pen: "pen", + //Touch: "touch", +}; + +/** + * Look up a PointerType. + * + * @param {string} str + * Name of pointer type. + * + * @return {string} + * A pointer type for processing pointer parameters. + * + * @throws {InvalidArgumentError} + * If |str| is not a valid pointer type. + */ +action.PointerType.get = function (str) { + let name = capitalize(str); + assert.in(name, this, error.pprint`Unknown pointerType: ${str}`); + return this[name]; +}; + +/** + * Input state associated with current session. This is a map between input ID and + * the device state for that input source, with one entry for each active input source. + * + * Initialized in listener.js + */ +action.inputStateMap = undefined; + +/** + * List of |action.Action| associated with current session. Used to manage dispatching + * events when resetting the state of the input sources. Reset operations are assumed + * to be idempotent. + * + * Initialized in listener.js + */ +action.inputsToCancel = undefined; + +/** + * Represents device state for an input source. + */ +class InputState { + constructor() { + this.type = this.constructor.name.toLowerCase(); + } + + /** + * Check equality of this InputState object with another. + * + * @para{?} other + * Object representing an input state. + * @return {boolean} + * True if |this| has the same |type| as |other|. + */ + is(other) { + if (typeof other == "undefined") { + return false; + } + return this.type === other.type; + } + + toString() { + return `[object ${this.constructor.name}InputState]`; + } + + /** + * @param {?} obj + * Object with property |type| and optionally |parameters| or |pointerType|, + * representing an action sequence or an action item. + * + * @return {action.InputState} + * An |action.InputState| object for the type of the |actionSequence|. + * + * @throws {InvalidArgumentError} + * If |actionSequence.type| is not valid. + */ + static fromJson(obj) { + let type = obj.type; + assert.in(type, ACTIONS, error.pprint`Unknown action type: ${type}`); + let name = type == "none" ? "Null" : capitalize(type); + if (name == "Pointer") { + if (!obj.pointerType && (!obj.parameters || !obj.parameters.pointerType)) { + throw new InvalidArgumentError( + error.pprint`Expected obj to have pointerType, got: ${obj}`); + } + let pointerType = obj.pointerType || obj.parameters.pointerType; + return new action.InputState[name](pointerType); + } else { + return new action.InputState[name](); + } + } +} + +/** Possible kinds of |InputState| for supported input sources. */ +action.InputState = {}; + +/** + * Input state associated with a keyboard-type device. + */ +action.InputState.Key = class Key extends InputState { + constructor() { + super(); + this.pressed = new Set(); + this.alt = false; + this.shift = false; + this.ctrl = false; + this.meta = false; + } + + /** + * Update modifier state according to |key|. + * + * @param {string} key + * Normalized key value of a modifier key. + * @param {boolean} value + * Value to set the modifier attribute to. + * + * @throws {InvalidArgumentError} + * If |key| is not a modifier. + */ + setModState(key, value) { + if (key in MODIFIER_NAME_LOOKUP) { + this[MODIFIER_NAME_LOOKUP[key]] = value; + } else { + throw new InvalidArgumentError("Expected 'key' to be one of " + + `${Object.keys(MODIFIER_NAME_LOOKUP)}; got: ${key}`); + } + } + + /** + * Check whether |key| is pressed. + * + * @param {string} key + * Normalized key value. + * + * @return {boolean} + * True if |key| is in set of pressed keys. + */ + isPressed(key) { + return this.pressed.has(key); + } + + /** + * Add |key| to the set of pressed keys. + * + * @param {string} key + * Normalized key value. + * + * @return {boolean} + * True if |key| is in list of pressed keys. + */ + press(key) { + return this.pressed.add(key); + } + + /** + * Remove |key| from the set of pressed keys. + * + * @param {string} key + * Normalized key value. + * + * @return {boolean} + * True if |key| was present before removal, false otherwise. + */ + release(key) { + return this.pressed.delete(key); + } +}; + +/** + * Input state not associated with a specific physical device. + */ +action.InputState.Null = class Null extends InputState { + constructor() { + super(); + this.type = "none"; + } +}; + +/** + * Input state associated with a pointer-type input device. + * + * @param {string} subtype + * Kind of pointing device: mouse, pen, touch. + * + * @throws {InvalidArgumentError} + * If subtype is undefined or an invalid pointer type. + */ +action.InputState.Pointer = class Pointer extends InputState { + constructor(subtype) { + super(); + this.pressed = new Set(); + assert.defined(subtype, error.pprint`Expected subtype to be defined, got: ${subtype}`); + this.subtype = action.PointerType.get(subtype); + this.x = 0; + this.y = 0; + } + + /** + * Check whether |button| is pressed. + * + * @param {number} button + * Positive integer that refers to a mouse button. + * + * @return {boolean} + * True if |button| is in set of pressed buttons. + */ + isPressed(button) { + assert.positiveInteger(button); + return this.pressed.has(button); + } + + /** + * Add |button| to the set of pressed keys. + * + * @param {number} button + * Positive integer that refers to a mouse button. + * + * @return {Set} + * Set of pressed buttons. + */ + press(button) { + assert.positiveInteger(button); + return this.pressed.add(button); + } + + /** + * Remove |button| from the set of pressed buttons. + * + * @param {number} button + * A positive integer that refers to a mouse button. + * + * @return {boolean} + * True if |button| was present before removals, false otherwise. + */ + release(button) { + assert.positiveInteger(button); + return this.pressed.delete(button); + } +}; + +/** + * Repesents an action for dispatch. Used in |action.Chain| and |action.Sequence|. + * + * @param {string} id + * Input source ID. + * @param {string} type + * Action type: none, key, pointer. + * @param {string} subtype + * Action subtype: pause, keyUp, keyDown, pointerUp, pointerDown, pointerMove, pointerCancel. + * + * @throws {InvalidArgumentError} + * If any parameters are undefined. + */ +action.Action = class { + constructor(id, type, subtype) { + if ([id, type, subtype].includes(undefined)) { + throw new InvalidArgumentError("Missing id, type or subtype"); + } + for (let attr of [id, type, subtype]) { + assert.string(attr, error.pprint`Expected string, got: ${attr}`); + } + this.id = id; + this.type = type; + this.subtype = subtype; + }; + + toString() { + return `[action ${this.type}]`; + } + + /** + * @param {?} actionSequence + * Object representing sequence of actions from one input source. + * @param {?} actionItem + * Object representing a single action from |actionSequence|. + * + * @return {action.Action} + * An action that can be dispatched; corresponds to |actionItem|. + * + * @throws {InvalidArgumentError} + * If any |actionSequence| or |actionItem| attributes are invalid. + * @throws {UnsupportedOperationError} + * If |actionItem.type| is |pointerCancel|. + */ + static fromJson(actionSequence, actionItem) { + let type = actionSequence.type; + let id = actionSequence.id; + let subtypes = ACTIONS[type]; + if (!subtypes) { + throw new InvalidArgumentError("Unknown type: " + type); + } + let subtype = actionItem.type; + if (!subtypes.has(subtype)) { + throw new InvalidArgumentError(`Unknown subtype for ${type} action: ${subtype}`); + } + + let item = new action.Action(id, type, subtype); + if (type === "pointer") { + action.processPointerAction(id, + action.PointerParameters.fromJson(actionSequence.parameters), item); + } + + switch (item.subtype) { + case action.KeyUp: + case action.KeyDown: + let key = actionItem.value; + // TODO countGraphemes + // TODO key.value could be a single code point like "\uE012" (see rawKey) + // or "grapheme cluster" + assert.string(key, + error.pprint("Expected 'value' to be a string that represents single code point " + + `or grapheme cluster, got: ${key}`)); + item.value = key; + break; + + case action.PointerDown: + case action.PointerUp: + assert.positiveInteger(actionItem.button, + error.pprint`Expected 'button' (${actionItem.button}) to be >= 0`); + item.button = actionItem.button; + break; + + case action.PointerMove: + item.duration = actionItem.duration; + if (typeof item.duration != "undefined"){ + assert.positiveInteger(item.duration, + error.pprint`Expected 'duration' (${item.duration}) to be >= 0`); + } + item.origin = action.PointerOrigin.get(actionItem.origin); + item.x = actionItem.x; + if (typeof item.x != "undefined") { + assert.integer(item.x, error.pprint`Expected 'x' (${item.x}) to be an Integer`); + } + item.y = actionItem.y; + if (typeof item.y != "undefined") { + assert.integer(item.y, error.pprint`Expected 'y' (${item.y}) to be an Integer`); + } + break; + + case action.PointerCancel: + throw new UnsupportedOperationError(); + break; + + case action.Pause: + item.duration = actionItem.duration; + if (typeof item.duration != "undefined") { + assert.positiveInteger(item.duration, + error.pprint`Expected 'duration' (${item.duration}) to be >= 0`); + } + break; + } + + return item; + } +}; + +/** + * Represents a series of ticks, specifying which actions to perform at each tick. + */ +action.Chain = class extends Array { + toString() { + return `[chain ${super.toString()}]`; + } + + /** + * @param {Array.} actions + * Array of objects that each represent an action sequence. + * + * @return {action.Chain} + * Transpose of |actions| such that actions to be performed in a single tick + * are grouped together. + * + * @throws {InvalidArgumentError} + * If |actions| is not an Array. + */ + static fromJson(actions) { + assert.array(actions, + error.pprint`Expected 'actions' to be an Array, got: ${actions}`); + let actionsByTick = new action.Chain(); + // TODO check that each actionSequence in actions refers to a different input ID + for (let actionSequence of actions) { + let inputSourceActions = action.Sequence.fromJson(actionSequence); + for (let i = 0; i < inputSourceActions.length; i++) { + // new tick + if (actionsByTick.length < (i + 1)) { + actionsByTick.push([]); + } + actionsByTick[i].push(inputSourceActions[i]); + } + } + return actionsByTick; + } +}; + +/** + * Represents one input source action sequence; this is essentially an |Array.|. + */ +action.Sequence = class extends Array { + toString() { + return `[sequence ${super.toString()}]`; + } + + /** + * @param {?} actionSequence + * Object that represents a sequence action items for one input source. + * + * @return {action.Sequence} + * Sequence of actions that can be dispatched. + * + * @throws {InvalidArgumentError} + * If |actionSequence.id| is not a string or it's aleady mapped + * to an |action.InputState} incompatible with |actionSequence.type|. + * If |actionSequence.actions| is not an Array. + */ + static fromJson(actionSequence) { + // used here to validate 'type' in addition to InputState type below + let inputSourceState = InputState.fromJson(actionSequence); + let id = actionSequence.id; + assert.defined(id, "Expected 'id' to be defined"); + assert.string(id, error.pprint`Expected 'id' to be a string, got: ${id}`); + let actionItems = actionSequence.actions; + assert.array(actionItems, + error.pprint("Expected 'actionSequence.actions' to be an Array, " + + `got: ${actionSequence.actions}`)); + if (!action.inputStateMap.has(id)) { + action.inputStateMap.set(id, inputSourceState); + } else if (!action.inputStateMap.get(id).is(inputSourceState)) { + throw new InvalidArgumentError( + `Expected ${id} to be mapped to ${inputSourceState}, ` + + `got: ${action.inputStateMap.get(id)}`); + } + let actions = new action.Sequence(); + for (let actionItem of actionItems) { + actions.push(action.Action.fromJson(actionSequence, actionItem)); + } + return actions; + } +}; + +/** + * Represents parameters in an action for a pointer input source. + * + * @param {string=} pointerType + * Type of pointing device. If the parameter is undefined, "mouse" is used. + */ +action.PointerParameters = class { + constructor(pointerType = "mouse") { + this.pointerType = action.PointerType.get(pointerType); + } + + toString() { + return `[pointerParameters ${this.pointerType}]`; + } + + /** + * @param {?} parametersData + * Object that represents pointer parameters. + * + * @return {action.PointerParameters} + * Validated pointer paramters. + */ + static fromJson(parametersData) { + if (typeof parametersData == "undefined") { + return new action.PointerParameters(); + } else { + return new action.PointerParameters(parametersData.pointerType); + } + } +}; + +/** + * Adds |pointerType| attribute to Action |act|. Helper function + * for |action.Action.fromJson|. + * + * @param {string} id + * Input source ID. + * @param {action.PointerParams} pointerParams + * Input source pointer parameters. + * @param {action.Action} act + * Action to be updated. + * + * @throws {InvalidArgumentError} + * If |id| is already mapped to an |action.InputState| that is + * not compatible with |act.type| or |pointerParams.pointerType|. + */ +action.processPointerAction = function processPointerAction(id, pointerParams, act) { + if (action.inputStateMap.has(id) && action.inputStateMap.get(id).type !== act.type) { + throw new InvalidArgumentError( + `Expected 'id' ${id} to be mapped to InputState whose type is ` + + `${action.inputStateMap.get(id).type}, got: ${act.type}`); + } + let pointerType = pointerParams.pointerType; + if (action.inputStateMap.has(id) && action.inputStateMap.get(id).subtype !== pointerType) { + throw new InvalidArgumentError( + `Expected 'id' ${id} to be mapped to InputState whose subtype is ` + + `${action.inputStateMap.get(id).subtype}, got: ${pointerType}`); + } + act.pointerType = pointerParams.pointerType; +}; + +/** Collect properties associated with KeyboardEvent */ +action.Key = class { + constructor(rawKey) { + this.key = NORMALIZED_KEY_LOOKUP[rawKey] || rawKey; + this.code = KEY_CODE_LOOKUP[rawKey]; + this.location = KEY_LOCATION_LOOKUP[rawKey] || 0; + this.altKey = false; + this.shiftKey = false; + this.ctrlKey = false; + this.metaKey = false; + this.repeat = false; + this.isComposing = false; + // Prevent keyCode from being guessed in event.js; we don't want to use it anyway. + this.keyCode = 0; + } + + update(inputState) { + this.altKey = inputState.alt; + this.shiftKey = inputState.shift; + this.ctrlKey = inputState.ctrl; + this.metaKey = inputState.meta; + } +}; + +/** Collect properties associated with MouseEvent */ +action.Mouse = class { + constructor(type, button = 0) { + this.type = type; + assert.positiveInteger(button); + this.button = button; + this.buttons = 0; + } + + update(inputState) { + let allButtons = Array.from(inputState.pressed); + this.buttons = allButtons.reduce((a, i) => a + Math.pow(2, i), 0); + } +}; + +/** + * Dispatch a chain of actions over |chain.length| ticks. + * + * This is done by creating a Promise for each tick that resolves once all the + * Promises for individual tick-actions are resolved. The next tick's actions are + * not dispatched until the Promise for the current tick is resolved. + * + * @param {action.Chain} chain + * Actions grouped by tick; each element in |chain| is a sequence of + * actions for one tick. + * @param {element.Store} seenEls + * Element store. + * @param {?} container + * Object with |frame| attribute of type |nsIDOMWindow|. + * + * @return {Promise} + * Promise for dispatching all actions in |chain|. + */ +action.dispatch = function(chain, seenEls, container) { + let chainEvents = Task.spawn(function*() { + for (let tickActions of chain) { + yield action.dispatchTickActions( + tickActions, action.computeTickDuration(tickActions), seenEls, container); + } + }); + return chainEvents; +}; + +/** + * Dispatch sequence of actions for one tick. + * + * This creates a Promise for one tick that resolves once the Promise for each + * tick-action is resolved, which takes at least |tickDuration| milliseconds. + * The resolved set of events for each tick is followed by firing of pending DOM events. + * + * Note that the tick-actions are dispatched in order, but they may have different + * durations and therefore may not end in the same order. + * + * @param {Array.} tickActions + * List of actions for one tick. + * @param {number} tickDuration + * Duration in milliseconds of this tick. + * @param {element.Store} seenEls + * Element store. + * @param {?} container + * Object with |frame| attribute of type |nsIDOMWindow|. + * + * @return {Promise} + * Promise for dispatching all tick-actions and pending DOM events. + */ +action.dispatchTickActions = function(tickActions, tickDuration, seenEls, container) { + let pendingEvents = tickActions.map(toEvents(tickDuration, seenEls, container)); + return Promise.all(pendingEvents).then(() => flushEvents(container)); +}; + +/** + * Compute tick duration in milliseconds for a collection of actions. + * + * @param {Array.} tickActions + * List of actions for one tick. + * + * @return {number} + * Longest action duration in |tickActions| if any, or 0. + */ +action.computeTickDuration = function(tickActions) { + let max = 0; + for (let a of tickActions) { + let affectsWallClockTime = a.subtype == action.Pause || + (a.type == "pointer" && a.subtype == action.PointerMove); + if (affectsWallClockTime && a.duration) { + max = Math.max(a.duration, max); + } + } + return max; +}; + +/** + * Compute viewport coordinates of pointer target based on given origin. + * + * @param {action.Action} a + * Action that specifies pointer origin and x and y coordinates of target. + * @param {action.InputState} inputState + * Input state that specifies current x and y coordinates of pointer. + * @param {Map.=} center + * Object representing x and y coordinates of an element center-point. + * This is only used if |a.origin| is a web element reference. + * + * @return {Map.} + * x and y coordinates of pointer destination. + */ +action.computePointerDestination = function(a, inputState, center = undefined) { + let {x, y} = a; + switch (a.origin) { + case action.PointerOrigin.Viewport: + break; + case action.PointerOrigin.Pointer: + x += inputState.x; + y += inputState.y; + break; + default: + // origin represents web element + assert.defined(center); + assert.in("x", center); + assert.in("y", center); + x += center.x; + y += center.y; + } + return {"x": x, "y": y}; +}; + +/** + * Create a closure to use as a map from action definitions to Promise events. + * + * @param {number} tickDuration + * Duration in milliseconds of this tick. + * @param {element.Store} seenEls + * Element store. + * @param {?} container + * Object with |frame| attribute of type |nsIDOMWindow|. + * + * @return {function(action.Action): Promise} + * Function that takes an action and returns a Promise for dispatching + * the event that corresponds to that action. + */ +function toEvents(tickDuration, seenEls, container) { + return function (a) { + let inputState = action.inputStateMap.get(a.id); + switch (a.subtype) { + case action.KeyUp: + return dispatchKeyUp(a, inputState, container.frame); + + case action.KeyDown: + return dispatchKeyDown(a, inputState, container.frame); + + case action.PointerDown: + return dispatchPointerDown(a, inputState, container.frame); + + case action.PointerUp: + return dispatchPointerUp(a, inputState, container.frame); + + case action.PointerMove: + return dispatchPointerMove(a, inputState, tickDuration, seenEls, container); + + case action.PointerCancel: + throw new UnsupportedOperationError(); + + case action.Pause: + return dispatchPause(a, tickDuration); + } + }; +} + +/** + * Dispatch a keyDown action equivalent to pressing a key on a keyboard. + * + * @param {action.Action} a + * Action to dispatch. + * @param {action.InputState} inputState + * Input state for this action's input source. + * @param {nsIDOMWindow} win + * Current window. + * + * @return {Promise} + * Promise to dispatch at least a keydown event, and keypress if appropriate. + */ +function dispatchKeyDown(a, inputState, win) { + return new Promise(resolve => { + let keyEvent = new action.Key(a.value); + keyEvent.repeat = inputState.isPressed(keyEvent.key); + inputState.press(keyEvent.key); + if (keyEvent.key in MODIFIER_NAME_LOOKUP) { + inputState.setModState(keyEvent.key, true); + } + // Append a copy of |a| with keyUp subtype + action.inputsToCancel.push(Object.assign({}, a, {subtype: action.KeyUp})); + keyEvent.update(inputState); + event.sendKeyDown(keyEvent.key, keyEvent, win); + + resolve(); + }); +} + +/** + * Dispatch a keyUp action equivalent to releasing a key on a keyboard. + * + * @param {action.Action} a + * Action to dispatch. + * @param {action.InputState} inputState + * Input state for this action's input source. + * @param {nsIDOMWindow} win + * Current window. + * + * @return {Promise} + * Promise to dispatch a keyup event. + */ +function dispatchKeyUp(a, inputState, win) { + return new Promise(resolve => { + let keyEvent = new action.Key(a.value); + if (!inputState.isPressed(keyEvent.key)) { + resolve(); + return; + } + if (keyEvent.key in MODIFIER_NAME_LOOKUP) { + inputState.setModState(keyEvent.key, false); + } + inputState.release(keyEvent.key); + keyEvent.update(inputState); + event.sendKeyUp(keyEvent.key, keyEvent, win); + + resolve(); + }); +} + +/** + * Dispatch a pointerDown action equivalent to pressing a pointer-device + * button. + * + * @param {action.Action} a + * Action to dispatch. + * @param {action.InputState} inputState + * Input state for this action's input source. + * @param {nsIDOMWindow} win + * Current window. + * + * @return {Promise} + * Promise to dispatch at least a pointerdown event. + */ +function dispatchPointerDown(a, inputState, win) { + return new Promise(resolve => { + if (inputState.isPressed(a.button)) { + resolve(); + return; + } + inputState.press(a.button); + // Append a copy of |a| with pointerUp subtype + action.inputsToCancel.push(Object.assign({}, a, {subtype: action.PointerUp})); + switch (inputState.subtype) { + case action.PointerType.Mouse: + let mouseEvent = new action.Mouse("mousedown", a.button); + mouseEvent.update(inputState); + event.synthesizeMouseAtPoint(inputState.x, inputState.y, mouseEvent, win); + break; + case action.PointerType.Pen: + case action.PointerType.Touch: + throw new UnsupportedOperationError("Only 'mouse' pointer type is supported"); + break; + default: + throw new TypeError(`Unknown pointer type: ${inputState.subtype}`); + } + resolve(); + }); +} + +/** + * Dispatch a pointerUp action equivalent to releasing a pointer-device + * button. + * + * @param {action.Action} a + * Action to dispatch. + * @param {action.InputState} inputState + * Input state for this action's input source. + * @param {nsIDOMWindow} win + * Current window. + * + * @return {Promise} + * Promise to dispatch at least a pointerup event. + */ +function dispatchPointerUp(a, inputState, win) { + return new Promise(resolve => { + if (!inputState.isPressed(a.button)) { + resolve(); + return; + } + inputState.release(a.button); + switch (inputState.subtype) { + case action.PointerType.Mouse: + let mouseEvent = new action.Mouse("mouseup", a.button); + mouseEvent.update(inputState); + event.synthesizeMouseAtPoint(inputState.x, inputState.y, + mouseEvent, win); + break; + case action.PointerType.Pen: + case action.PointerType.Touch: + throw new UnsupportedOperationError("Only 'mouse' pointer type is supported"); + default: + throw new TypeError(`Unknown pointer type: ${inputState.subtype}`); + } + resolve(); + }); +} + +/** + * Dispatch a pointerMove action equivalent to moving pointer device in a line. + * + * If the action duration is 0, the pointer jumps immediately to the target coordinates. + * Otherwise, events are synthesized to mimic a pointer travelling in a discontinuous, + * approximately straight line, with the pointer coordinates being updated around 60 + * times per second. + * + * @param {action.Action} a + * Action to dispatch. + * @param {action.InputState} inputState + * Input state for this action's input source. + * @param {element.Store} seenEls + * Element store. + * @param {?} container + * Object with |frame| attribute of type |nsIDOMWindow|. + * + * @return {Promise} + * Promise to dispatch at least one pointermove event, as well as mousemove events + * as appropriate. + */ +function dispatchPointerMove(a, inputState, tickDuration, seenEls, container) { + const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + // interval between pointermove increments in ms, based on common vsync + const fps60 = 17; + return new Promise(resolve => { + const start = Date.now(); + const [startX, startY] = [inputState.x, inputState.y]; + let target = action.computePointerDestination(a, inputState, + getElementCenter(a.origin, seenEls, container)); + const [targetX, targetY] = [target.x, target.y]; + if (!inViewPort(targetX, targetY, container.frame)) { + throw new MoveTargetOutOfBoundsError( + `(${targetX}, ${targetY}) is out of bounds of viewport ` + + `width (${container.frame.innerWidth}) and height (${container.frame.innerHeight})`); + } + + const duration = typeof a.duration == "undefined" ? tickDuration : a.duration; + if (duration === 0) { + // move pointer to destination in one step + performOnePointerMove(inputState, targetX, targetY, container.frame); + resolve(); + return; + } + + const distanceX = targetX - startX; + const distanceY = targetY - startY; + const ONE_SHOT = Ci.nsITimer.TYPE_ONE_SHOT; + let intermediatePointerEvents = Task.spawn(function* () { + // wait |fps60| ms before performing first incremental pointer move + yield new Promise(resolveTimer => + timer.initWithCallback(resolveTimer, fps60, ONE_SHOT) + ); + let durationRatio = Math.floor(Date.now() - start) / duration; + const epsilon = fps60 / duration / 10; + while ((1 - durationRatio) > epsilon) { + let x = Math.floor(durationRatio * distanceX + startX); + let y = Math.floor(durationRatio * distanceY + startY); + performOnePointerMove(inputState, x, y, container.frame); + // wait |fps60| ms before performing next pointer move + yield new Promise(resolveTimer => + timer.initWithCallback(resolveTimer, fps60, ONE_SHOT)); + durationRatio = Math.floor(Date.now() - start) / duration; + } + }); + // perform last pointer move after all incremental moves are resolved and + // durationRatio is close enough to 1 + intermediatePointerEvents.then(() => { + performOnePointerMove(inputState, targetX, targetY, container.frame); + resolve(); + }); + + }); +} + +function performOnePointerMove(inputState, targetX, targetY, win) { + if (targetX == inputState.x && targetY == inputState.y) { + return; + } + switch (inputState.subtype) { + case action.PointerType.Mouse: + let mouseEvent = new action.Mouse("mousemove"); + mouseEvent.update(inputState); + //TODO both pointermove (if available) and mousemove + event.synthesizeMouseAtPoint(targetX, targetY, mouseEvent, win); + break; + case action.PointerType.Pen: + case action.PointerType.Touch: + throw new UnsupportedOperationError("Only 'mouse' pointer type is supported"); + default: + throw new TypeError(`Unknown pointer type: ${inputState.subtype}`); + } + inputState.x = targetX; + inputState.y = targetY; +} + +/** + * Dispatch a pause action equivalent waiting for |a.duration| milliseconds, or a + * default time interval of |tickDuration|. + * + * @param {action.Action} a + * Action to dispatch. + * @param {number} tickDuration + * Duration in milliseconds of this tick. + * + * @return {Promise} + * Promise that is resolved after the specified time interval. + */ +function dispatchPause(a, tickDuration) { + const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + let duration = typeof a.duration == "undefined" ? tickDuration : a.duration; + return new Promise(resolve => + timer.initWithCallback(resolve, duration, Ci.nsITimer.TYPE_ONE_SHOT) + ); +} + +// helpers +/** + * Force any pending DOM events to fire. + * + * @param {?} container + * Object with |frame| attribute of type |nsIDOMWindow|. + * + * @return {Promise} + * Promise to flush DOM events. + */ +function flushEvents(container) { + return new Promise(resolve => container.frame.requestAnimationFrame(resolve)); +} + +function capitalize(str) { + assert.string(str); + return str.charAt(0).toUpperCase() + str.slice(1); +} + +function inViewPort(x, y, win) { + assert.number(x, `Expected x to be finite number`); + assert.number(y, `Expected y to be finite number`); + // Viewport includes scrollbars if rendered. + return !(x < 0 || y < 0 || x > win.innerWidth || y > win.innerHeight); +} + +function getElementCenter(elementReference, seenEls, container) { + if (element.isWebElementReference(elementReference)) { + let uuid = elementReference[element.Key] || elementReference[element.LegacyKey]; + let el = seenEls.get(uuid, container); + return element.coordinates(el); + } +} diff --git a/testing/marionette/addon.js b/testing/marionette/addon.js new file mode 100644 index 000000000..d2ead6fb2 --- /dev/null +++ b/testing/marionette/addon.js @@ -0,0 +1,104 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/AddonManager.jsm"); +Cu.import("resource://gre/modules/FileUtils.jsm"); + +Cu.import("chrome://marionette/content/error.js"); + +this.EXPORTED_SYMBOLS = ["addon"]; + +this.addon = {}; + +// from https://developer.mozilla.org/en-US/Add-ons/Add-on_Manager/AddonManager#AddonInstall_errors +addon.Errors = { + [-1]: "ERROR_NETWORK_FAILURE: A network error occured.", + [-2]: "ERROR_INCORECT_HASH: The downloaded file did not match the expected hash.", + [-3]: "ERROR_CORRUPT_FILE: The file appears to be corrupt.", + [-4]: "ERROR_FILE_ACCESS: There was an error accessing the filesystem.", + [-5]: "ERROR_SIGNEDSTATE_REQUIRED: The addon must be signed and isn't.", +}; + +function lookupError(code) { + let msg = addon.Errors[code]; + return new UnknownError(msg); +} + +/** + * Install a Firefox addon. + * + * If the addon is restartless, it can be used right away. Otherwise a + * restart is required. + * + * Temporary addons will automatically be uninstalled on shutdown and + * do not need to be signed, though they must be restartless. + * + * @param {string} path + * Full path to the extension package archive. + * @param {boolean=} temporary + * True to install the addon temporarily, false (default) otherwise. + * + * @return {Promise: string} + * Addon ID. + * + * @throws {UnknownError} + * If there is a problem installing the addon. + */ +addon.install = function (path, temporary = false) { + return new Promise((resolve, reject) => { + let file = new FileUtils.File(path); + + let listener = { + onInstallEnded: function (install, addon) { + resolve(addon.id); + }, + + onInstallFailed: function (install) { + reject(lookupError(install.error)); + }, + + onInstalled: function (addon) { + AddonManager.removeAddonListener(listener); + resolve(addon.id); + } + }; + + if (!temporary) { + AddonManager.getInstallForFile(file, function (aInstall) { + if (aInstall.error !== 0) { + reject(lookupError(aInstall.error)); + } + aInstall.addListener(listener); + aInstall.install(); + }); + } else { + AddonManager.addAddonListener(listener); + AddonManager.installTemporaryAddon(file); + } + }); +}; + +/** + * Uninstall a Firefox addon. + * + * If the addon is restartless it will be uninstalled right away. + * Otherwise, Firefox must be restarted for the change to take effect. + * + * @param {string} id + * ID of the addon to uninstall. + * + * @return {Promise} + */ +addon.uninstall = function (id) { + return new Promise(resolve => { + AddonManager.getAddonByID(id, function (addon) { + addon.uninstall(); + resolve(); + }); + }); +}; diff --git a/testing/marionette/assert.js b/testing/marionette/assert.js new file mode 100644 index 000000000..d1a55bd7c --- /dev/null +++ b/testing/marionette/assert.js @@ -0,0 +1,322 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/AppConstants.jsm"); +Cu.import("resource://gre/modules/Preferences.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +Cu.import("chrome://marionette/content/error.js"); + +this.EXPORTED_SYMBOLS = ["assert"]; + +const isFennec = () => AppConstants.platform == "android"; +const isB2G = () => AppConstants.MOZ_B2G; +const isFirefox = () => Services.appinfo.name == "Firefox"; + +/** Shorthands for common assertions made in Marionette. */ +this.assert = {}; + +/** + * Asserts that Marionette has a session. + * + * @param {GeckoDriver} driver + * Marionette driver instance. + * @param {string=} msg + * Custom error message. + * + * @return {string} + * Session ID. + * + * @throws {InvalidSessionIDError} + * If |driver| does not have a session ID. + */ +assert.session = function (driver, msg = "") { + assert.that(sessionID => sessionID, + msg, InvalidSessionIDError)(driver.sessionId); + return driver.sessionId; +}; + +/** + * Asserts that the current browser is Firefox Desktop. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If current browser is not Firefox. + */ +assert.firefox = function (msg = "") { + msg = msg || "Only supported in Firefox"; + assert.that(isFirefox, msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that the current browser is Fennec, or Firefox for Android. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If current browser is not Fennec. + */ +assert.fennec = function (msg = "") { + msg = msg || "Only supported in Fennec"; + assert.that(isFennec, msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that the current browser is B2G. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If the current browser is not B2G. + */ +assert.b2g = function (msg = "") { + msg = msg || "Only supported in B2G"; + assert.that(isB2G, msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that the current |context| is content. + * + * @param {string} context + * Context to test. + * @param {string=} msg + * Custom error message. + * + * @return {string} + * |context| is returned unaltered. + * + * @throws {UnsupportedOperationError} + * If |context| is not content. + */ +assert.content = function (context, msg = "") { + msg = msg || "Only supported in content context"; + assert.that(c => c.toString() == "content", msg, UnsupportedOperationError)(context); +}; + +/** + * Asserts that the current browser is a mobile browser, that is either + * B2G or Fennec. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If the current browser is not B2G or Fennec. + */ +assert.mobile = function (msg = "") { + msg = msg || "Only supported in Fennec or B2G"; + assert.that(() => isFennec() || isB2G(), msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that |obj| is defined. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {?} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not defined. + */ +assert.defined = function (obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be defined`; + return assert.that(o => typeof o != "undefined", msg)(obj); +}; + +/** + * Asserts that |obj| is a finite number. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {number} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not a number. + */ +assert.number = function (obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be finite number`; + return assert.that(Number.isFinite, msg)(obj); +}; + +/** + * Asserts that |obj| is an integer. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {number} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not an integer. + */ +assert.integer = function (obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be an integer`; + return assert.that(Number.isInteger, msg)(obj); +}; + +/** + * Asserts that |obj| is a positive integer. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {number} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not a positive integer. + */ +assert.positiveInteger = function (obj, msg = "") { + assert.integer(obj, msg); + msg = msg || error.pprint`Expected ${obj} to be >= 0`; + return assert.that(n => n >= 0, msg)(obj); +}; + +/** + * Asserts that |obj| is a boolean. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {boolean} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not a boolean. + */ +assert.boolean = function (obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be boolean`; + return assert.that(b => typeof b == "boolean", msg)(obj); +}; + +/** + * Asserts that |obj| is a string. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {string} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not a string. + */ +assert.string = function (obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be a string`; + return assert.that(s => typeof s == "string", msg)(obj); +}; + +/** + * Asserts that |obj| is an object. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {Object} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not an object. + */ +assert.object = function (obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be an object`; + return assert.that(o => + Object.prototype.toString.call(o) == "[object Object]", msg)(obj); +}; + +/** + * Asserts that |prop| is in |obj|. + * + * @param {?} prop + * Own property to test if is in |obj|. + * @param {?} obj + * Object. + * @param {string=} msg + * Custom error message. + * + * @return {?} + * Value of |obj|'s own property |prop|. + * + * @throws {InvalidArgumentError} + * If |prop| is not in |obj|, or |obj| is not an object. + */ +assert.in = function (prop, obj, msg = "") { + assert.object(obj, msg); + msg = msg || error.pprint`Expected ${prop} in ${obj}`; + assert.that(p => obj.hasOwnProperty(p), msg)(prop); + return obj[prop]; +}; + +/** + * Asserts that |obj| is an Array. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {Object} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not an Array. + */ +assert.array = function (obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be an Array`; + return assert.that(Array.isArray, msg)(obj); +}; + +/** + * Returns a function that is used to assert the |predicate|. + * + * @param {function(?): boolean} predicate + * Evaluated on calling the return value of this function. If its + * return value of the inner function is false, |error| is thrown + * with |message|. + * @param {string=} message + * Custom error message. + * @param {Error=} error + * Custom error type by its class. + * + * @return {function(?): ?} + * Function that takes and returns the passed in value unaltered, and + * which may throw |error| with |message| if |predicate| evaluates + * to false. + */ +assert.that = function ( + predicate, message = "", error = InvalidArgumentError) { + return obj => { + if (!predicate(obj)) { + throw new error(message); + } + return obj; + }; +}; diff --git a/testing/marionette/atom.js b/testing/marionette/atom.js new file mode 100644 index 000000000..369e5c44c --- /dev/null +++ b/testing/marionette/atom.js @@ -0,0 +1,192 @@ +// Copyright 2011-2014 Software Freedom Conservancy +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +this.EXPORTED_SYMBOLS = ["atom"]; + +this.atom = {}; + +atom.clearElement = function (element, window){return function(){function g(a){throw a;}var h=void 0,i=!0,k=null,l=!1;function n(a){return function(){return this[a]}}function o(a){return function(){return a}}var p,q=this; +function aa(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function r(a){return a!==h}function ba(a){var b=aa(a);return"array"==b||"object"==b&&"number"==typeof a.length}function t(a){return"string"==typeof a}function w(a){return"function"==aa(a)}function ca(a){a=aa(a);return"object"==a||"array"==a||"function"==a}var da="closure_uid_"+Math.floor(2147483648*Math.random()).toString(36),ea=0,fa=Date.now||function(){return+new Date}; +function x(a,b){function c(){}c.prototype=b.prototype;a.$=b.prototype;a.prototype=new c};function ga(a,b){for(var c=1;c")&&(a=a.replace(ma,">"));-1!=a.indexOf('"')&&(a=a.replace(na,"""));return a}var ka=/&/g,la=//g,na=/\"/g,ja=/[&<>\"]/; +function oa(a,b){for(var c=0,d=ha(""+a).split("."),e=ha(""+b).split("."),f=Math.max(d.length,e.length),j=0;0==c&&j(0==v[1].length?0:parseInt(v[1],10))?1:0)||((0==u[2].length)<(0==v[2].length)?-1:(0== +u[2].length)>(0==v[2].length)?1:0)||(u[2]v[2]?1:0)}while(0==c)}return c}var pa=2147483648*Math.random()|0,qa={};function ra(a){return qa[a]||(qa[a]=(""+a).replace(/\-([a-z])/g,function (a,c){return c.toUpperCase()}))};var sa,ta;function ua(){return q.navigator?q.navigator.userAgent:k}var va,wa=q.navigator;va=wa&&wa.platform||"";sa=-1!=va.indexOf("Mac");ta=-1!=va.indexOf("Win");var xa=-1!=va.indexOf("Linux"),ya,za="",Aa=/rv\:([^\);]+)(\)|;)/.exec(ua());ya=za=Aa?Aa[1]:"";var Ba={};var Ca=window;function Da(a,b){for(var c in a)b.call(h,a[c],c,a)}function Ea(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b};function y(a,b){this.code=a;this.message=b||"";this.name=Fa[a]||Fa[13];var c=Error(this.message);c.name=this.name;this.stack=c.stack||""}x(y,Error); +var Fa={7:"NoSuchElementError",8:"NoSuchFrameError",9:"UnknownCommandError",10:"StaleElementReferenceError",11:"ElementNotVisibleError",12:"InvalidElementStateError",13:"UnknownError",15:"ElementNotSelectableError",19:"XPathLookupError",23:"NoSuchWindowError",24:"InvalidCookieDomainError",25:"UnableToSetCookieError",26:"ModalDialogOpenedError",27:"NoModalDialogOpenError",28:"ScriptTimeoutError",32:"InvalidSelectorError",33:"SqlDatabaseError",34:"MoveTargetOutOfBoundsError"}; +y.prototype.toString=function(){return"["+this.name+"] "+this.message};function Ga(a){this.stack=Error().stack||"";a&&(this.message=""+a)}x(Ga,Error);Ga.prototype.name="CustomError";function Ha(a,b){b.unshift(a);Ga.call(this,ga.apply(k,b));b.shift()}x(Ha,Ga);Ha.prototype.name="AssertionError";function Ia(a,b,c){if(!a){var d=Array.prototype.slice.call(arguments,2),e="Assertion failed";if(b)var e=e+(": "+b),f=d;g(new Ha(""+e,f||[]))}}function Ja(a,b){g(new Ha("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1)))};function z(a){return a[a.length-1]}var Ka=Array.prototype;function A(a,b){if(t(a))return!t(b)||1!=b.length?-1:a.indexOf(b,0);for(var c=0;cc?k:t(a)?a.charAt(c):a[c]}function Qa(a){return Ka.concat.apply(Ka,arguments)} +function Ra(a){if("array"==aa(a))return Qa(a);for(var b=[],c=0,d=a.length;c=arguments.length?Ka.slice.call(a,b):Ka.slice.call(a,b,c)};var Ta;Ba["1.9.1"]||(Ba["1.9.1"]=0<=oa(ya,"1.9.1"));function Ua(a,b){var c;c=(c=a.className)&&"function"==typeof c.split?c.split(/\s+/):[];var d=Sa(arguments,1),e;e=c;for(var f=0,j=0;j=a.length&&g(I);if(b in a)return a[b++];b++}};return c}g(Error("Not implemented"))};function K(a,b,c,d,e){this.o=!!b;a&&L(this,a,d);this.depth=e!=h?e:this.q||0;this.o&&(this.depth*=-1);this.za=!c}x(K,J);p=K.prototype;p.p=k;p.q=0;p.ha=l;function L(a,b,c,d){if(a.p=b)a.q="number"==typeof c?c:1!=a.p.nodeType?0:a.o?-1:1;"number"==typeof d&&(a.depth=d)} +p.next=function(){var a;if(this.ha){(!this.p||this.za&&0==this.depth)&&g(I);a=this.p;var b=this.o?-1:1;if(this.q==b){var c=this.o?a.lastChild:a.firstChild;c?L(this,c):L(this,a,-1*b)}else(c=this.o?a.previousSibling:a.nextSibling)?L(this,c):L(this,a.parentNode,-1*b);this.depth+=this.q*(this.o?-1:1)}else this.ha=i;(a=this.p)||g(I);return a}; +p.splice=function (a){var b=this.p,c=this.o?1:-1;this.q==c&&(this.q=-1*c,this.depth+=this.q*(this.o?-1:1));this.o=!this.o;K.prototype.next.call(this);this.o=!this.o;for(var c=ba(arguments[0])?arguments[0]:arguments,d=c.length-1;0<=d;d--)b.parentNode&&b.parentNode.insertBefore(c[d],b.nextSibling);bb(b)};function tb(a,b,c,d){K.call(this,a,b,c,k,d)}x(tb,K);tb.prototype.next=function(){do tb.$.next.call(this);while(-1==this.q);return this.p};function ub(a,b){var c=D(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,k))?c[b]||c.getPropertyValue(b):""}function vb(a,b){return ub(a,b)||(a.currentStyle?a.currentStyle[b]:k)||a.style&&a.style[b]} +function wb(a){for(var b=D(a),c=vb(a,"position"),d="fixed"==c||"absolute"==c,a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=vb(a,"position"),d=d&&"static"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||"fixed"==c||"absolute"==c||"relative"==c))return a;return k} +function xb(a){var b=new B;if(1==a.nodeType)if(a.getBoundingClientRect)a=a.getBoundingClientRect(),b.x=a.left,b.y=a.top;else{var c=mb(Wa(a));var d,e=D(a),f=vb(a,"position"),j=e.getBoxObjectFor&&!a.getBoundingClientRect&&"absolute"==f&&(d=e.getBoxObjectFor(a))&&(0>d.screenX||0>d.screenY),f=new B(0,0),m=(e?9==e.nodeType?e:D(e):document).documentElement;if(a!=m)if(a.getBoundingClientRect)d=a.getBoundingClientRect(),a=mb(Wa(e)),f.x=d.left+a.x,f.y=d.top+a.y;else if(e.getBoxObjectFor&&!j)d=e.getBoxObjectFor(a), +a=e.getBoxObjectFor(m),f.x=d.screenX-a.screenX,f.y=d.screenY-a.screenY;else{d=a;do f.x+=d.offsetLeft,f.y+=d.offsetTop,d!=a&&(f.x+=d.clientLeft||0,f.y+=d.clientTop||0),d=d.offsetParent;while(d&&d!=a);for(d=a;(d=wb(d))&&d!=e.body&&d!=m;)f.x-=d.scrollLeft,f.y-=d.scrollTop}b.x=f.x-c.x;b.y=f.y-c.y}else c=w(a.pa),d=a,a.targetTouches?d=a.targetTouches[0]:c&&a.pa().targetTouches&&(d=a.pa().targetTouches[0]),b.x=d.clientX,b.y=d.clientY;return b} +function yb(a){var b=a.offsetWidth,c=a.offsetHeight;return!r(b)&&a.getBoundingClientRect?(a=a.getBoundingClientRect(),new Va(a.right-a.left,a.bottom-a.top)):new Va(b,c)};function M(a,b){return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}var zb={"class":"className",readonly:"readOnly"},Ab=["checked","disabled","draggable","hidden"];function Bb(a,b){var c=zb[b]||b,d=a[c];if(!r(d)&&0<=A(Ab,c))return l;if(c="value"==b)if(c=M(a,"OPTION")){var e;c=b.toLowerCase();if(a.hasAttribute)e=a.hasAttribute(c);else try{e=a.attributes[c].specified}catch(f){e=l}c=!e}c&&(d=[],kb(a,d,l),d=d.join(""));return d} +var Cb="async,autofocus,autoplay,checked,compact,complete,controls,declare,defaultchecked,defaultselected,defer,disabled,draggable,ended,formnovalidate,hidden,indeterminate,iscontenteditable,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,paused,pubdate,readonly,required,reversed,scoped,seamless,seeking,selected,spellcheck,truespeed,willvalidate".split(","),Db="BUTTON,INPUT,OPTGROUP,OPTION,SELECT,TEXTAREA".split(","); +function Eb(a){var b=a.tagName.toUpperCase();return!(0<=A(Db,b))?i:Bb(a,"disabled")?l:a.parentNode&&1==a.parentNode.nodeType&&"OPTGROUP"==b||"OPTION"==b?Eb(a.parentNode):i}var Fb="text,search,tel,url,email,password,number".split(",");function Gb(a){return M(a,"TEXTAREA")?i:M(a,"INPUT")?0<=A(Fb,a.type.toLowerCase()):Hb(a)?i:l} +function Hb(a){function b(a){return"inherit"==a.contentEditable?(a=Ib(a))?b(a):l:"true"==a.contentEditable}return!r(a.contentEditable)?l:r(a.isContentEditable)?a.isContentEditable:b(a)}function Ib(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return M(a)?a:k}function Jb(a,b){b=ra(b);return ub(a,b)||Kb(a,b)} +function Kb(a,b){var c=a.currentStyle||a.style,d=c[b];!r(d)&&w(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?r(d)?d:k:(c=Ib(a))?Kb(c,b):k}function Lb(a){if(w(a.getBBox))try{var b=a.getBBox();if(b)return b}catch(c){}if("none"!=vb(a,"display"))a=yb(a);else{var b=a.style,d=b.display,e=b.visibility,f=b.position;b.visibility="hidden";b.position="absolute";b.display="inline";a=yb(a);b.display=d;b.position=f;b.visibility=e}return a} +function Mb(a,b){function c(a){if("none"==Jb(a,"display"))return l;a=Ib(a);return!a||c(a)}function d(a){var b=Lb(a);return 0=c.length&&g(I);var j=c[b++];return a?j:d[":"+j]}};return j};function jc(a){this.n=new hc;a&&this.aa(a)}function kc(a){var b=typeof a;return"object"==b&&a||"function"==b?"o"+(a[da]||(a[da]=++ea)):b.substr(0,1)+a}p=jc.prototype;p.add=function (a){this.n.set(kc(a),a)};p.aa=function (a){for(var a=gc(a),b=a.length,c=0;c");R(191,"/","?");R(192,"`","~");R(219,"[","{");R(220,"\\","|");R(221,"]","}");R({c:59,e:186,opera:59},";",":");R(222,"'",'"');lc.prototype.X=function (a){return this.Ha.contains(a)};function oc(a){return pc(a||arguments.callee.caller,[])} +function pc(a,b){var c=[];if(0<=A(b,a))c.push("[...circular reference...]");else if(a&&50>b.length){c.push(qc(a)+"(");for(var d=a.arguments,e=0;e=xc(this).value){a=this.Ca(a,b,c);b="log:"+a.Fa;q.console&&(q.console.timeStamp?q.console.timeStamp(b):q.console.markTimeline&&q.console.markTimeline(b));q.msWriteProfilerMark&&q.msWriteProfilerMark(b);for(b=this;b;){var c=b,d=a;if(c.ra)for(var e=0,f=h;f=c.ra[e];e++)f(d);b=b.getParent()}}}; +S.prototype.Ca=function (a,b,c){var d=new sc(a,""+b,this.Ga);if(c){d.oa=c;var e;var f=arguments.callee.caller;try{var j;var m;c:{for(var s=["window","location","href"],O=q,E;E=s.shift();)if(O[E]!=k)O=O[E];else{m=k;break c}m=O}if(t(c))j={message:c,name:"Unknown error",lineNumber:"Not available",fileName:m,stack:"Not available"};else{var u,v,s=l;try{u=c.lineNumber||c.Ma||"Not available"}catch(md){u="Not available",s=i}try{v=c.fileName||c.filename||c.sourceURL||m}catch(nd){v="Not available",s=i}j=s|| +!c.lineNumber||!c.fileName||!c.stack?{message:c.message,name:c.name,lineNumber:u,fileName:v,stack:c.stack||"Not available"}:c}e="Message: "+ia(j.message)+'\nUrl: '+j.fileName+"\nLine: "+j.lineNumber+"\n\nBrowser stack:\n"+ia(j.stack+"-> ")+"[end]\n\nJS stack traversal:\n"+ia(oc(f)+"-> ")}catch(kd){e="Exception trying to expose exception! You win, we lose. "+kd}d.na=e}return d};var yc={},zc=k; +function Ac(a){zc||(zc=new S(""),yc[""]=zc,zc.va(wc));var b;if(!(b=yc[a])){b=new S(a);var c=a.lastIndexOf("."),d=a.substr(c+1),c=Ac(a.substr(0,c));c.ba||(c.ba={});c.ba[d]=b;b.Y=c;yc[a]=b}return b};function Bc(){}x(Bc,function(){});Ac("goog.dom.SavedRange");x(function (a){this.Ja="goog_"+pa++;this.Aa="goog_"+pa++;this.la=Wa(a.ea());a.R(this.la.da("SPAN",{id:this.Ja}),this.la.da("SPAN",{id:this.Aa}))},Bc);function T(){}function Cc(a){if(a.getSelection)return a.getSelection();var a=a.document,b=a.selection;if(b){try{var c=b.createRange();if(c.parentElement){if(c.parentElement().document!=a)return k}else if(!c.length||c.item(0).document!=a)return k}catch(d){return k}return b}return k}function Dc(a){for(var b=[],c=0,d=a.D();c=this.l(d,1,0):0<=this.l(d,0,0)&&0>=this.l(d,1,1)}catch(e){g(e)}};Hc.prototype.containsNode=function (a,b){return this.u(Fc(a),b)};Hc.prototype.r=function(){return new Gc(this.b(),this.j(),this.g(),this.k())};function Ic(a){this.a=a}x(Ic,Hc);p=Ic.prototype;p.C=function(){return this.a.commonAncestorContainer};p.b=function(){return this.a.startContainer};p.j=function(){return this.a.startOffset};p.g=function(){return this.a.endContainer};p.k=function(){return this.a.endOffset};p.l=function (a,b,c){return this.a.compareBoundaryPoints(1==c?1==b?q.Range.START_TO_START:q.Range.START_TO_END:1==b?q.Range.END_TO_START:q.Range.END_TO_END,a)};p.isCollapsed=function(){return this.a.collapsed}; +p.select=function (a){this.Z(F(D(this.b())).getSelection(),a)};p.Z=function (a){a.removeAllRanges();a.addRange(this.a)};p.insertNode=function (a,b){var c=this.a.cloneRange();c.collapse(b);c.insertNode(a);c.detach();return a}; +p.R=function (a,b){var c=F(D(this.b()));if(c=(c=Cc(c||window))&&Jc(c))var d=c.b(),e=c.g(),f=c.j(),j=c.k();var m=this.a.cloneRange(),s=this.a.cloneRange();m.collapse(l);s.collapse(i);m.insertNode(b);s.insertNode(a);m.detach();s.detach();if(c){if(d.nodeType==C)for(;f>d.length;){f-=d.length;do d=d.nextSibling;while(d==a||d==b)}if(e.nodeType==C)for(;j>e.length;){j-=e.length;do e=e.nextSibling;while(e==a||e==b)}c=new Kc;c.G=Lc(d,f,e,j);"BR"==d.tagName&&(m=d.parentNode,f=A(m.childNodes,d),d=m);"BR"==e.tagName&& +(m=e.parentNode,j=A(m.childNodes,e),e=m);c.G?(c.f=e,c.i=j,c.d=d,c.h=f):(c.f=d,c.i=f,c.d=e,c.h=j);c.select()}};p.collapse=function (a){this.a.collapse(a)};function W(a){this.a=a}x(W,Ic);function Fc(a){var b=D(a).createRange();if(a.nodeType==C)b.setStart(a,0),b.setEnd(a,a.length);else if(X(a)){for(var c,d=a;(c=d.firstChild)&&X(c);)d=c;b.setStart(d,0);for(d=a;(c=d.lastChild)&&X(c);)d=c;b.setEnd(d,1==d.nodeType?d.childNodes.length:d.length)}else c=a.parentNode,a=A(c.childNodes,a),b.setStart(c,a),b.setEnd(c,a+1);return new W(b)} +W.prototype.Z=function (a,b){var c=b?this.g():this.b(),d=b?this.k():this.j(),e=b?this.b():this.g(),f=b?this.j():this.k();a.collapse(c,d);(c!=e||d!=f)&&a.extend(e,f)};function Mc(a){this.a=a}x(Mc,Hc);Ac("goog.dom.browserrange.IeRange");function Nc(a){var b=D(a).body.createTextRange();if(1==a.nodeType)b.moveToElementText(a),X(a)&&!a.childNodes.length&&b.collapse(l);else{for(var c=0,d=a;d=d.previousSibling;){var e=d.nodeType;if(e==C)c+=d.length;else if(1==e){b.moveToElementText(d);break}}d||b.moveToElementText(a.parentNode);b.collapse(!d);c&&b.move("character",c);b.moveEnd("character",a.length)}return b}p=Mc.prototype;p.O=k;p.f=k;p.d=k;p.i=-1;p.h=-1; +p.s=function(){this.O=this.f=this.d=k;this.i=this.h=-1}; +p.C=function(){if(!this.O){var a=this.a.text,b=this.a.duplicate(),c=a.replace(/ +$/,"");(c=a.length-c.length)&&b.moveEnd("character",-c);c=b.parentElement();b=b.htmlText.replace(/(\r\n|\r|\n)+/g," ").length;if(this.isCollapsed()&&0c.outerHTML.replace(/(\r\n|\r|\n)+/g," ").length;)c=c.parentNode;for(;1==c.childNodes.length&&c.innerText==(c.firstChild.nodeType==C?c.firstChild.nodeValue:c.firstChild.innerText)&&X(c.firstChild);)c=c.firstChild;0==a.length&&(c=Oc(this,c));this.O= +c}return this.O};function Oc(a,b){for(var c=b.childNodes,d=0,e=c.length;d=a.l(j,1,0):a.a.inRange(j))return Oc(a,f)}}return b}p.b=function(){this.f||(this.f=Pc(this,1),this.isCollapsed()&&(this.d=this.f));return this.f};p.j=function(){0>this.i&&(this.i=Qc(this,1),this.isCollapsed()&&(this.h=this.i));return this.i}; +p.g=function(){if(this.isCollapsed())return this.b();this.d||(this.d=Pc(this,0));return this.d};p.k=function(){if(this.isCollapsed())return this.j();0>this.h&&(this.h=Qc(this,0),this.isCollapsed()&&(this.i=this.h));return this.h};p.l=function (a,b,c){return this.a.compareEndPoints((1==b?"Start":"End")+"To"+(1==c?"Start":"End"),a)}; +function Pc(a,b,c){c=c||a.C();if(!c||!c.firstChild)return c;for(var d=1==b,e=0,f=c.childNodes.length;ea.l(E,1,0)&&0(0==F[1].length?0:parseInt(F[1],10))?1:0)||((0==E[2].length)<(0==F[2].length)?-1:(0== +E[2].length)>(0==F[2].length)?1:0)||(E[2]F[2]?1:0)}while(0==v)}p["1.9.1"]=0<=v};var G={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},H={IMG:" ",BR:"\n"};function I(a,c,b){if(!(a.nodeName in G))if(3==a.nodeType)b?c.push((""+a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):c.push(a.nodeValue);else if(a.nodeName in H)c.push(H[a.nodeName]);else for(a=a.firstChild;a;)I(a,c,b),a=a.nextSibling};(function(){var a=h.Components;if(!a)return g;try{if(!a.classes)return g}catch(c){return g}var b=a.classes,a=a.interfaces;b["@mozilla.org/xpcom/version-comparator;1"].getService(a.nsIVersionComparator);b["@mozilla.org/xre/app-info;1"].getService(a.nsIXULAppInfo);return!0})();var J="StopIteration"in h?h.StopIteration:Error("StopIteration");function K(){}K.prototype.next=function(){throw J;};function L(a,c,b,d,e){this.a=!!c;a&&M(this,a,d);this.depth=void 0!=e?e:this.c||0;this.a&&(this.depth*=-1);this.e=!b}j(L,K);L.prototype.b=f;L.prototype.c=0;L.prototype.d=g;function M(a,c,b){if(a.b=c)a.c="number"==typeof b?b:1!=a.b.nodeType?0:a.a?-1:1} +L.prototype.next=function(){var a;if(this.d){if(!this.b||this.e&&0==this.depth)throw J;a=this.b;var c=this.a?-1:1;if(this.c==c){var b=this.a?a.lastChild:a.firstChild;b?M(this,b):M(this,a,-1*c)}else(b=this.a?a.previousSibling:a.nextSibling)?M(this,b):M(this,a.parentNode,-1*c);this.depth+=this.c*(this.a?-1:1)}else this.d=!0;a=this.b;if(!this.b)throw J;return a}; +L.prototype.splice=function (a){var c=this.b,b=this.a?1:-1;this.c==b&&(this.c=-1*b,this.depth+=this.c*(this.a?-1:1));this.a=!this.a;L.prototype.next.call(this);this.a=!this.a;for(var b=arguments[0],d=i(b),b="array"==d||"object"==d&&"number"==typeof b.length?arguments[0]:arguments,d=b.length-1;0<=d;d--)c.parentNode&&c.parentNode.insertBefore(b[d],c.nextSibling);c&&c.parentNode&&c.parentNode.removeChild(c)};function N(a,c,b,d){L.call(this,a,c,b,f,d)}j(N,L);N.prototype.next=function(){do N.f.next.call(this);while(-1==this.c);return this.b};function O(a,c){return!!a&&1==a.nodeType&&(!c||a.tagName.toUpperCase()==c)}function P(a){return O(a,"OPTION")?!0:O(a,"INPUT")?(a=a.type.toLowerCase(),"checkbox"==a||"radio"==a):g}var Q={"class":"className",readonly:"readOnly"},R=["checked","disabled","draggable","hidden"]; +function S(a,c){var b=Q[c]||c,d=a[b];if(void 0===d&&0<=u(R,b))return g;if(b="value"==c)if(b=O(a,"OPTION")){var e;b=c.toLowerCase();if(a.hasAttribute)e=a.hasAttribute(b);else try{e=a.attributes[b].specified}catch(Y){e=g}b=!e}b&&(d=[],I(a,d,g),d=d.join(""));return d}var T="async,autofocus,autoplay,checked,compact,complete,controls,declare,defaultchecked,defaultselected,defer,disabled,draggable,ended,formnovalidate,hidden,indeterminate,iscontenteditable,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,paused,pubdate,readonly,required,reversed,scoped,seamless,seeking,selected,spellcheck,truespeed,willvalidate".split(","); +function U(a,c){if(8==a.nodeType)return f;c=c.toLowerCase();if("style"==c){var b=l(a.style.cssText).toLowerCase();return b=";"==b.charAt(b.length-1)?b:b+";"}b=a.getAttributeNode(c);return!b?f:0<=u(T,c)?"true":b.specified?b.value:f};function V(a,c){var b=f,d=c.toLowerCase();if("style"==c.toLowerCase()){if((b=a.style)&&"string"!=typeof b)b=b.cssText;return b}if("selected"==d||"checked"==d&&P(a)){if(!P(a))throw new q(15,"Element is not selectable");var e="selected",d=a.type&&a.type.toLowerCase();if("checkbox"==d||"radio"==d)e="checked";return S(a,e)?"true":f}b=O(a,"A");if(O(a,"IMG")&&"src"==d||b&&"href"==d)return(b=U(a,d))&&(b=S(a,d)),b;try{e=S(a,c)}catch(Y){}if(!(d=e==f))d=i(e),d="object"==d||"array"==d||"function"==d;b=d?U(a, +c):e;return b!=f?b.toString():f}var W=["_"],X=h;!(W[0]in X)&&X.execScript&&X.execScript("var "+W[0]);for(var Z;W.length&&(Z=W.shift());)!W.length&&void 0!==V?X[Z]=V:X=X[Z]?X[Z]:X[Z]={};; return this._.apply(null,arguments);}.apply({navigator:typeof window!='undefined'?window.navigator:null}, arguments);} + +atom.getElementText = function (element, window){return function(){var g=void 0,h=!0,i=null,j=!1,k=this; +function l(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function m(a){return"string"==typeof a}function n(a,b){function c(){}c.prototype=b.prototype;a.h=b.prototype;a.prototype=new c};function o(a){var b=a.length-1;return 0<=b&&a.indexOf(" ",b)==b}function aa(a,b){for(var c=1;c(0==H[1].length?0:parseInt(H[1],10))?1:0)||((0==G[2].length)<(0==H[2].length)?-1: +(0==G[2].length)>(0==H[2].length)?1:0)||(G[2]H[2]?1:0)}while(0==C)}v["1.9.1"]=0<=C};function I(a,b){this.x=a!==g?a:0;this.y=b!==g?b:0}I.prototype.toString=function(){return"("+this.x+", "+this.y+")"};function J(a,b){this.width=a;this.height=b}J.prototype.toString=function(){return"("+this.width+" x "+this.height+")"};var K=3;function L(a){return 9==a.nodeType?a:a.ownerDocument||a.document}function la(a,b){var c=[];return M(a,b,c,h)?c[0]:g}function M(a,b,c,d){if(a!=i)for(a=a.firstChild;a;){if(b(a)&&(c.push(a),d)||M(a,b,c,d))return h;a=a.nextSibling}return j}function ma(a,b){for(var a=a.parentNode,c=0;a;){if(b(a))return a;a=a.parentNode;c++}return i}function N(a){this.g=a||k.document||document} +function na(a){var b=a.g,a="CSS1Compat"==b.compatMode?b.documentElement:b.body,b=b.parentWindow||b.defaultView;return new I(b.pageXOffset||a.scrollLeft,b.pageYOffset||a.scrollTop)};var oa=function(){var a={i:"http://www.w3.org/2000/svg"};return function (b){return a[b]||i}}(); +function pa(a,b){var c=function(){var c;a:{var e=L(b);if(e.implementation.hasFeature("XPath","3.0")){try{var f=e.createNSResolver?e.createNSResolver(e.documentElement):oa;c=e.evaluate(a,b,f,9,i);break a}catch(r){if("NS_ERROR_ILLEGAL_VALUE"!=r.name)throw new w(32,"Unable to locate an element with the xpath expression "+a+" because of the following error:\n"+r);}c=g}else c=i}return c?c.singleNodeValue||i:b.selectSingleNode?(c=L(b),c.setProperty&&c.setProperty("SelectionLanguage","XPath"),b.selectSingleNode(a)): +i}();if(c!==i&&(!c||1!=c.nodeType))throw new w(32,'The result of the xpath expression "'+a+'" is: '+c+". It should be an element.");return c};(function(){var a=k.Components;if(!a)return j;try{if(!a.classes)return j}catch(b){return j}var c=a.classes,a=a.interfaces;c["@mozilla.org/xpcom/version-comparator;1"].getService(a.nsIVersionComparator);c["@mozilla.org/xre/app-info;1"].getService(a.nsIXULAppInfo);return h})();var P="StopIteration"in k?k.StopIteration:Error("StopIteration");function qa(){}qa.prototype.next=function(){throw P;};function Q(a,b,c,d,e){this.a=!!b;a&&R(this,a,d);this.depth=e!=g?e:this.c||0;this.a&&(this.depth*=-1);this.f=!c}n(Q,qa);Q.prototype.b=i;Q.prototype.c=0;Q.prototype.e=j;function R(a,b,c){if(a.b=b)a.c="number"==typeof c?c:1!=a.b.nodeType?0:a.a?-1:1} +Q.prototype.next=function(){var a;if(this.e){if(!this.b||this.f&&0==this.depth)throw P;a=this.b;var b=this.a?-1:1;if(this.c==b){var c=this.a?a.lastChild:a.firstChild;c?R(this,c):R(this,a,-1*b)}else(c=this.a?a.previousSibling:a.nextSibling)?R(this,c):R(this,a.parentNode,-1*b);this.depth+=this.c*(this.a?-1:1)}else this.e=h;a=this.b;if(!this.b)throw P;return a}; +Q.prototype.splice=function (a){var b=this.b,c=this.a?1:-1;this.c==c&&(this.c=-1*c,this.depth+=this.c*(this.a?-1:1));this.a=!this.a;Q.prototype.next.call(this);this.a=!this.a;for(var c=arguments[0],d=l(c),c="array"==d||"object"==d&&"number"==typeof c.length?arguments[0]:arguments,d=c.length-1;0<=d;d--)b.parentNode&&b.parentNode.insertBefore(c[d],b.nextSibling);b&&b.parentNode&&b.parentNode.removeChild(b)};function S(a,b,c,d){Q.call(this,a,b,c,i,d)}n(S,Q);S.prototype.next=function(){do S.h.next.call(this);while(-1==this.c);return this.b};function ra(a,b){var c=L(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,i))?c[b]||c.getPropertyValue(b):""}function T(a,b){return ra(a,b)||(a.currentStyle?a.currentStyle[b]:i)||a.style&&a.style[b]} +function sa(a){for(var b=L(a),c=T(a,"position"),d="fixed"==c||"absolute"==c,a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=T(a,"position"),d=d&&"static"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||"fixed"==c||"absolute"==c||"relative"==c))return a;return i} +function ta(a){var b=new I;if(1==a.nodeType)if(a.getBoundingClientRect)a=a.getBoundingClientRect(),b.x=a.left,b.y=a.top;else{var c=na(a?new N(L(a)):B||(B=new N));var d,e=L(a),f=T(a,"position"),r=e.getBoxObjectFor&&!a.getBoundingClientRect&&"absolute"==f&&(d=e.getBoxObjectFor(a))&&(0>d.screenX||0>d.screenY),f=new I(0,0),t=(e?9==e.nodeType?e:L(e):document).documentElement;if(a!=t)if(a.getBoundingClientRect)d=a.getBoundingClientRect(),a=na(e?new N(L(e)):B||(B=new N)),f.x=d.left+a.x,f.y=d.top+a.y;else if(e.getBoxObjectFor&& +!r)d=e.getBoxObjectFor(a),a=e.getBoxObjectFor(t),f.x=d.screenX-a.screenX,f.y=d.screenY-a.screenY;else{d=a;do f.x+=d.offsetLeft,f.y+=d.offsetTop,d!=a&&(f.x+=d.clientLeft||0,f.y+=d.clientTop||0),d=d.offsetParent;while(d&&d!=a);for(d=a;(d=sa(d))&&d!=e.body&&d!=t;)f.x-=d.scrollLeft,f.y-=d.scrollTop}b.x=f.x-c.x;b.y=f.y-c.y}else c="function"==l(a.d),d=a,a.targetTouches?d=a.targetTouches[0]:c&&a.d().targetTouches&&(d=a.d().targetTouches[0]),b.x=d.clientX,b.y=d.clientY;return b} +function ua(a){var b=a.offsetWidth,c=a.offsetHeight;return b===g&&a.getBoundingClientRect?(a=a.getBoundingClientRect(),new J(a.right-a.left,a.bottom-a.top)):new J(b,c)};function U(a,b){return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}var va="async,autofocus,autoplay,checked,compact,complete,controls,declare,defaultchecked,defaultselected,defer,disabled,draggable,ended,formnovalidate,hidden,indeterminate,iscontenteditable,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,paused,pubdate,readonly,required,reversed,scoped,seamless,seeking,selected,spellcheck,truespeed,willvalidate".split(","); +function V(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return U(a)?a:i}function W(a,b){b=ba(b);return ra(a,b)||wa(a,b)}function wa(a,b){var c=a.currentStyle||a.style,d=c[b];d===g&&"function"==l(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?d!==g?d:i:(c=V(a))?wa(c,b):i} +function xa(a){if("function"==l(a.getBBox))try{var b=a.getBBox();if(b)return b}catch(c){}if("none"!=T(a,"display"))a=ua(a);else{var b=a.style,d=b.display,e=b.visibility,f=b.position;b.visibility="hidden";b.position="absolute";b.display="inline";a=ua(a);b.display=d;b.position=f;b.visibility=e}return a} +function X(a,b){function c(a){if("none"==W(a,"display"))return j;a=V(a);return!a||c(a)}function d(a){var b=xa(a);return 0(0==B[1].length? +0:parseInt(B[1],10))?1:0)||((0==A[2].length)<(0==B[2].length)?-1:(0==A[2].length)>(0==B[2].length)?1:0)||(A[2]B[2]?1:0)}while(0==q)}k["1.9.1"]=0<=q};(function(){var a=e.Components;if(!a)return!1;try{if(!a.classes)return!1}catch(c){return!1}var b=a.classes,a=a.interfaces;b["@mozilla.org/xpcom/version-comparator;1"].getService(a.nsIVersionComparator);b["@mozilla.org/xre/app-info;1"].getService(a.nsIXULAppInfo);return!0})();function C(a,c,b,d,y){this.b=!!c;if(a&&(this.a=a))this.c="number"==typeof d?d:1!=this.a.nodeType?0:this.b?-1:1;this.depth=void 0!=y?y:this.c||0;this.b&&(this.depth*=-1)}f(C,function(){});C.prototype.a=null;C.prototype.c=0;f(function (a,c,b,d){C.call(this,a,c,0,null,d)},C);var D={"class":"className",readonly:"readOnly"},E=["checked","disabled","draggable","hidden"],F="BUTTON,INPUT,OPTGROUP,OPTION,SELECT,TEXTAREA".split(",");function G(a){var c=a.tagName.toUpperCase();if(p(F,c)){var b;b=D.disabled||"disabled";var d=a[b];b=void 0===d&&p(E,b)?!1:d;a=b?!1:a.parentNode&&1==a.parentNode.nodeType&&"OPTGROUP"==c||"OPTION"==c?G(a.parentNode):!0}else a=!0;return a};var H=G,I=["_"],J=e;!(I[0]in J)&&J.execScript&&J.execScript("var "+I[0]);for(var K;I.length&&(K=I.shift());)!I.length&&void 0!==H?J[K]=H:J=J[K]?J[K]:J[K]={};; return this._.apply(null,arguments);}.apply({navigator:typeof window!='undefined'?window.navigator:null}, arguments);} + +atom.isElementSelected = function (element, window){return function(){var f=!1,g=this;function h(a,b){function c(){}c.prototype=b.prototype;a.d=b.prototype;a.prototype=new c};function i(a,b){for(var c=1;c(0==C[1].length? +0:parseInt(C[1],10))?1:0)||((0==B[2].length)<(0==C[2].length)?-1:(0==B[2].length)>(0==C[2].length)?1:0)||(B[2]C[2]?1:0)}while(0==s)}n["1.9.1"]=0<=s};var D={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},E={IMG:" ",BR:"\n"};function F(a,b,c){if(!(a.nodeName in D))if(3==a.nodeType)c?b.push((""+a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):b.push(a.nodeValue);else if(a.nodeName in E)b.push(E[a.nodeName]);else for(a=a.firstChild;a;)F(a,b,c),a=a.nextSibling};(function(){var a=g.Components;if(!a)return f;try{if(!a.classes)return f}catch(b){return f}var c=a.classes,a=a.interfaces;c["@mozilla.org/xpcom/version-comparator;1"].getService(a.nsIVersionComparator);c["@mozilla.org/xre/app-info;1"].getService(a.nsIXULAppInfo);return!0})();function G(a,b,c,d,e){this.b=!!b;if(a&&(this.a=a))this.c="number"==typeof d?d:1!=this.a.nodeType?0:this.b?-1:1;this.depth=void 0!=e?e:this.c||0;this.b&&(this.depth*=-1)}h(G,function(){});G.prototype.a=null;G.prototype.c=0;h(function (a,b,c,d){G.call(this,a,b,0,null,d)},G);function H(a,b){return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}function I(a){return H(a,"OPTION")?!0:H(a,"INPUT")?(a=a.type.toLowerCase(),"checkbox"==a||"radio"==a):f}var J={"class":"className",readonly:"readOnly"},K=["checked","disabled","draggable","hidden"];function L(a){if(I(a)){if(!I(a))throw new o(15,"Element is not selectable");var b="selected",c=a.type&&a.type.toLowerCase();if("checkbox"==c||"radio"==c)b="checked";var c=b,d=J[c]||c,b=a[d],e;if(e=void 0===b){b:if("string"==typeof K)d="string"!=typeof d||1!=d.length?-1:K.indexOf(d,0);else{for(e=0;e(0==v[1].length? +0:parseInt(v[1],10))?1:0)||((0==l[2].length)<(0==v[2].length)?-1:(0==l[2].length)>(0==v[2].length)?1:0)||(l[2]v[2]?1:0)}while(0==b)}return b}function aa(a){return String(a).replace(/\-([a-z])/g,function (a,c){return c.toUpperCase()})};var s=Array.prototype;function t(a,b){for(var c=a.length,d=n(a)?a.split(""):a,e=0;e=arguments.length?s.slice.call(a,b):s.slice.call(a,b,c)};var u={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400", +darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc", +ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a", +lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1", +moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57", +seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};var fa="background-color border-top-color border-right-color border-bottom-color border-left-color color outline-color".split(" "),ga=/#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/;function ha(a){if(!x.test(a))throw Error("'"+a+"' is not a valid hex color");4==a.length&&(a=a.replace(ga,"#$1$1$2$2$3$3"));return a.toLowerCase()}var x=/^#(?:[0-9a-f]{3}){1,2}$/i,ia=/^(?:rgba)?\((\d{1,3}),\s?(\d{1,3}),\s?(\d{1,3}),\s?(0|1|0\.\d*)\)$/i; +function ja(a){var b=a.match(ia);if(b){a=Number(b[1]);var c=Number(b[2]),d=Number(b[3]),b=Number(b[4]);if(0<=a&&255>=a&&0<=c&&255>=c&&0<=d&&255>=d&&0<=b&&1>=b)return[a,c,d,b]}return[]}var ka=/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;function la(a){var b=a.match(ka);if(b){a=Number(b[1]);var c=Number(b[2]),b=Number(b[3]);if(0<=a&&255>=a&&0<=c&&255>=c&&0<=b&&255>=b)return[a,c,b]}return[]};function y(a,b){this.code=a;this.state=z[a]||ma;this.message=b||"";var c=this.state.replace(/((?:^|\s+)[a-z])/g,function (a){return a.toUpperCase().replace(/^[\s\xa0]+/g,"")}),d=c.length-5;if(0>d||c.indexOf("Error",d)!=d)c+="Error";this.name=c;c=Error(this.message);c.name=this.name;this.stack=c.stack||""}(function(){var a=Error;function b(){}b.prototype=a.prototype;y.I=a.prototype;y.prototype=new b})(); +var ma="unknown error",z={15:"element not selectable",11:"element not visible",31:"ime engine activation failed",30:"ime not available",24:"invalid cookie domain",29:"invalid element coordinates",12:"invalid element state",32:"invalid selector",51:"invalid selector",52:"invalid selector",17:"javascript error",405:"unsupported operation",34:"move target out of bounds",27:"no such alert",7:"no such element",8:"no such frame",23:"no such window",28:"script timeout",33:"session not created",10:"stale element reference", +0:"success",21:"timeout",25:"unable to set cookie",26:"unexpected alert open"};z[13]=ma;z[9]="unknown command";y.prototype.toString=function(){return this.name+": "+this.message};var r,na="",oa=/rv\:([^\);]+)(\)|;)/.exec(k.navigator?k.navigator.userAgent:null);r=na=oa?oa[1]:"";var A={};var B;A["1.9.1"]||(A["1.9.1"]=0<=q("1.9.1"));function C(a,b){this.x=void 0!==a?a:0;this.y=void 0!==b?b:0}C.prototype.toString=function(){return"("+this.x+", "+this.y+")"};C.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};C.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};C.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function D(a,b){this.width=a;this.height=b}D.prototype.toString=function(){return"("+this.width+" x "+this.height+")"};D.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};D.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};D.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var pa=3;function E(a,b){if(a.contains&&1==b.nodeType)return a==b||a.contains(b);if("undefined"!=typeof a.compareDocumentPosition)return a==b||Boolean(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a} +function qa(a,b){if(a==b)return 0;if(a.compareDocumentPosition)return a.compareDocumentPosition(b)&2?1:-1;if("sourceIndex"in a||a.parentNode&&"sourceIndex"in a.parentNode){var c=1==a.nodeType,d=1==b.nodeType;if(c&&d)return a.sourceIndex-b.sourceIndex;var e=a.parentNode,f=b.parentNode;return e==f?ra(a,b):!c&&E(e,b)?-1*sa(a,b):!d&&E(f,a)?sa(b,a):(c?a.sourceIndex:e.sourceIndex)-(d?b.sourceIndex:f.sourceIndex)}d=F(a);c=d.createRange();c.selectNode(a);c.collapse(!0);d=d.createRange();d.selectNode(b);d.collapse(!0); +return c.compareBoundaryPoints(k.Range.START_TO_END,d)}function sa(a,b){var c=a.parentNode;if(c==b)return-1;for(var d=b;d.parentNode!=c;)d=d.parentNode;return ra(d,a)}function ra(a,b){for(var c=b;c=c.previousSibling;)if(c==a)return-1;return 1}function F(a){return 9==a.nodeType?a:a.ownerDocument||a.document}function ta(a,b){a=a.parentNode;for(var c=0;a;){if(b(a))return a;a=a.parentNode;c++}return null}function G(a){this.p=a||k.document||document} +function ua(a){var b=a.p;a="CSS1Compat"==b.compatMode?b.documentElement:b.body;b=b.parentWindow||b.defaultView;return new C(b.pageXOffset||a.scrollLeft,b.pageYOffset||a.scrollTop)}G.prototype.contains=E;function H(a){var b=null,c=a.nodeType;1==c&&(b=a.textContent,b=void 0==b||null==b?a.innerText:b,b=void 0==b||null==b?"":b);if("string"!=typeof b)if(9==c||1==c){a=9==c?a.documentElement:a.firstChild;for(var c=0,d=[],b="";a;){do 1!=a.nodeType&&(b+=a.nodeValue),d[c++]=a;while(a=a.firstChild);for(;c&&!(a=d[--c].nextSibling););}}else b=a.nodeValue;return""+b} +function I(a,b,c){if(null===b)return!0;try{if(!a.getAttribute)return!1}catch(d){return!1}return null==c?!!a.getAttribute(b):a.getAttribute(b,2)==c}function J(a,b,c,d,e){return va.call(null,a,b,n(c)?c:null,n(d)?d:null,e||new K)} +function va(a,b,c,d,e){b.getElementsByName&&d&&"name"==c?(b=b.getElementsByName(d),t(b,function (b){a.matches(b)&&e.add(b)})):b.getElementsByClassName&&d&&"class"==c?(b=b.getElementsByClassName(d),t(b,function (b){b.className==d&&a.matches(b)&&e.add(b)})):b.getElementsByTagName&&(b=b.getElementsByTagName(a.getName()),t(b,function (a){I(a,c,d)&&e.add(a)}));return e}function wa(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)I(b,c,d)&&a.matches(b)&&e.add(b);return e};function K(){this.d=this.c=null;this.g=0}function xa(a){this.m=a;this.next=this.i=null}K.prototype.unshift=function (a){a=new xa(a);a.next=this.c;this.d?this.c.i=a:this.c=this.d=a;this.c=a;this.g++};K.prototype.add=function (a){a=new xa(a);a.i=this.d;this.c?this.d.next=a:this.c=this.d=a;this.d=a;this.g++};function ya(a){return(a=a.c)?a.m:null}function L(a){return new za(a,!1)}function za(a,b){this.F=a;this.j=(this.n=b)?a.d:a.c;this.r=null} +za.prototype.next=function(){var a=this.j;if(null==a)return null;var b=this.r=a;this.j=this.n?a.i:a.next;return b.m};function M(a,b,c,d,e){b=b.evaluate(d);c=c.evaluate(d);var f;if(b instanceof K&&c instanceof K){e=L(b);for(d=e.next();d;d=e.next())for(b=L(c),f=b.next();f;f=b.next())if(a(H(d),H(f)))return!0;return!1}if(b instanceof K||c instanceof K){b instanceof K?e=b:(e=c,c=b);e=L(e);b=typeof c;for(d=e.next();d;d=e.next()){switch(b){case "number":d=+H(d);break;case "boolean":d=!!H(d);break;case "string":d=H(d);break;default:throw Error("Illegal primitive type for comparison.");}if(a(d,c))return!0}return!1}return e? +"boolean"==typeof b||"boolean"==typeof c?a(!!b,!!c):"number"==typeof b||"number"==typeof c?a(+b,+c):a(b,c):a(+b,+c)}function Aa(a,b,c,d){this.s=a;this.H=b;this.o=c;this.q=d}Aa.prototype.toString=function(){return this.s};var Ba={};function N(a,b,c,d){if(a in Ba)throw Error("Binary operator already created: "+a);a=new Aa(a,b,c,d);Ba[a.toString()]=a}N("div",6,1,function (a,b,c){return a.b(c)/b.b(c)});N("mod",6,1,function (a,b,c){return a.b(c)%b.b(c)});N("*",6,1,function (a,b,c){return a.b(c)*b.b(c)}); +N("+",5,1,function (a,b,c){return a.b(c)+b.b(c)});N("-",5,1,function (a,b,c){return a.b(c)-b.b(c)});N("<",4,2,function (a,b,c){return M(function (a,b){return a",4,2,function (a,b,c){return M(function (a,b){return a>b},a,b,c)});N("<=",4,2,function (a,b,c){return M(function (a,b){return a<=b},a,b,c)});N(">=",4,2,function (a,b,c){return M(function (a,b){return a>=b},a,b,c)});N("=",3,2,function (a,b,c){return M(function (a,b){return a==b},a,b,c,!0)}); +N("!=",3,2,function (a,b,c){return M(function (a,b){return a!=b},a,b,c,!0)});N("and",2,2,function (a,b,c){return a.f(c)&&b.f(c)});N("or",1,2,function (a,b,c){return a.f(c)||b.f(c)});function Ca(a,b,c,d,e,f,g,w,p){this.h=a;this.o=b;this.D=c;this.C=d;this.B=e;this.q=f;this.A=g;this.w=void 0!==w?w:g;this.G=!!p}Ca.prototype.toString=function(){return this.h};var Da={};function O(a,b,c,d,e,f,g,w){if(a in Da)throw Error("Function already created: "+a+".");Da[a]=new Ca(a,b,c,d,!1,e,f,g,w)}O("boolean",2,!1,!1,function (a,b){return b.f(a)},1);O("ceiling",1,!1,!1,function (a,b){return Math.ceil(b.b(a))},1); +O("concat",3,!1,!1,function (a,b){var c=ea(arguments,1);return ba(c,function (b,c){return b+c.a(a)})},2,null);O("contains",2,!1,!1,function (a,b,c){b=b.a(a);a=c.a(a);return-1!=b.indexOf(a)},2);O("count",1,!1,!1,function (a,b){return b.evaluate(a).g},1,1,!0);O("false",2,!1,!1,h(!1),0);O("floor",1,!1,!1,function (a,b){return Math.floor(b.b(a))},1); +O("id",4,!1,!1,function (a,b){var c=a.e(),d=9==c.nodeType?c:c.ownerDocument,c=b.a(a).split(/\s+/),e=[];t(c,function (a){(a=d.getElementById(a))&&!da(e,a)&&e.push(a)});e.sort(qa);var f=new K;t(e,function (a){f.add(a)});return f},1);O("lang",2,!1,!1,h(!1),1);O("last",1,!0,!1,function (a){if(1!=arguments.length)throw Error("Function last expects ()");return a.u()},0);O("local-name",3,!1,!0,function (a,b){var c=b?ya(b.evaluate(a)):a.e();return c?c.nodeName.toLowerCase():""},0,1,!0); +O("name",3,!1,!0,function (a,b){var c=b?ya(b.evaluate(a)):a.e();return c?c.nodeName.toLowerCase():""},0,1,!0);O("namespace-uri",3,!0,!1,h(""),0,1,!0);O("normalize-space",3,!1,!0,function (a,b){return(b?b.a(a):H(a.e())).replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"")},0,1);O("not",2,!1,!1,function (a,b){return!b.f(a)},1);O("number",1,!1,!0,function (a,b){return b?b.b(a):+H(a.e())},0,1);O("position",1,!0,!1,function (a){return a.v()},0);O("round",1,!1,!1,function (a,b){return Math.round(b.b(a))},1); +O("starts-with",2,!1,!1,function (a,b,c){b=b.a(a);a=c.a(a);return 0==b.lastIndexOf(a,0)},2);O("string",3,!1,!0,function (a,b){return b?b.a(a):H(a.e())},0,1);O("string-length",1,!1,!0,function (a,b){return(b?b.a(a):H(a.e())).length},0,1); +O("substring",3,!1,!1,function (a,b,c,d){c=c.b(a);if(isNaN(c)||Infinity==c||-Infinity==c)return"";d=d?d.b(a):Infinity;if(isNaN(d)||-Infinity===d)return"";c=Math.round(c)-1;var e=Math.max(c,0);a=b.a(a);if(Infinity==d)return a.substring(e);b=Math.round(d);return a.substring(e,c+b)},2,3);O("substring-after",3,!1,!1,function (a,b,c){b=b.a(a);a=c.a(a);c=b.indexOf(a);return-1==c?"":b.substring(c+a.length)},2); +O("substring-before",3,!1,!1,function (a,b,c){b=b.a(a);a=c.a(a);a=b.indexOf(a);return-1==a?"":b.substring(0,a)},2);O("sum",1,!1,!1,function (a,b){for(var c=L(b.evaluate(a)),d=0,e=c.next();e;e=c.next())d+=+H(e);return d},1,1,!0);O("translate",3,!1,!1,function (a,b,c,d){b=b.a(a);c=c.a(a);var e=d.a(a);a=[];for(d=0;d=a.left+a.width&&this.top<=a.top&&this.top+this.height>=a.top+a.height:a.x>=this.left&&a.x<=this.left+this.width&&a.y>=this.top&&a.y<=this.top+this.height}; +Q.prototype.ceil=function(){this.left=Math.ceil(this.left);this.top=Math.ceil(this.top);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};Q.prototype.floor=function(){this.left=Math.floor(this.left);this.top=Math.floor(this.top);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this}; +Q.prototype.round=function(){this.left=Math.round(this.left);this.top=Math.round(this.top);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function Ia(a,b){var c=F(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,null))?c[b]||c.getPropertyValue(b)||"":""}function R(a,b){return Ia(a,b)||(a.currentStyle?a.currentStyle[b]:null)||a.style&&a.style[b]}function Ja(a){var b;try{b=a.getBoundingClientRect()}catch(c){return{left:0,top:0,right:0,bottom:0}}return b} +function Ka(a){var b=F(a),c=R(a,"position"),d="fixed"==c||"absolute"==c;for(a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=R(a,"position"),d=d&&"static"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||"fixed"==c||"absolute"==c||"relative"==c))return a;return null} +function La(a){if(1==a.nodeType){var b;if(a.getBoundingClientRect)b=Ja(a),b=new C(b.left,b.top);else{b=ua(a?new G(F(a)):B||(B=new G));var c,d=F(a),e=R(a,"position"),f=d.getBoxObjectFor&&!a.getBoundingClientRect&&"absolute"==e&&(c=d.getBoxObjectFor(a))&&(0>c.screenX||0>c.screenY),e=new C(0,0),g=(d?F(d):document).documentElement;if(a!=g)if(a.getBoundingClientRect)c=Ja(a),d=ua(d?new G(F(d)):B||(B=new G)),e.x=c.left+d.x,e.y=c.top+d.y;else if(d.getBoxObjectFor&&!f)c=d.getBoxObjectFor(a),d=d.getBoxObjectFor(g), +e.x=c.screenX-d.screenX,e.y=c.screenY-d.screenY;else{c=a;do e.x+=c.offsetLeft,e.y+=c.offsetTop,c!=a&&(e.x+=c.clientLeft||0,e.y+=c.clientTop||0),c=c.offsetParent;while(c&&c!=a);for(c=a;(c=Ka(c))&&c!=d.body&&c!=g;)e.x-=c.scrollLeft,e.y-=c.scrollTop}b=new C(e.x-b.x,e.y-b.y)}A[12]||(A[12]=0<=q(12))?a=b:((c=R(a,"-moz-transform"))||(c=R(a,"transform")),a=c?(a=c.match(Ma))?new C(parseFloat(a[1]),parseFloat(a[2])):new C(0,0):new C(0,0),a=new C(b.x+a.x,b.y+a.y));return a}b="function"==m(a.k);c=a;a.targetTouches? +c=a.targetTouches[0]:b&&a.k().targetTouches&&(c=a.k().targetTouches[0]);return new C(c.clientX,c.clientY)}var Ma=/matrix\([0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, ([0-9\.\-]+)p?x?, ([0-9\.\-]+)p?x?\)/;function S(a,b){return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}function T(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return S(a)?a:null} +function U(a,b){var c=aa(b);if("float"==c||"cssFloat"==c||"styleFloat"==c)c="cssFloat";c=Ia(a,c)||Na(a,c);if(null===c)c=null;else if(da(fa,b)&&(x.test("#"==c.charAt(0)?c:"#"+c)||la(c).length||u&&u[c.toLowerCase()]||ja(c).length)){var d=ja(c);if(!d.length){a:if(d=la(c),!d.length){d=(d=u[c.toLowerCase()])?d:"#"==c.charAt(0)?c:"#"+c;if(x.test(d)&&(d=ha(d),d=ha(d),d=[parseInt(d.substr(1,2),16),parseInt(d.substr(3,2),16),parseInt(d.substr(5,2),16)],d.length))break a;d=[]}3==d.length&&d.push(1)}c=4!=d.length? +c:"rgba("+d.join(", ")+")"}return c}function Na(a,b){var c=a.currentStyle||a.style,d=c[b];void 0===d&&"function"==m(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?void 0!==d?d:null:(c=T(a))?Na(c,b):null} +function V(a,b){function c(a){if("none"==U(a,"display"))return!1;a=T(a);return!a||c(a)}function d(a){if(a.hasAttribute){if(a.hasAttribute("hidden"))return!1}else return!0;a=T(a);return!a||d(a)}function e(a){var b=W(a);return 0=p.left+p.width,p=d.top>=p.top+p.height;if(l&&"hidden"==e.x||p&&"hidden"==e.y)return X;if(l&&"visible"!=e.x||p&&"visible"!=e.y)return Qa(a)==X?X:"scroll"}return"none"} +function W(a){var b=Oa(a);if(b)return b.rect;if("function"==m(a.getBBox))try{var c=a.getBBox();return new Q(c.x,c.y,c.width,c.height)}catch(d){if("NS_ERROR_FAILURE"===d.name||-1!=d.message.indexOf("Component returned failure code: 0x80004005"))return new Q(0,0,0,0);throw d;}else{if(S(a,"HTML"))return a=((F(a)?F(a).parentWindow||F(a).defaultView:window)||window).document,a="CSS1Compat"==a.compatMode?a.documentElement:a.body,a=new D(a.clientWidth,a.clientHeight),new Q(0,0,a.width,a.height);b=La(a); +return new Q(b.x,b.y,a.offsetWidth,a.offsetHeight)}} +function Oa(a){var b=S(a,"MAP");if(!b&&!S(a,"AREA"))return null;var c=b?a:S(a.parentNode,"MAP")?a.parentNode:null,d=null,e=null;if(c&&c.name&&(d=Ha('/descendant::*[@usemap = "#'+c.name+'"]',F(c)))&&(e=W(d),!b&&"default"!=a.shape.toLowerCase())){var f=Ra(a);a=Math.min(Math.max(f.left,0),e.width);b=Math.min(Math.max(f.top,0),e.height);c=Math.min(f.width,e.width-a);f=Math.min(f.height,e.height-b);e=new Q(a+e.left,b+e.top,c,f)}return{l:d,rect:e||new Q(0,0,0,0)}} +function Ra(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4==a.length){var b=a[0],c=a[1];return new Q(b,c,a[2]-b,a[3]-c)}if("circle"==b&&3==a.length)return b=a[2],new Q(a[0]-b,a[1]-b,2*b,2*b);if("poly"==b&&2 for the specified tab. + * + * @param {} tab + * The tab whose browser needs to be returned. + * + * @return {} + * The linked browser for the tab or null if no browser can be found. + */ +browser.getBrowserForTab = function (tab) { + if ("browser" in tab) { + // Fennec + return tab.browser; + + } else if ("linkedBrowser" in tab) { + // Firefox + return tab.linkedBrowser; + + } else { + return null; + } +}; + +/** + * Return the tab browser for the specified chrome window. + * + * @param {nsIDOMWindow} win + * The window whose tabbrowser needs to be accessed. + * + * @return {} + * Tab browser or null if it's not a browser window. + */ +browser.getTabBrowser = function (win) { + if ("BrowserApp" in win) { + // Fennec + return win.BrowserApp; + + } else if ("gBrowser" in win) { + // Firefox + return win.gBrowser; + + } else { + return null; + } +}; + +/** + * Creates a browsing context wrapper. + * + * Browsing contexts handle interactions with the browser, according to + * the current environment (desktop, B2G, Fennec, &c). + * + * @param {nsIDOMWindow} win + * The window whose browser needs to be accessed. + * @param {GeckoDriver} driver + * Reference to the driver the browser is attached to. + */ +browser.Context = class { + + /** + * @param {} win + * Frame that is expected to contain the view of the web document. + * @param {GeckoDriver} driver + * Reference to driver instance. + */ + constructor(win, driver) { + this.window = win; + this.driver = driver; + + // In Firefox this is (not !) + // and BrowserApp in Fennec + this.tabBrowser = browser.getTabBrowser(win); + + this.knownFrames = []; + + // Used in B2G to identify the homescreen content page + this.mainContentId = null; + + // Used to set curFrameId upon new session + this.newSession = true; + + this.seenEls = new element.Store(); + + // A reference to the tab corresponding to the current window handle, if any. + // Specifically, this.tab refers to the last tab that Marionette switched + // to in this browser window. Note that this may not equal the currently + // selected tab. For example, if Marionette switches to tab A, and then + // clicks on a button that opens a new tab B in the same browser window, + // this.tab will still point to tab A, despite tab B being the currently + // selected tab. + this.tab = null; + this.pendingCommands = []; + + // We should have one frame.Manager per browser.Context so that we + // can handle modals in each . + this.frameManager = new frame.Manager(driver); + this.frameRegsPending = 0; + + // register all message listeners + this.frameManager.addMessageManagerListeners(driver.mm); + this.getIdForBrowser = driver.getIdForBrowser.bind(driver); + this.updateIdForBrowser = driver.updateIdForBrowser.bind(driver); + this._curFrameId = null; + this._browserWasRemote = null; + this._hasRemotenessChange = false; + } + + /** + * The current frame ID is managed per browser element on desktop in + * case the ID needs to be refreshed. The currently selected window is + * identified by a tab. + */ + get curFrameId() { + let rv = null; + if (this.driver.appName == "B2G") { + rv = this._curFrameId; + } else if (this.tab) { + rv = this.getIdForBrowser(browser.getBrowserForTab(this.tab)); + } + return rv; + } + + set curFrameId(id) { + if (this.driver.appName != "Firefox") { + this._curFrameId = id; + } + } + + /** + * Retrieves the current tabmodal UI object. According to the browser + * associated with the currently selected tab. + */ + getTabModalUI() { + let br = browser.getBrowserForTab(this.tab); + if (!br.hasAttribute("tabmodalPromptShowing")) { + return null; + } + + // The modal is a direct sibling of the browser element. + // See tabbrowser.xml's getTabModalPromptBox. + let modals = br.parentNode.getElementsByTagNameNS( + XUL_NS, "tabmodalprompt"); + return modals[0].ui; + } + + /** + * Close the current window. + * + * @return {Promise} + * A promise which is resolved when the current window has been closed. + */ + closeWindow() { + return new Promise(resolve => { + this.window.addEventListener("unload", ev => { + resolve(); + }, {once: true}); + this.window.close(); + }); + } + + /** Called when we start a session with this browser. */ + startSession(newSession, win, callback) { + callback(win, newSession); + } + + /** + * Close the current tab. + * + * @return {Promise} + * A promise which is resolved when the current tab has been closed. + * + * @throws UnsupportedOperationError + * If tab handling for the current application isn't supported. + */ + closeTab() { + // If the current window is not a browser then close it directly. Do the + // same if only one remaining tab is open, or no tab selected at all. + if (!this.tabBrowser || this.tabBrowser.tabs.length === 1 || !this.tab) { + return this.closeWindow(); + } + + return new Promise((resolve, reject) => { + if (this.tabBrowser.closeTab) { + // Fennec + this.tabBrowser.deck.addEventListener("TabClose", ev => { + resolve(); + }, {once: true}); + this.tabBrowser.closeTab(this.tab); + + } else if (this.tabBrowser.removeTab) { + // Firefox + this.tab.addEventListener("TabClose", ev => { + resolve(); + }, {once: true}); + this.tabBrowser.removeTab(this.tab); + + } else { + reject(new UnsupportedOperationError( + `closeTab() not supported in ${this.driver.appName}`)); + } + }); + } + + /** + * Opens a tab with given URI. + * + * @param {string} uri + * URI to open. + */ + addTab(uri) { + return this.tabBrowser.addTab(uri, true); + } + + /** + * Set the current tab and update remoteness tracking if a tabbrowser is available. + * + * @param {number=} index + * Tab index to switch to. If the parameter is undefined, + * the currently selected tab will be used. + * @param {nsIDOMWindow=} win + * Switch to this window before selecting the tab. + * @param {boolean=} focus + * A boolean value which determins whether to focus + * the window. Defaults to true. + * + * @throws UnsupportedOperationError + * If tab handling for the current application isn't supported. + */ + switchToTab(index, win, focus = true) { + if (win) { + this.window = win; + this.tabBrowser = browser.getTabBrowser(win); + } + + if (!this.tabBrowser) { + return; + } + + if (typeof index == "undefined") { + this.tab = this.tabBrowser.selectedTab; + } else { + this.tab = this.tabBrowser.tabs[index]; + + if (focus) { + if (this.tabBrowser.selectTab) { + // Fennec + this.tabBrowser.selectTab(this.tab); + + } else if ("selectedTab" in this.tabBrowser) { + // Firefox + this.tabBrowser.selectedTab = this.tab; + + } else { + throw new UnsupportedOperationError("switchToTab() not supported"); + } + } + } + + if (this.driver.appName == "Firefox") { + this._browserWasRemote = browser.getBrowserForTab(this.tab).isRemoteBrowser; + this._hasRemotenessChange = false; + } + } + + /** + * Registers a new frame, and sets its current frame id to this frame + * if it is not already assigned, and if a) we already have a session + * or b) we're starting a new session and it is the right start frame. + * + * @param {string} uid + * Frame uid for use by Marionette. + * @param the XUL that was the target of the originating message. + */ + register(uid, target) { + let remotenessChange = this.hasRemotenessChange(); + if (this.curFrameId === null || remotenessChange) { + if (this.tabBrowser) { + // If we're setting up a new session on Firefox, we only process the + // registration for this frame if it belongs to the current tab. + if (!this.tab) { + this.switchToTab(); + } + + if (target == browser.getBrowserForTab(this.tab)) { + this.updateIdForBrowser(browser.getBrowserForTab(this.tab), uid); + this.mainContentId = uid; + } + } else { + this._curFrameId = uid; + this.mainContentId = uid; + } + } + + // used to delete sessions + this.knownFrames.push(uid); + return remotenessChange; + } + + /** + * When navigating between pages results in changing a browser's + * process, we need to take measures not to lose contact with a listener + * script. This function does the necessary bookkeeping. + */ + hasRemotenessChange() { + // None of these checks are relevant on b2g or if we don't have a tab yet, + // and may not apply on Fennec. + if (this.driver.appName != "Firefox" || + this.tab === null || + browser.getBrowserForTab(this.tab) === null) { + return false; + } + + if (this._hasRemotenessChange) { + return true; + } + + let currentIsRemote = browser.getBrowserForTab(this.tab).isRemoteBrowser; + this._hasRemotenessChange = this._browserWasRemote !== currentIsRemote; + this._browserWasRemote = currentIsRemote; + return this._hasRemotenessChange; + } + + /** + * Flushes any pending commands queued when a remoteness change is being + * processed and mark this remotenessUpdate as complete. + */ + flushPendingCommands() { + if (!this._hasRemotenessChange) { + return; + } + + this._hasRemotenessChange = false; + this.pendingCommands.forEach(cb => cb()); + this.pendingCommands = []; + } + + /** + * This function intercepts commands interacting with content and queues + * or executes them as needed. + * + * No commands interacting with content are safe to process until + * the new listener script is loaded and registers itself. + * This occurs when a command whose effect is asynchronous (such + * as goBack) results in a remoteness change and new commands + * are subsequently posted to the server. + */ + executeWhenReady(cb) { + if (this.hasRemotenessChange()) { + this.pendingCommands.push(cb); + } else { + cb(); + } + } + + /** + * Returns the position of the OS window. + */ + get position() { + return { + x: this.window.screenX, + y: this.window.screenY, + }; + } + +}; + +/** + * The window storage is used to save outer window IDs mapped to weak + * references of Window objects. + * + * Usage: + * + * let wins = new browser.Windows(); + * wins.set(browser.outerWindowID, window); + * + * ... + * + * let win = wins.get(browser.outerWindowID); + * + */ +browser.Windows = class extends Map { + + /** + * Save a weak reference to the Window object. + * + * @param {string} id + * Outer window ID. + * @param {Window} win + * Window object to save. + * + * @return {browser.Windows} + * Instance of self. + */ + set(id, win) { + let wref = Cu.getWeakReference(win); + super.set(id, wref); + return this; + } + + /** + * Get the window object stored by provided |id|. + * + * @param {string} id + * Outer window ID. + * + * @return {Window} + * Saved window object, or |undefined| if no window is stored by + * provided |id|. + */ + get(id) { + let wref = super.get(id); + if (wref) { + return wref.get(); + } + } + +}; diff --git a/testing/marionette/capture.js b/testing/marionette/capture.js new file mode 100644 index 000000000..274d20567 --- /dev/null +++ b/testing/marionette/capture.js @@ -0,0 +1,193 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {utils: Cu} = Components; +Cu.importGlobalProperties(["crypto"]); + +this.EXPORTED_SYMBOLS = ["capture"]; + +const CONTEXT_2D = "2d"; +const BG_COLOUR = "rgb(255,255,255)"; +const PNG_MIME = "image/png"; +const XHTML_NS = "http://www.w3.org/1999/xhtml"; + +/** Provides primitives to capture screenshots. */ +this.capture = {}; + +capture.Format = { + Base64: 0, + Hash: 1, +}; + +/** + * Take a screenshot of a single element. + * + * @param {Node} node + * The node to take a screenshot of. + * @param {Array.=} highlights + * Optional array of nodes, around which a border will be marked to + * highlight them in the screenshot. + * + * @return {HTMLCanvasElement} + * The canvas element where the element has been painted on. + */ +capture.element = function (node, highlights = []) { + let win = node.ownerDocument.defaultView; + let rect = node.getBoundingClientRect(); + + return capture.canvas( + win, + rect.left, + rect.top, + rect.width, + rect.height, + highlights); +}; + +/** + * Take a screenshot of the window's viewport by taking into account + * the current offsets. + * + * @param {DOMWindow} win + * The DOM window providing the document element to capture, + * and the offsets for the viewport. + * @param {Array.=} highlights + * Optional array of nodes, around which a border will be marked to + * highlight them in the screenshot. + * + * @return {HTMLCanvasElement} + * The canvas element where the viewport has been painted on. + */ +capture.viewport = function (win, highlights = []) { + let rootNode = win.document.documentElement; + + return capture.canvas( + win, + win.pageXOffset, + win.pageYOffset, + rootNode.clientWidth, + rootNode.clientHeight, + highlights); +}; + +/** + * Low-level interface to draw a rectangle off the framebuffer. + * + * @param {DOMWindow} win + * The DOM window used for the framebuffer, and providing the interfaces + * for creating an HTMLCanvasElement. + * @param {number} left + * The left, X axis offset of the rectangle. + * @param {number} top + * The top, Y axis offset of the rectangle. + * @param {number} width + * The width dimension of the rectangle to paint. + * @param {number} height + * The height dimension of the rectangle to paint. + * @param {Array.=} highlights + * Optional array of nodes, around which a border will be marked to + * highlight them in the screenshot. + * + * @return {HTMLCanvasElement} + * The canvas on which the selection from the window's framebuffer + * has been painted on. + */ +capture.canvas = function (win, left, top, width, height, highlights = []) { + let scale = win.devicePixelRatio; + + let canvas = win.document.createElementNS(XHTML_NS, "canvas"); + canvas.width = width * scale; + canvas.height = height * scale; + + let ctx = canvas.getContext(CONTEXT_2D); + let flags = ctx.DRAWWINDOW_DRAW_CARET; + // Disabled in bug 1243415 for webplatform-test failures due to out of view elements. + // Needs https://github.com/w3c/web-platform-tests/issues/4383 fixed. + // ctx.DRAWWINDOW_DRAW_VIEW; + // Bug 1009762 - Crash in [@ mozilla::gl::ReadPixelsIntoDataSurface] + // ctx.DRAWWINDOW_USE_WIDGET_LAYERS; + + ctx.scale(scale, scale); + ctx.drawWindow(win, left, top, width, height, BG_COLOUR, flags); + ctx = capture.highlight_(ctx, highlights, top, left); + + return canvas; +}; + +capture.highlight_ = function (context, highlights, top = 0, left = 0) { + if (!highlights) { + return; + } + + context.lineWidth = "2"; + context.strokeStyle = "red"; + context.save(); + + for (let el of highlights) { + let rect = el.getBoundingClientRect(); + let oy = -top; + let ox = -left; + + context.strokeRect( + rect.left + ox, + rect.top + oy, + rect.width, + rect.height); + } + + return context; +}; + +/** + * Encode the contents of an HTMLCanvasElement to a Base64 encoded string. + * + * @param {HTMLCanvasElement} canvas + * The canvas to encode. + * + * @return {string} + * A Base64 encoded string. + */ +capture.toBase64 = function (canvas) { + let u = canvas.toDataURL(PNG_MIME); + return u.substring(u.indexOf(",") + 1); +}; + +/** +* Hash the contents of an HTMLCanvasElement to a SHA-256 hex digest. +* +* @param {HTMLCanvasElement} canvas +* The canvas to encode. +* +* @return {string} +* A hex digest of the SHA-256 hash of the base64 encoded string. +*/ +capture.toHash = function (canvas) { + let u = capture.toBase64(canvas); + let buffer = new TextEncoder("utf-8").encode(u); + return crypto.subtle.digest("SHA-256", buffer).then(hash => hex(hash)); +}; + +/** +* Convert buffer into to hex. +* +* @param {ArrayBuffer} buffer +* The buffer containing the data to convert to hex. +* +* @return {string} +* A hex digest of the input buffer. +*/ +function hex(buffer) { + let hexCodes = []; + let view = new DataView(buffer); + for (let i = 0; i < view.byteLength; i += 4) { + let value = view.getUint32(i); + let stringValue = value.toString(16); + let padding = '00000000'; + let paddedValue = (padding + stringValue).slice(-padding.length); + hexCodes.push(paddedValue); + } + return hexCodes.join(""); +}; \ No newline at end of file diff --git a/testing/marionette/cert.js b/testing/marionette/cert.js new file mode 100644 index 000000000..c0b24d23b --- /dev/null +++ b/testing/marionette/cert.js @@ -0,0 +1,140 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +Cu.import("resource://gre/modules/Preferences.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +this.EXPORTED_SYMBOLS = ["cert"]; + +const registrar = + Components.manager.QueryInterface(Ci.nsIComponentRegistrar); +const sss = Cc["@mozilla.org/ssservice;1"] + .getService(Ci.nsISiteSecurityService); + +const CONTRACT_ID = "@mozilla.org/security/certoverride;1"; +const CERT_PINNING_ENFORCEMENT_PREF = + "security.cert_pinning.enforcement_level"; +const HSTS_PRELOAD_LIST_PREF = + "network.stricttransportsecurity.preloadlist"; + +/** TLS certificate service override management for Marionette. */ +this.cert = { + Error: { + Untrusted: 1, + Mismatch: 2, + Time: 4, + }, + + currentOverride: null, +}; + +/** + * Installs a TLS certificate service override. + * + * The provided |service| must implement the |register| and |unregister| + * functions that causes a new |nsICertOverrideService| interface + * implementation to be registered with the |nsIComponentRegistrar|. + * + * After |service| is registered and made the |cert.currentOverride|, + * |nsICertOverrideService| is reinitialised to cause all Gecko components + * to pick up the new service. + * + * If an override is already installed, i.e. when |cert.currentOverride| + * is not null, this functions acts as a NOOP. + * + * @param {cert.Override} service + * Service generator that registers and unregisters the XPCOM service. + * + * @throws {Components.Exception} + * If unable to register or initialise |service|. + */ +cert.installOverride = function (service) { + if (this.currentOverride) { + return; + } + + service.register(); + cert.currentOverride = service; +}; + +/** + * Uninstall a TLS certificate service override. + * + * After the service has been unregistered, |cert.currentOverride| + * is reset to null. + * + * If there no current override installed, i.e. if |cert.currentOverride| + * is null, this function acts as a NOOP. + */ +cert.uninstallOverride = function() { + if (!cert.currentOverride) { + return; + } + cert.currentOverride.unregister(); + this.currentOverride = null; +}; + +/** + * Certificate override service that acts in an all-inclusive manner + * on TLS certificates. + * + * When an invalid certificate is encountered, it is overriden + * with the |matching| bit level, which is typically a combination of + * |cert.Error.Untrusted|, |cert.Error.Mismatch|, and |cert.Error.Time|. + * + * @type cert.Override + * + * @throws {Components.Exception} + * If there are any problems registering the service. + */ +cert.InsecureSweepingOverride = function() { + const CID = Components.ID("{4b67cce0-a51c-11e6-9598-0800200c9a66}"); + const DESC = "All-encompassing cert service that matches on a bitflag"; + + // This needs to be an old-style class with a function constructor + // and prototype assignment because... XPCOM. Any attempt at + // modernisation will be met with cryptic error messages which will + // make your life miserable. + let service = function() {}; + service.prototype = { + hasMatchingOverride: function ( + aHostName, aPort, aCert, aOverrideBits, aIsTemporary) { + aIsTemporary.value = false; + aOverrideBits.value = + cert.Error.Untrusted | cert.Error.Mismatch | cert.Error.Time; + + return true; + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsICertOverrideService]), + }; + let factory = XPCOMUtils.generateSingletonFactory(service); + + return { + register: function() { + // make it possible to register certificate overrides for domains + // that use HSTS or HPKP + Preferences.set(HSTS_PRELOAD_LIST_PREF, false); + Preferences.set(CERT_PINNING_ENFORCEMENT_PREF, 0); + + registrar.registerFactory(CID, DESC, CONTRACT_ID, factory); + }, + + unregister: function() { + registrar.unregisterFactory(CID, factory); + + Preferences.reset(HSTS_PRELOAD_LIST_PREF); + Preferences.reset(CERT_PINNING_ENFORCEMENT_PREF); + + // clear collected HSTS and HPKP state + // through the site security service + sss.clearAll(); + sss.clearPreloads(); + }, + }; +}; diff --git a/testing/marionette/chrome/test.xul b/testing/marionette/chrome/test.xul new file mode 100644 index 000000000..2baa28e5f --- /dev/null +++ b/testing/marionette/chrome/test.xul @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + +I'm a normal link +I go to an anchor +I open a window with javascript +Click me + +I'm a green link +

looooooooooong short looooooooooong +

+ +
+ click to add an event listener +
+
+ this will show the button clicked +
+333333 +

I have a span

And another span

+ + diff --git a/testing/marionette/harness/marionette_harness/www/cssTransform.html b/testing/marionette/harness/marionette_harness/www/cssTransform.html new file mode 100644 index 000000000..c3b99648a --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/cssTransform.html @@ -0,0 +1,61 @@ + + +
+You shouldn't see anything other than this sentence on the page +
+
+ I have a hidden child +
+ I am a hidden child +
+
+
+ I have a hidden child +
+ I am a hidden child +
+
+
I am a hidden element
+
I am a hidden element
diff --git a/testing/marionette/harness/marionette_harness/www/cssTransform2.html b/testing/marionette/harness/marionette_harness/www/cssTransform2.html new file mode 100644 index 000000000..602924bfb --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/cssTransform2.html @@ -0,0 +1,20 @@ + + +
+
+
+
+
+
+
I am not a hidden element
diff --git a/testing/marionette/harness/marionette_harness/www/datetimePage.html b/testing/marionette/harness/marionette_harness/www/datetimePage.html new file mode 100644 index 000000000..87a05f6d2 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/datetimePage.html @@ -0,0 +1,15 @@ + + + + + Testing date and time inputs + + +
+ + +
+ + diff --git a/testing/marionette/harness/marionette_harness/www/deletingFrame.html b/testing/marionette/harness/marionette_harness/www/deletingFrame.html new file mode 100644 index 000000000..d891605af --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/deletingFrame.html @@ -0,0 +1,29 @@ + + + + + + + +
+ + +
+
+ +
+ + + diff --git a/testing/marionette/harness/marionette_harness/www/double_click.html b/testing/marionette/harness/marionette_harness/www/double_click.html new file mode 100644 index 000000000..fb3ec217a --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/double_click.html @@ -0,0 +1,18 @@ + + + + + Testing Double Click + +
+

zyxw

+
+ +
+
+ +
+
+ diff --git a/testing/marionette/harness/marionette_harness/www/element_bottom.html b/testing/marionette/harness/marionette_harness/www/element_bottom.html new file mode 100644 index 000000000..470199a07 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/element_bottom.html @@ -0,0 +1,12 @@ + + +
+ diff --git a/testing/marionette/harness/marionette_harness/www/element_left.html b/testing/marionette/harness/marionette_harness/www/element_left.html new file mode 100644 index 000000000..c98b945f9 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/element_left.html @@ -0,0 +1,12 @@ + + +
+ diff --git a/testing/marionette/harness/marionette_harness/www/element_outside_viewport.html b/testing/marionette/harness/marionette_harness/www/element_outside_viewport.html new file mode 100644 index 000000000..69b66b875 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/element_outside_viewport.html @@ -0,0 +1,41 @@ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ diff --git a/testing/marionette/harness/marionette_harness/www/element_right.html b/testing/marionette/harness/marionette_harness/www/element_right.html new file mode 100644 index 000000000..ff8774ab6 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/element_right.html @@ -0,0 +1,12 @@ + + +
+ diff --git a/testing/marionette/harness/marionette_harness/www/element_top.html b/testing/marionette/harness/marionette_harness/www/element_top.html new file mode 100644 index 000000000..b975e34c4 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/element_top.html @@ -0,0 +1,12 @@ + + +
+ diff --git a/testing/marionette/harness/marionette_harness/www/empty.html b/testing/marionette/harness/marionette_harness/www/empty.html new file mode 100644 index 000000000..0a9d08cd6 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/empty.html @@ -0,0 +1,12 @@ + + + + + +Marionette Test + + + + diff --git a/testing/marionette/harness/marionette_harness/www/formPage.html b/testing/marionette/harness/marionette_harness/www/formPage.html new file mode 100644 index 000000000..ee1ff9f2b --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/formPage.html @@ -0,0 +1,116 @@ + + + We Leave From Here + + + + +There should be a form here: + +
+ + +
+ +
+ Here's a checkbox: + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ + Cheese
+ Peas
+ Cheese and peas
+ Not a sausage
+ Not another sausage + + + +

I like cheese

+ + + Cumberland sausage +
+ + + +
+

+ +

+
+ + + diff --git a/testing/marionette/harness/marionette_harness/www/frameset.html b/testing/marionette/harness/marionette_harness/www/frameset.html new file mode 100644 index 000000000..209d705b5 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/frameset.html @@ -0,0 +1,14 @@ + + + Unique title + + + + + + + + + + + \ No newline at end of file diff --git a/testing/marionette/harness/marionette_harness/www/framesetPage2.html b/testing/marionette/harness/marionette_harness/www/framesetPage2.html new file mode 100644 index 000000000..5190ceb6c --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/framesetPage2.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/hidden.html b/testing/marionette/harness/marionette_harness/www/hidden.html new file mode 100644 index 000000000..0e8097e97 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/hidden.html @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/testing/marionette/harness/marionette_harness/www/html5/blue.jpg b/testing/marionette/harness/marionette_harness/www/html5/blue.jpg new file mode 100644 index 000000000..8ea27c42f Binary files /dev/null and b/testing/marionette/harness/marionette_harness/www/html5/blue.jpg differ diff --git a/testing/marionette/harness/marionette_harness/www/html5/boolean_attributes.html b/testing/marionette/harness/marionette_harness/www/html5/boolean_attributes.html new file mode 100644 index 000000000..eb0d458b8 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/html5/boolean_attributes.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/testing/marionette/harness/marionette_harness/www/html5/geolocation.js b/testing/marionette/harness/marionette_harness/www/html5/geolocation.js new file mode 100644 index 000000000..f07af148e --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/html5/geolocation.js @@ -0,0 +1,18 @@ +function success(position) { + var message = document.getElementById("status"); + message.innerHTML =""; + message.innerHTML += "

Longitude: " + position.coords.longitude + "

"; + message.innerHTML += "

Latitude: " + position.coords.latitude + "

"; + message.innerHTML += "

Altitude: " + position.coords.altitude + "

"; +} + +function error(msg) { + var message = document.getElementById("status"); + message.innerHTML = "Failed to get geolocation."; +} + +if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition(success, error); +} else { + error('Geolocation is not supported.'); +} \ No newline at end of file diff --git a/testing/marionette/harness/marionette_harness/www/html5/green.jpg b/testing/marionette/harness/marionette_harness/www/html5/green.jpg new file mode 100644 index 000000000..6a0d3bea4 Binary files /dev/null and b/testing/marionette/harness/marionette_harness/www/html5/green.jpg differ diff --git a/testing/marionette/harness/marionette_harness/www/html5/offline.html b/testing/marionette/harness/marionette_harness/www/html5/offline.html new file mode 100644 index 000000000..c24178b5f --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/html5/offline.html @@ -0,0 +1 @@ +Offline diff --git a/testing/marionette/harness/marionette_harness/www/html5/red.jpg b/testing/marionette/harness/marionette_harness/www/html5/red.jpg new file mode 100644 index 000000000..f296e2719 Binary files /dev/null and b/testing/marionette/harness/marionette_harness/www/html5/red.jpg differ diff --git a/testing/marionette/harness/marionette_harness/www/html5/status.html b/testing/marionette/harness/marionette_harness/www/html5/status.html new file mode 100644 index 000000000..394116a52 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/html5/status.html @@ -0,0 +1 @@ +Online diff --git a/testing/marionette/harness/marionette_harness/www/html5/test.appcache b/testing/marionette/harness/marionette_harness/www/html5/test.appcache new file mode 100644 index 000000000..3bc4e0025 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/html5/test.appcache @@ -0,0 +1,11 @@ +CACHE MANIFEST + +CACHE: +# Additional items to cache. +yellow.jpg +red.jpg +blue.jpg +green.jpg + +FALLBACK: +status.html offline.html diff --git a/testing/marionette/harness/marionette_harness/www/html5/test_html_inputs.html b/testing/marionette/harness/marionette_harness/www/html5/test_html_inputs.html new file mode 100644 index 000000000..96c9b97e3 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/html5/test_html_inputs.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/testing/marionette/harness/marionette_harness/www/html5/yellow.jpg b/testing/marionette/harness/marionette_harness/www/html5/yellow.jpg new file mode 100644 index 000000000..7c609b371 Binary files /dev/null and b/testing/marionette/harness/marionette_harness/www/html5/yellow.jpg differ diff --git a/testing/marionette/harness/marionette_harness/www/html5Page.html b/testing/marionette/harness/marionette_harness/www/html5Page.html new file mode 100644 index 000000000..4197cd122 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/html5Page.html @@ -0,0 +1,45 @@ + + + + + +HTML5 + + + +

Geolocation Test

+
Location unknown
+ + +

Application Cache Test

+
+

Current network status:

+ + + + + +
+ + + diff --git a/testing/marionette/harness/marionette_harness/www/javascriptPage.html b/testing/marionette/harness/marionette_harness/www/javascriptPage.html new file mode 100644 index 000000000..b47c902c5 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/javascriptPage.html @@ -0,0 +1,278 @@ + + + + + Testing Javascript + + + + + +

Type Stuff

+ +
+ +
+ +
  +
+

 

+
+ +
+ +
+
+ Key Up:
+ Key Down:
+ Key Press:
+ Change:
+ + + + + + + + +
+
+ + + +
What's for dinner?
+ +
+

Click for the mouse down event

+

Here's some text

+
+ +
+

Click for the mouse up event

+
+ +
+

Click for the mouse click event

+
+ +
+

Click to show button

+
+ +
+ Clicking this causes a JS exception in the click handler +
+ +
+
+ + + + + + + + + +
+ +
+ +
+

+ + +

+
+
+ + + +
+

Displayed

+ +
+ + + + + + + +
+ + + Check box you can't see + +
+ + +
+ +
+
+ + +
+
+ + +
+

This should be greenish

+
    +
  • So should this
  • +
  • But this is red
  • +
+
+ +Close window + +
+

I should be deleted when you click my containing div

+

Whereas, I should not

+
+ +
+ Click to hide me. +
+ +
+ Click actions delayed by 3000ms: +
+ Click to show black box +
+ +
+
+ +Click me to open a new window + +Mouse over me will throw a JS error + +
+ + Click on me to show the related target + +
+ +
+
+ +
+
+ + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/macbeth.html b/testing/marionette/harness/marionette_harness/www/macbeth.html new file mode 100644 index 000000000..2404f1d72 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/macbeth.html @@ -0,0 +1,5254 @@ + + + + Macbeth: Entire Play + + + + + + + +Quick link to last speech + +

ACT I

+

SCENE I. A desert place.

+

+Thunder and lightning. Enter three Witches +
+ +First Witch +
+When shall we three meet again
+In thunder, lightning, or in rain?
+
+ +Second Witch +
+When the hurlyburly's done,
+When the battle's lost and won.
+
+ +Third Witch +
+That will be ere the set of sun.
+
+ +First Witch +
+Where the place?
+
+ +Second Witch +
+ Upon the heath.
+
+ +Third Witch +
+There to meet with Macbeth.
+
+ +First Witch +
+I come, Graymalkin!
+
+ +Second Witch +
+Paddock calls.
+
+ +Third Witch +
+Anon.
+
+ +ALL +
+Fair is foul, and foul is fair:
+Hover through the fog and filthy air.
+

Exeunt

+
+

SCENE II. A camp near Forres.

+

+Alarum within. Enter DUNCAN, MALCOLM, DONALBAIN, LENNOX, with Attendants, meeting a bleeding Sergeant +
+ +DUNCAN +
+What bloody man is that? He can report,
+As seemeth by his plight, of the revolt
+The newest state.
+
+ +MALCOLM +
+ This is the sergeant
+Who like a good and hardy soldier fought
+'Gainst my captivity. Hail, brave friend!
+Say to the king the knowledge of the broil
+As thou didst leave it.
+
+ +Sergeant +
+Doubtful it stood;
+As two spent swimmers, that do cling together
+And choke their art. The merciless Macdonwald--
+Worthy to be a rebel, for to that
+The multiplying villanies of nature
+Do swarm upon him--from the western isles
+Of kerns and gallowglasses is supplied;
+And fortune, on his damned quarrel smiling,
+Show'd like a rebel's whore: but all's too weak:
+For brave Macbeth--well he deserves that name--
+Disdaining fortune, with his brandish'd steel,
+Which smoked with bloody execution,
+Like valour's minion carved out his passage
+Till he faced the slave;
+Which ne'er shook hands, nor bade farewell to him,
+Till he unseam'd him from the nave to the chaps,
+And fix'd his head upon our battlements.
+
+ +DUNCAN +
+O valiant cousin! worthy gentleman!
+
+ +Sergeant +
+As whence the sun 'gins his reflection
+Shipwrecking storms and direful thunders break,
+So from that spring whence comfort seem'd to come
+Discomfort swells. Mark, king of Scotland, mark:
+No sooner justice had with valour arm'd
+Compell'd these skipping kerns to trust their heels,
+But the Norweyan lord surveying vantage,
+With furbish'd arms and new supplies of men
+Began a fresh assault.
+
+ +DUNCAN +
+Dismay'd not this
+Our captains, Macbeth and Banquo?
+
+ +Sergeant +
+Yes;
+As sparrows eagles, or the hare the lion.
+If I say sooth, I must report they were
+As cannons overcharged with double cracks, so they
+Doubly redoubled strokes upon the foe:
+Except they meant to bathe in reeking wounds,
+Or memorise another Golgotha,
+I cannot tell.
+But I am faint, my gashes cry for help.
+
+ +DUNCAN +
+So well thy words become thee as thy wounds;
+They smack of honour both. Go get him surgeons.
+

Exit Sergeant, attended

+Who comes here?
+

Enter ROSS

+
+ +MALCOLM +
+ The worthy thane of Ross.
+
+ +LENNOX +
+What a haste looks through his eyes! So should he look
+That seems to speak things strange.
+
+ +ROSS +
+God save the king!
+
+ +DUNCAN +
+Whence camest thou, worthy thane?
+
+ +ROSS +
+From Fife, great king;
+Where the Norweyan banners flout the sky
+And fan our people cold. Norway himself,
+With terrible numbers,
+Assisted by that most disloyal traitor
+The thane of Cawdor, began a dismal conflict;
+Till that Bellona's bridegroom, lapp'd in proof,
+Confronted him with self-comparisons,
+Point against point rebellious, arm 'gainst arm.
+Curbing his lavish spirit: and, to conclude,
+The victory fell on us.
+
+ +DUNCAN +
+Great happiness!
+
+ +ROSS +
+That now
+Sweno, the Norways' king, craves composition:
+Nor would we deign him burial of his men
+Till he disbursed at Saint Colme's inch
+Ten thousand dollars to our general use.
+
+ +DUNCAN +
+No more that thane of Cawdor shall deceive
+Our bosom interest: go pronounce his present death,
+And with his former title greet Macbeth.
+
+ +ROSS +
+I'll see it done.
+
+ +DUNCAN +
+What he hath lost noble Macbeth hath won.
+

Exeunt

+
+

SCENE III. A heath near Forres.

+

+Thunder. Enter the three Witches +
+ +First Witch +
+Where hast thou been, sister?
+
+ +Second Witch +
+Killing swine.
+
+ +Third Witch +
+Sister, where thou?
+
+ +First Witch +
+A sailor's wife had chestnuts in her lap,
+And munch'd, and munch'd, and munch'd:--
+'Give me,' quoth I:
+'Aroint thee, witch!' the rump-fed ronyon cries.
+Her husband's to Aleppo gone, master o' the Tiger:
+But in a sieve I'll thither sail,
+And, like a rat without a tail,
+I'll do, I'll do, and I'll do.
+
+ +Second Witch +
+I'll give thee a wind.
+
+ +First Witch +
+Thou'rt kind.
+
+ +Third Witch +
+And I another.
+
+ +First Witch +
+I myself have all the other,
+And the very ports they blow,
+All the quarters that they know
+I' the shipman's card.
+I will drain him dry as hay:
+Sleep shall neither night nor day
+Hang upon his pent-house lid;
+He shall live a man forbid:
+Weary se'nnights nine times nine
+Shall he dwindle, peak and pine:
+Though his bark cannot be lost,
+Yet it shall be tempest-tost.
+Look what I have.
+
+ +Second Witch +
+Show me, show me.
+
+ +First Witch +
+Here I have a pilot's thumb,
+Wreck'd as homeward he did come.
+

Drum within

+
+ +Third Witch +
+A drum, a drum!
+Macbeth doth come.
+
+ +ALL +
+The weird sisters, hand in hand,
+Posters of the sea and land,
+Thus do go about, about:
+Thrice to thine and thrice to mine
+And thrice again, to make up nine.
+Peace! the charm's wound up.
+

Enter MACBETH and BANQUO

+
+ +MACBETH +
+So foul and fair a day I have not seen.
+
+ +BANQUO +
+How far is't call'd to Forres? What are these
+So wither'd and so wild in their attire,
+That look not like the inhabitants o' the earth,
+And yet are on't? Live you? or are you aught
+That man may question? You seem to understand me,
+By each at once her chappy finger laying
+Upon her skinny lips: you should be women,
+And yet your beards forbid me to interpret
+That you are so.
+
+ +MACBETH +
+ Speak, if you can: what are you?
+
+ +First Witch +
+All hail, Macbeth! hail to thee, thane of Glamis!
+
+ +Second Witch +
+All hail, Macbeth, hail to thee, thane of Cawdor!
+
+ +Third Witch +
+All hail, Macbeth, thou shalt be king hereafter!
+
+ +BANQUO +
+Good sir, why do you start; and seem to fear
+Things that do sound so fair? I' the name of truth,
+Are ye fantastical, or that indeed
+Which outwardly ye show? My noble partner
+You greet with present grace and great prediction
+Of noble having and of royal hope,
+That he seems rapt withal: to me you speak not.
+If you can look into the seeds of time,
+And say which grain will grow and which will not,
+Speak then to me, who neither beg nor fear
+Your favours nor your hate.
+
+ +First Witch +
+Hail!
+
+ +Second Witch +
+Hail!
+
+ +Third Witch +
+Hail!
+
+ +First Witch +
+Lesser than Macbeth, and greater.
+
+ +Second Witch +
+Not so happy, yet much happier.
+
+ +Third Witch +
+Thou shalt get kings, though thou be none:
+So all hail, Macbeth and Banquo!
+
+ +First Witch +
+Banquo and Macbeth, all hail!
+
+ +MACBETH +
+Stay, you imperfect speakers, tell me more:
+By Sinel's death I know I am thane of Glamis;
+But how of Cawdor? the thane of Cawdor lives,
+A prosperous gentleman; and to be king
+Stands not within the prospect of belief,
+No more than to be Cawdor. Say from whence
+You owe this strange intelligence? or why
+Upon this blasted heath you stop our way
+With such prophetic greeting? Speak, I charge you.
+

Witches vanish

+
+ +BANQUO +
+The earth hath bubbles, as the water has,
+And these are of them. Whither are they vanish'd?
+
+ +MACBETH +
+Into the air; and what seem'd corporal melted
+As breath into the wind. Would they had stay'd!
+
+ +BANQUO +
+Were such things here as we do speak about?
+Or have we eaten on the insane root
+That takes the reason prisoner?
+
+ +MACBETH +
+Your children shall be kings.
+
+ +BANQUO +
+You shall be king.
+
+ +MACBETH +
+And thane of Cawdor too: went it not so?
+
+ +BANQUO +
+To the selfsame tune and words. Who's here?
+

Enter ROSS and ANGUS

+
+ +ROSS +
+The king hath happily received, Macbeth,
+The news of thy success; and when he reads
+Thy personal venture in the rebels' fight,
+His wonders and his praises do contend
+Which should be thine or his: silenced with that,
+In viewing o'er the rest o' the selfsame day,
+He finds thee in the stout Norweyan ranks,
+Nothing afeard of what thyself didst make,
+Strange images of death. As thick as hail
+Came post with post; and every one did bear
+Thy praises in his kingdom's great defence,
+And pour'd them down before him.
+
+ +ANGUS +
+We are sent
+To give thee from our royal master thanks;
+Only to herald thee into his sight,
+Not pay thee.
+
+ +ROSS +
+And, for an earnest of a greater honour,
+He bade me, from him, call thee thane of Cawdor:
+In which addition, hail, most worthy thane!
+For it is thine.
+
+ +BANQUO +
+ What, can the devil speak true?
+
+ +MACBETH +
+The thane of Cawdor lives: why do you dress me
+In borrow'd robes?
+
+ +ANGUS +
+ Who was the thane lives yet;
+But under heavy judgment bears that life
+Which he deserves to lose. Whether he was combined
+With those of Norway, or did line the rebel
+With hidden help and vantage, or that with both
+He labour'd in his country's wreck, I know not;
+But treasons capital, confess'd and proved,
+Have overthrown him.
+
+ +MACBETH +
+[Aside] Glamis, and thane of Cawdor!
+The greatest is behind.
+

To ROSS and ANGUS

+Thanks for your pains.
+

To BANQUO

+Do you not hope your children shall be kings,
+When those that gave the thane of Cawdor to me
+Promised no less to them?
+
+ +BANQUO +
+That trusted home
+Might yet enkindle you unto the crown,
+Besides the thane of Cawdor. But 'tis strange:
+And oftentimes, to win us to our harm,
+The instruments of darkness tell us truths,
+Win us with honest trifles, to betray's
+In deepest consequence.
+Cousins, a word, I pray you.
+
+ +MACBETH +
+[Aside] Two truths are told,
+As happy prologues to the swelling act
+Of the imperial theme.--I thank you, gentlemen.
+

Aside

+Cannot be ill, cannot be good: if ill,
+Why hath it given me earnest of success,
+Commencing in a truth? I am thane of Cawdor:
+If good, why do I yield to that suggestion
+Whose horrid image doth unfix my hair
+And make my seated heart knock at my ribs,
+Against the use of nature? Present fears
+Are less than horrible imaginings:
+My thought, whose murder yet is but fantastical,
+Shakes so my single state of man that function
+Is smother'd in surmise, and nothing is
+But what is not.
+
+ +BANQUO +
+ Look, how our partner's rapt.
+
+ +MACBETH +
+[Aside] If chance will have me king, why, chance may crown me,
+Without my stir.
+
+ +BANQUO +
+ New horrors come upon him,
+Like our strange garments, cleave not to their mould
+But with the aid of use.
+
+ +MACBETH +
+[Aside] Come what come may,
+Time and the hour runs through the roughest day.
+
+ +BANQUO +
+Worthy Macbeth, we stay upon your leisure.
+
+ +MACBETH +
+Give me your favour: my dull brain was wrought
+With things forgotten. Kind gentlemen, your pains
+Are register'd where every day I turn
+The leaf to read them. Let us toward the king.
+Think upon what hath chanced, and, at more time,
+The interim having weigh'd it, let us speak
+Our free hearts each to other.
+
+ +BANQUO +
+Very gladly.
+
+ +MACBETH +
+Till then, enough. Come, friends.
+

Exeunt

+
+

SCENE IV. Forres. The palace.

+

+Flourish. Enter DUNCAN, MALCOLM, DONALBAIN, LENNOX, and Attendants +
+ +DUNCAN +
+Is execution done on Cawdor? Are not
+Those in commission yet return'd?
+
+ +MALCOLM +
+My liege,
+They are not yet come back. But I have spoke
+With one that saw him die: who did report
+That very frankly he confess'd his treasons,
+Implored your highness' pardon and set forth
+A deep repentance: nothing in his life
+Became him like the leaving it; he died
+As one that had been studied in his death
+To throw away the dearest thing he owed,
+As 'twere a careless trifle.
+
+ +DUNCAN +
+There's no art
+To find the mind's construction in the face:
+He was a gentleman on whom I built
+An absolute trust.
+

Enter MACBETH, BANQUO, ROSS, and ANGUS

+O worthiest cousin!
+The sin of my ingratitude even now
+Was heavy on me: thou art so far before
+That swiftest wing of recompense is slow
+To overtake thee. Would thou hadst less deserved,
+That the proportion both of thanks and payment
+Might have been mine! only I have left to say,
+More is thy due than more than all can pay.
+
+ +MACBETH +
+The service and the loyalty I owe,
+In doing it, pays itself. Your highness' part
+Is to receive our duties; and our duties
+Are to your throne and state children and servants,
+Which do but what they should, by doing every thing
+Safe toward your love and honour.
+
+ +DUNCAN +
+Welcome hither:
+I have begun to plant thee, and will labour
+To make thee full of growing. Noble Banquo,
+That hast no less deserved, nor must be known
+No less to have done so, let me enfold thee
+And hold thee to my heart.
+
+ +BANQUO +
+There if I grow,
+The harvest is your own.
+
+ +DUNCAN +
+My plenteous joys,
+Wanton in fulness, seek to hide themselves
+In drops of sorrow. Sons, kinsmen, thanes,
+And you whose places are the nearest, know
+We will establish our estate upon
+Our eldest, Malcolm, whom we name hereafter
+The Prince of Cumberland; which honour must
+Not unaccompanied invest him only,
+But signs of nobleness, like stars, shall shine
+On all deservers. From hence to Inverness,
+And bind us further to you.
+
+ +MACBETH +
+The rest is labour, which is not used for you:
+I'll be myself the harbinger and make joyful
+The hearing of my wife with your approach;
+So humbly take my leave.
+
+ +DUNCAN +
+My worthy Cawdor!
+
+ +MACBETH +
+[Aside] The Prince of Cumberland! that is a step
+On which I must fall down, or else o'erleap,
+For in my way it lies. Stars, hide your fires;
+Let not light see my black and deep desires:
+The eye wink at the hand; yet let that be,
+Which the eye fears, when it is done, to see.
+

Exit

+
+ +DUNCAN +
+True, worthy Banquo; he is full so valiant,
+And in his commendations I am fed;
+It is a banquet to me. Let's after him,
+Whose care is gone before to bid us welcome:
+It is a peerless kinsman.
+

Flourish. Exeunt

+
+

SCENE V. Inverness. Macbeth's castle.

+

+Enter LADY MACBETH, reading a letter +
+ +LADY MACBETH +
+'They met me in the day of success: and I have
+learned by the perfectest report, they have more in
+them than mortal knowledge. When I burned in desire
+to question them further, they made themselves air,
+into which they vanished. Whiles I stood rapt in
+the wonder of it, came missives from the king, who
+all-hailed me 'Thane of Cawdor;' by which title,
+before, these weird sisters saluted me, and referred
+me to the coming on of time, with 'Hail, king that
+shalt be!' This have I thought good to deliver
+thee, my dearest partner of greatness, that thou
+mightst not lose the dues of rejoicing, by being
+ignorant of what greatness is promised thee. Lay it
+to thy heart, and farewell.'
+Glamis thou art, and Cawdor; and shalt be
+What thou art promised: yet do I fear thy nature;
+It is too full o' the milk of human kindness
+To catch the nearest way: thou wouldst be great;
+Art not without ambition, but without
+The illness should attend it: what thou wouldst highly,
+That wouldst thou holily; wouldst not play false,
+And yet wouldst wrongly win: thou'ldst have, great Glamis,
+That which cries 'Thus thou must do, if thou have it;
+And that which rather thou dost fear to do
+Than wishest should be undone.' Hie thee hither,
+That I may pour my spirits in thine ear;
+And chastise with the valour of my tongue
+All that impedes thee from the golden round,
+Which fate and metaphysical aid doth seem
+To have thee crown'd withal.
+

Enter a Messenger

+What is your tidings?
+
+ +Messenger +
+The king comes here to-night.
+
+ +LADY MACBETH +
+Thou'rt mad to say it:
+Is not thy master with him? who, were't so,
+Would have inform'd for preparation.
+
+ +Messenger +
+So please you, it is true: our thane is coming:
+One of my fellows had the speed of him,
+Who, almost dead for breath, had scarcely more
+Than would make up his message.
+
+ +LADY MACBETH +
+Give him tending;
+He brings great news.
+

Exit Messenger

+The raven himself is hoarse
+That croaks the fatal entrance of Duncan
+Under my battlements. Come, you spirits
+That tend on mortal thoughts, unsex me here,
+And fill me from the crown to the toe top-full
+Of direst cruelty! make thick my blood;
+Stop up the access and passage to remorse,
+That no compunctious visitings of nature
+Shake my fell purpose, nor keep peace between
+The effect and it! Come to my woman's breasts,
+And take my milk for gall, you murdering ministers,
+Wherever in your sightless substances
+You wait on nature's mischief! Come, thick night,
+And pall thee in the dunnest smoke of hell,
+That my keen knife see not the wound it makes,
+Nor heaven peep through the blanket of the dark,
+To cry 'Hold, hold!'
+

Enter MACBETH

+Great Glamis! worthy Cawdor!
+Greater than both, by the all-hail hereafter!
+Thy letters have transported me beyond
+This ignorant present, and I feel now
+The future in the instant.
+
+ +MACBETH +
+My dearest love,
+Duncan comes here to-night.
+
+ +LADY MACBETH +
+And when goes hence?
+
+ +MACBETH +
+To-morrow, as he purposes.
+
+ +LADY MACBETH +
+O, never
+Shall sun that morrow see!
+Your face, my thane, is as a book where men
+May read strange matters. To beguile the time,
+Look like the time; bear welcome in your eye,
+Your hand, your tongue: look like the innocent flower,
+But be the serpent under't. He that's coming
+Must be provided for: and you shall put
+This night's great business into my dispatch;
+Which shall to all our nights and days to come
+Give solely sovereign sway and masterdom.
+
+ +MACBETH +
+We will speak further.
+
+ +LADY MACBETH +
+Only look up clear;
+To alter favour ever is to fear:
+Leave all the rest to me.
+

Exeunt

+
+

SCENE VI. Before Macbeth's castle.

+

+Hautboys and torches. Enter DUNCAN, MALCOLM, DONALBAIN, BANQUO, LENNOX, MACDUFF, ROSS, ANGUS, and Attendants +
+ +DUNCAN +
+This castle hath a pleasant seat; the air
+Nimbly and sweetly recommends itself
+Unto our gentle senses.
+
+ +BANQUO +
+This guest of summer,
+The temple-haunting martlet, does approve,
+By his loved mansionry, that the heaven's breath
+Smells wooingly here: no jutty, frieze,
+Buttress, nor coign of vantage, but this bird
+Hath made his pendent bed and procreant cradle:
+Where they most breed and haunt, I have observed,
+The air is delicate.
+

Enter LADY MACBETH

+
+ +DUNCAN +
+See, see, our honour'd hostess!
+The love that follows us sometime is our trouble,
+Which still we thank as love. Herein I teach you
+How you shall bid God 'ild us for your pains,
+And thank us for your trouble.
+
+ +LADY MACBETH +
+All our service
+In every point twice done and then done double
+Were poor and single business to contend
+Against those honours deep and broad wherewith
+Your majesty loads our house: for those of old,
+And the late dignities heap'd up to them,
+We rest your hermits.
+
+ +DUNCAN +
+Where's the thane of Cawdor?
+We coursed him at the heels, and had a purpose
+To be his purveyor: but he rides well;
+And his great love, sharp as his spur, hath holp him
+To his home before us. Fair and noble hostess,
+We are your guest to-night.
+
+ +LADY MACBETH +
+Your servants ever
+Have theirs, themselves and what is theirs, in compt,
+To make their audit at your highness' pleasure,
+Still to return your own.
+
+ +DUNCAN +
+Give me your hand;
+Conduct me to mine host: we love him highly,
+And shall continue our graces towards him.
+By your leave, hostess.
+

Exeunt

+
+

SCENE VII. Macbeth's castle.

+

+Hautboys and torches. Enter a Sewer, and divers Servants with dishes and service, and pass over the stage. Then enter MACBETH +
+ +MACBETH +
+If it were done when 'tis done, then 'twere well
+It were done quickly: if the assassination
+Could trammel up the consequence, and catch
+With his surcease success; that but this blow
+Might be the be-all and the end-all here,
+But here, upon this bank and shoal of time,
+We'ld jump the life to come. But in these cases
+We still have judgment here; that we but teach
+Bloody instructions, which, being taught, return
+To plague the inventor: this even-handed justice
+Commends the ingredients of our poison'd chalice
+To our own lips. He's here in double trust;
+First, as I am his kinsman and his subject,
+Strong both against the deed; then, as his host,
+Who should against his murderer shut the door,
+Not bear the knife myself. Besides, this Duncan
+Hath borne his faculties so meek, hath been
+So clear in his great office, that his virtues
+Will plead like angels, trumpet-tongued, against
+The deep damnation of his taking-off;
+And pity, like a naked new-born babe,
+Striding the blast, or heaven's cherubim, horsed
+Upon the sightless couriers of the air,
+Shall blow the horrid deed in every eye,
+That tears shall drown the wind. I have no spur
+To prick the sides of my intent, but only
+Vaulting ambition, which o'erleaps itself
+And falls on the other.
+

Enter LADY MACBETH

+How now! what news?
+
+ +LADY MACBETH +
+He has almost supp'd: why have you left the chamber?
+
+ +MACBETH +
+Hath he ask'd for me?
+
+ +LADY MACBETH +
+Know you not he has?
+
+ +MACBETH +
+We will proceed no further in this business:
+He hath honour'd me of late; and I have bought
+Golden opinions from all sorts of people,
+Which would be worn now in their newest gloss,
+Not cast aside so soon.
+
+ +LADY MACBETH +
+Was the hope drunk
+Wherein you dress'd yourself? hath it slept since?
+And wakes it now, to look so green and pale
+At what it did so freely? From this time
+Such I account thy love. Art thou afeard
+To be the same in thine own act and valour
+As thou art in desire? Wouldst thou have that
+Which thou esteem'st the ornament of life,
+And live a coward in thine own esteem,
+Letting 'I dare not' wait upon 'I would,'
+Like the poor cat i' the adage?
+
+ +MACBETH +
+Prithee, peace:
+I dare do all that may become a man;
+Who dares do more is none.
+
+ +LADY MACBETH +
+What beast was't, then,
+That made you break this enterprise to me?
+When you durst do it, then you were a man;
+And, to be more than what you were, you would
+Be so much more the man. Nor time nor place
+Did then adhere, and yet you would make both:
+They have made themselves, and that their fitness now
+Does unmake you. I have given suck, and know
+How tender 'tis to love the babe that milks me:
+I would, while it was smiling in my face,
+Have pluck'd my nipple from his boneless gums,
+And dash'd the brains out, had I so sworn as you
+Have done to this.
+
+ +MACBETH +
+ If we should fail?
+
+ +LADY MACBETH +
+We fail!
+But screw your courage to the sticking-place,
+And we'll not fail. When Duncan is asleep--
+Whereto the rather shall his day's hard journey
+Soundly invite him--his two chamberlains
+Will I with wine and wassail so convince
+That memory, the warder of the brain,
+Shall be a fume, and the receipt of reason
+A limbeck only: when in swinish sleep
+Their drenched natures lie as in a death,
+What cannot you and I perform upon
+The unguarded Duncan? what not put upon
+His spongy officers, who shall bear the guilt
+Of our great quell?
+
+ +MACBETH +
+Bring forth men-children only;
+For thy undaunted mettle should compose
+Nothing but males. Will it not be received,
+When we have mark'd with blood those sleepy two
+Of his own chamber and used their very daggers,
+That they have done't?
+
+ +LADY MACBETH +
+Who dares receive it other,
+As we shall make our griefs and clamour roar
+Upon his death?
+
+ +MACBETH +
+ I am settled, and bend up
+Each corporal agent to this terrible feat.
+Away, and mock the time with fairest show:
+False face must hide what the false heart doth know.
+

Exeunt

+

+

ACT II

+

SCENE I. Court of Macbeth's castle.

+

+Enter BANQUO, and FLEANCE bearing a torch before him +
+ +BANQUO +
+How goes the night, boy?
+
+ +FLEANCE +
+The moon is down; I have not heard the clock.
+
+ +BANQUO +
+And she goes down at twelve.
+
+ +FLEANCE +
+I take't, 'tis later, sir.
+
+ +BANQUO +
+Hold, take my sword. There's husbandry in heaven;
+Their candles are all out. Take thee that too.
+A heavy summons lies like lead upon me,
+And yet I would not sleep: merciful powers,
+Restrain in me the cursed thoughts that nature
+Gives way to in repose!
+

Enter MACBETH, and a Servant with a torch

+Give me my sword.
+Who's there?
+
+ +MACBETH +
+A friend.
+
+ +BANQUO +
+What, sir, not yet at rest? The king's a-bed:
+He hath been in unusual pleasure, and
+Sent forth great largess to your offices.
+This diamond he greets your wife withal,
+By the name of most kind hostess; and shut up
+In measureless content.
+
+ +MACBETH +
+Being unprepared,
+Our will became the servant to defect;
+Which else should free have wrought.
+
+ +BANQUO +
+All's well.
+I dreamt last night of the three weird sisters:
+To you they have show'd some truth.
+
+ +MACBETH +
+I think not of them:
+Yet, when we can entreat an hour to serve,
+We would spend it in some words upon that business,
+If you would grant the time.
+
+ +BANQUO +
+At your kind'st leisure.
+
+ +MACBETH +
+If you shall cleave to my consent, when 'tis,
+It shall make honour for you.
+
+ +BANQUO +
+So I lose none
+In seeking to augment it, but still keep
+My bosom franchised and allegiance clear,
+I shall be counsell'd.
+
+ +MACBETH +
+Good repose the while!
+
+ +BANQUO +
+Thanks, sir: the like to you!
+

Exeunt BANQUO and FLEANCE

+
+ +MACBETH +
+Go bid thy mistress, when my drink is ready,
+She strike upon the bell. Get thee to bed.
+

Exit Servant

+Is this a dagger which I see before me,
+The handle toward my hand? Come, let me clutch thee.
+I have thee not, and yet I see thee still.
+Art thou not, fatal vision, sensible
+To feeling as to sight? or art thou but
+A dagger of the mind, a false creation,
+Proceeding from the heat-oppressed brain?
+I see thee yet, in form as palpable
+As this which now I draw.
+Thou marshall'st me the way that I was going;
+And such an instrument I was to use.
+Mine eyes are made the fools o' the other senses,
+Or else worth all the rest; I see thee still,
+And on thy blade and dudgeon gouts of blood,
+Which was not so before. There's no such thing:
+It is the bloody business which informs
+Thus to mine eyes. Now o'er the one halfworld
+Nature seems dead, and wicked dreams abuse
+The curtain'd sleep; witchcraft celebrates
+Pale Hecate's offerings, and wither'd murder,
+Alarum'd by his sentinel, the wolf,
+Whose howl's his watch, thus with his stealthy pace.
+With Tarquin's ravishing strides, towards his design
+Moves like a ghost. Thou sure and firm-set earth,
+Hear not my steps, which way they walk, for fear
+Thy very stones prate of my whereabout,
+And take the present horror from the time,
+Which now suits with it. Whiles I threat, he lives:
+Words to the heat of deeds too cold breath gives.
+

A bell rings

+I go, and it is done; the bell invites me.
+Hear it not, Duncan; for it is a knell
+That summons thee to heaven or to hell.
+

Exit

+
+

SCENE II. The same.

+

+Enter LADY MACBETH +
+ +LADY MACBETH +
+That which hath made them drunk hath made me bold;
+What hath quench'd them hath given me fire.
+Hark! Peace!
+It was the owl that shriek'd, the fatal bellman,
+Which gives the stern'st good-night. He is about it:
+The doors are open; and the surfeited grooms
+Do mock their charge with snores: I have drugg'd
+their possets,
+That death and nature do contend about them,
+Whether they live or die.
+
+ +MACBETH +
+[Within] Who's there? what, ho!
+
+ +LADY MACBETH +
+Alack, I am afraid they have awaked,
+And 'tis not done. The attempt and not the deed
+Confounds us. Hark! I laid their daggers ready;
+He could not miss 'em. Had he not resembled
+My father as he slept, I had done't.
+

Enter MACBETH

+My husband!
+
+ +MACBETH +
+I have done the deed. Didst thou not hear a noise?
+
+ +LADY MACBETH +
+I heard the owl scream and the crickets cry.
+Did not you speak?
+
+ +MACBETH +
+ When?
+
+ +LADY MACBETH +
+Now.
+
+ +MACBETH +
+As I descended?
+
+ +LADY MACBETH +
+Ay.
+
+ +MACBETH +
+Hark!
+Who lies i' the second chamber?
+
+ +LADY MACBETH +
+Donalbain.
+
+ +MACBETH +
+This is a sorry sight.
+

Looking on his hands

+
+ +LADY MACBETH +
+A foolish thought, to say a sorry sight.
+
+ +MACBETH +
+There's one did laugh in's sleep, and one cried
+'Murder!'
+That they did wake each other: I stood and heard them:
+But they did say their prayers, and address'd them
+Again to sleep.
+
+ +LADY MACBETH +
+ There are two lodged together.
+
+ +MACBETH +
+One cried 'God bless us!' and 'Amen' the other;
+As they had seen me with these hangman's hands.
+Listening their fear, I could not say 'Amen,'
+When they did say 'God bless us!'
+
+ +LADY MACBETH +
+Consider it not so deeply.
+
+ +MACBETH +
+But wherefore could not I pronounce 'Amen'?
+I had most need of blessing, and 'Amen'
+Stuck in my throat.
+
+ +LADY MACBETH +
+These deeds must not be thought
+After these ways; so, it will make us mad.
+
+ +MACBETH +
+Methought I heard a voice cry 'Sleep no more!
+Macbeth does murder sleep', the innocent sleep,
+Sleep that knits up the ravell'd sleeve of care,
+The death of each day's life, sore labour's bath,
+Balm of hurt minds, great nature's second course,
+Chief nourisher in life's feast,--
+
+ +LADY MACBETH +
+What do you mean?
+
+ +MACBETH +
+Still it cried 'Sleep no more!' to all the house:
+'Glamis hath murder'd sleep, and therefore Cawdor
+Shall sleep no more; Macbeth shall sleep no more.'
+
+ +LADY MACBETH +
+Who was it that thus cried? Why, worthy thane,
+You do unbend your noble strength, to think
+So brainsickly of things. Go get some water,
+And wash this filthy witness from your hand.
+Why did you bring these daggers from the place?
+They must lie there: go carry them; and smear
+The sleepy grooms with blood.
+
+ +MACBETH +
+I'll go no more:
+I am afraid to think what I have done;
+Look on't again I dare not.
+
+ +LADY MACBETH +
+Infirm of purpose!
+Give me the daggers: the sleeping and the dead
+Are but as pictures: 'tis the eye of childhood
+That fears a painted devil. If he do bleed,
+I'll gild the faces of the grooms withal;
+For it must seem their guilt.
+

Exit. Knocking within

+
+ +MACBETH +
+Whence is that knocking?
+How is't with me, when every noise appals me?
+What hands are here? ha! they pluck out mine eyes.
+Will all great Neptune's ocean wash this blood
+Clean from my hand? No, this my hand will rather
+The multitudinous seas in incarnadine,
+Making the green one red.
+

Re-enter LADY MACBETH

+
+ +LADY MACBETH +
+My hands are of your colour; but I shame
+To wear a heart so white.
+

Knocking within

+I hear a knocking
+At the south entry: retire we to our chamber;
+A little water clears us of this deed:
+How easy is it, then! Your constancy
+Hath left you unattended.
+

Knocking within

+Hark! more knocking.
+Get on your nightgown, lest occasion call us,
+And show us to be watchers. Be not lost
+So poorly in your thoughts.
+
+ +MACBETH +
+To know my deed, 'twere best not know myself.
+

Knocking within

+Wake Duncan with thy knocking! I would thou couldst!
+

Exeunt

+
+

SCENE III. The same.

+

+Knocking within. Enter a Porter +
+ +Porter +
+Here's a knocking indeed! If a
+man were porter of hell-gate, he should have
+old turning the key.
+

Knocking within

+Knock,
+knock, knock! Who's there, i' the name of
+Beelzebub? Here's a farmer, that hanged
+himself on the expectation of plenty: come in
+time; have napkins enow about you; here
+you'll sweat for't.
+

Knocking within

+Knock,
+knock! Who's there, in the other devil's
+name? Faith, here's an equivocator, that could
+swear in both the scales against either scale;
+who committed treason enough for God's sake,
+yet could not equivocate to heaven: O, come
+in, equivocator.
+

Knocking within

+Knock,
+knock, knock! Who's there? Faith, here's an
+English tailor come hither, for stealing out of
+a French hose: come in, tailor; here you may
+roast your goose.
+

Knocking within

+Knock,
+knock; never at quiet! What are you? But
+this place is too cold for hell. I'll devil-porter
+it no further: I had thought to have let in
+some of all professions that go the primrose
+way to the everlasting bonfire.
+

Knocking within

+Anon, anon! I pray you, remember the porter.
+

Opens the gate

+

Enter MACDUFF and LENNOX

+
+ +MACDUFF +
+Was it so late, friend, ere you went to bed,
+That you do lie so late?
+
+ +Porter +
+'Faith sir, we were carousing till the
+second cock: and drink, sir, is a great
+provoker of three things.
+
+ +MACDUFF +
+What three things does drink especially provoke?
+
+ +Porter +
+Marry, sir, nose-painting, sleep, and
+urine. Lechery, sir, it provokes, and unprovokes;
+it provokes the desire, but it takes
+away the performance: therefore, much drink
+may be said to be an equivocator with lechery:
+it makes him, and it mars him; it sets
+him on, and it takes him off; it persuades him,
+and disheartens him; makes him stand to, and
+not stand to; in conclusion, equivocates him
+in a sleep, and, giving him the lie, leaves him.
+
+ +MACDUFF +
+I believe drink gave thee the lie last night.
+
+ +Porter +
+That it did, sir, i' the very throat on
+me: but I requited him for his lie; and, I
+think, being too strong for him, though he took
+up my legs sometime, yet I made a shift to cast
+him.
+
+ +MACDUFF +
+Is thy master stirring?
+

Enter MACBETH

+Our knocking has awaked him; here he comes.
+
+ +LENNOX +
+Good morrow, noble sir.
+
+ +MACBETH +
+Good morrow, both.
+
+ +MACDUFF +
+Is the king stirring, worthy thane?
+
+ +MACBETH +
+Not yet.
+
+ +MACDUFF +
+He did command me to call timely on him:
+I have almost slipp'd the hour.
+
+ +MACBETH +
+I'll bring you to him.
+
+ +MACDUFF +
+I know this is a joyful trouble to you;
+But yet 'tis one.
+
+ +MACBETH +
+The labour we delight in physics pain.
+This is the door.
+
+ +MACDUFF +
+ I'll make so bold to call,
+For 'tis my limited service.
+

Exit

+
+ +LENNOX +
+Goes the king hence to-day?
+
+ +MACBETH +
+He does: he did appoint so.
+
+ +LENNOX +
+The night has been unruly: where we lay,
+Our chimneys were blown down; and, as they say,
+Lamentings heard i' the air; strange screams of death,
+And prophesying with accents terrible
+Of dire combustion and confused events
+New hatch'd to the woeful time: the obscure bird
+Clamour'd the livelong night: some say, the earth
+Was feverous and did shake.
+
+ +MACBETH +
+'Twas a rough night.
+
+ +LENNOX +
+My young remembrance cannot parallel
+A fellow to it.
+

Re-enter MACDUFF

+
+ +MACDUFF +
+O horror, horror, horror! Tongue nor heart
+Cannot conceive nor name thee!
+
+ +MACBETH + +LENNOX +
+What's the matter.
+
+ +MACDUFF +
+Confusion now hath made his masterpiece!
+Most sacrilegious murder hath broke ope
+The Lord's anointed temple, and stole thence
+The life o' the building!
+
+ +MACBETH +
+What is 't you say? the life?
+
+ +LENNOX +
+Mean you his majesty?
+
+ +MACDUFF +
+Approach the chamber, and destroy your sight
+With a new Gorgon: do not bid me speak;
+See, and then speak yourselves.
+

Exeunt MACBETH and LENNOX

+Awake, awake!
+Ring the alarum-bell. Murder and treason!
+Banquo and Donalbain! Malcolm! awake!
+Shake off this downy sleep, death's counterfeit,
+And look on death itself! up, up, and see
+The great doom's image! Malcolm! Banquo!
+As from your graves rise up, and walk like sprites,
+To countenance this horror! Ring the bell.
+

Bell rings

+

Enter LADY MACBETH

+
+ +LADY MACBETH +
+What's the business,
+That such a hideous trumpet calls to parley
+The sleepers of the house? speak, speak!
+
+ +MACDUFF +
+O gentle lady,
+'Tis not for you to hear what I can speak:
+The repetition, in a woman's ear,
+Would murder as it fell.
+

Enter BANQUO

+O Banquo, Banquo,
+Our royal master 's murder'd!
+
+ +LADY MACBETH +
+Woe, alas!
+What, in our house?
+
+ +BANQUO +
+Too cruel any where.
+Dear Duff, I prithee, contradict thyself,
+And say it is not so.
+

Re-enter MACBETH and LENNOX, with ROSS

+
+ +MACBETH +
+Had I but died an hour before this chance,
+I had lived a blessed time; for, from this instant,
+There 's nothing serious in mortality:
+All is but toys: renown and grace is dead;
+The wine of life is drawn, and the mere lees
+Is left this vault to brag of.
+

Enter MALCOLM and DONALBAIN

+
+ +DONALBAIN +
+What is amiss?
+
+ +MACBETH +
+ You are, and do not know't:
+The spring, the head, the fountain of your blood
+Is stopp'd; the very source of it is stopp'd.
+
+ +MACDUFF +
+Your royal father 's murder'd.
+
+ +MALCOLM +
+O, by whom?
+
+ +LENNOX +
+Those of his chamber, as it seem'd, had done 't:
+Their hands and faces were an badged with blood;
+So were their daggers, which unwiped we found
+Upon their pillows:
+They stared, and were distracted; no man's life
+Was to be trusted with them.
+
+ +MACBETH +
+O, yet I do repent me of my fury,
+That I did kill them.
+
+ +MACDUFF +
+Wherefore did you so?
+
+ +MACBETH +
+Who can be wise, amazed, temperate and furious,
+Loyal and neutral, in a moment? No man:
+The expedition my violent love
+Outrun the pauser, reason. Here lay Duncan,
+His silver skin laced with his golden blood;
+And his gash'd stabs look'd like a breach in nature
+For ruin's wasteful entrance: there, the murderers,
+Steep'd in the colours of their trade, their daggers
+Unmannerly breech'd with gore: who could refrain,
+That had a heart to love, and in that heart
+Courage to make 's love kno wn?
+
+ +LADY MACBETH +
+Help me hence, ho!
+
+ +MACDUFF +
+Look to the lady.
+
+ +MALCOLM +
+[Aside to DONALBAIN] Why do we hold our tongues,
+That most may claim this argument for ours?
+
+ +DONALBAIN +
+[Aside to MALCOLM] What should be spoken here,
+where our fate,
+Hid in an auger-hole, may rush, and seize us?
+Let 's away;
+Our tears are not yet brew'd.
+
+ +MALCOLM +
+[Aside to DONALBAIN] Nor our strong sorrow
+Upon the foot of motion.
+
+ +BANQUO +
+Look to the lady:
+

LADY MACBETH is carried out

+And when we have our naked frailties hid,
+That suffer in exposure, let us meet,
+And question this most bloody piece of work,
+To know it further. Fears and scruples shake us:
+In the great hand of God I stand; and thence
+Against the undivulged pretence I fight
+Of treasonous malice.
+
+ +MACDUFF +
+And so do I.
+
+ +ALL +
+So all.
+
+ +MACBETH +
+Let's briefly put on manly readiness,
+And meet i' the hall together.
+
+ +ALL +
+Well contented.
+

Exeunt all but Malcolm and Donalbain.

+
+ +MALCOLM +
+What will you do? Let's not consort with them:
+To show an unfelt sorrow is an office
+Which the false man does easy. I'll to England.
+
+ +DONALBAIN +
+To Ireland, I; our separated fortune
+Shall keep us both the safer: where we are,
+There's daggers in men's smiles: the near in blood,
+The nearer bloody.
+
+ +MALCOLM +
+ This murderous shaft that's shot
+Hath not yet lighted, and our safest way
+Is to avoid the aim. Therefore, to horse;
+And let us not be dainty of leave-taking,
+But shift away: there's warrant in that theft
+Which steals itself, when there's no mercy left.
+

Exeunt

+
+

SCENE IV. Outside Macbeth's castle.

+

+Enter ROSS and an old Man +
+ +Old Man +
+Threescore and ten I can remember well:
+Within the volume of which time I have seen
+Hours dreadful and things strange; but this sore night
+Hath trifled former knowings.
+
+ +ROSS +
+Ah, good father,
+Thou seest, the heavens, as troubled with man's act,
+Threaten his bloody stage: by the clock, 'tis day,
+And yet dark night strangles the travelling lamp:
+Is't night's predominance, or the day's shame,
+That darkness does the face of earth entomb,
+When living light should kiss it?
+
+ +Old Man +
+'Tis unnatural,
+Even like the deed that's done. On Tuesday last,
+A falcon, towering in her pride of place,
+Was by a mousing owl hawk'd at and kill'd.
+
+ +ROSS +
+And Duncan's horses--a thing most strange and certain--
+Beauteous and swift, the minions of their race,
+Turn'd wild in nature, broke their stalls, flung out,
+Contending 'gainst obedience, as they would make
+War with mankind.
+
+ +Old Man +
+'Tis said they eat each other.
+
+ +ROSS +
+They did so, to the amazement of mine eyes
+That look'd upon't. Here comes the good Macduff.
+

Enter MACDUFF

+How goes the world, sir, now?
+
+ +MACDUFF +
+Why, see you not?
+
+ +ROSS +
+Is't known who did this more than bloody deed?
+
+ +MACDUFF +
+Those that Macbeth hath slain.
+
+ +ROSS +
+Alas, the day!
+What good could they pretend?
+
+ +MACDUFF +
+They were suborn'd:
+Malcolm and Donalbain, the king's two sons,
+Are stol'n away and fled; which puts upon them
+Suspicion of the deed.
+
+ +ROSS +
+'Gainst nature still!
+Thriftless ambition, that wilt ravin up
+Thine own life's means! Then 'tis most like
+The sovereignty will fall upon Macbeth.
+
+ +MACDUFF +
+He is already named, and gone to Scone
+To be invested.
+
+ +ROSS +
+ Where is Duncan's body?
+
+ +MACDUFF +
+Carried to Colmekill,
+The sacred storehouse of his predecessors,
+And guardian of their bones.
+
+ +ROSS +
+Will you to Scone?
+
+ +MACDUFF +
+No, cousin, I'll to Fife.
+
+ +ROSS +
+Well, I will thither.
+
+ +MACDUFF +
+Well, may you see things well done there: adieu!
+Lest our old robes sit easier than our new!
+
+ +ROSS +
+Farewell, father.
+
+ +Old Man +
+God's benison go with you; and with those
+That would make good of bad, and friends of foes!
+

Exeunt

+

+

ACT III

+

SCENE I. Forres. The palace.

+

+Enter BANQUO +
+ +BANQUO +
+Thou hast it now: king, Cawdor, Glamis, all,
+As the weird women promised, and, I fear,
+Thou play'dst most foully for't: yet it was said
+It should not stand in thy posterity,
+But that myself should be the root and father
+Of many kings. If there come truth from them--
+As upon thee, Macbeth, their speeches shine--
+Why, by the verities on thee made good,
+May they not be my oracles as well,
+And set me up in hope? But hush! no more.
+

Sennet sounded. Enter MACBETH, as king, LADY MACBETH, as queen, LENNOX, ROSS, Lords, Ladies, and Attendants

+
+ +MACBETH +
+Here's our chief guest.
+
+ +LADY MACBETH +
+If he had been forgotten,
+It had been as a gap in our great feast,
+And all-thing unbecoming.
+
+ +MACBETH +
+To-night we hold a solemn supper sir,
+And I'll request your presence.
+
+ +BANQUO +
+Let your highness
+Command upon me; to the which my duties
+Are with a most indissoluble tie
+For ever knit.
+
+ +MACBETH +
+ Ride you this afternoon?
+
+ +BANQUO +
+Ay, my good lord.
+
+ +MACBETH +
+We should have else desired your good advice,
+Which still hath been both grave and prosperous,
+In this day's council; but we'll take to-morrow.
+Is't far you ride?
+
+ +BANQUO +
+As far, my lord, as will fill up the time
+'Twixt this and supper: go not my horse the better,
+I must become a borrower of the night
+For a dark hour or twain.
+
+ +MACBETH +
+Fail not our feast.
+
+ +BANQUO +
+My lord, I will not.
+
+ +MACBETH +
+We hear, our bloody cousins are bestow'd
+In England and in Ireland, not confessing
+Their cruel parricide, filling their hearers
+With strange invention: but of that to-morrow,
+When therewithal we shall have cause of state
+Craving us jointly. Hie you to horse: adieu,
+Till you return at night. Goes Fleance with you?
+
+ +BANQUO +
+Ay, my good lord: our time does call upon 's.
+
+ +MACBETH +
+I wish your horses swift and sure of foot;
+And so I do commend you to their backs. Farewell.
+

Exit BANQUO

+Let every man be master of his time
+Till seven at night: to make society
+The sweeter welcome, we will keep ourself
+Till supper-time alone: while then, God be with you!
+

Exeunt all but MACBETH, and an attendant

+Sirrah, a word with you: attend those men
+Our pleasure?
+
+ +ATTENDANT +
+They are, my lord, without the palace gate.
+
+ +MACBETH +
+Bring them before us.
+

Exit Attendant

+To be thus is nothing;
+But to be safely thus.--Our fears in Banquo
+Stick deep; and in his royalty of nature
+Reigns that which would be fear'd: 'tis much he dares;
+And, to that dauntless temper of his mind,
+He hath a wisdom that doth guide his valour
+To act in safety. There is none but he
+Whose being I do fear: and, under him,
+My Genius is rebuked; as, it is said,
+Mark Antony's was by Caesar. He chid the sisters
+When first they put the name of king upon me,
+And bade them speak to him: then prophet-like
+They hail'd him father to a line of kings:
+Upon my head they placed a fruitless crown,
+And put a barren sceptre in my gripe,
+Thence to be wrench'd with an unlineal hand,
+No son of mine succeeding. If 't be so,
+For Banquo's issue have I filed my mind;
+For them the gracious Duncan have I murder'd;
+Put rancours in the vessel of my peace
+Only for them; and mine eternal jewel
+Given to the common enemy of man,
+To make them kings, the seed of Banquo kings!
+Rather than so, come fate into the list.
+And champion me to the utterance! Who's there!
+

Re-enter Attendant, with two Murderers

+Now go to the door, and stay there till we call.
+

Exit Attendant

+Was it not yesterday we spoke together?
+
+ +First Murderer +
+It was, so please your highness.
+
+ +MACBETH +
+Well then, now
+Have you consider'd of my speeches? Know
+That it was he in the times past which held you
+So under fortune, which you thought had been
+Our innocent self: this I made good to you
+In our last conference, pass'd in probation with you,
+How you were borne in hand, how cross'd,
+the instruments,
+Who wrought with them, and all things else that might
+To half a soul and to a notion crazed
+Say 'Thus did Banquo.'
+
+ +First Murderer +
+You made it known to us.
+
+ +MACBETH +
+I did so, and went further, which is now
+Our point of second meeting. Do you find
+Your patience so predominant in your nature
+That you can let this go? Are you so gospell'd
+To pray for this good man and for his issue,
+Whose heavy hand hath bow'd you to the grave
+And beggar'd yours for ever?
+
+ +First Murderer +
+We are men, my liege.
+
+ +MACBETH +
+Ay, in the catalogue ye go for men;
+As hounds and greyhounds, mongrels, spaniels, curs,
+Shoughs, water-rugs and demi-wolves, are clept
+All by the name of dogs: the valued file
+Distinguishes the swift, the slow, the subtle,
+The housekeeper, the hunter, every one
+According to the gift which bounteous nature
+Hath in him closed; whereby he does receive
+Particular addition. from the bill
+That writes them all alike: and so of men.
+Now, if you have a station in the file,
+Not i' the worst rank of manhood, say 't;
+And I will put that business in your bosoms,
+Whose execution takes your enemy off,
+Grapples you to the heart and love of us,
+Who wear our health but sickly in his life,
+Which in his death were perfect.
+
+ +Second Murderer +
+I am one, my liege,
+Whom the vile blows and buffets of the world
+Have so incensed that I am reckless what
+I do to spite the world.
+
+ +First Murderer +
+And I another
+So weary with disasters, tugg'd with fortune,
+That I would set my lie on any chance,
+To mend it, or be rid on't.
+
+ +MACBETH +
+Both of you
+Know Banquo was your enemy.
+
+ +Both Murderers +
+True, my lord.
+
+ +MACBETH +
+So is he mine; and in such bloody distance,
+That every minute of his being thrusts
+Against my near'st of life: and though I could
+With barefaced power sweep him from my sight
+And bid my will avouch it, yet I must not,
+For certain friends that are both his and mine,
+Whose loves I may not drop, but wail his fall
+Who I myself struck down; and thence it is,
+That I to your assistance do make love,
+Masking the business from the common eye
+For sundry weighty reasons.
+
+ +Second Murderer +
+We shall, my lord,
+Perform what you command us.
+
+ +First Murderer +
+Though our lives--
+
+ +MACBETH +
+Your spirits shine through you. Within this hour at most
+I will advise you where to plant yourselves;
+Acquaint you with the perfect spy o' the time,
+The moment on't; for't must be done to-night,
+And something from the palace; always thought
+That I require a clearness: and with him--
+To leave no rubs nor botches in the work--
+Fleance his son, that keeps him company,
+Whose absence is no less material to me
+Than is his father's, must embrace the fate
+Of that dark hour. Resolve yourselves apart:
+I'll come to you anon.
+
+ +Both Murderers +
+We are resolved, my lord.
+
+ +MACBETH +
+I'll call upon you straight: abide within.
+

Exeunt Murderers

+It is concluded. Banquo, thy soul's flight,
+If it find heaven, must find it out to-night.
+

Exit

+
+

SCENE II. The palace.

+

+Enter LADY MACBETH and a Servant +
+ +LADY MACBETH +
+Is Banquo gone from court?
+
+ +Servant +
+Ay, madam, but returns again to-night.
+
+ +LADY MACBETH +
+Say to the king, I would attend his leisure
+For a few words.
+
+ +Servant +
+ Madam, I will.
+

Exit

+
+ +LADY MACBETH +
+Nought's had, all's spent,
+Where our desire is got without content:
+'Tis safer to be that which we destroy
+Than by destruction dwell in doubtful joy.
+

Enter MACBETH

+How now, my lord! why do you keep alone,
+Of sorriest fancies your companions making,
+Using those thoughts which should indeed have died
+With them they think on? Things without all remedy
+Should be without regard: what's done is done.
+
+ +MACBETH +
+We have scotch'd the snake, not kill'd it:
+She'll close and be herself, whilst our poor malice
+Remains in danger of her former tooth.
+But let the frame of things disjoint, both the
+worlds suffer,
+Ere we will eat our meal in fear and sleep
+In the affliction of these terrible dreams
+That shake us nightly: better be with the dead,
+Whom we, to gain our peace, have sent to peace,
+Than on the torture of the mind to lie
+In restless ecstasy. Duncan is in his grave;
+After life's fitful fever he sleeps well;
+Treason has done his worst: nor steel, nor poison,
+Malice domestic, foreign levy, nothing,
+Can touch him further.
+
+ +LADY MACBETH +
+Come on;
+Gentle my lord, sleek o'er your rugged looks;
+Be bright and jovial among your guests to-night.
+
+ +MACBETH +
+So shall I, love; and so, I pray, be you:
+Let your remembrance apply to Banquo;
+Present him eminence, both with eye and tongue:
+Unsafe the while, that we
+Must lave our honours in these flattering streams,
+And make our faces vizards to our hearts,
+Disguising what they are.
+
+ +LADY MACBETH +
+You must leave this.
+
+ +MACBETH +
+O, full of scorpions is my mind, dear wife!
+Thou know'st that Banquo, and his Fleance, lives.
+
+ +LADY MACBETH +
+But in them nature's copy's not eterne.
+
+ +MACBETH +
+There's comfort yet; they are assailable;
+Then be thou jocund: ere the bat hath flown
+His cloister'd flight, ere to black Hecate's summons
+The shard-borne beetle with his drowsy hums
+Hath rung night's yawning peal, there shall be done
+A deed of dreadful note.
+
+ +LADY MACBETH +
+What's to be done?
+
+ +MACBETH +
+Be innocent of the knowledge, dearest chuck,
+Till thou applaud the deed. Come, seeling night,
+Scarf up the tender eye of pitiful day;
+And with thy bloody and invisible hand
+Cancel and tear to pieces that great bond
+Which keeps me pale! Light thickens; and the crow
+Makes wing to the rooky wood:
+Good things of day begin to droop and drowse;
+While night's black agents to their preys do rouse.
+Thou marvell'st at my words: but hold thee still;
+Things bad begun make strong themselves by ill.
+So, prithee, go with me.
+

Exeunt

+
+

SCENE III. A park near the palace.

+

+Enter three Murderers +
+ +First Murderer +
+But who did bid thee join with us?
+
+ +Third Murderer +
+Macbeth.
+
+ +Second Murderer +
+He needs not our mistrust, since he delivers
+Our offices and what we have to do
+To the direction just.
+
+ +First Murderer +
+Then stand with us.
+The west yet glimmers with some streaks of day:
+Now spurs the lated traveller apace
+To gain the timely inn; and near approaches
+The subject of our watch.
+
+ +Third Murderer +
+Hark! I hear horses.
+
+ +BANQUO +
+[Within] Give us a light there, ho!
+
+ +Second Murderer +
+Then 'tis he: the rest
+That are within the note of expectation
+Already are i' the court.
+
+ +First Murderer +
+His horses go about.
+
+ +Third Murderer +
+Almost a mile: but he does usually,
+So all men do, from hence to the palace gate
+Make it their walk.
+
+ +Second Murderer +
+A light, a light!
+

Enter BANQUO, and FLEANCE with a torch

+
+ +Third Murderer +
+'Tis he.
+
+ +First Murderer +
+Stand to't.
+
+ +BANQUO +
+It will be rain to-night.
+
+ +First Murderer +
+Let it come down.
+

They set upon BANQUO

+
+ +BANQUO +
+O, treachery! Fly, good Fleance, fly, fly, fly!
+Thou mayst revenge. O slave!
+

Dies. FLEANCE escapes

+
+ +Third Murderer +
+Who did strike out the light?
+
+ +First Murderer +
+Wast not the way?
+
+ +Third Murderer +
+There's but one down; the son is fled.
+
+ +Second Murderer +
+We have lost
+Best half of our affair.
+
+ +First Murderer +
+Well, let's away, and say how much is done.
+

Exeunt

+
+

SCENE IV. The same. Hall in the palace.

+

+A banquet prepared. Enter MACBETH, LADY MACBETH, ROSS, LENNOX, Lords, and Attendants +
+ +MACBETH +
+You know your own degrees; sit down: at first
+And last the hearty welcome.
+
+ +Lords +
+Thanks to your majesty.
+
+ +MACBETH +
+Ourself will mingle with society,
+And play the humble host.
+Our hostess keeps her state, but in best time
+We will require her welcome.
+
+ +LADY MACBETH +
+Pronounce it for me, sir, to all our friends;
+For my heart speaks they are welcome.
+

First Murderer appears at the door

+
+ +MACBETH +
+See, they encounter thee with their hearts' thanks.
+Both sides are even: here I'll sit i' the midst:
+Be large in mirth; anon we'll drink a measure
+The table round.
+

Approaching the door

+There's blood on thy face.
+
+ +First Murderer +
+'Tis Banquo's then.
+
+ +MACBETH +
+'Tis better thee without than he within.
+Is he dispatch'd?
+
+ +First Murderer +
+My lord, his throat is cut; that I did for him.
+
+ +MACBETH +
+Thou art the best o' the cut-throats: yet he's good
+That did the like for Fleance: if thou didst it,
+Thou art the nonpareil.
+
+ +First Murderer +
+Most royal sir,
+Fleance is 'scaped.
+
+ +MACBETH +
+Then comes my fit again: I had else been perfect,
+Whole as the marble, founded as the rock,
+As broad and general as the casing air:
+But now I am cabin'd, cribb'd, confined, bound in
+To saucy doubts and fears. But Banquo's safe?
+
+ +First Murderer +
+Ay, my good lord: safe in a ditch he bides,
+With twenty trenched gashes on his head;
+The least a death to nature.
+
+ +MACBETH +
+Thanks for that:
+There the grown serpent lies; the worm that's fled
+Hath nature that in time will venom breed,
+No teeth for the present. Get thee gone: to-morrow
+We'll hear, ourselves, again.
+

Exit Murderer

+
+ +LADY MACBETH +
+My royal lord,
+You do not give the cheer: the feast is sold
+That is not often vouch'd, while 'tis a-making,
+'Tis given with welcome: to feed were best at home;
+From thence the sauce to meat is ceremony;
+Meeting were bare without it.
+
+ +MACBETH +
+Sweet remembrancer!
+Now, good digestion wait on appetite,
+And health on both!
+
+ +LENNOX +
+May't please your highness sit.
+

The GHOST OF BANQUO enters, and sits in MACBETH's place

+
+ +MACBETH +
+Here had we now our country's honour roof'd,
+Were the graced person of our Banquo present;
+Who may I rather challenge for unkindness
+Than pity for mischance!
+
+ +ROSS +
+His absence, sir,
+Lays blame upon his promise. Please't your highness
+To grace us with your royal company.
+
+ +MACBETH +
+The table's full.
+
+ +LENNOX +
+ Here is a place reserved, sir.
+
+ +MACBETH +
+Where?
+
+ +LENNOX +
+Here, my good lord. What is't that moves your highness?
+
+ +MACBETH +
+Which of you have done this?
+
+ +Lords +
+What, my good lord?
+
+ +MACBETH +
+Thou canst not say I did it: never shake
+Thy gory locks at me.
+
+ +ROSS +
+Gentlemen, rise: his highness is not well.
+
+ +LADY MACBETH +
+Sit, worthy friends: my lord is often thus,
+And hath been from his youth: pray you, keep seat;
+The fit is momentary; upon a thought
+He will again be well: if much you note him,
+You shall offend him and extend his passion:
+Feed, and regard him not. Are you a man?
+
+ +MACBETH +
+Ay, and a bold one, that dare look on that
+Which might appal the devil.
+
+ +LADY MACBETH +
+O proper stuff!
+This is the very painting of your fear:
+This is the air-drawn dagger which, you said,
+Led you to Duncan. O, these flaws and starts,
+Impostors to true fear, would well become
+A woman's story at a winter's fire,
+Authorized by her grandam. Shame itself!
+Why do you make such faces? When all's done,
+You look but on a stool.
+
+ +MACBETH +
+Prithee, see there! behold! look! lo!
+how say you?
+Why, what care I? If thou canst nod, speak too.
+If charnel-houses and our graves must send
+Those that we bury back, our monuments
+Shall be the maws of kites.
+

GHOST OF BANQUO vanishes

+
+ +LADY MACBETH +
+What, quite unmann'd in folly?
+
+ +MACBETH +
+If I stand here, I saw him.
+
+ +LADY MACBETH +
+Fie, for shame!
+
+ +MACBETH +
+Blood hath been shed ere now, i' the olden time,
+Ere human statute purged the gentle weal;
+Ay, and since too, murders have been perform'd
+Too terrible for the ear: the times have been,
+That, when the brains were out, the man would die,
+And there an end; but now they rise again,
+With twenty mortal murders on their crowns,
+And push us from our stools: this is more strange
+Than such a murder is.
+
+ +LADY MACBETH +
+My worthy lord,
+Your noble friends do lack you.
+
+ +MACBETH +
+I do forget.
+Do not muse at me, my most worthy friends,
+I have a strange infirmity, which is nothing
+To those that know me. Come, love and health to all;
+Then I'll sit down. Give me some wine; fill full.
+I drink to the general joy o' the whole table,
+And to our dear friend Banquo, whom we miss;
+Would he were here! to all, and him, we thirst,
+And all to all.
+
+ +Lords +
+ Our duties, and the pledge.
+

Re-enter GHOST OF BANQUO

+
+ +MACBETH +
+Avaunt! and quit my sight! let the earth hide thee!
+Thy bones are marrowless, thy blood is cold;
+Thou hast no speculation in those eyes
+Which thou dost glare with!
+
+ +LADY MACBETH +
+Think of this, good peers,
+But as a thing of custom: 'tis no other;
+Only it spoils the pleasure of the time.
+
+ +MACBETH +
+What man dare, I dare:
+Approach thou like the rugged Russian bear,
+The arm'd rhinoceros, or the Hyrcan tiger;
+Take any shape but that, and my firm nerves
+Shall never tremble: or be alive again,
+And dare me to the desert with thy sword;
+If trembling I inhabit then, protest me
+The baby of a girl. Hence, horrible shadow!
+Unreal mockery, hence!
+

GHOST OF BANQUO vanishes

+Why, so: being gone,
+I am a man again. Pray you, sit still.
+
+ +LADY MACBETH +
+You have displaced the mirth, broke the good meeting,
+With most admired disorder.
+
+ +MACBETH +
+Can such things be,
+And overcome us like a summer's cloud,
+Without our special wonder? You make me strange
+Even to the disposition that I owe,
+When now I think you can behold such sights,
+And keep the natural ruby of your cheeks,
+When mine is blanched with fear.
+
+ +ROSS +
+What sights, my lord?
+
+ +LADY MACBETH +
+I pray you, speak not; he grows worse and worse;
+Question enrages him. At once, good night:
+Stand not upon the order of your going,
+But go at once.
+
+ +LENNOX +
+ Good night; and better health
+Attend his majesty!
+
+ +LADY MACBETH +
+A kind good night to all!
+

Exeunt all but MACBETH and LADY MACBETH

+
+ +MACBETH +
+It will have blood; they say, blood will have blood:
+Stones have been known to move and trees to speak;
+Augurs and understood relations have
+By magot-pies and choughs and rooks brought forth
+The secret'st man of blood. What is the night?
+
+ +LADY MACBETH +
+Almost at odds with morning, which is which.
+
+ +MACBETH +
+How say'st thou, that Macduff denies his person
+At our great bidding?
+
+ +LADY MACBETH +
+Did you send to him, sir?
+
+ +MACBETH +
+I hear it by the way; but I will send:
+There's not a one of them but in his house
+I keep a servant fee'd. I will to-morrow,
+And betimes I will, to the weird sisters:
+More shall they speak; for now I am bent to know,
+By the worst means, the worst. For mine own good,
+All causes shall give way: I am in blood
+Stepp'd in so far that, should I wade no more,
+Returning were as tedious as go o'er:
+Strange things I have in head, that will to hand;
+Which must be acted ere they may be scann'd.
+
+ +LADY MACBETH +
+You lack the season of all natures, sleep.
+
+ +MACBETH +
+Come, we'll to sleep. My strange and self-abuse
+Is the initiate fear that wants hard use:
+We are yet but young in deed.
+

Exeunt

+
+

SCENE V. A Heath.

+

+Thunder. Enter the three Witches meeting HECATE +
+ +First Witch +
+Why, how now, Hecate! you look angerly.
+
+ +HECATE +
+Have I not reason, beldams as you are,
+Saucy and overbold? How did you dare
+To trade and traffic with Macbeth
+In riddles and affairs of death;
+And I, the mistress of your charms,
+The close contriver of all harms,
+Was never call'd to bear my part,
+Or show the glory of our art?
+And, which is worse, all you have done
+Hath been but for a wayward son,
+Spiteful and wrathful, who, as others do,
+Loves for his own ends, not for you.
+But make amends now: get you gone,
+And at the pit of Acheron
+Meet me i' the morning: thither he
+Will come to know his destiny:
+Your vessels and your spells provide,
+Your charms and every thing beside.
+I am for the air; this night I'll spend
+Unto a dismal and a fatal end:
+Great business must be wrought ere noon:
+Upon the corner of the moon
+There hangs a vaporous drop profound;
+I'll catch it ere it come to ground:
+And that distill'd by magic sleights
+Shall raise such artificial sprites
+As by the strength of their illusion
+Shall draw him on to his confusion:
+He shall spurn fate, scorn death, and bear
+He hopes 'bove wisdom, grace and fear:
+And you all know, security
+Is mortals' chiefest enemy.
+

Music and a song within: 'Come away, come away,' & c

+Hark! I am call'd; my little spirit, see,
+Sits in a foggy cloud, and stays for me.
+

Exit

+
+ +First Witch +
+Come, let's make haste; she'll soon be back again.
+

Exeunt

+
+

SCENE VI. Forres. The palace.

+

+Enter LENNOX and another Lord +
+ +LENNOX +
+My former speeches have but hit your thoughts,
+Which can interpret further: only, I say,
+Things have been strangely borne. The
+gracious Duncan
+Was pitied of Macbeth: marry, he was dead:
+And the right-valiant Banquo walk'd too late;
+Whom, you may say, if't please you, Fleance kill'd,
+For Fleance fled: men must not walk too late.
+Who cannot want the thought how monstrous
+It was for Malcolm and for Donalbain
+To kill their gracious father? damned fact!
+How it did grieve Macbeth! did he not straight
+In pious rage the two delinquents tear,
+That were the slaves of drink and thralls of sleep?
+Was not that nobly done? Ay, and wisely too;
+For 'twould have anger'd any heart alive
+To hear the men deny't. So that, I say,
+He has borne all things well: and I do think
+That had he Duncan's sons under his key--
+As, an't please heaven, he shall not--they
+should find
+What 'twere to kill a father; so should Fleance.
+But, peace! for from broad words and 'cause he fail'd
+His presence at the tyrant's feast, I hear
+Macduff lives in disgrace: sir, can you tell
+Where he bestows himself?
+
+ +Lord +
+The son of Duncan,
+From whom this tyrant holds the due of birth
+Lives in the English court, and is received
+Of the most pious Edward with such grace
+That the malevolence of fortune nothing
+Takes from his high respect: thither Macduff
+Is gone to pray the holy king, upon his aid
+To wake Northumberland and warlike Siward:
+That, by the help of these--with Him above
+To ratify the work--we may again
+Give to our tables meat, sleep to our nights,
+Free from our feasts and banquets bloody knives,
+Do faithful homage and receive free honours:
+All which we pine for now: and this report
+Hath so exasperate the king that he
+Prepares for some attempt of war.
+
+ +LENNOX +
+Sent he to Macduff?
+
+ +Lord +
+He did: and with an absolute 'Sir, not I,'
+The cloudy messenger turns me his back,
+And hums, as who should say 'You'll rue the time
+That clogs me with this answer.'
+
+ +LENNOX +
+And that well might
+Advise him to a caution, to hold what distance
+His wisdom can provide. Some holy angel
+Fly to the court of England and unfold
+His message ere he come, that a swift blessing
+May soon return to this our suffering country
+Under a hand accursed!
+
+ +Lord +
+I'll send my prayers with him.
+

Exeunt

+

+

ACT IV

+

SCENE I. A cavern. In the middle, a boiling cauldron.

+

+Thunder. Enter the three Witches +
+ +First Witch +
+Thrice the brinded cat hath mew'd.
+
+ +Second Witch +
+Thrice and once the hedge-pig whined.
+
+ +Third Witch +
+Harpier cries 'Tis time, 'tis time.
+
+ +First Witch +
+Round about the cauldron go;
+In the poison'd entrails throw.
+Toad, that under cold stone
+Days and nights has thirty-one
+Swelter'd venom sleeping got,
+Boil thou first i' the charmed pot.
+
+ +ALL +
+Double, double toil and trouble;
+Fire burn, and cauldron bubble.
+
+ +Second Witch +
+Fillet of a fenny snake,
+In the cauldron boil and bake;
+Eye of newt and toe of frog,
+Wool of bat and tongue of dog,
+Adder's fork and blind-worm's sting,
+Lizard's leg and owlet's wing,
+For a charm of powerful trouble,
+Like a hell-broth boil and bubble.
+
+ +ALL +
+Double, double toil and trouble;
+Fire burn and cauldron bubble.
+
+ +Third Witch +
+Scale of dragon, tooth of wolf,
+Witches' mummy, maw and gulf
+Of the ravin'd salt-sea shark,
+Root of hemlock digg'd i' the dark,
+Liver of blaspheming Jew,
+Gall of goat, and slips of yew
+Silver'd in the moon's eclipse,
+Nose of Turk and Tartar's lips,
+Finger of birth-strangled babe
+Ditch-deliver'd by a drab,
+Make the gruel thick and slab:
+Add thereto a tiger's chaudron,
+For the ingredients of our cauldron.
+
+ +ALL +
+Double, double toil and trouble;
+Fire burn and cauldron bubble.
+
+ +Second Witch +
+Cool it with a baboon's blood,
+Then the charm is firm and good.
+

Enter HECATE to the other three Witches

+
+ +HECATE +
+O well done! I commend your pains;
+And every one shall share i' the gains;
+And now about the cauldron sing,
+Live elves and fairies in a ring,
+Enchanting all that you put in.
+

Music and a song: 'Black spirits,' & c

+

HECATE retires

+
+ +Second Witch +
+By the pricking of my thumbs,
+Something wicked this way comes.
+Open, locks,
+Whoever knocks!
+

Enter MACBETH

+
+ +MACBETH +
+How now, you secret, black, and midnight hags!
+What is't you do?
+
+ +ALL +
+ A deed without a name.
+
+ +MACBETH +
+I conjure you, by that which you profess,
+Howe'er you come to know it, answer me:
+Though you untie the winds and let them fight
+Against the churches; though the yesty waves
+Confound and swallow navigation up;
+Though bladed corn be lodged and trees blown down;
+Though castles topple on their warders' heads;
+Though palaces and pyramids do slope
+Their heads to their foundations; though the treasure
+Of nature's germens tumble all together,
+Even till destruction sicken; answer me
+To what I ask you.
+
+ +First Witch +
+ Speak.
+
+ +Second Witch +
+Demand.
+
+ +Third Witch +
+We'll answer.
+
+ +First Witch +
+Say, if thou'dst rather hear it from our mouths,
+Or from our masters?
+
+ +MACBETH +
+Call 'em; let me see 'em.
+
+ +First Witch +
+Pour in sow's blood, that hath eaten
+Her nine farrow; grease that's sweaten
+From the murderer's gibbet throw
+Into the flame.
+
+ +ALL +
+ Come, high or low;
+Thyself and office deftly show!
+

Thunder. First Apparition: an armed Head

+
+ +MACBETH +
+Tell me, thou unknown power,--
+
+ +First Witch +
+He knows thy thought:
+Hear his speech, but say thou nought.
+
+ +First Apparition +
+Macbeth! Macbeth! Macbeth! beware Macduff;
+Beware the thane of Fife. Dismiss me. Enough.
+

Descends

+
+ +MACBETH +
+Whate'er thou art, for thy good caution, thanks;
+Thou hast harp'd my fear aright: but one
+word more,--
+
+ +First Witch +
+He will not be commanded: here's another,
+More potent than the first.
+

Thunder. Second Apparition: A bloody Child

+
+ +Second Apparition +
+Macbeth! Macbeth! Macbeth!
+
+ +MACBETH +
+Had I three ears, I'ld hear thee.
+
+ +Second Apparition +
+Be bloody, bold, and resolute; laugh to scorn
+The power of man, for none of woman born
+Shall harm Macbeth.
+

Descends

+
+ +MACBETH +
+Then live, Macduff: what need I fear of thee?
+But yet I'll make assurance double sure,
+And take a bond of fate: thou shalt not live;
+That I may tell pale-hearted fear it lies,
+And sleep in spite of thunder.
+

Thunder. Third Apparition: a Child crowned, with a tree in his hand

+What is this
+That rises like the issue of a king,
+And wears upon his baby-brow the round
+And top of sovereignty?
+
+ +ALL +
+Listen, but speak not to't.
+
+ +Third Apparition +
+Be lion-mettled, proud; and take no care
+Who chafes, who frets, or where conspirers are:
+Macbeth shall never vanquish'd be until
+Great Birnam wood to high Dunsinane hill
+Shall come against him.
+

Descends

+
+ +MACBETH +
+That will never be
+Who can impress the forest, bid the tree
+Unfix his earth-bound root? Sweet bodements! good!
+Rebellion's head, rise never till the wood
+Of Birnam rise, and our high-placed Macbeth
+Shall live the lease of nature, pay his breath
+To time and mortal custom. Yet my heart
+Throbs to know one thing: tell me, if your art
+Can tell so much: shall Banquo's issue ever
+Reign in this kingdom?
+
+ +ALL +
+Seek to know no more.
+
+ +MACBETH +
+I will be satisfied: deny me this,
+And an eternal curse fall on you! Let me know.
+Why sinks that cauldron? and what noise is this?
+

Hautboys

+
+ +First Witch +
+Show!
+
+ +Second Witch +
+Show!
+
+ +Third Witch +
+Show!
+
+ +ALL +
+Show his eyes, and grieve his heart;
+Come like shadows, so depart!
+

A show of Eight Kings, the last with a glass in his hand; GHOST OF BANQUO following

+
+ +MACBETH +
+Thou art too like the spirit of Banquo: down!
+Thy crown does sear mine eye-balls. And thy hair,
+Thou other gold-bound brow, is like the first.
+A third is like the former. Filthy hags!
+Why do you show me this? A fourth! Start, eyes!
+What, will the line stretch out to the crack of doom?
+Another yet! A seventh! I'll see no more:
+And yet the eighth appears, who bears a glass
+Which shows me many more; and some I see
+That two-fold balls and treble scepters carry:
+Horrible sight! Now, I see, 'tis true;
+For the blood-bolter'd Banquo smiles upon me,
+And points at them for his.
+

Apparitions vanish

+What, is this so?
+
+ +First Witch +
+Ay, sir, all this is so: but why
+Stands Macbeth thus amazedly?
+Come, sisters, cheer we up his sprites,
+And show the best of our delights:
+I'll charm the air to give a sound,
+While you perform your antic round:
+That this great king may kindly say,
+Our duties did his welcome pay.
+

Music. The witches dance and then vanish, with HECATE

+
+ +MACBETH +
+Where are they? Gone? Let this pernicious hour
+Stand aye accursed in the calendar!
+Come in, without there!
+

Enter LENNOX

+
+ +LENNOX +
+What's your grace's will?
+
+ +MACBETH +
+Saw you the weird sisters?
+
+ +LENNOX +
+No, my lord.
+
+ +MACBETH +
+Came they not by you?
+
+ +LENNOX +
+No, indeed, my lord.
+
+ +MACBETH +
+Infected be the air whereon they ride;
+And damn'd all those that trust them! I did hear
+The galloping of horse: who was't came by?
+
+ +LENNOX +
+'Tis two or three, my lord, that bring you word
+Macduff is fled to England.
+
+ +MACBETH +
+Fled to England!
+
+ +LENNOX +
+Ay, my good lord.
+
+ +MACBETH +
+Time, thou anticipatest my dread exploits:
+The flighty purpose never is o'ertook
+Unless the deed go with it; from this moment
+The very firstlings of my heart shall be
+The firstlings of my hand. And even now,
+To crown my thoughts with acts, be it thought and done:
+The castle of Macduff I will surprise;
+Seize upon Fife; give to the edge o' the sword
+His wife, his babes, and all unfortunate souls
+That trace him in his line. No boasting like a fool;
+This deed I'll do before this purpose cool.
+But no more sights!--Where are these gentlemen?
+Come, bring me where they are.
+

Exeunt

+
+

SCENE II. Fife. Macduff's castle.

+

+Enter LADY MACDUFF, her Son, and ROSS +
+ +LADY MACDUFF +
+What had he done, to make him fly the land?
+
+ +ROSS +
+You must have patience, madam.
+
+ +LADY MACDUFF +
+He had none:
+His flight was madness: when our actions do not,
+Our fears do make us traitors.
+
+ +ROSS +
+You know not
+Whether it was his wisdom or his fear.
+
+ +LADY MACDUFF +
+Wisdom! to leave his wife, to leave his babes,
+His mansion and his titles in a place
+From whence himself does fly? He loves us not;
+He wants the natural touch: for the poor wren,
+The most diminutive of birds, will fight,
+Her young ones in her nest, against the owl.
+All is the fear and nothing is the love;
+As little is the wisdom, where the flight
+So runs against all reason.
+
+ +ROSS +
+My dearest coz,
+I pray you, school yourself: but for your husband,
+He is noble, wise, judicious, and best knows
+The fits o' the season. I dare not speak
+much further;
+But cruel are the times, when we are traitors
+And do not know ourselves, when we hold rumour
+From what we fear, yet know not what we fear,
+But float upon a wild and violent sea
+Each way and move. I take my leave of you:
+Shall not be long but I'll be here again:
+Things at the worst will cease, or else climb upward
+To what they were before. My pretty cousin,
+Blessing upon you!
+
+ +LADY MACDUFF +
+Father'd he is, and yet he's fatherless.
+
+ +ROSS +
+I am so much a fool, should I stay longer,
+It would be my disgrace and your discomfort:
+I take my leave at once.
+

Exit

+
+ +LADY MACDUFF +
+Sirrah, your father's dead;
+And what will you do now? How will you live?
+
+ +Son +
+As birds do, mother.
+
+ +LADY MACDUFF +
+What, with worms and flies?
+
+ +Son +
+With what I get, I mean; and so do they.
+
+ +LADY MACDUFF +
+Poor bird! thou'ldst never fear the net nor lime,
+The pitfall nor the gin.
+
+ +Son +
+Why should I, mother? Poor birds they are not set for.
+My father is not dead, for all your saying.
+
+ +LADY MACDUFF +
+Yes, he is dead; how wilt thou do for a father?
+
+ +Son +
+Nay, how will you do for a husband?
+
+ +LADY MACDUFF +
+Why, I can buy me twenty at any market.
+
+ +Son +
+Then you'll buy 'em to sell again.
+
+ +LADY MACDUFF +
+Thou speak'st with all thy wit: and yet, i' faith,
+With wit enough for thee.
+
+ +Son +
+Was my father a traitor, mother?
+
+ +LADY MACDUFF +
+Ay, that he was.
+
+ +Son +
+What is a traitor?
+
+ +LADY MACDUFF +
+Why, one that swears and lies.
+
+ +Son +
+And be all traitors that do so?
+
+ +LADY MACDUFF +
+Every one that does so is a traitor, and must be hanged.
+
+ +Son +
+And must they all be hanged that swear and lie?
+
+ +LADY MACDUFF +
+Every one.
+
+ +Son +
+Who must hang them?
+
+ +LADY MACDUFF +
+Why, the honest men.
+
+ +Son +
+Then the liars and swearers are fools,
+for there are liars and swearers enow to beat
+the honest men and hang up them.
+
+ +LADY MACDUFF +
+Now, God help thee, poor monkey!
+But how wilt thou do for a father?
+
+ +Son +
+If he were dead, you'ld weep for
+him: if you would not, it were a good sign
+that I should quickly have a new father.
+
+ +LADY MACDUFF +
+Poor prattler, how thou talk'st!
+

Enter a Messenger

+
+ +Messenger +
+Bless you, fair dame! I am not to you known,
+Though in your state of honour I am perfect.
+I doubt some danger does approach you nearly:
+If you will take a homely man's advice,
+Be not found here; hence, with your little ones.
+To fright you thus, methinks, I am too savage;
+To do worse to you were fell cruelty,
+Which is too nigh your person. Heaven preserve you!
+I dare abide no longer.
+

Exit

+
+ +LADY MACDUFF +
+Whither should I fly?
+I have done no harm. But I remember now
+I am in this earthly world; where to do harm
+Is often laudable, to do good sometime
+Accounted dangerous folly: why then, alas,
+Do I put up that womanly defence,
+To say I have done no harm?
+

Enter Murderers

+What are these faces?
+
+ +First Murderer +
+Where is your husband?
+
+ +LADY MACDUFF +
+I hope, in no place so unsanctified
+Where such as thou mayst find him.
+
+ +First Murderer +
+He's a traitor.
+
+ +Son +
+Thou liest, thou shag-hair'd villain!
+
+ +First Murderer +
+What, you egg!
+

Stabbing him

+Young fry of treachery!
+
+ +Son +
+He has kill'd me, mother:
+Run away, I pray you!
+

Dies

+

Exit LADY MACDUFF, crying 'Murder!' Exeunt Murderers, following her

+
+

SCENE III. England. Before the King's palace.

+

+Enter MALCOLM and MACDUFF +
+ +MALCOLM +
+Let us seek out some desolate shade, and there
+Weep our sad bosoms empty.
+
+ +MACDUFF +
+Let us rather
+Hold fast the mortal sword, and like good men
+Bestride our down-fall'n birthdom: each new morn
+New widows howl, new orphans cry, new sorrows
+Strike heaven on the face, that it resounds
+As if it felt with Scotland and yell'd out
+Like syllable of dolour.
+
+ +MALCOLM +
+What I believe I'll wail,
+What know believe, and what I can redress,
+As I shall find the time to friend, I will.
+What you have spoke, it may be so perchance.
+This tyrant, whose sole name blisters our tongues,
+Was once thought honest: you have loved him well.
+He hath not touch'd you yet. I am young;
+but something
+You may deserve of him through me, and wisdom
+To offer up a weak poor innocent lamb
+To appease an angry god.
+
+ +MACDUFF +
+I am not treacherous.
+
+ +MALCOLM +
+But Macbeth is.
+A good and virtuous nature may recoil
+In an imperial charge. But I shall crave
+your pardon;
+That which you are my thoughts cannot transpose:
+Angels are bright still, though the brightest fell;
+Though all things foul would wear the brows of grace,
+Yet grace must still look so.
+
+ +MACDUFF +
+I have lost my hopes.
+
+ +MALCOLM +
+Perchance even there where I did find my doubts.
+Why in that rawness left you wife and child,
+Those precious motives, those strong knots of love,
+Without leave-taking? I pray you,
+Let not my jealousies be your dishonours,
+But mine own safeties. You may be rightly just,
+Whatever I shall think.
+
+ +MACDUFF +
+Bleed, bleed, poor country!
+Great tyranny! lay thou thy basis sure,
+For goodness dare not cheque thee: wear thou
+thy wrongs;
+The title is affeer'd! Fare thee well, lord:
+I would not be the villain that thou think'st
+For the whole space that's in the tyrant's grasp,
+And the rich East to boot.
+
+ +MALCOLM +
+Be not offended:
+I speak not as in absolute fear of you.
+I think our country sinks beneath the yoke;
+It weeps, it bleeds; and each new day a gash
+Is added to her wounds: I think withal
+There would be hands uplifted in my right;
+And here from gracious England have I offer
+Of goodly thousands: but, for all this,
+When I shall tread upon the tyrant's head,
+Or wear it on my sword, yet my poor country
+Shall have more vices than it had before,
+More suffer and more sundry ways than ever,
+By him that shall succeed.
+
+ +MACDUFF +
+What should he be?
+
+ +MALCOLM +
+It is myself I mean: in whom I know
+All the particulars of vice so grafted
+That, when they shall be open'd, black Macbeth
+Will seem as pure as snow, and the poor state
+Esteem him as a lamb, being compared
+With my confineless harms.
+
+ +MACDUFF +
+Not in the legions
+Of horrid hell can come a devil more damn'd
+In evils to top Macbeth.
+
+ +MALCOLM +
+I grant him bloody,
+Luxurious, avaricious, false, deceitful,
+Sudden, malicious, smacking of every sin
+That has a name: but there's no bottom, none,
+In my voluptuousness: your wives, your daughters,
+Your matrons and your maids, could not fill up
+The cistern of my lust, and my desire
+All continent impediments would o'erbear
+That did oppose my will: better Macbeth
+Than such an one to reign.
+
+ +MACDUFF +
+Boundless intemperance
+In nature is a tyranny; it hath been
+The untimely emptying of the happy throne
+And fall of many kings. But fear not yet
+To take upon you what is yours: you may
+Convey your pleasures in a spacious plenty,
+And yet seem cold, the time you may so hoodwink.
+We have willing dames enough: there cannot be
+That vulture in you, to devour so many
+As will to greatness dedicate themselves,
+Finding it so inclined.
+
+ +MALCOLM +
+With this there grows
+In my most ill-composed affection such
+A stanchless avarice that, were I king,
+I should cut off the nobles for their lands,
+Desire his jewels and this other's house:
+And my more-having would be as a sauce
+To make me hunger more; that I should forge
+Quarrels unjust against the good and loyal,
+Destroying them for wealth.
+
+ +MACDUFF +
+This avarice
+Sticks deeper, grows with more pernicious root
+Than summer-seeming lust, and it hath been
+The sword of our slain kings: yet do not fear;
+Scotland hath foisons to fill up your will.
+Of your mere own: all these are portable,
+With other graces weigh'd.
+
+ +MALCOLM +
+But I have none: the king-becoming graces,
+As justice, verity, temperance, stableness,
+Bounty, perseverance, mercy, lowliness,
+Devotion, patience, courage, fortitude,
+I have no relish of them, but abound
+In the division of each several crime,
+Acting it many ways. Nay, had I power, I should
+Pour the sweet milk of concord into hell,
+Uproar the universal peace, confound
+All unity on earth.
+
+ +MACDUFF +
+O Scotland, Scotland!
+
+ +MALCOLM +
+If such a one be fit to govern, speak:
+I am as I have spoken.
+
+ +MACDUFF +
+Fit to govern!
+No, not to live. O nation miserable,
+With an untitled tyrant bloody-scepter'd,
+When shalt thou see thy wholesome days again,
+Since that the truest issue of thy throne
+By his own interdiction stands accursed,
+And does blaspheme his breed? Thy royal father
+Was a most sainted king: the queen that bore thee,
+Oftener upon her knees than on her feet,
+Died every day she lived. Fare thee well!
+These evils thou repeat'st upon thyself
+Have banish'd me from Scotland. O my breast,
+Thy hope ends here!
+
+ +MALCOLM +
+Macduff, this noble passion,
+Child of integrity, hath from my soul
+Wiped the black scruples, reconciled my thoughts
+To thy good truth and honour. Devilish Macbeth
+By many of these trains hath sought to win me
+Into his power, and modest wisdom plucks me
+From over-credulous haste: but God above
+Deal between thee and me! for even now
+I put myself to thy direction, and
+Unspeak mine own detraction, here abjure
+The taints and blames I laid upon myself,
+For strangers to my nature. I am yet
+Unknown to woman, never was forsworn,
+Scarcely have coveted what was mine own,
+At no time broke my faith, would not betray
+The devil to his fellow and delight
+No less in truth than life: my first false speaking
+Was this upon myself: what I am truly,
+Is thine and my poor country's to command:
+Whither indeed, before thy here-approach,
+Old Siward, with ten thousand warlike men,
+Already at a point, was setting forth.
+Now we'll together; and the chance of goodness
+Be like our warranted quarrel! Why are you silent?
+
+ +MACDUFF +
+Such welcome and unwelcome things at once
+'Tis hard to reconcile.
+

Enter a Doctor

+
+ +MALCOLM +
+Well; more anon.--Comes the king forth, I pray you?
+
+ +Doctor +
+Ay, sir; there are a crew of wretched souls
+That stay his cure: their malady convinces
+The great assay of art; but at his touch--
+Such sanctity hath heaven given his hand--
+They presently amend.
+
+ +MALCOLM +
+I thank you, doctor.
+

Exit Doctor

+
+ +MACDUFF +
+What's the disease he means?
+
+ +MALCOLM +
+'Tis call'd the evil:
+A most miraculous work in this good king;
+Which often, since my here-remain in England,
+I have seen him do. How he solicits heaven,
+Himself best knows: but strangely-visited people,
+All swoln and ulcerous, pitiful to the eye,
+The mere despair of surgery, he cures,
+Hanging a golden stamp about their necks,
+Put on with holy prayers: and 'tis spoken,
+To the succeeding royalty he leaves
+The healing benediction. With this strange virtue,
+He hath a heavenly gift of prophecy,
+And sundry blessings hang about his throne,
+That speak him full of grace.
+

Enter ROSS

+
+ +MACDUFF +
+See, who comes here?
+
+ +MALCOLM +
+My countryman; but yet I know him not.
+
+ +MACDUFF +
+My ever-gentle cousin, welcome hither.
+
+ +MALCOLM +
+I know him now. Good God, betimes remove
+The means that makes us strangers!
+
+ +ROSS +
+Sir, amen.
+
+ +MACDUFF +
+Stands Scotland where it did?
+
+ +ROSS +
+Alas, poor country!
+Almost afraid to know itself. It cannot
+Be call'd our mother, but our grave; where nothing,
+But who knows nothing, is once seen to smile;
+Where sighs and groans and shrieks that rend the air
+Are made, not mark'd; where violent sorrow seems
+A modern ecstasy; the dead man's knell
+Is there scarce ask'd for who; and good men's lives
+Expire before the flowers in their caps,
+Dying or ere they sicken.
+
+ +MACDUFF +
+O, relation
+Too nice, and yet too true!
+
+ +MALCOLM +
+What's the newest grief?
+
+ +ROSS +
+That of an hour's age doth hiss the speaker:
+Each minute teems a new one.
+
+ +MACDUFF +
+How does my wife?
+
+ +ROSS +
+Why, well.
+
+ +MACDUFF +
+ And all my children?
+
+ +ROSS +
+Well too.
+
+ +MACDUFF +
+The tyrant has not batter'd at their peace?
+
+ +ROSS +
+No; they were well at peace when I did leave 'em.
+
+ +MACDUFF +
+But not a niggard of your speech: how goes't?
+
+ +ROSS +
+When I came hither to transport the tidings,
+Which I have heavily borne, there ran a rumour
+Of many worthy fellows that were out;
+Which was to my belief witness'd the rather,
+For that I saw the tyrant's power a-foot:
+Now is the time of help; your eye in Scotland
+Would create soldiers, make our women fight,
+To doff their dire distresses.
+
+ +MALCOLM +
+Be't their comfort
+We are coming thither: gracious England hath
+Lent us good Siward and ten thousand men;
+An older and a better soldier none
+That Christendom gives out.
+
+ +ROSS +
+Would I could answer
+This comfort with the like! But I have words
+That would be howl'd out in the desert air,
+Where hearing should not latch them.
+
+ +MACDUFF +
+What concern they?
+The general cause? or is it a fee-grief
+Due to some single breast?
+
+ +ROSS +
+No mind that's honest
+But in it shares some woe; though the main part
+Pertains to you alone.
+
+ +MACDUFF +
+If it be mine,
+Keep it not from me, quickly let me have it.
+
+ +ROSS +
+Let not your ears despise my tongue for ever,
+Which shall possess them with the heaviest sound
+That ever yet they heard.
+
+ +MACDUFF +
+Hum! I guess at it.
+
+ +ROSS +
+Your castle is surprised; your wife and babes
+Savagely slaughter'd: to relate the manner,
+Were, on the quarry of these murder'd deer,
+To add the death of you.
+
+ +MALCOLM +
+Merciful heaven!
+What, man! ne'er pull your hat upon your brows;
+Give sorrow words: the grief that does not speak
+Whispers the o'er-fraught heart and bids it break.
+
+ +MACDUFF +
+My children too?
+
+ +ROSS +
+ Wife, children, servants, all
+That could be found.
+
+ +MACDUFF +
+And I must be from thence!
+My wife kill'd too?
+
+ +ROSS +
+I have said.
+
+ +MALCOLM +
+Be comforted:
+Let's make us medicines of our great revenge,
+To cure this deadly grief.
+
+ +MACDUFF +
+He has no children. All my pretty ones?
+Did you say all? O hell-kite! All?
+What, all my pretty chickens and their dam
+At one fell swoop?
+
+ +MALCOLM +
+Dispute it like a man.
+
+ +MACDUFF +
+I shall do so;
+But I must also feel it as a man:
+I cannot but remember such things were,
+That were most precious to me. Did heaven look on,
+And would not take their part? Sinful Macduff,
+They were all struck for thee! naught that I am,
+Not for their own demerits, but for mine,
+Fell slaughter on their souls. Heaven rest them now!
+
+ +MALCOLM +
+Be this the whetstone of your sword: let grief
+Convert to anger; blunt not the heart, enrage it.
+
+ +MACDUFF +
+O, I could play the woman with mine eyes
+And braggart with my tongue! But, gentle heavens,
+Cut short all intermission; front to front
+Bring thou this fiend of Scotland and myself;
+Within my sword's length set him; if he 'scape,
+Heaven forgive him too!
+
+ +MALCOLM +
+This tune goes manly.
+Come, go we to the king; our power is ready;
+Our lack is nothing but our leave; Macbeth
+Is ripe for shaking, and the powers above
+Put on their instruments. Receive what cheer you may:
+The night is long that never finds the day.
+

Exeunt

+

+

ACT V

+

SCENE I. Dunsinane. Ante-room in the castle.

+

+Enter a Doctor of Physic and a Waiting-Gentlewoman +
+ +Doctor +
+I have two nights watched with you, but can perceive
+no truth in your report. When was it she last walked?
+
+ +Gentlewoman +
+Since his majesty went into the field, I have seen
+her rise from her bed, throw her night-gown upon
+her, unlock her closet, take forth paper, fold it,
+write upon't, read it, afterwards seal it, and again
+return to bed; yet all this while in a most fast sleep.
+
+ +Doctor +
+A great perturbation in nature, to receive at once
+the benefit of sleep, and do the effects of
+watching! In this slumbery agitation, besides her
+walking and other actual performances, what, at any
+time, have you heard her say?
+
+ +Gentlewoman +
+That, sir, which I will not report after her.
+
+ +Doctor +
+You may to me: and 'tis most meet you should.
+
+ +Gentlewoman +
+Neither to you nor any one; having no witness to
+confirm my speech.
+

Enter LADY MACBETH, with a taper

+Lo you, here she comes! This is her very guise;
+and, upon my life, fast asleep. Observe her; stand close.
+
+ +Doctor +
+How came she by that light?
+
+ +Gentlewoman +
+Why, it stood by her: she has light by her
+continually; 'tis her command.
+
+ +Doctor +
+You see, her eyes are open.
+
+ +Gentlewoman +
+Ay, but their sense is shut.
+
+ +Doctor +
+What is it she does now? Look, how she rubs her hands.
+
+ +Gentlewoman +
+It is an accustomed action with her, to seem thus
+washing her hands: I have known her continue in
+this a quarter of an hour.
+
+ +LADY MACBETH +
+Yet here's a spot.
+
+ +Doctor +
+Hark! she speaks: I will set down what comes from
+her, to satisfy my remembrance the more strongly.
+
+ +LADY MACBETH +
+Out, damned spot! out, I say!--One: two: why,
+then, 'tis time to do't.--Hell is murky!--Fie, my
+lord, fie! a soldier, and afeard? What need we
+fear who knows it, when none can call our power to
+account?--Yet who would have thought the old man
+to have had so much blood in him.
+
+ +Doctor +
+Do you mark that?
+
+ +LADY MACBETH +
+The thane of Fife had a wife: where is she now?--
+What, will these hands ne'er be clean?--No more o'
+that, my lord, no more o' that: you mar all with
+this starting.
+
+ +Doctor +
+Go to, go to; you have known what you should not.
+
+ +Gentlewoman +
+She has spoke what she should not, I am sure of
+that: heaven knows what she has known.
+
+ +LADY MACBETH +
+Here's the smell of the blood still: all the
+perfumes of Arabia will not sweeten this little
+hand. Oh, oh, oh!
+
+ +Doctor +
+What a sigh is there! The heart is sorely charged.
+
+ +Gentlewoman +
+I would not have such a heart in my bosom for the
+dignity of the whole body.
+
+ +Doctor +
+Well, well, well,--
+
+ +Gentlewoman +
+Pray God it be, sir.
+
+ +Doctor +
+This disease is beyond my practise: yet I have known
+those which have walked in their sleep who have died
+holily in their beds.
+
+ +LADY MACBETH +
+Wash your hands, put on your nightgown; look not so
+pale.--I tell you yet again, Banquo's buried; he
+cannot come out on's grave.
+
+ +Doctor +
+Even so?
+
+ +LADY MACBETH +
+To bed, to bed! there's knocking at the gate:
+come, come, come, come, give me your hand. What's
+done cannot be undone.--To bed, to bed, to bed!
+

Exit

+
+ +Doctor +
+Will she go now to bed?
+
+ +Gentlewoman +
+Directly.
+
+ +Doctor +
+Foul whisperings are abroad: unnatural deeds
+Do breed unnatural troubles: infected minds
+To their deaf pillows will discharge their secrets:
+More needs she the divine than the physician.
+God, God forgive us all! Look after her;
+Remove from her the means of all annoyance,
+And still keep eyes upon her. So, good night:
+My mind she has mated, and amazed my sight.
+I think, but dare not speak.
+
+ +Gentlewoman +
+Good night, good doctor.
+

Exeunt

+
+

SCENE II. The country near Dunsinane.

+

+Drum and colours. Enter MENTEITH, CAITHNESS, ANGUS, LENNOX, and Soldiers +
+ +MENTEITH +
+The English power is near, led on by Malcolm,
+His uncle Siward and the good Macduff:
+Revenges burn in them; for their dear causes
+Would to the bleeding and the grim alarm
+Excite the mortified man.
+
+ +ANGUS +
+Near Birnam wood
+Shall we well meet them; that way are they coming.
+
+ +CAITHNESS +
+Who knows if Donalbain be with his brother?
+
+ +LENNOX +
+For certain, sir, he is not: I have a file
+Of all the gentry: there is Siward's son,
+And many unrough youths that even now
+Protest their first of manhood.
+
+ +MENTEITH +
+What does the tyrant?
+
+ +CAITHNESS +
+Great Dunsinane he strongly fortifies:
+Some say he's mad; others that lesser hate him
+Do call it valiant fury: but, for certain,
+He cannot buckle his distemper'd cause
+Within the belt of rule.
+
+ +ANGUS +
+Now does he feel
+His secret murders sticking on his hands;
+Now minutely revolts upbraid his faith-breach;
+Those he commands move only in command,
+Nothing in love: now does he feel his title
+Hang loose about him, like a giant's robe
+Upon a dwarfish thief.
+
+ +MENTEITH +
+Who then shall blame
+His pester'd senses to recoil and start,
+When all that is within him does condemn
+Itself for being there?
+
+ +CAITHNESS +
+Well, march we on,
+To give obedience where 'tis truly owed:
+Meet we the medicine of the sickly weal,
+And with him pour we in our country's purge
+Each drop of us.
+
+ +LENNOX +
+ Or so much as it needs,
+To dew the sovereign flower and drown the weeds.
+Make we our march towards Birnam.
+

Exeunt, marching

+
+

SCENE III. Dunsinane. A room in the castle.

+

+Enter MACBETH, Doctor, and Attendants +
+ +MACBETH +
+Bring me no more reports; let them fly all:
+Till Birnam wood remove to Dunsinane,
+I cannot taint with fear. What's the boy Malcolm?
+Was he not born of woman? The spirits that know
+All mortal consequences have pronounced me thus:
+'Fear not, Macbeth; no man that's born of woman
+Shall e'er have power upon thee.' Then fly,
+false thanes,
+And mingle with the English epicures:
+The mind I sway by and the heart I bear
+Shall never sag with doubt nor shake with fear.
+

Enter a Servant

+The devil damn thee black, thou cream-faced loon!
+Where got'st thou that goose look?
+
+ +Servant +
+There is ten thousand--
+
+ +MACBETH +
+Geese, villain!
+
+ +Servant +
+Soldiers, sir.
+
+ +MACBETH +
+Go prick thy face, and over-red thy fear,
+Thou lily-liver'd boy. What soldiers, patch?
+Death of thy soul! those linen cheeks of thine
+Are counsellors to fear. What soldiers, whey-face?
+
+ +Servant +
+The English force, so please you.
+
+ +MACBETH +
+Take thy face hence.
+

Exit Servant

+Seyton!--I am sick at heart,
+When I behold--Seyton, I say!--This push
+Will cheer me ever, or disseat me now.
+I have lived long enough: my way of life
+Is fall'n into the sear, the yellow leaf;
+And that which should accompany old age,
+As honour, love, obedience, troops of friends,
+I must not look to have; but, in their stead,
+Curses, not loud but deep, mouth-honour, breath,
+Which the poor heart would fain deny, and dare not. Seyton!
+

Enter SEYTON

+
+ +SEYTON +
+What is your gracious pleasure?
+
+ +MACBETH +
+What news more?
+
+ +SEYTON +
+All is confirm'd, my lord, which was reported.
+
+ +MACBETH +
+I'll fight till from my bones my flesh be hack'd.
+Give me my armour.
+
+ +SEYTON +
+'Tis not needed yet.
+
+ +MACBETH +
+I'll put it on.
+Send out more horses; skirr the country round;
+Hang those that talk of fear. Give me mine armour.
+How does your patient, doctor?
+
+ +Doctor +
+Not so sick, my lord,
+As she is troubled with thick coming fancies,
+That keep her from her rest.
+
+ +MACBETH +
+Cure her of that.
+Canst thou not minister to a mind diseased,
+Pluck from the memory a rooted sorrow,
+Raze out the written troubles of the brain
+And with some sweet oblivious antidote
+Cleanse the stuff'd bosom of that perilous stuff
+Which weighs upon the heart?
+
+ +Doctor +
+Therein the patient
+Must minister to himself.
+
+ +MACBETH +
+Throw physic to the dogs; I'll none of it.
+Come, put mine armour on; give me my staff.
+Seyton, send out. Doctor, the thanes fly from me.
+Come, sir, dispatch. If thou couldst, doctor, cast
+The water of my land, find her disease,
+And purge it to a sound and pristine health,
+I would applaud thee to the very echo,
+That should applaud again.--Pull't off, I say.--
+What rhubarb, cyme, or what purgative drug,
+Would scour these English hence? Hear'st thou of them?
+
+ +Doctor +
+Ay, my good lord; your royal preparation
+Makes us hear something.
+
+ +MACBETH +
+Bring it after me.
+I will not be afraid of death and bane,
+Till Birnam forest come to Dunsinane.
+
+ +Doctor +
+[Aside] Were I from Dunsinane away and clear,
+Profit again should hardly draw me here.
+

Exeunt

+
+

SCENE IV. Country near Birnam wood.

+

+Drum and colours. Enter MALCOLM, SIWARD and YOUNG SIWARD, MACDUFF, MENTEITH, CAITHNESS, ANGUS, LENNOX, ROSS, and Soldiers, marching +
+ +MALCOLM +
+Cousins, I hope the days are near at hand
+That chambers will be safe.
+
+ +MENTEITH +
+We doubt it nothing.
+
+ +SIWARD +
+What wood is this before us?
+
+ +MENTEITH +
+The wood of Birnam.
+
+ +MALCOLM +
+Let every soldier hew him down a bough
+And bear't before him: thereby shall we shadow
+The numbers of our host and make discovery
+Err in report of us.
+
+ +Soldiers +
+It shall be done.
+
+ +SIWARD +
+We learn no other but the confident tyrant
+Keeps still in Dunsinane, and will endure
+Our setting down before 't.
+
+ +MALCOLM +
+'Tis his main hope:
+For where there is advantage to be given,
+Both more and less have given him the revolt,
+And none serve with him but constrained things
+Whose hearts are absent too.
+
+ +MACDUFF +
+Let our just censures
+Attend the true event, and put we on
+Industrious soldiership.
+
+ +SIWARD +
+The time approaches
+That will with due decision make us know
+What we shall say we have and what we owe.
+Thoughts speculative their unsure hopes relate,
+But certain issue strokes must arbitrate:
+Towards which advance the war.
+

Exeunt, marching

+
+

SCENE V. Dunsinane. Within the castle.

+

+Enter MACBETH, SEYTON, and Soldiers, with drum and colours +
+ +MACBETH +
+Hang out our banners on the outward walls;
+The cry is still 'They come:' our castle's strength
+Will laugh a siege to scorn: here let them lie
+Till famine and the ague eat them up:
+Were they not forced with those that should be ours,
+We might have met them dareful, beard to beard,
+And beat them backward home.
+

A cry of women within

+What is that noise?
+
+ +SEYTON +
+It is the cry of women, my good lord.
+

Exit

+
+ +MACBETH +
+I have almost forgot the taste of fears;
+The time has been, my senses would have cool'd
+To hear a night-shriek; and my fell of hair
+Would at a dismal treatise rouse and stir
+As life were in't: I have supp'd full with horrors;
+Direness, familiar to my slaughterous thoughts
+Cannot once start me.
+

Re-enter SEYTON

+Wherefore was that cry?
+
+ +SEYTON +
+The queen, my lord, is dead.
+
+ +MACBETH +
+She should have died hereafter;
+There would have been a time for such a word.
+To-morrow, and to-morrow, and to-morrow,
+Creeps in this petty pace from day to day
+To the last syllable of recorded time,
+And all our yesterdays have lighted fools
+The way to dusty death. Out, out, brief candle!
+Life's but a walking shadow, a poor player
+That struts and frets his hour upon the stage
+And then is heard no more: it is a tale
+Told by an idiot, full of sound and fury,
+Signifying nothing.
+

Enter a Messenger

+Thou comest to use thy tongue; thy story quickly.
+
+ +Messenger +
+Gracious my lord,
+I should report that which I say I saw,
+But know not how to do it.
+
+ +MACBETH +
+Well, say, sir.
+
+ +Messenger +
+As I did stand my watch upon the hill,
+I look'd toward Birnam, and anon, methought,
+The wood began to move.
+
+ +MACBETH +
+Liar and slave!
+
+ +Messenger +
+Let me endure your wrath, if't be not so:
+Within this three mile may you see it coming;
+I say, a moving grove.
+
+ +MACBETH +
+If thou speak'st false,
+Upon the next tree shalt thou hang alive,
+Till famine cling thee: if thy speech be sooth,
+I care not if thou dost for me as much.
+I pull in resolution, and begin
+To doubt the equivocation of the fiend
+That lies like truth: 'Fear not, till Birnam wood
+Do come to Dunsinane:' and now a wood
+Comes toward Dunsinane. Arm, arm, and out!
+If this which he avouches does appear,
+There is nor flying hence nor tarrying here.
+I gin to be aweary of the sun,
+And wish the estate o' the world were now undone.
+Ring the alarum-bell! Blow, wind! come, wrack!
+At least we'll die with harness on our back.
+

Exeunt

+
+

SCENE VI. Dunsinane. Before the castle.

+

+Drum and colours. Enter MALCOLM, SIWARD, MACDUFF, and their Army, with boughs +
+ +MALCOLM +
+Now near enough: your leafy screens throw down.
+And show like those you are. You, worthy uncle,
+Shall, with my cousin, your right-noble son,
+Lead our first battle: worthy Macduff and we
+Shall take upon 's what else remains to do,
+According to our order.
+
+ +SIWARD +
+Fare you well.
+Do we but find the tyrant's power to-night,
+Let us be beaten, if we cannot fight.
+
+ +MACDUFF +
+Make all our trumpets speak; give them all breath,
+Those clamorous harbingers of blood and death.
+

Exeunt

+
+

SCENE VII. Another part of the field.

+

+Alarums. Enter MACBETH +
+ +MACBETH +
+They have tied me to a stake; I cannot fly,
+But, bear-like, I must fight the course. What's he
+That was not born of woman? Such a one
+Am I to fear, or none.
+

Enter YOUNG SIWARD

+
+ +YOUNG SIWARD +
+What is thy name?
+
+ +MACBETH +
+ Thou'lt be afraid to hear it.
+
+ +YOUNG SIWARD +
+No; though thou call'st thyself a hotter name
+Than any is in hell.
+
+ +MACBETH +
+My name's Macbeth.
+
+ +YOUNG SIWARD +
+The devil himself could not pronounce a title
+More hateful to mine ear.
+
+ +MACBETH +
+No, nor more fearful.
+
+ +YOUNG SIWARD +
+Thou liest, abhorred tyrant; with my sword
+I'll prove the lie thou speak'st.
+

They fight and YOUNG SIWARD is slain

+
+ +MACBETH +
+Thou wast born of woman
+But swords I smile at, weapons laugh to scorn,
+Brandish'd by man that's of a woman born.
+

Exit

+

Alarums. Enter MACDUFF

+
+ +MACDUFF +
+That way the noise is. Tyrant, show thy face!
+If thou be'st slain and with no stroke of mine,
+My wife and children's ghosts will haunt me still.
+I cannot strike at wretched kerns, whose arms
+Are hired to bear their staves: either thou, Macbeth,
+Or else my sword with an unbatter'd edge
+I sheathe again undeeded. There thou shouldst be;
+By this great clatter, one of greatest note
+Seems bruited. Let me find him, fortune!
+And more I beg not.
+

Exit. Alarums

+

Enter MALCOLM and SIWARD

+
+ +SIWARD +
+This way, my lord; the castle's gently render'd:
+The tyrant's people on both sides do fight;
+The noble thanes do bravely in the war;
+The day almost itself professes yours,
+And little is to do.
+
+ +MALCOLM +
+We have met with foes
+That strike beside us.
+
+ +SIWARD +
+Enter, sir, the castle.
+

Exeunt. Alarums

+
+

SCENE VIII. Another part of the field.

+

+Enter MACBETH +
+ +MACBETH +
+Why should I play the Roman fool, and die
+On mine own sword? whiles I see lives, the gashes
+Do better upon them.
+

Enter MACDUFF

+
+ +MACDUFF +
+Turn, hell-hound, turn!
+
+ +MACBETH +
+Of all men else I have avoided thee:
+But get thee back; my soul is too much charged
+With blood of thine already.
+
+ +MACDUFF +
+I have no words:
+My voice is in my sword: thou bloodier villain
+Than terms can give thee out!
+

They fight

+
+ +MACBETH +
+Thou losest labour:
+As easy mayst thou the intrenchant air
+With thy keen sword impress as make me bleed:
+Let fall thy blade on vulnerable crests;
+I bear a charmed life, which must not yield,
+To one of woman born.
+
+ +MACDUFF +
+Despair thy charm;
+And let the angel whom thou still hast served
+Tell thee, Macduff was from his mother's womb
+Untimely ripp'd.
+
+ +MACBETH +
+Accursed be that tongue that tells me so,
+For it hath cow'd my better part of man!
+And be these juggling fiends no more believed,
+That palter with us in a double sense;
+That keep the word of promise to our ear,
+And break it to our hope. I'll not fight with thee.
+
+ +MACDUFF +
+Then yield thee, coward,
+And live to be the show and gaze o' the time:
+We'll have thee, as our rarer monsters are,
+Painted on a pole, and underwrit,
+'Here may you see the tyrant.'
+
+ +MACBETH +
+I will not yield,
+To kiss the ground before young Malcolm's feet,
+And to be baited with the rabble's curse.
+Though Birnam wood be come to Dunsinane,
+And thou opposed, being of no woman born,
+Yet I will try the last. Before my body
+I throw my warlike shield. Lay on, Macduff,
+And damn'd be him that first cries, 'Hold, enough!'
+

Exeunt, fighting. Alarums

+

Retreat. Flourish. Enter, with drum and colours, MALCOLM, SIWARD, ROSS, the other Thanes, and Soldiers

+
+ +MALCOLM +
+I would the friends we miss were safe arrived.
+
+ +SIWARD +
+Some must go off: and yet, by these I see,
+So great a day as this is cheaply bought.
+
+ +MALCOLM +
+Macduff is missing, and your noble son.
+
+ +ROSS +
+Your son, my lord, has paid a soldier's debt:
+He only lived but till he was a man;
+The which no sooner had his prowess confirm'd
+In the unshrinking station where he fought,
+But like a man he died.
+
+ +SIWARD +
+Then he is dead?
+
+ +ROSS +
+Ay, and brought off the field: your cause of sorrow
+Must not be measured by his worth, for then
+It hath no end.
+
+ +SIWARD +
+ Had he his hurts before?
+
+ +ROSS +
+Ay, on the front.
+
+ +SIWARD +
+ Why then, God's soldier be he!
+Had I as many sons as I have hairs,
+I would not wish them to a fairer death:
+And so, his knell is knoll'd.
+
+ +MALCOLM +
+He's worth more sorrow,
+And that I'll spend for him.
+
+ +SIWARD +
+He's worth no more
+They say he parted well, and paid his score:
+And so, God be with him! Here comes newer comfort.
+

Re-enter MACDUFF, with MACBETH's head

+
+ +MACDUFF +
+Hail, king! for so thou art: behold, where stands
+The usurper's cursed head: the time is free:
+I see thee compass'd with thy kingdom's pearl,
+That speak my salutation in their minds;
+Whose voices I desire aloud with mine:
+Hail, King of Scotland!
+
+ +ALL +
+Hail, King of Scotland!
+

Flourish

+
+ +MALCOLM +
+We shall not spend a large expense of time
+Before we reckon with your several loves,
+And make us even with you. My thanes and kinsmen,
+Henceforth be earls, the first that ever Scotland
+In such an honour named. What's more to do,
+Which would be planted newly with the time,
+As calling home our exiled friends abroad
+That fled the snares of watchful tyranny;
+Producing forth the cruel ministers
+Of this dead butcher and his fiend-like queen,
+Who, as 'tis thought, by self and violent hands
+Took off her life; this, and what needful else
+That calls upon us, by the grace of Grace,
+We will perform in measure, time and place:
+So, thanks to all at once and to each one,
+Whom we invite to see us crown'd at Scone.
+

Flourish. Exeunt

+ + diff --git a/testing/marionette/harness/marionette_harness/www/modal_dialogs.html b/testing/marionette/harness/marionette_harness/www/modal_dialogs.html new file mode 100644 index 000000000..8da5b92a7 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/modal_dialogs.html @@ -0,0 +1,39 @@ + + + + + + Marionette Test + + + + Open an alert dialog. + Open a confirm dialog. + Open a prompt dialog. + Add an onbeforeunload handler. + Make text appear. +
+
+
+ + diff --git a/testing/marionette/harness/marionette_harness/www/nestedElements.html b/testing/marionette/harness/marionette_harness/www/nestedElements.html new file mode 100644 index 000000000..618bf3231 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/nestedElements.html @@ -0,0 +1,9 @@ + +hello world +hello worldhello world + + +hello worldhello worldhello world diff --git a/testing/marionette/harness/marionette_harness/www/rectangles.html b/testing/marionette/harness/marionette_harness/www/rectangles.html new file mode 100644 index 000000000..59871c6de --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/rectangles.html @@ -0,0 +1,40 @@ + + + + Rectangles + + + +
r1
+
r2
+
r3
+ + diff --git a/testing/marionette/harness/marionette_harness/www/resultPage.html b/testing/marionette/harness/marionette_harness/www/resultPage.html new file mode 100644 index 000000000..342e9930b --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/resultPage.html @@ -0,0 +1,17 @@ + + + + + We Arrive Here + + + + +
+ +
+ + + diff --git a/testing/marionette/harness/marionette_harness/www/scroll.html b/testing/marionette/harness/marionette_harness/www/scroll.html new file mode 100644 index 000000000..8a654bb50 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/scroll.html @@ -0,0 +1,30 @@ + + + + + + +
+
    +
  • line1
  • +
  • line2
  • +
  • line3
  • +
  • line4
  • +
  • line5
  • +
  • line6
  • +
  • line7
  • +
  • line8
  • +
  • line9
  • +
+
+ Clicked: +
+ + diff --git a/testing/marionette/harness/marionette_harness/www/scroll2.html b/testing/marionette/harness/marionette_harness/www/scroll2.html new file mode 100644 index 000000000..bd00f0e22 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/scroll2.html @@ -0,0 +1,24 @@ + + + + + +
    +
  • +
  • +
  • Text
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+ + diff --git a/testing/marionette/harness/marionette_harness/www/scroll3.html b/testing/marionette/harness/marionette_harness/www/scroll3.html new file mode 100644 index 000000000..b615e38c3 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/scroll3.html @@ -0,0 +1,18 @@ + + + + + + + + +



























































































































































+ +



+ +                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 +
























































































































































+ + diff --git a/testing/marionette/harness/marionette_harness/www/scroll4.html b/testing/marionette/harness/marionette_harness/www/scroll4.html new file mode 100644 index 000000000..ce0df0313 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/scroll4.html @@ -0,0 +1,15 @@ + + + + + + + + +


































































































+ +


































































































+ + diff --git a/testing/marionette/harness/marionette_harness/www/scroll5.html b/testing/marionette/harness/marionette_harness/www/scroll5.html new file mode 100644 index 000000000..3dd00721e --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/scroll5.html @@ -0,0 +1,20 @@ + + + + + + +
+
+
+
+ Clicked: +
+ + diff --git a/testing/marionette/harness/marionette_harness/www/shim.js b/testing/marionette/harness/marionette_harness/www/shim.js new file mode 100644 index 000000000..2a74e6949 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/shim.js @@ -0,0 +1,282 @@ +/** +* mouse_event_shim.js: generate mouse events from touch events. +* +* This library listens for touch events and generates mousedown, mousemove +* mouseup, and click events to match them. It captures and dicards any +* real mouse events (non-synthetic events with isTrusted true) that are +* send by gecko so that there are not duplicates. +* +* This library does emit mouseover/mouseout and mouseenter/mouseleave +* events. You can turn them off by setting MouseEventShim.trackMouseMoves to +* false. This means that mousemove events will always have the same target +* as the mousedown even that began the series. You can also call +* MouseEventShim.setCapture() from a mousedown event handler to prevent +* mouse tracking until the next mouseup event. +* +* This library does not support multi-touch but should be sufficient +* to do drags based on mousedown/mousemove/mouseup events. +* +* This library does not emit dblclick events or contextmenu events +*/ + +'use strict'; + +(function() { + // Make sure we don't run more than once + if (MouseEventShim) + return; + + // Bail if we're not on running on a platform that sends touch + // events. We don't need the shim code for mouse events. + try { + document.createEvent('TouchEvent'); + } catch (e) { + return; + } + + var starttouch; // The Touch object that we started with + var target; // The element the touch is currently over + var emitclick; // Will we be sending a click event after mouseup? + + // Use capturing listeners to discard all mouse events from gecko + window.addEventListener('mousedown', discardEvent, true); + window.addEventListener('mouseup', discardEvent, true); + window.addEventListener('mousemove', discardEvent, true); + window.addEventListener('click', discardEvent, true); + + function discardEvent(e) { + if (e.isTrusted) { + e.stopImmediatePropagation(); // so it goes no further + if (e.type === 'click') + e.preventDefault(); // so it doesn't trigger a change event + } + } + + // Listen for touch events that bubble up to the window. + // If other code has called stopPropagation on the touch events + // then we'll never see them. Also, we'll honor the defaultPrevented + // state of the event and will not generate synthetic mouse events + window.addEventListener('touchstart', handleTouchStart); + window.addEventListener('touchmove', handleTouchMove); + window.addEventListener('touchend', handleTouchEnd); + window.addEventListener('touchcancel', handleTouchEnd); // Same as touchend + + function handleTouchStart(e) { + // If we're already handling a touch, ignore this one + if (starttouch) + return; + + // Ignore any event that has already been prevented + if (e.defaultPrevented) + return; + + // Sometimes an unknown gecko bug causes us to get a touchstart event + // for an iframe target that we can't use because it is cross origin. + // Don't start handling a touch in that case + try { + e.changedTouches[0].target.ownerDocument; + } + catch (e) { + // Ignore the event if we can't see the properties of the target + return; + } + + // If there is more than one simultaneous touch, ignore all but the first + starttouch = e.changedTouches[0]; + target = starttouch.target; + emitclick = true; + + // Move to the position of the touch + emitEvent('mousemove', target, starttouch); + + // Now send a synthetic mousedown + var result = emitEvent('mousedown', target, starttouch); + + // If the mousedown was prevented, pass that on to the touch event. + // And remember not to send a click event + if (!result) { + e.preventDefault(); + emitclick = false; + } + } + + function handleTouchEnd(e) { + if (!starttouch) + return; + + // End a MouseEventShim.setCapture() call + if (MouseEventShim.capturing) { + MouseEventShim.capturing = false; + MouseEventShim.captureTarget = null; + } + + for (var i = 0; i < e.changedTouches.length; i++) { + var touch = e.changedTouches[i]; + // If the ended touch does not have the same id, skip it + if (touch.identifier !== starttouch.identifier) + continue; + + emitEvent('mouseup', target, touch); + + // If target is still the same element we started and the touch did not + // move more than the threshold and if the user did not prevent + // the mousedown, then send a click event, too. + if (emitclick) + emitEvent('click', starttouch.target, touch); + + starttouch = null; + return; + } + } + + function handleTouchMove(e) { + if (!starttouch) + return; + + for (var i = 0; i < e.changedTouches.length; i++) { + var touch = e.changedTouches[i]; + // If the ended touch does not have the same id, skip it + if (touch.identifier !== starttouch.identifier) + continue; + + // Don't send a mousemove if the touchmove was prevented + if (e.defaultPrevented) + return; + + // See if we've moved too much to emit a click event + var dx = Math.abs(touch.screenX - starttouch.screenX); + var dy = Math.abs(touch.screenY - starttouch.screenY); + if (dx > MouseEventShim.dragThresholdX || + dy > MouseEventShim.dragThresholdY) { + emitclick = false; + } + + var tracking = MouseEventShim.trackMouseMoves && + !MouseEventShim.capturing; + + if (tracking) { + // If the touch point moves, then the element it is over + // may have changed as well. Note that calling elementFromPoint() + // forces a layout if one is needed. + // XXX: how expensive is it to do this on each touchmove? + // Can we listen for (non-standard) touchleave events instead? + var oldtarget = target; + var newtarget = document.elementFromPoint(touch.clientX, touch.clientY); + if (newtarget === null) { + // this can happen as the touch is moving off of the screen, e.g. + newtarget = oldtarget; + } + if (newtarget !== oldtarget) { + leave(oldtarget, newtarget, touch); // mouseout, mouseleave + target = newtarget; + } + } + else if (MouseEventShim.captureTarget) { + target = MouseEventShim.captureTarget; + } + + emitEvent('mousemove', target, touch); + + if (tracking && newtarget !== oldtarget) { + enter(newtarget, oldtarget, touch); // mouseover, mouseenter + } + } + } + + // Return true if element a contains element b + function contains(a, b) { + return (a.compareDocumentPosition(b) & 16) !== 0; + } + + // A touch has left oldtarget and entered newtarget + // Send out all the events that are required + function leave(oldtarget, newtarget, touch) { + emitEvent('mouseout', oldtarget, touch, newtarget); + + // If the touch has actually left oldtarget (and has not just moved + // into a child of oldtarget) send a mouseleave event. mouseleave + // events don't bubble, so we have to repeat this up the hierarchy. + for (var e = oldtarget; !contains(e, newtarget); e = e.parentNode) { + emitEvent('mouseleave', e, touch, newtarget); + } + } + + // A touch has entered newtarget from oldtarget + // Send out all the events that are required. + function enter(newtarget, oldtarget, touch) { + emitEvent('mouseover', newtarget, touch, oldtarget); + + // Emit non-bubbling mouseenter events if the touch actually entered + // newtarget and wasn't already in some child of it + for (var e = newtarget; !contains(e, oldtarget); e = e.parentNode) { + emitEvent('mouseenter', e, touch, oldtarget); + } + } + + function emitEvent(type, target, touch, relatedTarget) { + var synthetic = document.createEvent('MouseEvents'); + var bubbles = (type !== 'mouseenter' && type !== 'mouseleave'); + var count = + (type === 'mousedown' || type === 'mouseup' || type === 'click') ? 1 : 0; + + synthetic.initMouseEvent(type, + bubbles, // canBubble + true, // cancelable + window, + count, // detail: click count + touch.screenX, + touch.screenY, + touch.clientX, + touch.clientY, + false, // ctrlKey: we don't have one + false, // altKey: we don't have one + false, // shiftKey: we don't have one + false, // metaKey: we don't have one + 0, // we're simulating the left button + relatedTarget || null); + + try { + return target.dispatchEvent(synthetic); + } + catch (e) { + console.warn('Exception calling dispatchEvent', type, e); + return true; + } + } +}()); + +var MouseEventShim = { + // It is a known gecko bug that synthetic events have timestamps measured + // in microseconds while regular events have timestamps measured in + // milliseconds. This utility function returns a the timestamp converted + // to milliseconds, if necessary. + getEventTimestamp: function(e) { + if (e.isTrusted) // XXX: Are real events always trusted? + return e.timeStamp; + else + return e.timeStamp / 1000; + }, + + // Set this to false if you don't care about mouseover/out events + // and don't want the target of mousemove events to follow the touch + trackMouseMoves: true, + + // Call this function from a mousedown event handler if you want to guarantee + // that the mousemove and mouseup events will go to the same element + // as the mousedown even if they leave the bounds of the element. This is + // like setting trackMouseMoves to false for just one drag. It is a + // substitute for event.target.setCapture(true) + setCapture: function(target) { + this.capturing = true; // Will be set back to false on mouseup + if (target) + this.captureTarget = target; + }, + + capturing: false, + + // Keep these in sync with ui.dragThresholdX and ui.dragThresholdY prefs. + // If a touch ever moves more than this many pixels from its starting point + // then we will not synthesize a click event when the touch ends. + dragThresholdX: 25, + dragThresholdY: 25 +}; diff --git a/testing/marionette/harness/marionette_harness/www/test.html b/testing/marionette/harness/marionette_harness/www/test.html new file mode 100644 index 000000000..053ff171d --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test.html @@ -0,0 +1,38 @@ + + + + + +Marionette Test + + +

Test Page

+ + Click me! + + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/testAction.html b/testing/marionette/harness/marionette_harness/www/testAction.html new file mode 100644 index 000000000..eb7e44f3e --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/testAction.html @@ -0,0 +1,94 @@ + + + + + + + +Marionette Test + + +

Test Page

+ + + + + + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/testPageSource.html b/testing/marionette/harness/marionette_harness/www/testPageSource.html new file mode 100644 index 000000000..f19b9d30c --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/testPageSource.html @@ -0,0 +1,14 @@ + + + + + + +PageSource Test + + +

Check the PageSource + + diff --git a/testing/marionette/harness/marionette_harness/www/testPageSource.xml b/testing/marionette/harness/marionette_harness/www/testPageSource.xml new file mode 100644 index 000000000..1480a1f38 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/testPageSource.xml @@ -0,0 +1,5 @@ + + + baz + + diff --git a/testing/marionette/harness/marionette_harness/www/testPageSourceWithUnicodeChars.html b/testing/marionette/harness/marionette_harness/www/testPageSourceWithUnicodeChars.html new file mode 100644 index 000000000..d16cf52c8 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/testPageSourceWithUnicodeChars.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/testSize.html b/testing/marionette/harness/marionette_harness/www/testSize.html new file mode 100644 index 000000000..1df27ad23 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/testSize.html @@ -0,0 +1,9 @@ + + + + Test page for element size + + +

Let's get the size of some really cool link

+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_accessibility.html b/testing/marionette/harness/marionette_harness/www/test_accessibility.html new file mode 100644 index 000000000..8cc9fd649 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_accessibility.html @@ -0,0 +1,57 @@ + + + + + + + +Marionette Test + + + + + I am a bad button with no accessible +

I am a bad button that is actually a header

+

+ I am a bad button that is actually an actionable header with a listener +

+ + + + + + I have no accessible object + + + I have no accessible object + Span button + Unexplorable Span button + +
+ +
+
+ +
+ + + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_columns.html b/testing/marionette/harness/marionette_harness/www/test_carets_columns.html new file mode 100644 index 000000000..495236108 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_columns.html @@ -0,0 +1,31 @@ + + + + + + + + + +
+
+

Before image 1

+

+

After image 1

+

Before image 2

+

+

After image 2

+
+
+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_cursor.html b/testing/marionette/harness/marionette_harness/www/test_carets_cursor.html new file mode 100644 index 000000000..fdbd6fe7a --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_cursor.html @@ -0,0 +1,31 @@ + + + + + + Marionette tests for AccessibleCaret in cursor mode + + + +
+ + +
+
+
+ + +
+
+
ABCDEFGHI
+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_display_none.html b/testing/marionette/harness/marionette_harness/www/test_carets_display_none.html new file mode 100644 index 000000000..766f32001 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_display_none.html @@ -0,0 +1,10 @@ + + + + + +
ABC DEF GHI
+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_iframe.html b/testing/marionette/harness/marionette_harness/www/test_carets_iframe.html new file mode 100644 index 000000000..f6e6df9ba --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_iframe.html @@ -0,0 +1,20 @@ + + + + + + + Marionette tests for AccessibleCaret in selection mode (iframe) + + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_longtext.html b/testing/marionette/harness/marionette_harness/www/test_carets_longtext.html new file mode 100644 index 000000000..7e2495509 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_longtext.html @@ -0,0 +1,9 @@ + + + Bug 1094072: Orientation change test for AccessibleCaret positions + + +

long long text for orientation change test long long text for orientation change test long long text for orientation change test long long text for orientation change test

+
bottom text
+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_multipleline.html b/testing/marionette/harness/marionette_harness/www/test_carets_multipleline.html new file mode 100644 index 000000000..ff46a954b --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_multipleline.html @@ -0,0 +1,24 @@ + + + + + + + Bug 1019441: Marionette tests for AccessibleCaret (multiple lines) + + + +
+
+
First Line

Second Line

Third Line
+
+
First Line

Second Line

Third Line
+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_multiplerange.html b/testing/marionette/harness/marionette_harness/www/test_carets_multiplerange.html new file mode 100644 index 000000000..394630c1f --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_multiplerange.html @@ -0,0 +1,19 @@ + + + +

user can select this 1

+

user can select this 2

+

user can select this 3

+

user cannot select this 1

+

user cannot select this 2

+

user can select this 4

+

user can select this 5

+

user cannot select this 3

+

user can select this 6

+

user can select this 7

+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_carets_selection.html b/testing/marionette/harness/marionette_harness/www/test_carets_selection.html new file mode 100644 index 000000000..f58b92fbf --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_carets_selection.html @@ -0,0 +1,38 @@ + + + + + + + Marionette tests for AccessibleCaret in selection mode + + + +
+ + +
+
+
+ + +
+
+
+
+
ABC DEF GHI
+
+
ABC DEF GHI
+
+
Non-selectable
+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_clearing.html b/testing/marionette/harness/marionette_harness/www/test_clearing.html new file mode 100644 index 000000000..2aa3c6a21 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_clearing.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + +
This is a contentEditable area
+ + diff --git a/testing/marionette/harness/marionette_harness/www/test_dynamic.html b/testing/marionette/harness/marionette_harness/www/test_dynamic.html new file mode 100644 index 000000000..dccc2c6ac --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_dynamic.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_iframe.html b/testing/marionette/harness/marionette_harness/www/test_iframe.html new file mode 100644 index 000000000..7ed88665c --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_iframe.html @@ -0,0 +1,16 @@ + + + + + +Marionette IFrame Test + + +

This is the heading

+ + + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_inner_iframe.html b/testing/marionette/harness/marionette_harness/www/test_inner_iframe.html new file mode 100644 index 000000000..c836fc6e4 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_inner_iframe.html @@ -0,0 +1,13 @@ + + + + + +Inner Iframe + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_nested_iframe.html b/testing/marionette/harness/marionette_harness/www/test_nested_iframe.html new file mode 100644 index 000000000..b4482183e --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_nested_iframe.html @@ -0,0 +1,13 @@ + + + + + +Marionette IFrame Test + + + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_oop_1.html b/testing/marionette/harness/marionette_harness/www/test_oop_1.html new file mode 100644 index 000000000..62e4ad047 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_oop_1.html @@ -0,0 +1,15 @@ + + + + + +OOP Test Frame 1 + + +

OOP Test Frame 1

+ Hello! + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_oop_2.html b/testing/marionette/harness/marionette_harness/www/test_oop_2.html new file mode 100644 index 000000000..05aca5adb --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_oop_2.html @@ -0,0 +1,15 @@ + + + + + +OOP Test Frame 2 + + +

OOP Test Frame 2

+ Hello! + + + diff --git a/testing/marionette/harness/marionette_harness/www/test_shadow_dom.html b/testing/marionette/harness/marionette_harness/www/test_shadow_dom.html new file mode 100644 index 000000000..3ee893e6d --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_shadow_dom.html @@ -0,0 +1,26 @@ + + + + + + + +Marionette Test + + +
+
+ + + diff --git a/testing/marionette/harness/marionette_harness/www/test_windows.html b/testing/marionette/harness/marionette_harness/www/test_windows.html new file mode 100644 index 000000000..da1fd799e --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/test_windows.html @@ -0,0 +1,14 @@ + + + + + + XHTML Test Page + + +

Open new window

+ + + diff --git a/testing/marionette/harness/marionette_harness/www/white.png b/testing/marionette/harness/marionette_harness/www/white.png new file mode 100644 index 000000000..8a68c1154 Binary files /dev/null and b/testing/marionette/harness/marionette_harness/www/white.png differ diff --git a/testing/marionette/harness/marionette_harness/www/windowHandles.html b/testing/marionette/harness/marionette_harness/www/windowHandles.html new file mode 100644 index 000000000..165526c8a --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/windowHandles.html @@ -0,0 +1,16 @@ + + + + + +Marionette New Tab Link + + + New Tab + New blank Tab + + New Window + + \ No newline at end of file diff --git a/testing/marionette/harness/marionette_harness/www/xhtmlTest.html b/testing/marionette/harness/marionette_harness/www/xhtmlTest.html new file mode 100644 index 000000000..146def33a --- /dev/null +++ b/testing/marionette/harness/marionette_harness/www/xhtmlTest.html @@ -0,0 +1,79 @@ + + + + + XHTML Test Page + + + + + + +
+

XHTML Might Be The Future

+ +

If you'd like to go elsewhere then click me.

+ +

Alternatively, this goes to the same place.

+ +
+ +
+ + This link has the same text as another link: click me. +
+ +
Another div starts here.

+

An H2 title

+

Some more text

+
+ +
+ Foo +
    + +
+ +
+
+
+ + +
+
+
+ + I have width +
+
+
+
+ + +

+

+
Link=equalssign + +

Spaced out

+ + +
first_div
+
second_div
+ first_span + second_span +
+ +
I'm a parent +
I'm a child
+
+ +
Woo woo
+ + diff --git a/testing/marionette/harness/requirements.txt b/testing/marionette/harness/requirements.txt new file mode 100644 index 000000000..75ab9ce92 --- /dev/null +++ b/testing/marionette/harness/requirements.txt @@ -0,0 +1,14 @@ +browsermob-proxy >= 0.6.0 +manifestparser >= 1.1 +marionette-driver >= 2.2.0 +mozcrash >= 0.5 +mozdevice >= 0.44 +mozinfo >= 0.8 +mozlog >= 3.0 +moznetwork >= 0.21 +mozprocess >= 0.9 +mozprofile >= 0.7 +mozrunner >= 6.13 +moztest >= 0.8 +mozversion >= 1.1 +wptserve >= 1.3.0 diff --git a/testing/marionette/harness/setup.py b/testing/marionette/harness/setup.py new file mode 100644 index 000000000..d28a970c1 --- /dev/null +++ b/testing/marionette/harness/setup.py @@ -0,0 +1,59 @@ +import os +import re + +from setuptools import find_packages, setup + + +THIS_DIR = os.path.dirname(os.path.realpath(__name__)) + + +def read(*parts): + with open(os.path.join(THIS_DIR, *parts)) as f: + return f.read() + + +def get_version(): + return re.findall("__version__ = '([\d\.]+)'", + read('marionette_harness', '__init__.py'), re.M)[0] + + +setup(name='marionette-harness', + version=get_version(), + description="Marionette test automation harness", + long_description=open('README.rst').read(), + # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX', + 'Topic :: Software Development :: Quality Assurance', + 'Topic :: Software Development :: Testing', + 'Topic :: Utilities', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2.7', + ], + keywords='mozilla', + author='Auto-tools', + author_email='tools-marionette@lists.mozilla.org', + url='https://wiki.mozilla.org/Auto-tools/Projects/Marionette', + license='Mozilla Public License 2.0 (MPL 2.0)', + packages=find_packages(), + package_data={ + 'marionette_harness': [ + 'runner/test.cert', + 'runner/test.key' + ], + }, + # Needed to include package data as specified in MANIFEST.in + include_package_data=True, + install_requires=read('requirements.txt').splitlines(), + zip_safe=False, + entry_points=""" + # -*- Entry points: -*- + [console_scripts] + marionette = marionette_harness.runtests:cli + """, + ) diff --git a/testing/marionette/interaction.js b/testing/marionette/interaction.js new file mode 100644 index 000000000..c8275665d --- /dev/null +++ b/testing/marionette/interaction.js @@ -0,0 +1,455 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {utils: Cu} = Components; + +Cu.import("chrome://marionette/content/accessibility.js"); +Cu.import("chrome://marionette/content/atom.js"); +Cu.import("chrome://marionette/content/error.js"); +Cu.import("chrome://marionette/content/element.js"); +Cu.import("chrome://marionette/content/event.js"); + +Cu.importGlobalProperties(["File"]); + +this.EXPORTED_SYMBOLS = ["interaction"]; + +/** + * XUL elements that support disabled attribute. + */ +const DISABLED_ATTRIBUTE_SUPPORTED_XUL = new Set([ + "ARROWSCROLLBOX", + "BUTTON", + "CHECKBOX", + "COLORPICKER", + "COMMAND", + "DATEPICKER", + "DESCRIPTION", + "KEY", + "KEYSET", + "LABEL", + "LISTBOX", + "LISTCELL", + "LISTHEAD", + "LISTHEADER", + "LISTITEM", + "MENU", + "MENUITEM", + "MENULIST", + "MENUSEPARATOR", + "PREFERENCE", + "RADIO", + "RADIOGROUP", + "RICHLISTBOX", + "RICHLISTITEM", + "SCALE", + "TAB", + "TABS", + "TEXTBOX", + "TIMEPICKER", + "TOOLBARBUTTON", + "TREE", +]); + +/** + * XUL elements that support checked property. + */ +const CHECKED_PROPERTY_SUPPORTED_XUL = new Set([ + "BUTTON", + "CHECKBOX", + "LISTITEM", + "TOOLBARBUTTON", +]); + +/** + * XUL elements that support selected property. + */ +const SELECTED_PROPERTY_SUPPORTED_XUL = new Set([ + "LISTITEM", + "MENU", + "MENUITEM", + "MENUSEPARATOR", + "RADIO", + "RICHLISTITEM", + "TAB", +]); + +this.interaction = {}; + +/** + * Interact with an element by clicking it. + * + * The element is scrolled into view before visibility- or interactability + * checks are performed. + * + * Selenium-style visibility checks will be performed if |specCompat| + * is false (default). Otherwise pointer-interactability checks will be + * performed. If either of these fail an + * {@code ElementNotInteractableError} is thrown. + * + * If |strict| is enabled (defaults to disabled), further accessibility + * checks will be performed, and these may result in an + * {@code ElementNotAccessibleError} being returned. + * + * When |el| is not enabled, an {@code InvalidElementStateError} + * is returned. + * + * @param {DOMElement|XULElement} el + * Element to click. + * @param {boolean=} strict + * Enforce strict accessibility tests. + * @param {boolean=} specCompat + * Use WebDriver specification compatible interactability definition. + * + * @throws {ElementNotInteractableError} + * If either Selenium-style visibility check or + * pointer-interactability check fails. + * @throws {ElementClickInterceptedError} + * If |el| is obscured by another element and a click would not hit, + * in |specCompat| mode. + * @throws {ElementNotAccessibleError} + * If |strict| is true and element is not accessible. + * @throws {InvalidElementStateError} + * If |el| is not enabled. + */ +interaction.clickElement = function* (el, strict = false, specCompat = false) { + const a11y = accessibility.get(strict); + if (specCompat) { + yield webdriverClickElement(el, a11y); + } else { + yield seleniumClickElement(el, a11y); + } +}; + +function* webdriverClickElement (el, a11y) { + const win = getWindow(el); + const doc = win.document; + + // step 3 + if (el.localName == "input" && el.type == "file") { + throw new InvalidArgumentError( + "Cannot click elements"); + } + + let containerEl = element.getContainer(el); + + // step 4 + if (!element.isInView(containerEl)) { + element.scrollIntoView(containerEl); + } + + // step 5 + // TODO(ato): wait for containerEl to be in view + + // step 6 + // if we cannot bring the container element into the viewport + // there is no point in checking if it is pointer-interactable + if (!element.isInView(containerEl)) { + throw new ElementNotInteractableError( + error.pprint`Element ${el} could not be scrolled into view`); + } + + // step 7 + let rects = containerEl.getClientRects(); + let clickPoint = element.getInViewCentrePoint(rects[0], win); + + if (!element.isPointerInteractable(containerEl)) { + throw new ElementClickInterceptedError(containerEl, clickPoint); + } + + yield a11y.getAccessible(el, true).then(acc => { + a11y.assertVisible(acc, el, true); + a11y.assertEnabled(acc, el, true); + a11y.assertActionable(acc, el); + }); + + // step 8 + + // chrome elements + if (element.isXULElement(el)) { + if (el.localName == "option") { + interaction.selectOption(el); + } else { + el.click(); + } + + // content elements + } else { + if (el.localName == "option") { + interaction.selectOption(el); + } else { + event.synthesizeMouseAtPoint(clickPoint.x, clickPoint.y, {}, win); + } + } + + // step 9 + yield interaction.flushEventLoop(win); + + // step 10 + // TODO(ato): if the click causes navigation, + // run post-navigation checks +} + +function* seleniumClickElement (el, a11y) { + let win = getWindow(el); + + let visibilityCheckEl = el; + if (el.localName == "option") { + visibilityCheckEl = element.getContainer(el); + } + + if (!element.isVisible(visibilityCheckEl)) { + throw new ElementNotInteractableError(); + } + + if (!atom.isElementEnabled(el)) { + throw new InvalidElementStateError("Element is not enabled"); + } + + yield a11y.getAccessible(el, true).then(acc => { + a11y.assertVisible(acc, el, true); + a11y.assertEnabled(acc, el, true); + a11y.assertActionable(acc, el); + }); + + // chrome elements + if (element.isXULElement(el)) { + if (el.localName == "option") { + interaction.selectOption(el); + } else { + el.click(); + } + + // content elements + } else { + if (el.localName == "option") { + interaction.selectOption(el); + } else { + let rects = el.getClientRects(); + let centre = element.getInViewCentrePoint(rects[0], win); + let opts = {}; + event.synthesizeMouseAtPoint(centre.x, centre.y, opts, win); + } + } +}; + +/** + * Select