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 --- dom/plugins/test/crashtests/110650-1.html | 11 + dom/plugins/test/crashtests/41276-1.html | 28 + dom/plugins/test/crashtests/48856-1.html | 10 + dom/plugins/test/crashtests/539897-1.html | 35 + dom/plugins/test/crashtests/540114-1.html | 40 + dom/plugins/test/crashtests/570884.html | 8 + dom/plugins/test/crashtests/598862.html | 77 + dom/plugins/test/crashtests/626602-1.html | 109 + dom/plugins/test/crashtests/752340.html | 19 + dom/plugins/test/crashtests/843086.xhtml | 1 + dom/plugins/test/crashtests/crashtests.list | 14 + dom/plugins/test/mochitest/307-xo-redirect.sjs | 6 + dom/plugins/test/mochitest/browser.ini | 15 + dom/plugins/test/mochitest/browser_bug1163570.js | 96 + dom/plugins/test/mochitest/browser_bug1196539.js | 119 + dom/plugins/test/mochitest/browser_pluginscroll.js | 302 ++ .../mochitest/browser_tabswitchbetweenplugins.js | 105 + dom/plugins/test/mochitest/chrome.ini | 34 + dom/plugins/test/mochitest/cocoa_focus.html | 142 + dom/plugins/test/mochitest/cocoa_window_focus.html | 95 + dom/plugins/test/mochitest/crashing_subpage.html | 4 + dom/plugins/test/mochitest/dialog_watcher.js | 183 + dom/plugins/test/mochitest/file_authident.js | 6 + dom/plugins/test/mochitest/file_bug1245545.js | 22 + dom/plugins/test/mochitest/file_bug738396.html | 87 + dom/plugins/test/mochitest/file_bug771202.html | 8 + dom/plugins/test/mochitest/file_bug863792.html | 45 + dom/plugins/test/mochitest/file_checkcookie.sjs | 17 + dom/plugins/test/mochitest/file_setcookie.html | 9 + dom/plugins/test/mochitest/hang_test.js | 114 + dom/plugins/test/mochitest/hangui_common.js | 20 + dom/plugins/test/mochitest/hangui_iface.js | 121 + dom/plugins/test/mochitest/hangui_subpage.html | 4 + dom/plugins/test/mochitest/head.js | 133 + dom/plugins/test/mochitest/large-pic.jpg | Bin 0 -> 98570 bytes dom/plugins/test/mochitest/loremipsum.txt | 11 + dom/plugins/test/mochitest/loremipsum.xtest | 11 + .../test/mochitest/loremipsum.xtest^headers^ | 1 + dom/plugins/test/mochitest/loremipsum_file.txt | 11 + dom/plugins/test/mochitest/loremipsum_nocache.txt | 11 + .../test/mochitest/loremipsum_nocache.txt^headers^ | 1 + dom/plugins/test/mochitest/mixed_case_mime.sjs | 8 + dom/plugins/test/mochitest/mochitest.ini | 150 + dom/plugins/test/mochitest/neverending.sjs | 16 + .../mochitest/npruntime_identifiers_subpage.html | 4 + .../test/mochitest/plugin-stream-referer.sjs | 12 + dom/plugins/test/mochitest/plugin-utils.js | 95 + .../test/mochitest/plugin_no_scroll_div.html | 10 + .../test/mochitest/plugin_scroll_invalidation.html | 60 + .../test/mochitest/plugin_subframe_test.html | 10 + dom/plugins/test/mochitest/plugin_test.html | 11 + .../test/mochitest/plugin_visibility_loader.html | 6 + dom/plugins/test/mochitest/plugin_window.html | 23 + dom/plugins/test/mochitest/pluginstream.js | 39 + dom/plugins/test/mochitest/post.sjs | 17 + .../test/mochitest/privatemode_perwindowpb.xul | 11 + .../test/mochitest/test_CrashService_crash.html | 28 + .../test/mochitest/test_CrashService_hang.html | 28 + dom/plugins/test/mochitest/test_GCrace.html | 62 + .../test/mochitest/test_NPNVdocumentOrigin.html | 47 + .../test_NPPVpluginWantsAllNetworkStreams.html | 77 + dom/plugins/test/mochitest/test_bug1092842.html | 46 + dom/plugins/test/mochitest/test_bug1165981.html | 81 + dom/plugins/test/mochitest/test_bug1245545.html | 52 + dom/plugins/test/mochitest/test_bug1307694.html | 41 + dom/plugins/test/mochitest/test_bug406541.html | 100 + dom/plugins/test/mochitest/test_bug479979.xul | 38 + dom/plugins/test/mochitest/test_bug532208.html | 29 + dom/plugins/test/mochitest/test_bug539565-1.html | 91 + dom/plugins/test/mochitest/test_bug539565-2.html | 111 + dom/plugins/test/mochitest/test_bug738396.html | 88 + dom/plugins/test/mochitest/test_bug751809.html | 84 + dom/plugins/test/mochitest/test_bug771202.html | 48 + dom/plugins/test/mochitest/test_bug777098.html | 58 + dom/plugins/test/mochitest/test_bug784131.html | 85 + dom/plugins/test/mochitest/test_bug813906.html | 54 + dom/plugins/test/mochitest/test_bug827160.html | 54 + dom/plugins/test/mochitest/test_bug852315.html | 62 + dom/plugins/test/mochitest/test_bug854082.html | 38 + dom/plugins/test/mochitest/test_bug863792.html | 40 + dom/plugins/test/mochitest/test_bug967694.html | 78 + dom/plugins/test/mochitest/test_bug985859.html | 27 + dom/plugins/test/mochitest/test_bug986930.html | 20 + dom/plugins/test/mochitest/test_busy_hang.xul | 47 + .../test/mochitest/test_clear_site_data.html | 242 ++ dom/plugins/test/mochitest/test_cocoa_focus.html | 28 + .../test/mochitest/test_cocoa_window_focus.html | 28 + dom/plugins/test/mochitest/test_convertpoint.xul | 83 + dom/plugins/test/mochitest/test_cookies.html | 23 + dom/plugins/test/mochitest/test_copyText.html | 40 + .../test/mochitest/test_crash_nested_loop.html | 46 + dom/plugins/test/mochitest/test_crash_notify.xul | 106 + .../test/mochitest/test_crash_notify_no_report.xul | 116 + dom/plugins/test/mochitest/test_crash_submit.xul | 157 + dom/plugins/test/mochitest/test_crashing.html | 62 + dom/plugins/test/mochitest/test_crashing2.html | 74 + dom/plugins/test/mochitest/test_defaultValue.html | 38 + dom/plugins/test/mochitest/test_enumerate.html | 36 + dom/plugins/test/mochitest/test_fullpage.html | 35 + .../test/mochitest/test_getauthenticationinfo.html | 81 + dom/plugins/test/mochitest/test_hang_submit.xul | 165 + dom/plugins/test/mochitest/test_hanging.html | 63 + dom/plugins/test/mochitest/test_hangui.xul | 262 ++ dom/plugins/test/mochitest/test_hidden_plugin.html | 44 + dom/plugins/test/mochitest/test_idle_hang.xul | 47 + .../test/mochitest/test_instance_re-parent.html | 123 + .../test/mochitest/test_instance_unparent1.html | 51 + .../test/mochitest/test_instance_unparent2.html | 62 + .../test/mochitest/test_instance_unparent3.html | 54 + dom/plugins/test/mochitest/test_instantiation.html | 33 + .../test/mochitest/test_mixed_case_mime.html | 29 + .../mochitest/test_multipleinstanceobjects.html | 24 + .../test/mochitest/test_newstreamondestroy.html | 36 + dom/plugins/test/mochitest/test_npn_asynccall.html | 33 + dom/plugins/test/mochitest/test_npn_timers.html | 33 + .../test/mochitest/test_npobject_getters.html | 21 + dom/plugins/test/mochitest/test_npruntime.xul | 29 + .../test/mochitest/test_npruntime_construct.html | 32 + .../test/mochitest/test_npruntime_identifiers.html | 67 + .../test/mochitest/test_npruntime_npnevaluate.html | 101 + .../test/mochitest/test_npruntime_npninvoke.html | 162 + .../mochitest/test_npruntime_npninvokedefault.html | 153 + dom/plugins/test/mochitest/test_object.html | 510 +++ dom/plugins/test/mochitest/test_painting.html | 121 + .../mochitest/test_plugin_scroll_invalidation.html | 109 + .../mochitest/test_plugin_scroll_painting.html | 64 + .../mochitest/test_plugin_tag_clicktoplay.html | 35 + .../test/mochitest/test_pluginstream_3rdparty.html | 76 + .../test/mochitest/test_pluginstream_asfile.html | 33 + .../mochitest/test_pluginstream_asfileonly.html | 30 + .../test/mochitest/test_pluginstream_err.html | 165 + .../test/mochitest/test_pluginstream_geturl.html | 31 + .../mochitest/test_pluginstream_geturlnotify.html | 30 + .../mochitest/test_pluginstream_newstream.html | 32 + .../test/mochitest/test_pluginstream_post.html | 33 + .../mochitest/test_pluginstream_poststream.html | 31 + .../test/mochitest/test_pluginstream_referer.html | 55 + .../test/mochitest/test_pluginstream_seek.html | 33 + .../mochitest/test_pluginstream_seek_close.html | 45 + .../test/mochitest/test_pluginstream_src.html | 33 + .../mochitest/test_pluginstream_src_dynamic.html | 43 + .../mochitest/test_pluginstream_src_referer.html | 30 + dom/plugins/test/mochitest/test_positioning.html | 56 + .../mochitest/test_privatemode_perwindowpb.xul | 120 + .../test/mochitest/test_propertyAndMethod.html | 51 + .../test/mochitest/test_queryCSSZoomFactor.html | 48 + .../mochitest/test_queryContentsScaleFactor.html | 31 + .../test_queryContentsScaleFactorWindowed.html | 31 + .../test/mochitest/test_redirect_handling.html | 67 + .../mochitest/test_refresh_navigator_plugins.html | 68 + dom/plugins/test/mochitest/test_secondPlugin.html | 73 + .../test/mochitest/test_src_url_change.html | 42 + dom/plugins/test/mochitest/test_streamNotify.html | 89 + dom/plugins/test/mochitest/test_streamatclose.html | 46 + .../test/mochitest/test_stringHandling.html | 35 + dom/plugins/test/mochitest/test_twostreams.html | 46 + dom/plugins/test/mochitest/test_visibility.html | 100 + .../test/mochitest/test_windowed_invalidate.html | 66 + .../test/mochitest/test_windowless_flash.html | 33 + .../test/mochitest/test_windowless_ime.html | 46 + dom/plugins/test/mochitest/test_wmode.xul | 38 + .../test/mochitest/test_x11_error_crash.html | 27 + .../test_xulbrowser_plugin_visibility.xul | 24 + dom/plugins/test/mochitest/test_zero_opacity.html | 44 + .../mochitest/xulbrowser_plugin_visibility.xul | 139 + dom/plugins/test/moz.build | 15 + dom/plugins/test/reftest/border-padding-1-ref.html | 10 + dom/plugins/test/reftest/border-padding-1.html | 16 + dom/plugins/test/reftest/border-padding-2-ref.html | 17 + dom/plugins/test/reftest/border-padding-2.html | 17 + dom/plugins/test/reftest/border-padding-3-ref.html | 10 + dom/plugins/test/reftest/border-padding-3.html | 35 + dom/plugins/test/reftest/div-alpha-opacity.html | 28 + dom/plugins/test/reftest/div-alpha-zindex.html | 27 + dom/plugins/test/reftest/div-sanity.html | 17 + dom/plugins/test/reftest/plugin-alpha-opacity.html | 29 + dom/plugins/test/reftest/plugin-alpha-zindex.html | 26 + .../test/reftest/plugin-background-1-step.html | 22 + .../test/reftest/plugin-background-10-step.html | 22 + .../test/reftest/plugin-background-2-step.html | 22 + .../test/reftest/plugin-background-5-step.html | 22 + .../test/reftest/plugin-background-ref.html | 17 + dom/plugins/test/reftest/plugin-background.css | 61 + dom/plugins/test/reftest/plugin-background.html | 20 + dom/plugins/test/reftest/plugin-background.js | 75 + .../test/reftest/plugin-busy-alpha-zindex.html | 56 + .../test/reftest/plugin-canvas-alpha-zindex.html | 41 + dom/plugins/test/reftest/plugin-sanity.html | 13 + .../test/reftest/plugin-transform-1-ref.html | 10 + dom/plugins/test/reftest/plugin-transform-1.html | 10 + .../test/reftest/plugin-transform-2-ref.html | 7 + dom/plugins/test/reftest/plugin-transform-2.html | 13 + .../reftest/plugin-transform-alpha-zindex.html | 28 + .../reftest/pluginproblemui-direction-1-ref.html | 21 + .../test/reftest/pluginproblemui-direction-1.html | 21 + .../reftest/pluginproblemui-direction-2-ref.html | 25 + .../test/reftest/pluginproblemui-direction-2.html | 25 + dom/plugins/test/reftest/reftest-stylo.list | 33 + dom/plugins/test/reftest/reftest.list | 26 + dom/plugins/test/reftest/shrink-1-ref.html | 12 + dom/plugins/test/reftest/shrink-1.html | 25 + dom/plugins/test/reftest/update-1-ref.html | 12 + dom/plugins/test/reftest/update-1.html | 59 + dom/plugins/test/reftest/utils.js | 18 + .../test/reftest/windowless-clipping-1-ref.html | 14 + .../test/reftest/windowless-clipping-1.html | 15 + .../test/reftest/windowless-layers-ref.html | 10 + dom/plugins/test/reftest/windowless-layers.html | 15 + dom/plugins/test/testaddon/Makefile.in | 25 + dom/plugins/test/testaddon/install.rdf | 23 + dom/plugins/test/testaddon/moz.build | 5 + dom/plugins/test/testplugin/Info.plist | 38 + dom/plugins/test/testplugin/README | 441 +++ dom/plugins/test/testplugin/flashplugin/Info.plist | 38 + dom/plugins/test/testplugin/flashplugin/moz.build | 11 + dom/plugins/test/testplugin/flashplugin/nptest.def | 7 + dom/plugins/test/testplugin/flashplugin/nptest.rc | 42 + .../test/testplugin/flashplugin/nptest_name.cpp | 7 + dom/plugins/test/testplugin/javaplugin/Info.plist | 38 + dom/plugins/test/testplugin/javaplugin/moz.build | 11 + dom/plugins/test/testplugin/javaplugin/nptest.def | 7 + dom/plugins/test/testplugin/javaplugin/nptest.rc | 42 + .../test/testplugin/javaplugin/nptest_name.cpp | 7 + dom/plugins/test/testplugin/moz.build | 13 + dom/plugins/test/testplugin/nptest.cpp | 4064 ++++++++++++++++++++ dom/plugins/test/testplugin/nptest.def | 7 + dom/plugins/test/testplugin/nptest.h | 171 + dom/plugins/test/testplugin/nptest.rc | 42 + dom/plugins/test/testplugin/nptest_droid.cpp | 105 + dom/plugins/test/testplugin/nptest_gtk2.cpp | 774 ++++ dom/plugins/test/testplugin/nptest_macosx.mm | 312 ++ dom/plugins/test/testplugin/nptest_name.cpp | 6 + dom/plugins/test/testplugin/nptest_platform.h | 160 + dom/plugins/test/testplugin/nptest_utils.cpp | 113 + dom/plugins/test/testplugin/nptest_utils.h | 45 + dom/plugins/test/testplugin/nptest_windows.cpp | 878 +++++ .../test/testplugin/secondplugin/Info.plist | 38 + dom/plugins/test/testplugin/secondplugin/moz.build | 11 + .../test/testplugin/secondplugin/nptest.def | 7 + dom/plugins/test/testplugin/secondplugin/nptest.rc | 42 + .../test/testplugin/secondplugin/nptest_name.cpp | 7 + .../test/testplugin/silverlightplugin/Info.plist | 38 + .../test/testplugin/silverlightplugin/moz.build | 11 + .../test/testplugin/silverlightplugin/nptest.def | 7 + .../test/testplugin/silverlightplugin/nptest.rc | 42 + .../testplugin/silverlightplugin/nptest_name.cpp | 7 + dom/plugins/test/testplugin/testplugin.mozbuild | 72 + dom/plugins/test/testplugin/thirdplugin/Info.plist | 38 + dom/plugins/test/testplugin/thirdplugin/moz.build | 11 + dom/plugins/test/testplugin/thirdplugin/nptest.def | 7 + dom/plugins/test/testplugin/thirdplugin/nptest.rc | 42 + .../test/testplugin/thirdplugin/nptest_name.cpp | 7 + dom/plugins/test/unit/head_plugins.js | 195 + dom/plugins/test/unit/test_allowed_types.js | 142 + dom/plugins/test/unit/test_bug471245.js | 23 + dom/plugins/test/unit/test_bug813245.js | 87 + dom/plugins/test/unit/test_bug854467.js | 40 + dom/plugins/test/unit/test_nice_plugin_name.js | 80 + dom/plugins/test/unit/test_persist_in_prefs.js | 76 + dom/plugins/test/unit/test_plugin_default_state.js | 31 + .../test/unit/test_plugin_default_state_xpi.js | 118 + dom/plugins/test/unit/xpcshell.ini | 29 + 262 files changed, 19506 insertions(+) create mode 100644 dom/plugins/test/crashtests/110650-1.html create mode 100644 dom/plugins/test/crashtests/41276-1.html create mode 100644 dom/plugins/test/crashtests/48856-1.html create mode 100644 dom/plugins/test/crashtests/539897-1.html create mode 100644 dom/plugins/test/crashtests/540114-1.html create mode 100644 dom/plugins/test/crashtests/570884.html create mode 100644 dom/plugins/test/crashtests/598862.html create mode 100644 dom/plugins/test/crashtests/626602-1.html create mode 100644 dom/plugins/test/crashtests/752340.html create mode 100644 dom/plugins/test/crashtests/843086.xhtml create mode 100644 dom/plugins/test/crashtests/crashtests.list create mode 100644 dom/plugins/test/mochitest/307-xo-redirect.sjs create mode 100644 dom/plugins/test/mochitest/browser.ini create mode 100644 dom/plugins/test/mochitest/browser_bug1163570.js create mode 100644 dom/plugins/test/mochitest/browser_bug1196539.js create mode 100644 dom/plugins/test/mochitest/browser_pluginscroll.js create mode 100644 dom/plugins/test/mochitest/browser_tabswitchbetweenplugins.js create mode 100644 dom/plugins/test/mochitest/chrome.ini create mode 100644 dom/plugins/test/mochitest/cocoa_focus.html create mode 100644 dom/plugins/test/mochitest/cocoa_window_focus.html create mode 100644 dom/plugins/test/mochitest/crashing_subpage.html create mode 100644 dom/plugins/test/mochitest/dialog_watcher.js create mode 100644 dom/plugins/test/mochitest/file_authident.js create mode 100644 dom/plugins/test/mochitest/file_bug1245545.js create mode 100644 dom/plugins/test/mochitest/file_bug738396.html create mode 100644 dom/plugins/test/mochitest/file_bug771202.html create mode 100644 dom/plugins/test/mochitest/file_bug863792.html create mode 100644 dom/plugins/test/mochitest/file_checkcookie.sjs create mode 100644 dom/plugins/test/mochitest/file_setcookie.html create mode 100644 dom/plugins/test/mochitest/hang_test.js create mode 100644 dom/plugins/test/mochitest/hangui_common.js create mode 100644 dom/plugins/test/mochitest/hangui_iface.js create mode 100644 dom/plugins/test/mochitest/hangui_subpage.html create mode 100644 dom/plugins/test/mochitest/head.js create mode 100644 dom/plugins/test/mochitest/large-pic.jpg create mode 100644 dom/plugins/test/mochitest/loremipsum.txt create mode 100644 dom/plugins/test/mochitest/loremipsum.xtest create mode 100644 dom/plugins/test/mochitest/loremipsum.xtest^headers^ create mode 100644 dom/plugins/test/mochitest/loremipsum_file.txt create mode 100644 dom/plugins/test/mochitest/loremipsum_nocache.txt create mode 100644 dom/plugins/test/mochitest/loremipsum_nocache.txt^headers^ create mode 100644 dom/plugins/test/mochitest/mixed_case_mime.sjs create mode 100644 dom/plugins/test/mochitest/mochitest.ini create mode 100644 dom/plugins/test/mochitest/neverending.sjs create mode 100644 dom/plugins/test/mochitest/npruntime_identifiers_subpage.html create mode 100644 dom/plugins/test/mochitest/plugin-stream-referer.sjs create mode 100644 dom/plugins/test/mochitest/plugin-utils.js create mode 100644 dom/plugins/test/mochitest/plugin_no_scroll_div.html create mode 100644 dom/plugins/test/mochitest/plugin_scroll_invalidation.html create mode 100644 dom/plugins/test/mochitest/plugin_subframe_test.html create mode 100644 dom/plugins/test/mochitest/plugin_test.html create mode 100644 dom/plugins/test/mochitest/plugin_visibility_loader.html create mode 100644 dom/plugins/test/mochitest/plugin_window.html create mode 100644 dom/plugins/test/mochitest/pluginstream.js create mode 100644 dom/plugins/test/mochitest/post.sjs create mode 100644 dom/plugins/test/mochitest/privatemode_perwindowpb.xul create mode 100644 dom/plugins/test/mochitest/test_CrashService_crash.html create mode 100644 dom/plugins/test/mochitest/test_CrashService_hang.html create mode 100644 dom/plugins/test/mochitest/test_GCrace.html create mode 100644 dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html create mode 100644 dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html create mode 100644 dom/plugins/test/mochitest/test_bug1092842.html create mode 100644 dom/plugins/test/mochitest/test_bug1165981.html create mode 100644 dom/plugins/test/mochitest/test_bug1245545.html create mode 100644 dom/plugins/test/mochitest/test_bug1307694.html create mode 100644 dom/plugins/test/mochitest/test_bug406541.html create mode 100644 dom/plugins/test/mochitest/test_bug479979.xul create mode 100644 dom/plugins/test/mochitest/test_bug532208.html create mode 100644 dom/plugins/test/mochitest/test_bug539565-1.html create mode 100644 dom/plugins/test/mochitest/test_bug539565-2.html create mode 100644 dom/plugins/test/mochitest/test_bug738396.html create mode 100644 dom/plugins/test/mochitest/test_bug751809.html create mode 100644 dom/plugins/test/mochitest/test_bug771202.html create mode 100644 dom/plugins/test/mochitest/test_bug777098.html create mode 100644 dom/plugins/test/mochitest/test_bug784131.html create mode 100644 dom/plugins/test/mochitest/test_bug813906.html create mode 100644 dom/plugins/test/mochitest/test_bug827160.html create mode 100644 dom/plugins/test/mochitest/test_bug852315.html create mode 100644 dom/plugins/test/mochitest/test_bug854082.html create mode 100644 dom/plugins/test/mochitest/test_bug863792.html create mode 100644 dom/plugins/test/mochitest/test_bug967694.html create mode 100644 dom/plugins/test/mochitest/test_bug985859.html create mode 100644 dom/plugins/test/mochitest/test_bug986930.html create mode 100644 dom/plugins/test/mochitest/test_busy_hang.xul create mode 100644 dom/plugins/test/mochitest/test_clear_site_data.html create mode 100644 dom/plugins/test/mochitest/test_cocoa_focus.html create mode 100644 dom/plugins/test/mochitest/test_cocoa_window_focus.html create mode 100644 dom/plugins/test/mochitest/test_convertpoint.xul create mode 100644 dom/plugins/test/mochitest/test_cookies.html create mode 100644 dom/plugins/test/mochitest/test_copyText.html create mode 100644 dom/plugins/test/mochitest/test_crash_nested_loop.html create mode 100644 dom/plugins/test/mochitest/test_crash_notify.xul create mode 100644 dom/plugins/test/mochitest/test_crash_notify_no_report.xul create mode 100644 dom/plugins/test/mochitest/test_crash_submit.xul create mode 100644 dom/plugins/test/mochitest/test_crashing.html create mode 100644 dom/plugins/test/mochitest/test_crashing2.html create mode 100644 dom/plugins/test/mochitest/test_defaultValue.html create mode 100644 dom/plugins/test/mochitest/test_enumerate.html create mode 100644 dom/plugins/test/mochitest/test_fullpage.html create mode 100644 dom/plugins/test/mochitest/test_getauthenticationinfo.html create mode 100644 dom/plugins/test/mochitest/test_hang_submit.xul create mode 100644 dom/plugins/test/mochitest/test_hanging.html create mode 100644 dom/plugins/test/mochitest/test_hangui.xul create mode 100644 dom/plugins/test/mochitest/test_hidden_plugin.html create mode 100644 dom/plugins/test/mochitest/test_idle_hang.xul create mode 100644 dom/plugins/test/mochitest/test_instance_re-parent.html create mode 100644 dom/plugins/test/mochitest/test_instance_unparent1.html create mode 100644 dom/plugins/test/mochitest/test_instance_unparent2.html create mode 100644 dom/plugins/test/mochitest/test_instance_unparent3.html create mode 100644 dom/plugins/test/mochitest/test_instantiation.html create mode 100644 dom/plugins/test/mochitest/test_mixed_case_mime.html create mode 100644 dom/plugins/test/mochitest/test_multipleinstanceobjects.html create mode 100644 dom/plugins/test/mochitest/test_newstreamondestroy.html create mode 100644 dom/plugins/test/mochitest/test_npn_asynccall.html create mode 100644 dom/plugins/test/mochitest/test_npn_timers.html create mode 100644 dom/plugins/test/mochitest/test_npobject_getters.html create mode 100644 dom/plugins/test/mochitest/test_npruntime.xul create mode 100644 dom/plugins/test/mochitest/test_npruntime_construct.html create mode 100644 dom/plugins/test/mochitest/test_npruntime_identifiers.html create mode 100644 dom/plugins/test/mochitest/test_npruntime_npnevaluate.html create mode 100644 dom/plugins/test/mochitest/test_npruntime_npninvoke.html create mode 100644 dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html create mode 100644 dom/plugins/test/mochitest/test_object.html create mode 100644 dom/plugins/test/mochitest/test_painting.html create mode 100644 dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html create mode 100644 dom/plugins/test/mochitest/test_plugin_scroll_painting.html create mode 100644 dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_3rdparty.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_asfile.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_asfileonly.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_err.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_geturl.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_newstream.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_post.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_poststream.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_referer.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_seek.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_seek_close.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_src.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html create mode 100644 dom/plugins/test/mochitest/test_pluginstream_src_referer.html create mode 100644 dom/plugins/test/mochitest/test_positioning.html create mode 100644 dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul create mode 100644 dom/plugins/test/mochitest/test_propertyAndMethod.html create mode 100644 dom/plugins/test/mochitest/test_queryCSSZoomFactor.html create mode 100644 dom/plugins/test/mochitest/test_queryContentsScaleFactor.html create mode 100644 dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html create mode 100644 dom/plugins/test/mochitest/test_redirect_handling.html create mode 100644 dom/plugins/test/mochitest/test_refresh_navigator_plugins.html create mode 100644 dom/plugins/test/mochitest/test_secondPlugin.html create mode 100644 dom/plugins/test/mochitest/test_src_url_change.html create mode 100644 dom/plugins/test/mochitest/test_streamNotify.html create mode 100644 dom/plugins/test/mochitest/test_streamatclose.html create mode 100644 dom/plugins/test/mochitest/test_stringHandling.html create mode 100644 dom/plugins/test/mochitest/test_twostreams.html create mode 100644 dom/plugins/test/mochitest/test_visibility.html create mode 100644 dom/plugins/test/mochitest/test_windowed_invalidate.html create mode 100644 dom/plugins/test/mochitest/test_windowless_flash.html create mode 100644 dom/plugins/test/mochitest/test_windowless_ime.html create mode 100644 dom/plugins/test/mochitest/test_wmode.xul create mode 100644 dom/plugins/test/mochitest/test_x11_error_crash.html create mode 100644 dom/plugins/test/mochitest/test_xulbrowser_plugin_visibility.xul create mode 100644 dom/plugins/test/mochitest/test_zero_opacity.html create mode 100644 dom/plugins/test/mochitest/xulbrowser_plugin_visibility.xul create mode 100644 dom/plugins/test/moz.build create mode 100644 dom/plugins/test/reftest/border-padding-1-ref.html create mode 100644 dom/plugins/test/reftest/border-padding-1.html create mode 100644 dom/plugins/test/reftest/border-padding-2-ref.html create mode 100644 dom/plugins/test/reftest/border-padding-2.html create mode 100644 dom/plugins/test/reftest/border-padding-3-ref.html create mode 100644 dom/plugins/test/reftest/border-padding-3.html create mode 100644 dom/plugins/test/reftest/div-alpha-opacity.html create mode 100644 dom/plugins/test/reftest/div-alpha-zindex.html create mode 100644 dom/plugins/test/reftest/div-sanity.html create mode 100644 dom/plugins/test/reftest/plugin-alpha-opacity.html create mode 100644 dom/plugins/test/reftest/plugin-alpha-zindex.html create mode 100644 dom/plugins/test/reftest/plugin-background-1-step.html create mode 100644 dom/plugins/test/reftest/plugin-background-10-step.html create mode 100644 dom/plugins/test/reftest/plugin-background-2-step.html create mode 100644 dom/plugins/test/reftest/plugin-background-5-step.html create mode 100644 dom/plugins/test/reftest/plugin-background-ref.html create mode 100644 dom/plugins/test/reftest/plugin-background.css create mode 100644 dom/plugins/test/reftest/plugin-background.html create mode 100644 dom/plugins/test/reftest/plugin-background.js create mode 100644 dom/plugins/test/reftest/plugin-busy-alpha-zindex.html create mode 100644 dom/plugins/test/reftest/plugin-canvas-alpha-zindex.html create mode 100644 dom/plugins/test/reftest/plugin-sanity.html create mode 100644 dom/plugins/test/reftest/plugin-transform-1-ref.html create mode 100644 dom/plugins/test/reftest/plugin-transform-1.html create mode 100644 dom/plugins/test/reftest/plugin-transform-2-ref.html create mode 100644 dom/plugins/test/reftest/plugin-transform-2.html create mode 100644 dom/plugins/test/reftest/plugin-transform-alpha-zindex.html create mode 100644 dom/plugins/test/reftest/pluginproblemui-direction-1-ref.html create mode 100644 dom/plugins/test/reftest/pluginproblemui-direction-1.html create mode 100644 dom/plugins/test/reftest/pluginproblemui-direction-2-ref.html create mode 100644 dom/plugins/test/reftest/pluginproblemui-direction-2.html create mode 100644 dom/plugins/test/reftest/reftest-stylo.list create mode 100644 dom/plugins/test/reftest/reftest.list create mode 100644 dom/plugins/test/reftest/shrink-1-ref.html create mode 100644 dom/plugins/test/reftest/shrink-1.html create mode 100644 dom/plugins/test/reftest/update-1-ref.html create mode 100644 dom/plugins/test/reftest/update-1.html create mode 100644 dom/plugins/test/reftest/utils.js create mode 100644 dom/plugins/test/reftest/windowless-clipping-1-ref.html create mode 100644 dom/plugins/test/reftest/windowless-clipping-1.html create mode 100644 dom/plugins/test/reftest/windowless-layers-ref.html create mode 100644 dom/plugins/test/reftest/windowless-layers.html create mode 100644 dom/plugins/test/testaddon/Makefile.in create mode 100644 dom/plugins/test/testaddon/install.rdf create mode 100644 dom/plugins/test/testaddon/moz.build create mode 100644 dom/plugins/test/testplugin/Info.plist create mode 100644 dom/plugins/test/testplugin/README create mode 100644 dom/plugins/test/testplugin/flashplugin/Info.plist create mode 100644 dom/plugins/test/testplugin/flashplugin/moz.build create mode 100644 dom/plugins/test/testplugin/flashplugin/nptest.def create mode 100644 dom/plugins/test/testplugin/flashplugin/nptest.rc create mode 100644 dom/plugins/test/testplugin/flashplugin/nptest_name.cpp create mode 100644 dom/plugins/test/testplugin/javaplugin/Info.plist create mode 100644 dom/plugins/test/testplugin/javaplugin/moz.build create mode 100644 dom/plugins/test/testplugin/javaplugin/nptest.def create mode 100644 dom/plugins/test/testplugin/javaplugin/nptest.rc create mode 100644 dom/plugins/test/testplugin/javaplugin/nptest_name.cpp create mode 100644 dom/plugins/test/testplugin/moz.build create mode 100644 dom/plugins/test/testplugin/nptest.cpp create mode 100644 dom/plugins/test/testplugin/nptest.def create mode 100644 dom/plugins/test/testplugin/nptest.h create mode 100644 dom/plugins/test/testplugin/nptest.rc create mode 100644 dom/plugins/test/testplugin/nptest_droid.cpp create mode 100644 dom/plugins/test/testplugin/nptest_gtk2.cpp create mode 100644 dom/plugins/test/testplugin/nptest_macosx.mm create mode 100644 dom/plugins/test/testplugin/nptest_name.cpp create mode 100644 dom/plugins/test/testplugin/nptest_platform.h create mode 100644 dom/plugins/test/testplugin/nptest_utils.cpp create mode 100644 dom/plugins/test/testplugin/nptest_utils.h create mode 100644 dom/plugins/test/testplugin/nptest_windows.cpp create mode 100644 dom/plugins/test/testplugin/secondplugin/Info.plist create mode 100644 dom/plugins/test/testplugin/secondplugin/moz.build create mode 100644 dom/plugins/test/testplugin/secondplugin/nptest.def create mode 100644 dom/plugins/test/testplugin/secondplugin/nptest.rc create mode 100644 dom/plugins/test/testplugin/secondplugin/nptest_name.cpp create mode 100644 dom/plugins/test/testplugin/silverlightplugin/Info.plist create mode 100644 dom/plugins/test/testplugin/silverlightplugin/moz.build create mode 100644 dom/plugins/test/testplugin/silverlightplugin/nptest.def create mode 100644 dom/plugins/test/testplugin/silverlightplugin/nptest.rc create mode 100644 dom/plugins/test/testplugin/silverlightplugin/nptest_name.cpp create mode 100644 dom/plugins/test/testplugin/testplugin.mozbuild create mode 100644 dom/plugins/test/testplugin/thirdplugin/Info.plist create mode 100644 dom/plugins/test/testplugin/thirdplugin/moz.build create mode 100644 dom/plugins/test/testplugin/thirdplugin/nptest.def create mode 100644 dom/plugins/test/testplugin/thirdplugin/nptest.rc create mode 100644 dom/plugins/test/testplugin/thirdplugin/nptest_name.cpp create mode 100644 dom/plugins/test/unit/head_plugins.js create mode 100644 dom/plugins/test/unit/test_allowed_types.js create mode 100644 dom/plugins/test/unit/test_bug471245.js create mode 100644 dom/plugins/test/unit/test_bug813245.js create mode 100644 dom/plugins/test/unit/test_bug854467.js create mode 100644 dom/plugins/test/unit/test_nice_plugin_name.js create mode 100644 dom/plugins/test/unit/test_persist_in_prefs.js create mode 100644 dom/plugins/test/unit/test_plugin_default_state.js create mode 100644 dom/plugins/test/unit/test_plugin_default_state_xpi.js create mode 100644 dom/plugins/test/unit/xpcshell.ini (limited to 'dom/plugins/test') diff --git a/dom/plugins/test/crashtests/110650-1.html b/dom/plugins/test/crashtests/110650-1.html new file mode 100644 index 0000000000..9826227b03 --- /dev/null +++ b/dom/plugins/test/crashtests/110650-1.html @@ -0,0 +1,11 @@ + + +123246 testcase + + + + + + + + diff --git a/dom/plugins/test/crashtests/41276-1.html b/dom/plugins/test/crashtests/41276-1.html new file mode 100644 index 0000000000..ba35c34fa0 --- /dev/null +++ b/dom/plugins/test/crashtests/41276-1.html @@ -0,0 +1,28 @@ +Plugin Limit + + +Mozilla has a hardcoded limit of 10 simultaneously embedded plugins.
+If that limit is exceeded, plugin instances are prematurely destroyed (see the empty boxes below).
+Leave or reload a page that has a prematurely destroyed plugin and mozilla will crash.
+Sometimes, just loading this page will cause mozilla to crash.
+ + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ diff --git a/dom/plugins/test/crashtests/48856-1.html b/dom/plugins/test/crashtests/48856-1.html new file mode 100644 index 0000000000..cd0de2ab94 --- /dev/null +++ b/dom/plugins/test/crashtests/48856-1.html @@ -0,0 +1,10 @@ + + + + Mozilla Bug 48856 + + + + + diff --git a/dom/plugins/test/crashtests/539897-1.html b/dom/plugins/test/crashtests/539897-1.html new file mode 100644 index 0000000000..f280e62e6e --- /dev/null +++ b/dom/plugins/test/crashtests/539897-1.html @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/dom/plugins/test/crashtests/540114-1.html b/dom/plugins/test/crashtests/540114-1.html new file mode 100644 index 0000000000..8243649aa3 --- /dev/null +++ b/dom/plugins/test/crashtests/540114-1.html @@ -0,0 +1,40 @@ + + + + + + + + + + diff --git a/dom/plugins/test/crashtests/570884.html b/dom/plugins/test/crashtests/570884.html new file mode 100644 index 0000000000..7af5cdba53 --- /dev/null +++ b/dom/plugins/test/crashtests/570884.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/dom/plugins/test/crashtests/598862.html b/dom/plugins/test/crashtests/598862.html new file mode 100644 index 0000000000..9b1ad38d75 --- /dev/null +++ b/dom/plugins/test/crashtests/598862.html @@ -0,0 +1,77 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/crashtests/626602-1.html b/dom/plugins/test/crashtests/626602-1.html new file mode 100644 index 0000000000..0a878bbd1d --- /dev/null +++ b/dom/plugins/test/crashtests/626602-1.html @@ -0,0 +1,109 @@ + + + + + + + + + +
+ + + + + diff --git a/dom/plugins/test/crashtests/752340.html b/dom/plugins/test/crashtests/752340.html new file mode 100644 index 0000000000..c4c8c464f5 --- /dev/null +++ b/dom/plugins/test/crashtests/752340.html @@ -0,0 +1,19 @@ + + + + + + + +
+ + diff --git a/dom/plugins/test/mochitest/plugin_test.html b/dom/plugins/test/mochitest/plugin_test.html new file mode 100644 index 0000000000..c7eb376cd0 --- /dev/null +++ b/dom/plugins/test/mochitest/plugin_test.html @@ -0,0 +1,11 @@ + + + + + + + +
+ + diff --git a/dom/plugins/test/mochitest/plugin_visibility_loader.html b/dom/plugins/test/mochitest/plugin_visibility_loader.html new file mode 100644 index 0000000000..22802d9a51 --- /dev/null +++ b/dom/plugins/test/mochitest/plugin_visibility_loader.html @@ -0,0 +1,6 @@ + + + +

This Page Has a Solid Plugin

+ +

diff --git a/dom/plugins/test/mochitest/plugin_window.html b/dom/plugins/test/mochitest/plugin_window.html new file mode 100644 index 0000000000..d3a298e89c --- /dev/null +++ b/dom/plugins/test/mochitest/plugin_window.html @@ -0,0 +1,23 @@ + + + + NPAPI Stream Tests + + +

+ +
+ +
+ + + + diff --git a/dom/plugins/test/mochitest/pluginstream.js b/dom/plugins/test/mochitest/pluginstream.js new file mode 100644 index 0000000000..9c47cd5f89 --- /dev/null +++ b/dom/plugins/test/mochitest/pluginstream.js @@ -0,0 +1,39 @@ + SimpleTest.waitForExplicitFinish(); + + function frameLoaded(finishWhenCalled = true, lastObject = false) { + var testframe = document.getElementById('testframe'); + function getNode(list) { + if (list.length === 0) + return undefined; + return lastObject ? list[list.length - 1] : list[0]; + } + var embed = getNode(document.getElementsByTagName('embed')); + if (undefined === embed) + embed = getNode(document.getElementsByTagName('object')); + + // In the file:// URI case, this ends up being cross-origin. + // Skip these checks in that case. + if (testframe.contentDocument) { + var content = testframe.contentDocument.body.innerHTML; + if (!content.length) + return; + + var filename = embed.getAttribute("src") || + embed.getAttribute("geturl") || + embed.getAttribute("geturlnotify") || + embed.getAttribute("data"); + + var req = new XMLHttpRequest(); + req.open('GET', filename, false); + req.overrideMimeType('text/plain; charset=x-user-defined'); + req.send(null); + is(req.status, 200, "bad XMLHttpRequest status"); + is(content, req.responseText.replace(/\r\n/g, "\n"), + "content doesn't match"); + } + + is(embed.getError(), "pass", "plugin reported error"); + if (finishWhenCalled) { + SimpleTest.finish(); + } + } diff --git a/dom/plugins/test/mochitest/post.sjs b/dom/plugins/test/mochitest/post.sjs new file mode 100644 index 0000000000..b391dbdd81 --- /dev/null +++ b/dom/plugins/test/mochitest/post.sjs @@ -0,0 +1,17 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream"); + +function handleRequest(request, response) +{ + var body = ""; + var bodyStream = new BinaryInputStream(request.bodyInputStream); + var bytes = [], avail = 0; + while ((avail = bodyStream.available()) > 0) + body += String.fromCharCode.apply(String, bodyStream.readByteArray(avail)); + + response.setHeader("Content-Type", "text/html", false); + response.write(body); +} + diff --git a/dom/plugins/test/mochitest/privatemode_perwindowpb.xul b/dom/plugins/test/mochitest/privatemode_perwindowpb.xul new file mode 100644 index 0000000000..ab7f06395c --- /dev/null +++ b/dom/plugins/test/mochitest/privatemode_perwindowpb.xul @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_CrashService_crash.html b/dom/plugins/test/mochitest/test_CrashService_crash.html new file mode 100644 index 0000000000..84508a6dc0 --- /dev/null +++ b/dom/plugins/test/mochitest/test_CrashService_crash.html @@ -0,0 +1,28 @@ + + nsICrashService plugin crash + + + + + + diff --git a/dom/plugins/test/mochitest/test_CrashService_hang.html b/dom/plugins/test/mochitest/test_CrashService_hang.html new file mode 100644 index 0000000000..6ecf7d419a --- /dev/null +++ b/dom/plugins/test/mochitest/test_CrashService_hang.html @@ -0,0 +1,28 @@ + + nsICrashService plugin hang + + + + + + diff --git a/dom/plugins/test/mochitest/test_GCrace.html b/dom/plugins/test/mochitest/test_GCrace.html new file mode 100644 index 0000000000..50b598ef1e --- /dev/null +++ b/dom/plugins/test/mochitest/test_GCrace.html @@ -0,0 +1,62 @@ + + GC race with actors on the parent + + + + + +

+ + + + diff --git a/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html b/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html new file mode 100644 index 0000000000..75ec66e138 --- /dev/null +++ b/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html @@ -0,0 +1,47 @@ + + + Test NPNVdocumentOrigin + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html b/dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html new file mode 100644 index 0000000000..588e785d30 --- /dev/null +++ b/dom/plugins/test/mochitest/test_NPPVpluginWantsAllNetworkStreams.html @@ -0,0 +1,77 @@ + + + Test NPPVpluginWantsAllNetworkStreams + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug1092842.html b/dom/plugins/test/mochitest/test_bug1092842.html new file mode 100644 index 0000000000..e22d0a3b9f --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug1092842.html @@ -0,0 +1,46 @@ + + + + Bug 1092842 + + + + + + + +
+ + +

diff --git a/dom/plugins/test/mochitest/test_bug1165981.html b/dom/plugins/test/mochitest/test_bug1165981.html new file mode 100644 index 0000000000..360d9312ad --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug1165981.html @@ -0,0 +1,81 @@ + + + Bug 1165981 Test + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug1245545.html b/dom/plugins/test/mochitest/test_bug1245545.html new file mode 100644 index 0000000000..23e3b21e0c --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug1245545.html @@ -0,0 +1,52 @@ + + + + + Test Modifying Plugin click-to-play Flag + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug1307694.html b/dom/plugins/test/mochitest/test_bug1307694.html new file mode 100644 index 0000000000..97ee1b6efc --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug1307694.html @@ -0,0 +1,41 @@ + + + + + + + + + + +

+ +
+ +
+ + diff --git a/dom/plugins/test/mochitest/test_bug406541.html b/dom/plugins/test/mochitest/test_bug406541.html new file mode 100644 index 0000000000..6ce9d4554f --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug406541.html @@ -0,0 +1,100 @@ + + + + Test for Bug 406541 + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug479979.xul b/dom/plugins/test/mochitest/test_bug479979.xul new file mode 100644 index 0000000000..1f295cbeb5 --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug479979.xul @@ -0,0 +1,38 @@ + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug532208.html b/dom/plugins/test/mochitest/test_bug532208.html new file mode 100644 index 0000000000..0a4cdb985a --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug532208.html @@ -0,0 +1,29 @@ + +Test for correct async delivery of large streams, bug +532208 + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug539565-1.html b/dom/plugins/test/mochitest/test_bug539565-1.html new file mode 100644 index 0000000000..022b8cfc61 --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug539565-1.html @@ -0,0 +1,91 @@ + + + + + Test #1 for Bug 539565 + + + + + + + + + +
+
+ +
+ + diff --git a/dom/plugins/test/mochitest/test_bug539565-2.html b/dom/plugins/test/mochitest/test_bug539565-2.html new file mode 100644 index 0000000000..7d8d02a42e --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug539565-2.html @@ -0,0 +1,111 @@ + + + + + Test #2 for Bug 539565 + + + + + + + + + +
+
+ +
+ + diff --git a/dom/plugins/test/mochitest/test_bug738396.html b/dom/plugins/test/mochitest/test_bug738396.html new file mode 100644 index 0000000000..ead7f5c1ab --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug738396.html @@ -0,0 +1,88 @@ + + + + Test for Bug 738396 + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug751809.html b/dom/plugins/test/mochitest/test_bug751809.html new file mode 100644 index 0000000000..8f4987a8af --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug751809.html @@ -0,0 +1,84 @@ + + + Bug 751809 + + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug771202.html b/dom/plugins/test/mochitest/test_bug771202.html new file mode 100644 index 0000000000..712c11de7a --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug771202.html @@ -0,0 +1,48 @@ + + + + + + Test for Bug 771202 + + + + + +Mozilla Bug 771202 +
+
+
+ + + + diff --git a/dom/plugins/test/mochitest/test_bug827160.html b/dom/plugins/test/mochitest/test_bug827160.html new file mode 100644 index 0000000000..13cedd62af --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug827160.html @@ -0,0 +1,54 @@ + + + + + + Test for Bug 827160 + + + + + + + +Mozilla Bug 827160 + + + + + + + + + + + + + +
+
+
+
+ + diff --git a/dom/plugins/test/mochitest/test_bug852315.html b/dom/plugins/test/mochitest/test_bug852315.html new file mode 100644 index 0000000000..cbbc3d34a8 --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug852315.html @@ -0,0 +1,62 @@ + + + + Test for Bug 852315 + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug854082.html b/dom/plugins/test/mochitest/test_bug854082.html new file mode 100644 index 0000000000..ff3d1e1e86 --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug854082.html @@ -0,0 +1,38 @@ + + + + Test for Bug 854082 + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug863792.html b/dom/plugins/test/mochitest/test_bug863792.html new file mode 100644 index 0000000000..ccd0fc83c9 --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug863792.html @@ -0,0 +1,40 @@ + + + + Test for Bug 863792 + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug967694.html b/dom/plugins/test/mochitest/test_bug967694.html new file mode 100644 index 0000000000..8a7602134d --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug967694.html @@ -0,0 +1,78 @@ + + + + Test for Bug 967694 + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug985859.html b/dom/plugins/test/mochitest/test_bug985859.html new file mode 100644 index 0000000000..1a4329ab4a --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug985859.html @@ -0,0 +1,27 @@ + + + + Test for Bug 985859 + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_bug986930.html b/dom/plugins/test/mochitest/test_bug986930.html new file mode 100644 index 0000000000..f86539e58f --- /dev/null +++ b/dom/plugins/test/mochitest/test_bug986930.html @@ -0,0 +1,20 @@ + + + + + Test for Bug 986930 + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_busy_hang.xul b/dom/plugins/test/mochitest/test_busy_hang.xul new file mode 100644 index 0000000000..824dcbb4da --- /dev/null +++ b/dom/plugins/test/mochitest/test_busy_hang.xul @@ -0,0 +1,47 @@ + + + + + Plugin Busy Hang Test + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_clear_site_data.html b/dom/plugins/test/mochitest/test_clear_site_data.html new file mode 100644 index 0000000000..88ba937d5b --- /dev/null +++ b/dom/plugins/test/mochitest/test_clear_site_data.html @@ -0,0 +1,242 @@ + + + NPAPI ClearSiteData/GetSitesWithData Functionality + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_cocoa_focus.html b/dom/plugins/test/mochitest/test_cocoa_focus.html new file mode 100644 index 0000000000..17043ebae3 --- /dev/null +++ b/dom/plugins/test/mochitest/test_cocoa_focus.html @@ -0,0 +1,28 @@ + + + NPCocoaEventFocusChanged Tests + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_cocoa_window_focus.html b/dom/plugins/test/mochitest/test_cocoa_window_focus.html new file mode 100644 index 0000000000..3458c24eb9 --- /dev/null +++ b/dom/plugins/test/mochitest/test_cocoa_window_focus.html @@ -0,0 +1,28 @@ + + + NPCocoaEventWindowFocusChanged Tests + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_convertpoint.xul b/dom/plugins/test/mochitest/test_convertpoint.xul new file mode 100644 index 0000000000..5db01a253e --- /dev/null +++ b/dom/plugins/test/mochitest/test_convertpoint.xul @@ -0,0 +1,83 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_cookies.html b/dom/plugins/test/mochitest/test_cookies.html new file mode 100644 index 0000000000..f527967706 --- /dev/null +++ b/dom/plugins/test/mochitest/test_cookies.html @@ -0,0 +1,23 @@ + + + NPAPI Cookie Tests + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_copyText.html b/dom/plugins/test/mochitest/test_copyText.html new file mode 100644 index 0000000000..553207e25b --- /dev/null +++ b/dom/plugins/test/mochitest/test_copyText.html @@ -0,0 +1,40 @@ + + + + Test copying text from browser to plugin + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_crash_nested_loop.html b/dom/plugins/test/mochitest/test_crash_nested_loop.html new file mode 100644 index 0000000000..379b693e78 --- /dev/null +++ b/dom/plugins/test/mochitest/test_crash_nested_loop.html @@ -0,0 +1,46 @@ + + Plugin crashing in nested loop + + + + + + diff --git a/dom/plugins/test/mochitest/test_crash_notify.xul b/dom/plugins/test/mochitest/test_crash_notify.xul new file mode 100644 index 0000000000..fac95b07d9 --- /dev/null +++ b/dom/plugins/test/mochitest/test_crash_notify.xul @@ -0,0 +1,106 @@ + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_crash_notify_no_report.xul b/dom/plugins/test/mochitest/test_crash_notify_no_report.xul new file mode 100644 index 0000000000..a1344bf0f4 --- /dev/null +++ b/dom/plugins/test/mochitest/test_crash_notify_no_report.xul @@ -0,0 +1,116 @@ + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_crash_submit.xul b/dom/plugins/test/mochitest/test_crash_submit.xul new file mode 100644 index 0000000000..22f39384b5 --- /dev/null +++ b/dom/plugins/test/mochitest/test_crash_submit.xul @@ -0,0 +1,157 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_crashing.html b/dom/plugins/test/mochitest/test_crashing.html new file mode 100644 index 0000000000..eac6e42bef --- /dev/null +++ b/dom/plugins/test/mochitest/test_crashing.html @@ -0,0 +1,62 @@ + + Plugin crashing + + + + + + diff --git a/dom/plugins/test/mochitest/test_crashing2.html b/dom/plugins/test/mochitest/test_crashing2.html new file mode 100644 index 0000000000..be61f3d501 --- /dev/null +++ b/dom/plugins/test/mochitest/test_crashing2.html @@ -0,0 +1,74 @@ + + Plugin crashing + + + + + + + diff --git a/dom/plugins/test/mochitest/test_defaultValue.html b/dom/plugins/test/mochitest/test_defaultValue.html new file mode 100644 index 0000000000..2cbe52efe0 --- /dev/null +++ b/dom/plugins/test/mochitest/test_defaultValue.html @@ -0,0 +1,38 @@ + + + NPObject [[DefaultValue]] implementation + + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_enumerate.html b/dom/plugins/test/mochitest/test_enumerate.html new file mode 100644 index 0000000000..af8431c7cc --- /dev/null +++ b/dom/plugins/test/mochitest/test_enumerate.html @@ -0,0 +1,36 @@ + + + NPAPI Cookie Tests + + + + + + + + + +

+ + + + diff --git a/dom/plugins/test/mochitest/test_fullpage.html b/dom/plugins/test/mochitest/test_fullpage.html new file mode 100644 index 0000000000..680eb73a01 --- /dev/null +++ b/dom/plugins/test/mochitest/test_fullpage.html @@ -0,0 +1,35 @@ + + Full-page seekable stream + + + + + + +

+ + + + + diff --git a/dom/plugins/test/mochitest/test_getauthenticationinfo.html b/dom/plugins/test/mochitest/test_getauthenticationinfo.html new file mode 100644 index 0000000000..f249386c7c --- /dev/null +++ b/dom/plugins/test/mochitest/test_getauthenticationinfo.html @@ -0,0 +1,81 @@ + + + + Test for Login Manager + + + + + +Test for NPN_GetAuthenticationInfo +

+ +
+ +
+ + + + diff --git a/dom/plugins/test/mochitest/test_hang_submit.xul b/dom/plugins/test/mochitest/test_hang_submit.xul new file mode 100644 index 0000000000..6c037ecd49 --- /dev/null +++ b/dom/plugins/test/mochitest/test_hang_submit.xul @@ -0,0 +1,165 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_hanging.html b/dom/plugins/test/mochitest/test_hanging.html new file mode 100644 index 0000000000..c8ea936cec --- /dev/null +++ b/dom/plugins/test/mochitest/test_hanging.html @@ -0,0 +1,63 @@ + + Plugin hanging + + + + + + diff --git a/dom/plugins/test/mochitest/test_hangui.xul b/dom/plugins/test/mochitest/test_hangui.xul new file mode 100644 index 0000000000..edb90db006 --- /dev/null +++ b/dom/plugins/test/mochitest/test_hangui.xul @@ -0,0 +1,262 @@ + + + + + Plugin Hang UI Test + + diff --git a/dom/plugins/test/mochitest/test_hidden_plugin.html b/dom/plugins/test/mochitest/test_hidden_plugin.html new file mode 100644 index 0000000000..446d8cbbd5 --- /dev/null +++ b/dom/plugins/test/mochitest/test_hidden_plugin.html @@ -0,0 +1,44 @@ + + + + Test whether we are adding the dummy plugin correctly when there is only 1 plugin and its hidden + + + + + + + diff --git a/dom/plugins/test/mochitest/test_idle_hang.xul b/dom/plugins/test/mochitest/test_idle_hang.xul new file mode 100644 index 0000000000..83ff28f52f --- /dev/null +++ b/dom/plugins/test/mochitest/test_idle_hang.xul @@ -0,0 +1,47 @@ + + + + + Plugin Idle Hang Test + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_instance_re-parent.html b/dom/plugins/test/mochitest/test_instance_re-parent.html new file mode 100644 index 0000000000..1ba87adb5b --- /dev/null +++ b/dom/plugins/test/mochitest/test_instance_re-parent.html @@ -0,0 +1,123 @@ + + + + Test re-parentinging an instance's DOM node + + + + + + + + +

+ +
+ + +
+
+
+ + diff --git a/dom/plugins/test/mochitest/test_instance_unparent1.html b/dom/plugins/test/mochitest/test_instance_unparent1.html new file mode 100644 index 0000000000..5a11dc5887 --- /dev/null +++ b/dom/plugins/test/mochitest/test_instance_unparent1.html @@ -0,0 +1,51 @@ + + + + Test removing an instance's DOM node + + + + + + + + +

+ +
+ +
+ + diff --git a/dom/plugins/test/mochitest/test_instance_unparent2.html b/dom/plugins/test/mochitest/test_instance_unparent2.html new file mode 100644 index 0000000000..eedbca8e4e --- /dev/null +++ b/dom/plugins/test/mochitest/test_instance_unparent2.html @@ -0,0 +1,62 @@ + + + + Test removing an instance's DOM node + + + + + + + + +

+ +
+ +
+ +
+
+ +
+
+ + diff --git a/dom/plugins/test/mochitest/test_instance_unparent3.html b/dom/plugins/test/mochitest/test_instance_unparent3.html new file mode 100644 index 0000000000..9e55c7ed92 --- /dev/null +++ b/dom/plugins/test/mochitest/test_instance_unparent3.html @@ -0,0 +1,54 @@ + + + + Test removing an instance's DOM node + + + + + + + + +

+ +
+
+ + + + diff --git a/dom/plugins/test/mochitest/test_instantiation.html b/dom/plugins/test/mochitest/test_instantiation.html new file mode 100644 index 0000000000..e8fc077459 --- /dev/null +++ b/dom/plugins/test/mochitest/test_instantiation.html @@ -0,0 +1,33 @@ + + Plugin instantiation + + + + + + + diff --git a/dom/plugins/test/mochitest/test_mixed_case_mime.html b/dom/plugins/test/mochitest/test_mixed_case_mime.html new file mode 100644 index 0000000000..9258541bb7 --- /dev/null +++ b/dom/plugins/test/mochitest/test_mixed_case_mime.html @@ -0,0 +1,29 @@ + + + Test mixed case mimetype for plugins + + + + + + +

+ + + + + diff --git a/dom/plugins/test/mochitest/test_multipleinstanceobjects.html b/dom/plugins/test/mochitest/test_multipleinstanceobjects.html new file mode 100644 index 0000000000..74749e019c --- /dev/null +++ b/dom/plugins/test/mochitest/test_multipleinstanceobjects.html @@ -0,0 +1,24 @@ + + NPNV*NPObject accessibility tests + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_newstreamondestroy.html b/dom/plugins/test/mochitest/test_newstreamondestroy.html new file mode 100644 index 0000000000..26c4709afb --- /dev/null +++ b/dom/plugins/test/mochitest/test_newstreamondestroy.html @@ -0,0 +1,36 @@ + + NPN_GetURL called from NPP_Destroy + + + + + + + + +

+ + diff --git a/dom/plugins/test/mochitest/test_npn_asynccall.html b/dom/plugins/test/mochitest/test_npn_asynccall.html new file mode 100644 index 0000000000..4f007aacb0 --- /dev/null +++ b/dom/plugins/test/mochitest/test_npn_asynccall.html @@ -0,0 +1,33 @@ + + + NPN_AsyncCallback Tests + + + + + + + +

+ + + + + + diff --git a/dom/plugins/test/mochitest/test_npn_timers.html b/dom/plugins/test/mochitest/test_npn_timers.html new file mode 100644 index 0000000000..64d5aebbda --- /dev/null +++ b/dom/plugins/test/mochitest/test_npn_timers.html @@ -0,0 +1,33 @@ + + + NPN_Timer Tests + + + + + + + +

+ + + + + + diff --git a/dom/plugins/test/mochitest/test_npobject_getters.html b/dom/plugins/test/mochitest/test_npobject_getters.html new file mode 100644 index 0000000000..5a9a47081a --- /dev/null +++ b/dom/plugins/test/mochitest/test_npobject_getters.html @@ -0,0 +1,21 @@ + + NPNV*NPObject accessibility tests + + + + + + + diff --git a/dom/plugins/test/mochitest/test_npruntime.xul b/dom/plugins/test/mochitest/test_npruntime.xul new file mode 100644 index 0000000000..7e5cc087f1 --- /dev/null +++ b/dom/plugins/test/mochitest/test_npruntime.xul @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_npruntime_construct.html b/dom/plugins/test/mochitest/test_npruntime_construct.html new file mode 100644 index 0000000000..bd85930a4f --- /dev/null +++ b/dom/plugins/test/mochitest/test_npruntime_construct.html @@ -0,0 +1,32 @@ + + + + Test whether windowless plugins receive correct visible/invisible notifications. + + + + + + + +

+ + + + diff --git a/dom/plugins/test/mochitest/test_npruntime_identifiers.html b/dom/plugins/test/mochitest/test_npruntime_identifiers.html new file mode 100644 index 0000000000..a19a59be52 --- /dev/null +++ b/dom/plugins/test/mochitest/test_npruntime_identifiers.html @@ -0,0 +1,67 @@ + + + NPN_Invoke Tests + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_npruntime_npnevaluate.html b/dom/plugins/test/mochitest/test_npruntime_npnevaluate.html new file mode 100644 index 0000000000..4a1c22978b --- /dev/null +++ b/dom/plugins/test/mochitest/test_npruntime_npnevaluate.html @@ -0,0 +1,101 @@ + + + NPN_Evaluate Tests + + + + + + + +

+ + + + +
+
+
+
+ + diff --git a/dom/plugins/test/mochitest/test_npruntime_npninvoke.html b/dom/plugins/test/mochitest/test_npruntime_npninvoke.html new file mode 100644 index 0000000000..ff4c92a6d5 --- /dev/null +++ b/dom/plugins/test/mochitest/test_npruntime_npninvoke.html @@ -0,0 +1,162 @@ + + + NPN_Invoke Tests + + + + + + + + +

+ + + + +
+
+ + diff --git a/dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html b/dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html new file mode 100644 index 0000000000..79a75e7551 --- /dev/null +++ b/dom/plugins/test/mochitest/test_npruntime_npninvokedefault.html @@ -0,0 +1,153 @@ + + + NPN_Invoke_Default Tests + + + + + + + +

+ + + + +
+
+ + diff --git a/dom/plugins/test/mochitest/test_object.html b/dom/plugins/test/mochitest/test_object.html new file mode 100644 index 0000000000..093333ea5e --- /dev/null +++ b/dom/plugins/test/mochitest/test_object.html @@ -0,0 +1,510 @@ + + + + Plugin instantiation + + + + + + diff --git a/dom/plugins/test/mochitest/test_painting.html b/dom/plugins/test/mochitest/test_painting.html new file mode 100644 index 0000000000..08ebd46757 --- /dev/null +++ b/dom/plugins/test/mochitest/test_painting.html @@ -0,0 +1,121 @@ + + + + Test for windowless plugin invalidation and expose events in clips + + + + + + + + + +

+
+ +
+ +
+
+ +
+
+ + + diff --git a/dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html b/dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html new file mode 100644 index 0000000000..65ea3498ac --- /dev/null +++ b/dom/plugins/test/mochitest/test_plugin_scroll_invalidation.html @@ -0,0 +1,109 @@ + + + + Test for plugin child widgets not being invalidated by scrolling + + + + + + + +

+ +

+ +
+
+ + + + diff --git a/dom/plugins/test/mochitest/test_plugin_scroll_painting.html b/dom/plugins/test/mochitest/test_plugin_scroll_painting.html new file mode 100644 index 0000000000..9626156b6a --- /dev/null +++ b/dom/plugins/test/mochitest/test_plugin_scroll_painting.html @@ -0,0 +1,64 @@ + + + + Test that scrolling a windowless plugin doesn't force us to repaint it + + + + + + +

+ +
+ +
+
+ + + +
+ + + diff --git a/dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html b/dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html new file mode 100644 index 0000000000..0679e6795e --- /dev/null +++ b/dom/plugins/test/mochitest/test_plugin_tag_clicktoplay.html @@ -0,0 +1,35 @@ + + + + + Test Modifying Plugin click-to-play Flag + + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_3rdparty.html b/dom/plugins/test/mochitest/test_pluginstream_3rdparty.html new file mode 100644 index 0000000000..aa7dbb5a1c --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_3rdparty.html @@ -0,0 +1,76 @@ + + + + NPAPI NPN_GetURL NPStream Test + + + + + + + + + +

+ + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_asfile.html b/dom/plugins/test/mochitest/test_pluginstream_asfile.html new file mode 100644 index 0000000000..b021a74ce4 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_asfile.html @@ -0,0 +1,33 @@ + + + NPAPI NP_ASFILE NPStream Test + + + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_asfileonly.html b/dom/plugins/test/mochitest/test_pluginstream_asfileonly.html new file mode 100644 index 0000000000..96c9b85dce --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_asfileonly.html @@ -0,0 +1,30 @@ + + + NPAPI NP_ASFILEONLY NPStream Test + + + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_err.html b/dom/plugins/test/mochitest/test_pluginstream_err.html new file mode 100644 index 0000000000..0ac2a5efc2 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_err.html @@ -0,0 +1,165 @@ + + + + + NPAPI Stream Error Tests + + + + + + + Mozilla Bug 517078 - Plugin Stream Error Tests +

+ +
+ +
+ + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_geturl.html b/dom/plugins/test/mochitest/test_pluginstream_geturl.html new file mode 100644 index 0000000000..fe69427a42 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_geturl.html @@ -0,0 +1,31 @@ + + + NPAPI NPN_GetURL NPStream Test + + + + + + + +

+ + + + + + + + \ No newline at end of file diff --git a/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html b/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html new file mode 100644 index 0000000000..ee4c2b119d --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_geturlnotify.html @@ -0,0 +1,30 @@ + + + NPAPI NPN_GetURLNotify Test + + + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_newstream.html b/dom/plugins/test/mochitest/test_pluginstream_newstream.html new file mode 100644 index 0000000000..3972fd7ed4 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_newstream.html @@ -0,0 +1,32 @@ + + + NPAPI NPN_NewStream NPStream Test + + + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_post.html b/dom/plugins/test/mochitest/test_pluginstream_post.html new file mode 100644 index 0000000000..da12ff3b0e --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_post.html @@ -0,0 +1,33 @@ + + + NPAPI NPN_PostURL NPStream Test + + + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_poststream.html b/dom/plugins/test/mochitest/test_pluginstream_poststream.html new file mode 100644 index 0000000000..ed2e8ce2c7 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_poststream.html @@ -0,0 +1,31 @@ + + + NPAPI NPN_PostURL NPStream Test + + + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_referer.html b/dom/plugins/test/mochitest/test_pluginstream_referer.html new file mode 100644 index 0000000000..e1b63fb959 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_referer.html @@ -0,0 +1,55 @@ + + Do plugin stream requests send the Referer header correctly? + + + + + + + +

+ + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_seek.html b/dom/plugins/test/mochitest/test_pluginstream_seek.html new file mode 100644 index 0000000000..6915a766e8 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_seek.html @@ -0,0 +1,33 @@ + + + NPAPI Seekable NPStream Test + + + + + + + +

+ + + + + + + \ No newline at end of file diff --git a/dom/plugins/test/mochitest/test_pluginstream_seek_close.html b/dom/plugins/test/mochitest/test_pluginstream_seek_close.html new file mode 100644 index 0000000000..46fd3962ab --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_seek_close.html @@ -0,0 +1,45 @@ + + + NPAPI Seekable NPStream Test + + + + + + +

+ + + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_src.html b/dom/plugins/test/mochitest/test_pluginstream_src.html new file mode 100644 index 0000000000..cf934d022d --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_src.html @@ -0,0 +1,33 @@ + + + NPAPI src="" NPStream Test + + + + + + + +

+ + + + + + + \ No newline at end of file diff --git a/dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html b/dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html new file mode 100644 index 0000000000..2a7db9916d --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_src_dynamic.html @@ -0,0 +1,43 @@ + + + NPAPI src="" NPStream Test + + + + + + + +

+ + + + + + + + diff --git a/dom/plugins/test/mochitest/test_pluginstream_src_referer.html b/dom/plugins/test/mochitest/test_pluginstream_src_referer.html new file mode 100644 index 0000000000..9e96016ff6 --- /dev/null +++ b/dom/plugins/test/mochitest/test_pluginstream_src_referer.html @@ -0,0 +1,30 @@ + + Do plugin stream src requests send the Referer header correctly? + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_positioning.html b/dom/plugins/test/mochitest/test_positioning.html new file mode 100644 index 0000000000..4a4fc1d3d0 --- /dev/null +++ b/dom/plugins/test/mochitest/test_positioning.html @@ -0,0 +1,56 @@ + + + + Test whether windowless plugins receive correct visible/invisible notifications. + + + + + + + +

+ + + + diff --git a/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul b/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul new file mode 100644 index 0000000000..ae6c9d292f --- /dev/null +++ b/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul @@ -0,0 +1,120 @@ + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_propertyAndMethod.html b/dom/plugins/test/mochitest/test_propertyAndMethod.html new file mode 100644 index 0000000000..6e638e4191 --- /dev/null +++ b/dom/plugins/test/mochitest/test_propertyAndMethod.html @@ -0,0 +1,51 @@ + + + NPObject with property and method with the same name + + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_queryCSSZoomFactor.html b/dom/plugins/test/mochitest/test_queryCSSZoomFactor.html new file mode 100644 index 0000000000..682d23ae60 --- /dev/null +++ b/dom/plugins/test/mochitest/test_queryCSSZoomFactor.html @@ -0,0 +1,48 @@ + + + NPAPI NPNVcontentsScaleFactor Test + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_queryContentsScaleFactor.html b/dom/plugins/test/mochitest/test_queryContentsScaleFactor.html new file mode 100644 index 0000000000..c1f8919abb --- /dev/null +++ b/dom/plugins/test/mochitest/test_queryContentsScaleFactor.html @@ -0,0 +1,31 @@ + + + NPAPI NPNVcontentsScaleFactor Test + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html b/dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html new file mode 100644 index 0000000000..6f11332cbf --- /dev/null +++ b/dom/plugins/test/mochitest/test_queryContentsScaleFactorWindowed.html @@ -0,0 +1,31 @@ + + + NPAPI NPNVcontentsScaleFactor Test + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_redirect_handling.html b/dom/plugins/test/mochitest/test_redirect_handling.html new file mode 100644 index 0000000000..7d60ec06e9 --- /dev/null +++ b/dom/plugins/test/mochitest/test_redirect_handling.html @@ -0,0 +1,67 @@ + + + Basic NPAPI Redirect Handling + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html b/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html new file mode 100644 index 0000000000..e39b3217a5 --- /dev/null +++ b/dom/plugins/test/mochitest/test_refresh_navigator_plugins.html @@ -0,0 +1,68 @@ + + + + + + Test Refreshing navigator.plugins (bug 820708) + + + + + + + diff --git a/dom/plugins/test/mochitest/test_secondPlugin.html b/dom/plugins/test/mochitest/test_secondPlugin.html new file mode 100644 index 0000000000..4c1f051ca3 --- /dev/null +++ b/dom/plugins/test/mochitest/test_secondPlugin.html @@ -0,0 +1,73 @@ + + + Second Test Plug-in Test + + + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_src_url_change.html b/dom/plugins/test/mochitest/test_src_url_change.html new file mode 100644 index 0000000000..8e8f4d326a --- /dev/null +++ b/dom/plugins/test/mochitest/test_src_url_change.html @@ -0,0 +1,42 @@ + + + + Test changing src attribute + + + + + + + + +

+ + + + + diff --git a/dom/plugins/test/mochitest/test_streamNotify.html b/dom/plugins/test/mochitest/test_streamNotify.html new file mode 100644 index 0000000000..d1aa8be8da --- /dev/null +++ b/dom/plugins/test/mochitest/test_streamNotify.html @@ -0,0 +1,89 @@ + + NPN_Get/PostURLNotify tests + + + + + + + diff --git a/dom/plugins/test/mochitest/test_streamatclose.html b/dom/plugins/test/mochitest/test_streamatclose.html new file mode 100644 index 0000000000..f308d7d796 --- /dev/null +++ b/dom/plugins/test/mochitest/test_streamatclose.html @@ -0,0 +1,46 @@ + + + Stream open at NPP_Destroy + + + + + + + +

+ + diff --git a/dom/plugins/test/mochitest/test_stringHandling.html b/dom/plugins/test/mochitest/test_stringHandling.html new file mode 100644 index 0000000000..023fcfcb05 --- /dev/null +++ b/dom/plugins/test/mochitest/test_stringHandling.html @@ -0,0 +1,35 @@ + + + NPAPI string test + + + + + + + + + +

+ + + + diff --git a/dom/plugins/test/mochitest/test_twostreams.html b/dom/plugins/test/mochitest/test_twostreams.html new file mode 100644 index 0000000000..c2b3672c83 --- /dev/null +++ b/dom/plugins/test/mochitest/test_twostreams.html @@ -0,0 +1,46 @@ + + + Dual NPAPI NP_ASFILEONLY NPStream Test + + + + + +

+ + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_visibility.html b/dom/plugins/test/mochitest/test_visibility.html new file mode 100644 index 0000000000..943fddaf4e --- /dev/null +++ b/dom/plugins/test/mochitest/test_visibility.html @@ -0,0 +1,100 @@ + + + + Test whether windowless plugins receive correct visible/invisible notifications. + + + + + + +

+ + + + + + + diff --git a/dom/plugins/test/mochitest/test_windowed_invalidate.html b/dom/plugins/test/mochitest/test_windowed_invalidate.html new file mode 100644 index 0000000000..a19e4c8c53 --- /dev/null +++ b/dom/plugins/test/mochitest/test_windowed_invalidate.html @@ -0,0 +1,66 @@ + + + Test NPN_Invalidate working for a windowed plugin + + + + + + + +

+ + + + +
+
+ + diff --git a/dom/plugins/test/mochitest/test_windowless_flash.html b/dom/plugins/test/mochitest/test_windowless_flash.html new file mode 100644 index 0000000000..8274a78aeb --- /dev/null +++ b/dom/plugins/test/mochitest/test_windowless_flash.html @@ -0,0 +1,33 @@ + + + + + + + + + + +

+ +
+ + + +
+ + diff --git a/dom/plugins/test/mochitest/test_windowless_ime.html b/dom/plugins/test/mochitest/test_windowless_ime.html new file mode 100644 index 0000000000..edc9940529 --- /dev/null +++ b/dom/plugins/test/mochitest/test_windowless_ime.html @@ -0,0 +1,46 @@ + + + + + Test #1 for Bug 539565 + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_wmode.xul b/dom/plugins/test/mochitest/test_wmode.xul new file mode 100644 index 0000000000..b45038835a --- /dev/null +++ b/dom/plugins/test/mochitest/test_wmode.xul @@ -0,0 +1,38 @@ + + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_x11_error_crash.html b/dom/plugins/test/mochitest/test_x11_error_crash.html new file mode 100644 index 0000000000..1b52d1e6f6 --- /dev/null +++ b/dom/plugins/test/mochitest/test_x11_error_crash.html @@ -0,0 +1,27 @@ + + Plugin terminating on X11 error + + + + + + diff --git a/dom/plugins/test/mochitest/test_xulbrowser_plugin_visibility.xul b/dom/plugins/test/mochitest/test_xulbrowser_plugin_visibility.xul new file mode 100644 index 0000000000..8cccb8bf7d --- /dev/null +++ b/dom/plugins/test/mochitest/test_xulbrowser_plugin_visibility.xul @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/mochitest/test_zero_opacity.html b/dom/plugins/test/mochitest/test_zero_opacity.html new file mode 100644 index 0000000000..c768cafd53 --- /dev/null +++ b/dom/plugins/test/mochitest/test_zero_opacity.html @@ -0,0 +1,44 @@ + + + + Test whether windowed plugins with opacity:0 get their window set correctly + + + + + + + +

+ + \ No newline at end of file diff --git a/dom/plugins/test/mochitest/xulbrowser_plugin_visibility.xul b/dom/plugins/test/mochitest/xulbrowser_plugin_visibility.xul new file mode 100644 index 0000000000..d087305200 --- /dev/null +++ b/dom/plugins/test/mochitest/xulbrowser_plugin_visibility.xul @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + diff --git a/dom/plugins/test/moz.build b/dom/plugins/test/moz.build new file mode 100644 index 0000000000..c7f7b01edc --- /dev/null +++ b/dom/plugins/test/moz.build @@ -0,0 +1,15 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DIRS += ['testplugin', 'testaddon'] + +XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini'] + +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'cocoa', 'windows'): + MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini'] + MOCHITEST_CHROME_MANIFESTS += ['mochitest/chrome.ini'] + BROWSER_CHROME_MANIFESTS += ['mochitest/browser.ini'] + diff --git a/dom/plugins/test/reftest/border-padding-1-ref.html b/dom/plugins/test/reftest/border-padding-1-ref.html new file mode 100644 index 0000000000..1a33644ac4 --- /dev/null +++ b/dom/plugins/test/reftest/border-padding-1-ref.html @@ -0,0 +1,10 @@ + + + +
+
+
+ + diff --git a/dom/plugins/test/reftest/border-padding-1.html b/dom/plugins/test/reftest/border-padding-1.html new file mode 100644 index 0000000000..6fa2446f40 --- /dev/null +++ b/dom/plugins/test/reftest/border-padding-1.html @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dom/plugins/test/reftest/border-padding-2-ref.html b/dom/plugins/test/reftest/border-padding-2-ref.html new file mode 100644 index 0000000000..ae92da4032 --- /dev/null +++ b/dom/plugins/test/reftest/border-padding-2-ref.html @@ -0,0 +1,17 @@ + + + + + + +
+ + +
+ + diff --git a/dom/plugins/test/reftest/border-padding-2.html b/dom/plugins/test/reftest/border-padding-2.html new file mode 100644 index 0000000000..6a39d2d819 --- /dev/null +++ b/dom/plugins/test/reftest/border-padding-2.html @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/dom/plugins/test/reftest/border-padding-3-ref.html b/dom/plugins/test/reftest/border-padding-3-ref.html new file mode 100644 index 0000000000..5c7bb74564 --- /dev/null +++ b/dom/plugins/test/reftest/border-padding-3-ref.html @@ -0,0 +1,10 @@ + + + +
+
+
+ + diff --git a/dom/plugins/test/reftest/border-padding-3.html b/dom/plugins/test/reftest/border-padding-3.html new file mode 100644 index 0000000000..533445601f --- /dev/null +++ b/dom/plugins/test/reftest/border-padding-3.html @@ -0,0 +1,35 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/reftest/div-alpha-opacity.html b/dom/plugins/test/reftest/div-alpha-opacity.html new file mode 100644 index 0000000000..fec913b640 --- /dev/null +++ b/dom/plugins/test/reftest/div-alpha-opacity.html @@ -0,0 +1,28 @@ + + + + + + +
+
+ + + diff --git a/dom/plugins/test/reftest/div-alpha-zindex.html b/dom/plugins/test/reftest/div-alpha-zindex.html new file mode 100644 index 0000000000..e4672b913b --- /dev/null +++ b/dom/plugins/test/reftest/div-alpha-zindex.html @@ -0,0 +1,27 @@ + + + + + + +
+
+ + + diff --git a/dom/plugins/test/reftest/div-sanity.html b/dom/plugins/test/reftest/div-sanity.html new file mode 100644 index 0000000000..9ffa539191 --- /dev/null +++ b/dom/plugins/test/reftest/div-sanity.html @@ -0,0 +1,17 @@ + + +div boxes + + + +
+
+
+
+ diff --git a/dom/plugins/test/reftest/plugin-alpha-opacity.html b/dom/plugins/test/reftest/plugin-alpha-opacity.html new file mode 100644 index 0000000000..2db6cc4de3 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-alpha-opacity.html @@ -0,0 +1,29 @@ + + + + + + + +
+ + + + diff --git a/dom/plugins/test/reftest/plugin-alpha-zindex.html b/dom/plugins/test/reftest/plugin-alpha-zindex.html new file mode 100644 index 0000000000..ead9b6f4ce --- /dev/null +++ b/dom/plugins/test/reftest/plugin-alpha-zindex.html @@ -0,0 +1,26 @@ + + + + + + + +
+ + + + diff --git a/dom/plugins/test/reftest/plugin-background-1-step.html b/dom/plugins/test/reftest/plugin-background-1-step.html new file mode 100644 index 0000000000..9498633b41 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background-1-step.html @@ -0,0 +1,22 @@ + + + + + + + + +
Test some plugin stuff.
+
+ + + +
+
+
+
+ + diff --git a/dom/plugins/test/reftest/plugin-background-10-step.html b/dom/plugins/test/reftest/plugin-background-10-step.html new file mode 100644 index 0000000000..7a0824a565 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background-10-step.html @@ -0,0 +1,22 @@ + + + + + + + + +
Test some plugin stuff.
+
+ + + +
+
+
+
+ + diff --git a/dom/plugins/test/reftest/plugin-background-2-step.html b/dom/plugins/test/reftest/plugin-background-2-step.html new file mode 100644 index 0000000000..cc186a5f29 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background-2-step.html @@ -0,0 +1,22 @@ + + + + + + + + +
Test some plugin stuff.
+
+ + + +
+
+
+
+ + diff --git a/dom/plugins/test/reftest/plugin-background-5-step.html b/dom/plugins/test/reftest/plugin-background-5-step.html new file mode 100644 index 0000000000..2630719c88 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background-5-step.html @@ -0,0 +1,22 @@ + + + + + + + + +
Test some plugin stuff.
+
+ + + +
+
+
+
+ + diff --git a/dom/plugins/test/reftest/plugin-background-ref.html b/dom/plugins/test/reftest/plugin-background-ref.html new file mode 100644 index 0000000000..651fdecef5 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background-ref.html @@ -0,0 +1,17 @@ + + + + + + +
Test some plugin stuff.
+
+ +
+ +
+
+
+
+ + diff --git a/dom/plugins/test/reftest/plugin-background.css b/dom/plugins/test/reftest/plugin-background.css new file mode 100644 index 0000000000..f6b251214d --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background.css @@ -0,0 +1,61 @@ +div { + position: absolute; +} +#bad { + left:220px; top:0px; + z-index: 0; +} +#good { + left:0px; top:0px; + width:220px; height:220px; + /* Core Animation alpha blending rounding differs + from the Core Graphics blending, adjust with care */ + background-color: rgba(0,255,0, 0.51); + z-index: 0; +} + +#topbar { + left:0px; top:0px; + width:220px; height:20px; + background-color: rgb(0,0,0); + z-index: 2; +} +#topbar { + left:0px; top:0px; + width:220px; height:20px; + background-color: rgb(0,0,0); + z-index: 2; +} +#leftbar { + left:0px; top:0px; + width:20px; height:220px; + background-color: rgb(0,0,0); + z-index: 2; +} +#rightbar { + left:200px; top:0px; + width:20px; height:220px; + background-color: rgb(0,0,0); + z-index: 2; +} +#bottombar { + left:0px; top:200px; + width:220px; height:20px; + background-color: rgb(0,0,0); + z-index: 2; +} + +div#plugin { + position: absolute; + left:1px; top:1px; + width:199px; height:199px; + background-color: rgba(0,0,255, 0.2); + z-index: 1; +} + +embed#plugin { + position: absolute; + left:1px; top:1px; + z-index: 1; +} + diff --git a/dom/plugins/test/reftest/plugin-background.html b/dom/plugins/test/reftest/plugin-background.html new file mode 100644 index 0000000000..4cd1e3f538 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background.html @@ -0,0 +1,20 @@ + + + + + + + +
Test some plugin stuff.
+
+ + + +
+
+
+
+ + diff --git a/dom/plugins/test/reftest/plugin-background.js b/dom/plugins/test/reftest/plugin-background.js new file mode 100644 index 0000000000..5d24562cff --- /dev/null +++ b/dom/plugins/test/reftest/plugin-background.js @@ -0,0 +1,75 @@ +// The including script sets this for us +//var NUM_STEPS; + +var plugin; +var left = 1, top = 1, width = 199, height = 199; +function movePluginTo(x, y, w, h) { + left = x; top = y; width = w; height = h; + plugin.width = w; + plugin.height = h; + plugin.style.left = left + "px"; + plugin.style.top = top + "px"; +} +function deltaInBounds(dx,dy, dw,dh) { + var l = dx + left; + var r = l + width + dw; + var t = dy + top; + var b = t + height + dh; + return (0 <= l && l <= 20 && + 0 <= t && t <= 20 && + 200 <= r && r <= 220 && + 200 <= b && b <= 220); +} + +var initialFrame; +function start() { + window.removeEventListener("MozReftestInvalidate", start, false); + + window.addEventListener("MozAfterPaint", step, false); + window.addEventListener("MozPaintWaitFinished", step, false); + + initialFrame = window.mozPaintCount; + plugin = document.getElementById("plugin"); + + movePluginTo(0,0, 200,200); +} + +var steps = 0; +var which = "move"; // or "grow" +var dx = 1, dy = 1, dw = 1, dh = 1; +function step() { + if (++steps >= NUM_STEPS) { + window.removeEventListener("MozAfterPaint", step, false); + window.removeEventListener("MozPaintWaitFinished", step, false); + return finish(); + } + + var didSomething = false; + if (which == "grow") { + if (deltaInBounds(0,0, dw,dh)) { + movePluginTo(left,top, width+dw, height+dh); + didSomething = true; + } else { + dw = -dw; dh = -dh; + } + } else { + // "move" + if (deltaInBounds(dx,dy, 0,0)) { + movePluginTo(left+dx,top+dy, width, height); + didSomething = true; + } else { + dx = -dx; dy = -dy; + } + } + which = (which == "grow") ? "move" : "grow"; + + if (!didSomething) { + step(); + } +} + +function finish() { + document.documentElement.removeAttribute("class"); +} + +window.addEventListener("MozReftestInvalidate", start, false); diff --git a/dom/plugins/test/reftest/plugin-busy-alpha-zindex.html b/dom/plugins/test/reftest/plugin-busy-alpha-zindex.html new file mode 100644 index 0000000000..e339dd2669 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-busy-alpha-zindex.html @@ -0,0 +1,56 @@ + + + + + + + + + + +
+ + + + + diff --git a/dom/plugins/test/reftest/plugin-canvas-alpha-zindex.html b/dom/plugins/test/reftest/plugin-canvas-alpha-zindex.html new file mode 100644 index 0000000000..517099d1b1 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-canvas-alpha-zindex.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + diff --git a/dom/plugins/test/reftest/plugin-sanity.html b/dom/plugins/test/reftest/plugin-sanity.html new file mode 100644 index 0000000000..4f9c30eee4 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-sanity.html @@ -0,0 +1,13 @@ + + + +Plugin boxes + + + + + + + + diff --git a/dom/plugins/test/reftest/plugin-transform-1-ref.html b/dom/plugins/test/reftest/plugin-transform-1-ref.html new file mode 100644 index 0000000000..259a78b41b --- /dev/null +++ b/dom/plugins/test/reftest/plugin-transform-1-ref.html @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/dom/plugins/test/reftest/plugin-transform-1.html b/dom/plugins/test/reftest/plugin-transform-1.html new file mode 100644 index 0000000000..19f6e8c20f --- /dev/null +++ b/dom/plugins/test/reftest/plugin-transform-1.html @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/dom/plugins/test/reftest/plugin-transform-2-ref.html b/dom/plugins/test/reftest/plugin-transform-2-ref.html new file mode 100644 index 0000000000..93a3924d7e --- /dev/null +++ b/dom/plugins/test/reftest/plugin-transform-2-ref.html @@ -0,0 +1,7 @@ + + + +
+ + diff --git a/dom/plugins/test/reftest/plugin-transform-2.html b/dom/plugins/test/reftest/plugin-transform-2.html new file mode 100644 index 0000000000..7f48640c19 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-transform-2.html @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/dom/plugins/test/reftest/plugin-transform-alpha-zindex.html b/dom/plugins/test/reftest/plugin-transform-alpha-zindex.html new file mode 100644 index 0000000000..52fda4bcf9 --- /dev/null +++ b/dom/plugins/test/reftest/plugin-transform-alpha-zindex.html @@ -0,0 +1,28 @@ + + + + + + + +
+ + + + diff --git a/dom/plugins/test/reftest/pluginproblemui-direction-1-ref.html b/dom/plugins/test/reftest/pluginproblemui-direction-1-ref.html new file mode 100644 index 0000000000..fafec34f43 --- /dev/null +++ b/dom/plugins/test/reftest/pluginproblemui-direction-1-ref.html @@ -0,0 +1,21 @@ + + + + Plugin Problem UI directionality test + + + + + + diff --git a/dom/plugins/test/reftest/pluginproblemui-direction-1.html b/dom/plugins/test/reftest/pluginproblemui-direction-1.html new file mode 100644 index 0000000000..9888850dc9 --- /dev/null +++ b/dom/plugins/test/reftest/pluginproblemui-direction-1.html @@ -0,0 +1,21 @@ + + + + Plugin Problem UI directionality test + + + + + + diff --git a/dom/plugins/test/reftest/pluginproblemui-direction-2-ref.html b/dom/plugins/test/reftest/pluginproblemui-direction-2-ref.html new file mode 100644 index 0000000000..e807b86b5b --- /dev/null +++ b/dom/plugins/test/reftest/pluginproblemui-direction-2-ref.html @@ -0,0 +1,25 @@ + + + + Plugin Problem UI directionality test + + + +
+ + + + diff --git a/dom/plugins/test/reftest/pluginproblemui-direction-2.html b/dom/plugins/test/reftest/pluginproblemui-direction-2.html new file mode 100644 index 0000000000..95b358e372 --- /dev/null +++ b/dom/plugins/test/reftest/pluginproblemui-direction-2.html @@ -0,0 +1,25 @@ + + + + Plugin Problem UI directionality test + + + +
+ + + + diff --git a/dom/plugins/test/reftest/reftest-stylo.list b/dom/plugins/test/reftest/reftest-stylo.list new file mode 100644 index 0000000000..0f900b369c --- /dev/null +++ b/dom/plugins/test/reftest/reftest-stylo.list @@ -0,0 +1,33 @@ +# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing +# basic sanity checking +# fails random-if(!haveTestPlugin) == plugin-sanity.html plugin-sanity.html +# fails-if(!haveTestPlugin) == plugin-sanity.html plugin-sanity.html +skip fails-if(!haveTestPlugin) fuzzy-if(skiaContent,1,160000) == plugin-alpha-zindex.html plugin-alpha-zindex.html +fails-if(!haveTestPlugin) fuzzy-if(skiaContent,1,164000) == plugin-alpha-opacity.html plugin-alpha-opacity.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == windowless-clipping-1.html windowless-clipping-1.html +# bug 631832 +# fuzzy because of anti-aliasing in dashed border +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-1.html border-padding-1.html +# bug 629430 +skip random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2.html +# bug 629430 +skip random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) skip-if(!haveTestPlugin) skip-if(Android||B2G) == border-padding-3.html border-padding-3.html +# bug 629430 +# bug 773482 +# The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced. +#random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-1.html pluginproblemui-direction-1.html +# bug 567367 +#random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-2.html pluginproblemui-direction-2.html +fails-if(!haveTestPlugin) fuzzy-if(skiaContent,1,160000) == plugin-canvas-alpha-zindex.html plugin-canvas-alpha-zindex.html +fails fails-if(!haveTestPlugin) fuzzy-if(skiaContent,1,160000) == plugin-transform-alpha-zindex.html plugin-transform-alpha-zindex.html +skip == plugin-busy-alpha-zindex.html plugin-busy-alpha-zindex.html +skip == plugin-background.html plugin-background.html +skip == plugin-background-1-step.html plugin-background-1-step.html +skip == plugin-background-2-step.html plugin-background-2-step.html +skip == plugin-background-5-step.html plugin-background-5-step.html +skip == plugin-background-10-step.html plugin-background-10-step.html +skip == plugin-transform-1.html plugin-transform-1.html +skip == plugin-transform-2.html plugin-transform-2.html +skip == shrink-1.html shrink-1.html +skip skip-if(!haveTestPlugin) == update-1.html update-1.html +skip skip-if(!haveTestPlugin) == windowless-layers.html windowless-layers.html diff --git a/dom/plugins/test/reftest/reftest.list b/dom/plugins/test/reftest/reftest.list new file mode 100644 index 0000000000..e2d8195367 --- /dev/null +++ b/dom/plugins/test/reftest/reftest.list @@ -0,0 +1,26 @@ +# basic sanity checking +random-if(!haveTestPlugin) != plugin-sanity.html about:blank +fails-if(!haveTestPlugin) == plugin-sanity.html div-sanity.html +fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-alpha-zindex.html div-alpha-zindex.html +fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,164000) == plugin-alpha-opacity.html div-alpha-opacity.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == windowless-clipping-1.html windowless-clipping-1-ref.html # bug 631832 +# fuzzy because of anti-aliasing in dashed border +fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-1.html border-padding-1-ref.html # bug 629430 +fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2-ref.html # bug 629430 +fuzzy(16,256) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) skip-if(!haveTestPlugin||Android) == border-padding-3.html border-padding-3-ref.html # bug 629430 # bug 773482 +# The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced. +#random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367 +#random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html +fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html +fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-transform-alpha-zindex.html div-alpha-zindex.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,160000) == plugin-busy-alpha-zindex.html div-alpha-zindex.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background.html plugin-background-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-1-step.html plugin-background-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-2-step.html plugin-background-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-5-step.html plugin-background-ref.html +random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) fuzzy-if(skiaContent&&haveTestPlugin,1,32400) == plugin-background-10-step.html plugin-background-ref.html +random-if(!haveTestPlugin) == plugin-transform-1.html plugin-transform-1-ref.html +fails-if(!haveTestPlugin) == plugin-transform-2.html plugin-transform-2-ref.html +skip-if(!haveTestPlugin) == shrink-1.html shrink-1-ref.html +skip-if(!haveTestPlugin) == update-1.html update-1-ref.html +skip-if(!haveTestPlugin) == windowless-layers.html windowless-layers-ref.html diff --git a/dom/plugins/test/reftest/shrink-1-ref.html b/dom/plugins/test/reftest/shrink-1-ref.html new file mode 100644 index 0000000000..0906fe5789 --- /dev/null +++ b/dom/plugins/test/reftest/shrink-1-ref.html @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/dom/plugins/test/reftest/shrink-1.html b/dom/plugins/test/reftest/shrink-1.html new file mode 100644 index 0000000000..4957056982 --- /dev/null +++ b/dom/plugins/test/reftest/shrink-1.html @@ -0,0 +1,25 @@ + + + + + + + + + + + diff --git a/dom/plugins/test/reftest/update-1-ref.html b/dom/plugins/test/reftest/update-1-ref.html new file mode 100644 index 0000000000..7303d19840 --- /dev/null +++ b/dom/plugins/test/reftest/update-1-ref.html @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/dom/plugins/test/reftest/update-1.html b/dom/plugins/test/reftest/update-1.html new file mode 100644 index 0000000000..f307b4394f --- /dev/null +++ b/dom/plugins/test/reftest/update-1.html @@ -0,0 +1,59 @@ + + + + Test for bugs 807728 and 810426 + + + + + + + + diff --git a/dom/plugins/test/reftest/utils.js b/dom/plugins/test/reftest/utils.js new file mode 100644 index 0000000000..f046089afc --- /dev/null +++ b/dom/plugins/test/reftest/utils.js @@ -0,0 +1,18 @@ +function forceLoadPluginElement(id) { + var e = document.getElementById(id); + var found = e.pluginFoundElement; +} + +function forceLoadPlugin(ids, skipRemoveAttribute) { + if (Array.isArray(ids)) { + ids.forEach(function(element, index, array) { + forceLoadPluginElement(element); + }); + } else { + forceLoadPluginElement(ids); + } + if (skipRemoveAttribute) { + return; + } + document.documentElement.removeAttribute("class"); +} diff --git a/dom/plugins/test/reftest/windowless-clipping-1-ref.html b/dom/plugins/test/reftest/windowless-clipping-1-ref.html new file mode 100644 index 0000000000..e59ecb79b2 --- /dev/null +++ b/dom/plugins/test/reftest/windowless-clipping-1-ref.html @@ -0,0 +1,14 @@ + + + + + +
+
+ +
+
+
+ + diff --git a/dom/plugins/test/reftest/windowless-clipping-1.html b/dom/plugins/test/reftest/windowless-clipping-1.html new file mode 100644 index 0000000000..dc1c25ac10 --- /dev/null +++ b/dom/plugins/test/reftest/windowless-clipping-1.html @@ -0,0 +1,15 @@ + + + + + +
+ +
+
+ +
+ + diff --git a/dom/plugins/test/reftest/windowless-layers-ref.html b/dom/plugins/test/reftest/windowless-layers-ref.html new file mode 100644 index 0000000000..765527b68f --- /dev/null +++ b/dom/plugins/test/reftest/windowless-layers-ref.html @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/dom/plugins/test/reftest/windowless-layers.html b/dom/plugins/test/reftest/windowless-layers.html new file mode 100644 index 0000000000..9e24c13a68 --- /dev/null +++ b/dom/plugins/test/reftest/windowless-layers.html @@ -0,0 +1,15 @@ + + + + + + +
+ +
+
+ +
+ + diff --git a/dom/plugins/test/testaddon/Makefile.in b/dom/plugins/test/testaddon/Makefile.in new file mode 100644 index 0000000000..7b6dd6bc5f --- /dev/null +++ b/dom/plugins/test/testaddon/Makefile.in @@ -0,0 +1,25 @@ +# 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/. + +include $(topsrcdir)/config/rules.mk + +ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) +plugin_file_names = Test.plugin SecondTest.plugin ThirdTest.plugin npswftest.plugin npctrltest.plugin +addon_file_name = testaddon_$(TARGET_XPCOM_ABI).xpi +else +plugin_file_names = $(DLL_PREFIX)nptest$(DLL_SUFFIX) $(DLL_PREFIX)npsecondtest$(DLL_SUFFIX) $(DLL_PREFIX)npthirdtest$(DLL_SUFFIX) $(DLL_PREFIX)npswftest$(DLL_SUFFIX) $(DLL_PREFIX)npctrltest$(DLL_SUFFIX) +addon_file_name = testaddon.xpi +endif + +# This is so hacky. Waiting on bug 988938. +testdir = $(topobjdir)/_tests/xpcshell/dom/plugins/test/unit/ +addonpath = $(testdir)/$(addon_file_name) + +ifdef COMPILE_ENVIRONMENT +libs:: + $(NSINSTALL) -D $(testdir) + rm -f $(addonpath) + cd $(srcdir) && zip -rD $(addonpath) install.rdf + cd $(DIST) && zip -rD $(addonpath) $(foreach name,$(plugin_file_names),plugins/$(name)) +endif diff --git a/dom/plugins/test/testaddon/install.rdf b/dom/plugins/test/testaddon/install.rdf new file mode 100644 index 0000000000..017badb00a --- /dev/null +++ b/dom/plugins/test/testaddon/install.rdf @@ -0,0 +1,23 @@ + + + + + + test-plugin-from-xpi@tests.mozilla.org + 1 + Test plugin from XPI + This tests shipping a plugin through an extensions. + + + + toolkit@mozilla.org + 0 + * + + + + true + + + diff --git a/dom/plugins/test/testaddon/moz.build b/dom/plugins/test/testaddon/moz.build new file mode 100644 index 0000000000..568f361a54 --- /dev/null +++ b/dom/plugins/test/testaddon/moz.build @@ -0,0 +1,5 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. diff --git a/dom/plugins/test/testplugin/Info.plist b/dom/plugins/test/testplugin/Info.plist new file mode 100644 index 0000000000..dc6aa5cec3 --- /dev/null +++ b/dom/plugins/test/testplugin/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + libnptest.dylib + CFBundleIdentifier + org.mozilla.TestPlugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0.0.0 + CFBundleSignature + TEST + CFBundleVersion + 1.0.0.0 + WebPluginName + Test Plug-in + WebPluginDescription + Plug-in for testing purposes.™ (हिन्दी 中文 العربية) + WebPluginMIMETypes + + application/x-test + + WebPluginExtensions + + tst + + WebPluginTypeDescription + Test ™ mimetype + + + + diff --git a/dom/plugins/test/testplugin/README b/dom/plugins/test/testplugin/README new file mode 100644 index 0000000000..b7ac703634 --- /dev/null +++ b/dom/plugins/test/testplugin/README @@ -0,0 +1,441 @@ += Instructions for using the test plugin = + +== MIME type == + +The test plugin registers itself for the MIME type "application/x-test". + +== Event Model == + +* getEventModel() +Returns the NPAPI event model in use. On platforms without event models, +simply returns 0; + +== Rendering == + +By default, the plugin fills its rectangle with gray, with a black border, and +renders the user-agent string (obtained from NPN_UserAgent) centered in black. +This rendering method is not supported for the async drawing models. + +The test plugin supports the following parameters: + +* drawmode="solid" +The plugin will draw a solid color instead of the default rendering described +above. The default solid color is completely transparent black (i.e., nothing). +This should be specified when using one of the async models. + +* asyncmodel="bitmap" +The plugin will use the NPAPI Async Bitmap drawing model extension. On +unsupported platforms this will fallback to non-async rendering. + +* asyncmodel="dxgi" +The plugin will use the NPAPI Async DXGI drawing model extension. Only +supported on Windows Vista or higher. On unsupported platforms this will +fallback to non-async rendering. + +* color +This specifies the color to use for drawmode="solid". The value should be 8 hex +digits, 2 per channel in AARRGGBB format. + +== Generic API Tests == + +* setUndefinedValueTest +Attempts to set the value of an undefined variable (0x0) via NPN_SetValue, +returns true if it succeeds and false if it doesn't. It should never succeed. + +* .getReflector() +Hands back an object which reflects properties as values, e.g. + .getReflector().foo = 'foo' + .getReflector()['foo'] = 'foo' + .getReflector()[1] = 1 + +* .getNPNVdocumentOrigin() +Returns the origin string retrieved from the browser by a NPNVdocumentOrigin +variable request. Does not cache the value, gets it from the browser every time. + +== NPN_ConvertPoint testing == + +* convertPointX(sourceSpace, sourceX, sourceY, destSpace) +* convertPointY(sourceSpace, sourceX, sourceY, destSpace) +The plugin uses NPN_ConvertPoint to convert sourceX and sourceY from the source +to dest space and returns the X or Y result based on the call. + +== NPCocoaEventWindowFocusChanged == + +* getTopLevelWindowActivationState() +Returns the activation state for the top-level window as set by the last +NPCocoaEventWindowFocusChanged event. Returns true for active, false for +inactive, and throws an exception if the state is unknown (uninitialized). + +* getTopLevelWindowActivationEventCount() +Returns the number of NPCocoaEventWindowFocusChanged events received by +the instance. + +== Focus Tests == + +* getFocusState() +Returns the plugin's focus state. Returns true for focused, false for unfocused, +and throws an exception if the state is unknown (uninitialized). This does not +necessarily correspond to actual input focus - this corresponds to focus as +defined by the NPAPI event model in use. + +* getFocusEventCount() +Returns the number of focus events received by the instance. + +== NPRuntime testing == + +The test plugin object supports the following scriptable methods: + +* identifierToStringTest(ident) +Converts a string, int32 or double parameter 'ident' to an NPIdentifier and +then to a string, which is returned. + +* npnEvaluateTest(script) +Calls NPN_Evaluate on the 'script' argument, which is a string containing +some script to be executed. Returns the result of the evaluation. + +* npnInvokeTest(method, expected, args...) +Causes the plugin to call the specified script method using NPN_Invoke, +passing it 1 or more arguments specified in args. The return value of this +call is compared against 'expected', and if they match, npnInvokeTest will +return true. Otherwise, it will return false. + +* npnInvokeDefaultTest(object, argument) +Causes the plugin to call NPN_InvokeDefault on the specified object, +with the specified argument. Returns the result of the invocation. + +* getError() +If an error has occurred during the last stream or npruntime function, +this will return a string error message, otherwise it returns "pass". + +* throwExceptionNextInvoke() +Sets a flag which causes the next call to a scriptable method to throw +one or more exceptions. If no parameters are passed to the next +scriptable method call, it will cause a generic exception to be thrown. +Otherwise there will be one exception thrown per argument, with the argument +used as the exception message. Example: + + plugin.throwExceptionNextInvoke(); + plugin.npnInvokeTest("first exception message", "second exception message"); + +* () - default method +Returns a string consisting of the plugin name, concatenated with any +arguments passed to the method. + +* .crash() - Crashes the plugin + +* getObjectValue() - Returns a custom plugin-implemented scriptable object. +* checkObjectValue(obj) - Returns true if the object from getObjectValue() is + the same object passed into this function. It should return true when + the object is passed to the same plugin instance, and false when passed + to other plugin instances, see bug 532246 and + test_multipleinstanceobjects.html. + +* callOnDestroy(fn) - Calls `fn` when the plugin instance is being destroyed + +* getAuthInfo(protocol, host, port, scheme, realm) - a wrapper for +NPN_GetAuthenticationInfo(). Returns a string "username|password" for +the specified auth criteria, or throws an exception if no data is +available. + +* timerTest(callback) - initiates tests of NPN_ScheduleTimer & +NPN_UnscheduleTimer. When finished, calls the script callback +with a boolean value, indicating whether the tests were successful. + +* asyncCallbackTest(callback) - initiates tests of +NPN_PluginThreadAsyncCall. When finished, calls the script callback +with a boolean value, indicating whether the tests were successful. + +* paintscript="..." content attribute +If the "paintscript" attribute is set on the plugin element during plugin +initialization, then every time the plugin paints it gets the contents of that +attribute and evaluates it as a script in the context of the plugin's DOM +window. This is useful for testing evil plugin code that might, for example, +modify the DOM during painting. + +== Private browsing == + +The test plugin object supports the following scriptable methods: + +* queryPrivateModeState +Returns the value of NPN_GetValue(NPNVprivateModeBool). + +* lastReportedPrivateModeState +Returns the last value set by NPP_SetValue(NPNVprivateModeBool). + +== Windowed/windowless mode == + +The test plugin is windowless by default. + +The test plugin supports the following parameter: + +* wmode="window" +The plugin will be given a native widget on platforms where we support this +(Windows and X). + +The test plugin object supports the following scriptable method: + +* hasWidget() +Returns true if the plugin has an associated widget. This will return true if +wmode="window" was specified and the platform supports windowed plugins. + +== Plugin invalidation == + +* setColor(colorString) +Sets the color used for drawmode="solid" and invalidates the plugin area. +This calls NPN_Invalidate, even for windowed plugins, since that should work +for windowed plugins too (Silverlight depends on it). + +* getPaintCount() +Returns the number of times this plugin instance has processed a paint request. +This can be used to detect whether painting has happened in a plugin's +window. + +* getWidthAtLastPaint() +Returns the window width that was current when the plugin last painted. + +* setInvalidateDuringPaint(value) +When value is true, every time the plugin paints, it will invalidate +itself *during the paint* using NPN_Invalidate. + +* setSlowPaint(value) +When value is true, the instance will sleep briefly during paint. + +== Plugin geometry == + +The test plugin supports the following scriptable methods: + +* getEdge(edge) +Returns the integer screen pixel coordinate of an edge of the plugin's +area: +-- edge=0: returns left edge coordinate +-- edge=1: returns top edge coordinate +-- edge=2: returns right edge coordinate +-- edge=3: returns bottom edge coordinate +The coordinates are relative to the top-left corner of the top-level window +containing the plugin, including the window decorations. Therefore: +-- On Mac, they're relative to the top-left corner of the toplevel Cocoa +window. +-- On Windows, they're relative to the top-left corner of the toplevel HWND's +non-client area. +-- On GTK2, they're relative to the top-left corner of the toplevel window's +window manager frame. +This means they can be added to Gecko's window.screenX/screenY (if DPI is set +to 96) to get screen coordinates. +On the platforms that support window-mode plugins (Windows/GTK2), this only +works for window-mode plugins. It will throw an error for windowless plugins. + +* getClipRegionRectCount() +Returns the number of rectangles in the plugin's clip region. +For plugins with widgets, the clip region is computed as the intersection of the +clip region for the widget (if the platform does not support clip regions +on native widgets, this would just be the widget's rectangle) with the +clip regions of all ancestor widgets which would clip this widget. +On the platforms that support window-mode plugins (Windows/GTK2), this only +works for window-mode plugins. It will throw an error for windowless plugins. +On Mac, all plugins have a clip region containing just a single clip +rectangle only. So if you request wmode="window" but the plugin reports +!hasWidget, you can assume that complex clip regions are not supported. + +* getClipRegionRectEdge(i, edge) +Returns the integer screen pixel coordinate of an edge of a rectangle from the +plugin's clip region. If i is less than zero or greater than or equal to +getClipRegionRectCount(), this will throw an error. The coordinates are +the same as for getEdge. See getClipRegionRectCount() above for +notes on platform plugin limitations. + +== Keyboard events == + +* getLastKeyText() +Returns the text which was inputted by last keyboard events. This is cleared at +every keydown event. +NOTE: Currently, this is implemented only on Windows. + +== Mouse events == + +The test plugin supports the following scriptable methods: + +* getLastMouseX() +Returns the X coordinate of the last mouse event (move, button up, or +button down), relative to the left edge of the plugin, or -1 if no mouse +event has been received. + +* getLastMouseX() +Returns the Y coordinate of the last mouse event (move, button up, or +button down), relative to the top edge of the plugin, or -1 if no mouse +event has been received. + +== Instance lifecycle == + +The test plugin supports the following scriptable methods: + +* startWatchingInstanceCount() +Marks all currently running instances as "ignored". Throws an exception if +there is already a watch (startWatchingInstanceCount has already been +called on some instance without a corresponding stopWatchingInstanceCount). + +* getInstanceCount() +Returns the count of currently running instances that are not ignored. +Throws an exception if there is no watch. + +* stopWatchingInstanceCount() +Stops watching. Throws an exception if there is no watch. + +== NPAPI Timers == + +* unscheduleAllTimers() +Instructs the plugin instance to cancel all timers created via +NPN_ScheduleTimer. + +== Stream Functionality == + +The test plugin enables a variety of NPAPI streaming tests, which are +initiated by passing a variety of attributes to the element which +causes the plugin to be initialized. The plugin stream test code is +designed to receive a stream from the browser (by specifying a "src", +"geturl", or "geturlnotify" attribute), and then (if a "frame" attribute +is specified) send the data from that stream back to the browser in another +stream, whereupon it will be displayed in the specified frame. If some +error occurs during stream processing, an error message will appear in the +frame instead of the stream data. If no "frame" attribute is present, a +stream can still be received by the plugin, but the plugin will do nothing +with it. + +The attributes which control stream tests are: + +"streammode": one of "normal", "asfile", "asfileonly", "seek". Sets the + stream mode to the specified mode in any call to NPP_NewStream. + Defaults to "asfileonly". + +"streamchunksize": the number of bytes the plugin reports it can accept + in calls to NPP_WriteReady. Defaults to 1,024. + +"src": a url. If specified, the browser will call NPP_NewStream for + this url as soon as the plugin is initialized. + +"geturl": a url. If specified, the plugin will request this url + from the browser when the plugin is initialized, via a call to + NPN_GetURL. + +"geturlnotify": a url. If specified, the plugin will request this url + from the browser when the plugin is initialized, via a call to + NPN_GetURLNotify. The plugin passes some "notifyData" to + NPN_GetURLNotify, which it verifies is present in the call to + NPP_URLNotify. If the "notifyData" does not match, an error + will be displayed in the test frame (if any), instead of the stream + data. + +"frame": the name of a frame in the same HTML document as the + element which instantiated the plugin. For any of the preceding three + attributes, a stream is received by the plugin via calls to NPP_NewStream, + NPP_WriteReady, NPP_Write, and NPP_DestroyStream. When NPP_DestroyStream + is called (or NPP_UrlNotify, in the case of "geturlnotify"), and a + "frame" attribute is present, the data from the stream is converted into a + data: url, and sent back to the browser in another stream via a call to + NPN_GetURL, whereupon it should be displayed in the specified frame. + +"range": one or more byte ranges, in the format "offset,length;offset,length". + Only valid when "streammode" = "seek". When "range" is present, the plugin + will request the specified byte ranges from the stream via a call to + NPN_RequestRead, which it makes after the browser makes its final call to + NPP_Write. The plugin verifies that the browser makes additional calls + to NPP_Write according to the requested byte ranges, and that the data + received is correct. Any errors will appear in the test "frame", if + specified. + +"posturl": a url. After the plugin receives a stream, and NPP_DestroyStream + is called, if "posturl" is specified, the plugin will post the contents + of the stream to the specified url via NPN_PostURL. See "postmode" for + additional details. + +"postmode": either "frame" or "stream". If "frame", and a "frame" attribute + is present, the plugin will pass the frame name to calls to NPN_PostURL, + so that the HTTP response from that operation will be displayed in the + specified frame. If "stream", the HTTP response is delivered to the plugin + via calls to NPP_NewStream etc, and if a "frame" attribute is present, the + contents of that stream will be passed back to the browser and displayed + in the specified frame via NPN_GetURL. + +"newstream": if "true", then any stream which is sent to a frame in the browser + is sent via calls to NPN_NewStream and NPN_Write. Doing so will cause + the browser to store the stream data in a file, and set the frame's + location to the corresponding file:// url. + +"functiontofail": one of "npp_newstream", "npp_write", "npp_destroystream". + When specified, the given function will return an error code (-1 for + NPP_Write, or else the value of the "failurecode" attribute) the first time + it is called by the browser. + +"failurecode": one of the NPError constants. Used to specify the error + that will be returned by the "functiontofail". + +If the plugin is instantiated as a full-page plugin, the following defaults +are used: + streammode="seek" frame="testframe" range="100,100" + +* streamTest(url, doPost, postData, writeCallback, notifyCallback, redirectCallback, allowRedirects) +This will test how NPN_GetURLNotify and NPN_PostURLNotify behave when they are +called with arbitrary (malformed) URLs. The function will return `true` if +NPN_[Get/Post]URLNotify succeeds, and `false` if it fails. +@url url to request +@param doPost whether to call NPN_PostURLNotify +@param postData null, or a string to send a postdata +@writeCallback will be called when data is received for the stream +@notifyCallback will be called when the urlnotify is received with the notify result +@redirectCallback will be called from urlredirectnotify if a redirect is attempted +@allowRedirects boolean value indicating whether or not to allow redirects + +* setPluginWantsAllStreams(wantsAllStreams) +Set the value returned by the plugin for NPPVpluginWantsAllNetworkStreams. + +== Internal consistency == + +* doInternalConsistencyCheck() +Does internal consistency checking, returning an empty string if everything is +OK, otherwise returning some kind of error string. On Windows, in windowed +mode, this checks that the position of the plugin's internal child +window has not been disturbed relative to the plugin window. + +== Windows native widget message behaviour == + +* Mouse events are handled (saving the last mouse event coordinate) and not +passed to the overridden windowproc. + +* WM_MOUSEWHEEL events are handled and not passed to the parent window or the +overridden windowproc. + +* WM_MOUSEACTIVATE events are handled by calling SetFocus on the plugin's +widget, if the plugin is windowed. If it's not windowed they're passed to +the overriden windowproc (but hopefully never sent by the browser anyway). + +== Getting and Setting Cookies == + +* setCookie(string) +Sets the given string as the cookie for window's URL. + +* getCookie() +Returns the cookie string for the window's URL, the cookie set by setCookie. + +== FPU Control == + +x86-only on some OSes: + +* The .enableFPExceptions() method will enable floating-point exceptions, + as evil plugins or extensions might do. + +== HiDPI Mode == + +* queryContentsScaleFactor() +Returns the contents scale factor. On platforms without support for this query +always returns 1.0 (a double value). Likewise on hardware without HiDPI mode +support. + +== Plugin audio channel support == + +* startAudioPlayback() +Simulates the plugin starting to play back audio. + +* stopAudioPlayback() +Simulates the plugin stopping to play back audio. + +* audioMuted() +Returns the last value set by NPP_SetValue(NPNVmuteAudioBool). diff --git a/dom/plugins/test/testplugin/flashplugin/Info.plist b/dom/plugins/test/testplugin/flashplugin/Info.plist new file mode 100644 index 0000000000..0e6168e686 --- /dev/null +++ b/dom/plugins/test/testplugin/flashplugin/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + libnpswftest.dylib + CFBundleIdentifier + org.mozilla.FlashTestPlugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0.0.0 + CFBundleSignature + FLASHTEST + CFBundleVersion + 1.0.0.0 + WebPluginName + Shockwave Flash + WebPluginDescription + Flash plug-in for testing purposes. + WebPluginMIMETypes + + application/x-shockwave-flash-test + + WebPluginExtensions + + swf + + WebPluginTypeDescription + Flash test type + + + + diff --git a/dom/plugins/test/testplugin/flashplugin/moz.build b/dom/plugins/test/testplugin/flashplugin/moz.build new file mode 100644 index 0000000000..3df524a2bc --- /dev/null +++ b/dom/plugins/test/testplugin/flashplugin/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SharedLibrary('npswftest') + +relative_path = 'flashplugin' +cocoa_name = 'npswftest' +include('../testplugin.mozbuild') diff --git a/dom/plugins/test/testplugin/flashplugin/nptest.def b/dom/plugins/test/testplugin/flashplugin/nptest.def new file mode 100644 index 0000000000..3a62d05d95 --- /dev/null +++ b/dom/plugins/test/testplugin/flashplugin/nptest.def @@ -0,0 +1,7 @@ +LIBRARY NPSWFTEST + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 + NP_GetMIMEDescription @4 diff --git a/dom/plugins/test/testplugin/flashplugin/nptest.rc b/dom/plugins/test/testplugin/flashplugin/nptest.rc new file mode 100644 index 0000000000..e970d26091 --- /dev/null +++ b/dom/plugins/test/testplugin/flashplugin/nptest.rc @@ -0,0 +1,42 @@ +#include + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "mozilla.org" + VALUE "FileDescription", L"Flash plug-in for testing purposes." + VALUE "FileExtents", "swf" + VALUE "FileOpenName", "Flash test type" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "npswftest" + VALUE "MIMEType", "application/x-shockwave-flash-test" + VALUE "OriginalFilename", "npswftest.dll" + VALUE "ProductName", "Shockwave Flash" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/dom/plugins/test/testplugin/flashplugin/nptest_name.cpp b/dom/plugins/test/testplugin/flashplugin/nptest_name.cpp new file mode 100644 index 0000000000..140e0225c2 --- /dev/null +++ b/dom/plugins/test/testplugin/flashplugin/nptest_name.cpp @@ -0,0 +1,7 @@ +/* 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/. */ + +const char *sPluginName = "Shockwave Flash"; +const char *sPluginDescription = "Flash plug-in for testing purposes."; +const char *sMimeDescription = "application/x-shockwave-flash-test:swf:Flash test type"; diff --git a/dom/plugins/test/testplugin/javaplugin/Info.plist b/dom/plugins/test/testplugin/javaplugin/Info.plist new file mode 100644 index 0000000000..16a45f2645 --- /dev/null +++ b/dom/plugins/test/testplugin/javaplugin/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + libnptestjava.dylib + CFBundleIdentifier + org.mozilla.JavaTestPlugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0.0.0 + CFBundleSignature + JAVATEST + CFBundleVersion + 1.0.0.0 + WebPluginName + Java Test Plug-in + WebPluginDescription + Dummy Java plug-in for testing purposes. + WebPluginMIMETypes + + application/x-java-test + + WebPluginExtensions + + tstjava + + WebPluginTypeDescription + Dummy java type + + + + diff --git a/dom/plugins/test/testplugin/javaplugin/moz.build b/dom/plugins/test/testplugin/javaplugin/moz.build new file mode 100644 index 0000000000..4e2abb3ed3 --- /dev/null +++ b/dom/plugins/test/testplugin/javaplugin/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SharedLibrary('nptestjava') + +relative_path = 'javaplugin' +cocoa_name = 'JavaTest' +include('../testplugin.mozbuild') diff --git a/dom/plugins/test/testplugin/javaplugin/nptest.def b/dom/plugins/test/testplugin/javaplugin/nptest.def new file mode 100644 index 0000000000..da24cc4b6d --- /dev/null +++ b/dom/plugins/test/testplugin/javaplugin/nptest.def @@ -0,0 +1,7 @@ +LIBRARY NPJAVATEST + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 + NP_GetMIMEDescription @4 diff --git a/dom/plugins/test/testplugin/javaplugin/nptest.rc b/dom/plugins/test/testplugin/javaplugin/nptest.rc new file mode 100644 index 0000000000..61b18ef6e4 --- /dev/null +++ b/dom/plugins/test/testplugin/javaplugin/nptest.rc @@ -0,0 +1,42 @@ +#include + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "mozilla.org" + VALUE "FileDescription", L"Dummy Java plug-in for testing purposes." + VALUE "FileExtents", "tstjava" + VALUE "FileOpenName", "Dummy java test type" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "nptestjava" + VALUE "MIMEType", "application/x-java-test" + VALUE "OriginalFilename", "nptestjava.dll" + VALUE "ProductName", "Java Test Plug-in" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/dom/plugins/test/testplugin/javaplugin/nptest_name.cpp b/dom/plugins/test/testplugin/javaplugin/nptest_name.cpp new file mode 100644 index 0000000000..ae3a8d1466 --- /dev/null +++ b/dom/plugins/test/testplugin/javaplugin/nptest_name.cpp @@ -0,0 +1,7 @@ +/* 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/. */ + +const char *sPluginName = "Java Test Plug-in"; +const char *sPluginDescription = "Dummy Java plug-in for testing purposes."; +const char *sMimeDescription = "application/x-java-test:tstjava:Dummy java type"; diff --git a/dom/plugins/test/testplugin/moz.build b/dom/plugins/test/testplugin/moz.build new file mode 100644 index 0000000000..a79e58c1d7 --- /dev/null +++ b/dom/plugins/test/testplugin/moz.build @@ -0,0 +1,13 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +DIRS += ['secondplugin', 'javaplugin', 'thirdplugin', 'flashplugin', 'silverlightplugin'] + +SharedLibrary('nptest') + +relative_path = '.' +cocoa_name = 'Test' +include('testplugin.mozbuild') diff --git a/dom/plugins/test/testplugin/nptest.cpp b/dom/plugins/test/testplugin/nptest.cpp new file mode 100644 index 0000000000..aa759ac16b --- /dev/null +++ b/dom/plugins/test/testplugin/nptest.cpp @@ -0,0 +1,4064 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (c) 2008, Mozilla Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Mozilla Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Dave Townsend + * Josh Aas + * + * ***** END LICENSE BLOCK ***** */ + +#include "nptest.h" +#include "nptest_utils.h" +#include "nptest_platform.h" + +#include "mozilla/ArrayUtils.h" +#include "mozilla/IntentionalCrash.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XP_WIN +#include +#include +#include +#define getpid _getpid +#define strcasecmp _stricmp +#else +#include +#include +#endif + +using namespace std; + +#define PLUGIN_VERSION "1.0.0.0" + +extern const char *sPluginName; +extern const char *sPluginDescription; +static char sPluginVersion[] = PLUGIN_VERSION; + +// +// Intentional crash +// + +int gCrashCount = 0; + +static void Crash() +{ + int *pi = nullptr; + *pi = 55; // Crash dereferencing null pointer + ++gCrashCount; +} + +static void +IntentionalCrash() +{ + mozilla::NoteIntentionalCrash("plugin"); + Crash(); +} + +// +// static data +// + +static NPNetscapeFuncs* sBrowserFuncs = nullptr; +static NPClass sNPClass; + +void +asyncCallback(void* cookie); + +// +// identifiers +// + +typedef bool (* ScriptableFunction) + (NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); + +static bool npnEvaluateTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool npnInvokeTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool npnInvokeDefaultTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setUndefinedValueTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool identifierToStringTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool timerTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool lastReportedPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool hasWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getClipRegionRectCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getClipRegionRectEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool startWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool stopWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getLastMouseX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getLastMouseY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getPaintCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool resetPaintCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getWidthAtLastPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setInvalidateDuringPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setSlowPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getError(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool doInternalConsistencyCheck(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setColor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool throwExceptionNextInvoke(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool convertPointX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool convertPointY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool streamTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setPluginWantsAllStreams(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool crashOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getJavaCodebase(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool checkObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool triggerXError(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool destroySharedGfxStuff(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool propertyAndMethod(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getTopLevelWindowActivationState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getTopLevelWindowActivationEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getFocusState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getFocusEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getEventModel(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getReflector(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool isVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getWindowPosition(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool queryContentsScaleFactor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool queryCSSZoomFactorGetValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool queryCSSZoomFactorSetValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool echoString(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool startAudioPlayback(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool stopAudioPlayback(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getAudioMuted(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool nativeWidgetIsVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +static bool getLastCompositionText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); + +static const NPUTF8* sPluginMethodIdentifierNames[] = { + "npnEvaluateTest", + "npnInvokeTest", + "npnInvokeDefaultTest", + "setUndefinedValueTest", + "identifierToStringTest", + "timerTest", + "queryPrivateModeState", + "lastReportedPrivateModeState", + "hasWidget", + "getEdge", + "getClipRegionRectCount", + "getClipRegionRectEdge", + "startWatchingInstanceCount", + "getInstanceCount", + "stopWatchingInstanceCount", + "getLastMouseX", + "getLastMouseY", + "getPaintCount", + "resetPaintCount", + "getWidthAtLastPaint", + "setInvalidateDuringPaint", + "setSlowPaint", + "getError", + "doInternalConsistencyCheck", + "setColor", + "throwExceptionNextInvoke", + "convertPointX", + "convertPointY", + "streamTest", + "setPluginWantsAllStreams", + "crash", + "crashOnDestroy", + "getObjectValue", + "getJavaCodebase", + "checkObjectValue", + "enableFPExceptions", + "setCookie", + "getCookie", + "getAuthInfo", + "asyncCallbackTest", + "checkGCRace", + "hang", + "stall", + "getClipboardText", + "callOnDestroy", + "reinitWidget", + "crashInNestedLoop", + "triggerXError", + "destroySharedGfxStuff", + "propertyAndMethod", + "getTopLevelWindowActivationState", + "getTopLevelWindowActivationEventCount", + "getFocusState", + "getFocusEventCount", + "getEventModel", + "getReflector", + "isVisible", + "getWindowPosition", + "constructObject", + "setSitesWithData", + "setSitesWithDataCapabilities", + "getLastKeyText", + "getNPNVdocumentOrigin", + "getMouseUpEventCount", + "queryContentsScaleFactor", + "queryCSSZoomFactorSetValue", + "queryCSSZoomFactorGetValue", + "echoString", + "startAudioPlayback", + "stopAudioPlayback", + "audioMuted", + "nativeWidgetIsVisible", + "getLastCompositionText", +}; +static NPIdentifier sPluginMethodIdentifiers[MOZ_ARRAY_LENGTH(sPluginMethodIdentifierNames)]; +static const ScriptableFunction sPluginMethodFunctions[] = { + npnEvaluateTest, + npnInvokeTest, + npnInvokeDefaultTest, + setUndefinedValueTest, + identifierToStringTest, + timerTest, + queryPrivateModeState, + lastReportedPrivateModeState, + hasWidget, + getEdge, + getClipRegionRectCount, + getClipRegionRectEdge, + startWatchingInstanceCount, + getInstanceCount, + stopWatchingInstanceCount, + getLastMouseX, + getLastMouseY, + getPaintCount, + resetPaintCount, + getWidthAtLastPaint, + setInvalidateDuringPaint, + setSlowPaint, + getError, + doInternalConsistencyCheck, + setColor, + throwExceptionNextInvoke, + convertPointX, + convertPointY, + streamTest, + setPluginWantsAllStreams, + crashPlugin, + crashOnDestroy, + getObjectValue, + getJavaCodebase, + checkObjectValue, + enableFPExceptions, + setCookie, + getCookie, + getAuthInfo, + asyncCallbackTest, + checkGCRace, + hangPlugin, + stallPlugin, + getClipboardText, + callOnDestroy, + reinitWidget, + crashPluginInNestedLoop, + triggerXError, + destroySharedGfxStuff, + propertyAndMethod, + getTopLevelWindowActivationState, + getTopLevelWindowActivationEventCount, + getFocusState, + getFocusEventCount, + getEventModel, + getReflector, + isVisible, + getWindowPosition, + constructObject, + setSitesWithData, + setSitesWithDataCapabilities, + getLastKeyText, + getNPNVdocumentOrigin, + getMouseUpEventCount, + queryContentsScaleFactor, + queryCSSZoomFactorGetValue, + queryCSSZoomFactorSetValue, + echoString, + startAudioPlayback, + stopAudioPlayback, + getAudioMuted, + nativeWidgetIsVisible, + getLastCompositionText, +}; + +static_assert(MOZ_ARRAY_LENGTH(sPluginMethodIdentifierNames) == + MOZ_ARRAY_LENGTH(sPluginMethodFunctions), + "Arrays should have the same size"); + +static const NPUTF8* sPluginPropertyIdentifierNames[] = { + "propertyAndMethod" +}; +static NPIdentifier sPluginPropertyIdentifiers[MOZ_ARRAY_LENGTH(sPluginPropertyIdentifierNames)]; +static NPVariant sPluginPropertyValues[MOZ_ARRAY_LENGTH(sPluginPropertyIdentifierNames)]; + +struct URLNotifyData +{ + const char* cookie; + NPObject* writeCallback; + NPObject* notifyCallback; + NPObject* redirectCallback; + bool allowRedirects; + uint32_t size; + char* data; +}; + +static URLNotifyData kNotifyData = { + "static-cookie", + nullptr, + nullptr, + nullptr, + false, + 0, + nullptr +}; + +static const char* SUCCESS_STRING = "pass"; + +static bool sIdentifiersInitialized = false; + +struct timerEvent { + int32_t timerIdReceive; + int32_t timerIdSchedule; + uint32_t timerInterval; + bool timerRepeat; + int32_t timerIdUnschedule; +}; +static timerEvent timerEvents[] = { + {-1, 0, 200, false, -1}, + {0, 0, 400, false, -1}, + {0, 0, 200, true, -1}, + {0, 1, 400, true, -1}, + {0, -1, 0, false, 0}, + {1, -1, 0, false, -1}, + {1, -1, 0, false, 1}, +}; +static uint32_t currentTimerEventCount = 0; +static uint32_t totalTimerEvents = sizeof(timerEvents) / sizeof(timerEvent); + +/** + * Incremented for every startWatchingInstanceCount. + */ +static int32_t sCurrentInstanceCountWatchGeneration = 0; +/** + * Tracks the number of instances created or destroyed since the last + * startWatchingInstanceCount. + */ +static int32_t sInstanceCount = 0; +/** + * True when we've had a startWatchingInstanceCount with no corresponding + * stopWatchingInstanceCount. + */ +static bool sWatchingInstanceCount = false; + +/** + * A list representing sites for which the plugin has stored data. See + * NPP_ClearSiteData and NPP_GetSitesWithData. + */ +struct siteData { + string site; + uint64_t flags; + uint64_t age; +}; +static list* sSitesWithData; +static bool sClearByAgeSupported; + +static void initializeIdentifiers() +{ + if (!sIdentifiersInitialized) { + NPN_GetStringIdentifiers(sPluginMethodIdentifierNames, + MOZ_ARRAY_LENGTH(sPluginMethodIdentifierNames), sPluginMethodIdentifiers); + NPN_GetStringIdentifiers(sPluginPropertyIdentifierNames, + MOZ_ARRAY_LENGTH(sPluginPropertyIdentifierNames), sPluginPropertyIdentifiers); + + sIdentifiersInitialized = true; + + // Check whether nullptr is handled in NPN_GetStringIdentifiers + NPIdentifier IDList[2]; + static char const *const kIDNames[2] = { nullptr, "setCookie" }; + NPN_GetStringIdentifiers(const_cast(kIDNames), 2, IDList); + } +} + +static void clearIdentifiers() +{ + memset(sPluginMethodIdentifiers, 0, + MOZ_ARRAY_LENGTH(sPluginMethodIdentifiers) * sizeof(NPIdentifier)); + memset(sPluginPropertyIdentifiers, 0, + MOZ_ARRAY_LENGTH(sPluginPropertyIdentifiers) * sizeof(NPIdentifier)); + + sIdentifiersInitialized = false; +} + +static void addRange(InstanceData* instanceData, const char* range) +{ + /* + increased rangestr size from 16 to 17, the 17byte is only for + null terminated value, maybe for actual capacity it needs 16 bytes + */ + char rangestr[17]; + memset(rangestr, 0, sizeof(rangestr)); + strncpy(rangestr, range, sizeof(rangestr) - sizeof(char)); + const char* str1 = strtok(rangestr, ","); + const char* str2 = str1 ? strtok(nullptr, ",") : nullptr; + if (str1 && str2) { + TestRange* byterange = new TestRange; + byterange->offset = atoi(str1); + byterange->length = atoi(str2); + byterange->waiting = true; + byterange->next = instanceData->testrange; + instanceData->testrange = byterange; + } +} + +static void sendBufferToFrame(NPP instance) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + string outbuf; + if (!instanceData->npnNewStream) outbuf = "data:text/html,"; + const char* buf = reinterpret_cast(instanceData->streamBuf); + int32_t bufsize = instanceData->streamBufSize; + if (instanceData->streamMode == NP_ASFILE || + instanceData->streamMode == NP_ASFILEONLY) { + buf = reinterpret_cast(instanceData->fileBuf); + bufsize = instanceData->fileBufSize; + } + if (instanceData->err.str().length() > 0) { + outbuf.append(instanceData->err.str()); + } + else if (bufsize > 0) { + outbuf.append(buf); + } + else { + outbuf.append("Error: no data in buffer"); + } + + if (instanceData->npnNewStream && + instanceData->err.str().length() == 0) { + char typeHTML[] = "text/html"; + NPStream* stream; + printf("calling NPN_NewStream..."); + NPError err = NPN_NewStream(instance, typeHTML, + instanceData->frame.c_str(), &stream); + printf("return value %d\n", err); + if (err != NPERR_NO_ERROR) { + instanceData->err << "NPN_NewStream returned " << err; + return; + } + + int32_t bytesToWrite = outbuf.length(); + int32_t bytesWritten = 0; + while ((bytesToWrite - bytesWritten) > 0) { + int32_t numBytes = (bytesToWrite - bytesWritten) < + instanceData->streamChunkSize ? + bytesToWrite - bytesWritten : instanceData->streamChunkSize; + int32_t written = NPN_Write(instance, stream, + numBytes, (void*)(outbuf.c_str() + bytesWritten)); + if (written <= 0) { + instanceData->err << "NPN_Write returned " << written; + break; + } + bytesWritten += numBytes; + printf("%d bytes written, total %d\n", written, bytesWritten); + } + err = NPN_DestroyStream(instance, stream, NPRES_DONE); + if (err != NPERR_NO_ERROR) { + instanceData->err << "NPN_DestroyStream returned " << err; + } + } + else { + // Convert CRLF to LF, and escape most other non-alphanumeric chars. + for (size_t i = 0; i < outbuf.length(); i++) { + if (outbuf[i] == '\n') { + outbuf.replace(i, 1, "%0a"); + i += 2; + } + else if (outbuf[i] == '\r') { + outbuf.replace(i, 1, ""); + i -= 1; + } + else { + int ascii = outbuf[i]; + if (!((ascii >= ',' && ascii <= ';') || + (ascii >= 'A' && ascii <= 'Z') || + (ascii >= 'a' && ascii <= 'z'))) { + char hex[8]; + sprintf(hex, "%%%x", ascii); + outbuf.replace(i, 1, hex); + i += 2; + } + } + } + + NPError err = NPN_GetURL(instance, outbuf.c_str(), + instanceData->frame.c_str()); + if (err != NPERR_NO_ERROR) { + instanceData->err << "NPN_GetURL returned " << err; + } + } +} + +static void XPSleep(unsigned int seconds) +{ +#ifdef XP_WIN + Sleep(1000 * seconds); +#else + sleep(seconds); +#endif +} + +TestFunction +getFuncFromString(const char* funcname) +{ + FunctionTable funcTable[] = + { + { FUNCTION_NPP_NEWSTREAM, "npp_newstream" }, + { FUNCTION_NPP_WRITEREADY, "npp_writeready" }, + { FUNCTION_NPP_WRITE, "npp_write" }, + { FUNCTION_NPP_DESTROYSTREAM, "npp_destroystream" }, + { FUNCTION_NPP_WRITE_RPC, "npp_write_rpc" }, + { FUNCTION_NONE, nullptr } + }; + int32_t i = 0; + while(funcTable[i].funcName) { + if (!strcmp(funcname, funcTable[i].funcName)) return funcTable[i].funcId; + i++; + } + return FUNCTION_NONE; +} + +static void +DuplicateNPVariant(NPVariant& aDest, const NPVariant& aSrc) +{ + if (NPVARIANT_IS_STRING(aSrc)) { + NPString src = NPVARIANT_TO_STRING(aSrc); + char* buf = new char[src.UTF8Length]; + strncpy(buf, src.UTF8Characters, src.UTF8Length); + STRINGN_TO_NPVARIANT(buf, src.UTF8Length, aDest); + } + else if (NPVARIANT_IS_OBJECT(aSrc)) { + NPObject* obj = + NPN_RetainObject(NPVARIANT_TO_OBJECT(aSrc)); + OBJECT_TO_NPVARIANT(obj, aDest); + } + else { + aDest = aSrc; + } +} + +static bool bug813906(NPP npp, const char* const function, const char* const url, const char* const frame) +{ + NPObject *windowObj = nullptr; + NPError err = NPN_GetValue(npp, NPNVWindowNPObject, &windowObj); + if (err != NPERR_NO_ERROR) { + return false; + } + + NPVariant result; + bool res = NPN_Invoke(npp, windowObj, NPN_GetStringIdentifier(function), nullptr, 0, &result); + NPN_ReleaseObject(windowObj); + if (!res) { + return false; + } + + NPN_ReleaseVariantValue(&result); + + err = NPN_GetURL(npp, url, frame); + if (err != NPERR_NO_ERROR) { + err = NPN_GetURL(npp, "about:blank", frame); + return false; + } + + return true; +} + +void +drawAsyncBitmapColor(InstanceData* instanceData) +{ + NPP npp = instanceData->npp; + + uint32_t *pixelData = (uint32_t*)instanceData->backBuffer->bitmap.data; + + uint32_t rgba = instanceData->scriptableObject->drawColor; + + unsigned char subpixels[4]; + memcpy(subpixels, &rgba, sizeof(subpixels)); + + subpixels[0] = uint8_t(float(subpixels[3] * subpixels[0]) / 0xFF); + subpixels[1] = uint8_t(float(subpixels[3] * subpixels[1]) / 0xFF); + subpixels[2] = uint8_t(float(subpixels[3] * subpixels[2]) / 0xFF); + uint32_t premultiplied; + memcpy(&premultiplied, subpixels, sizeof(premultiplied)); + + for (uint32_t* lastPixel = pixelData + instanceData->backBuffer->size.width * instanceData->backBuffer->size.height; + pixelData < lastPixel; + ++pixelData) + { + *pixelData = premultiplied; + } + + NPN_SetCurrentAsyncSurface(npp, instanceData->backBuffer, NULL); + NPAsyncSurface *oldFront = instanceData->frontBuffer; + instanceData->frontBuffer = instanceData->backBuffer; + instanceData->backBuffer = oldFront; +} + +// +// function signatures +// + +NPObject* scriptableAllocate(NPP npp, NPClass* aClass); +void scriptableDeallocate(NPObject* npobj); +void scriptableInvalidate(NPObject* npobj); +bool scriptableHasMethod(NPObject* npobj, NPIdentifier name); +bool scriptableInvoke(NPObject* npobj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result); +bool scriptableInvokeDefault(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); +bool scriptableHasProperty(NPObject* npobj, NPIdentifier name); +bool scriptableGetProperty(NPObject* npobj, NPIdentifier name, NPVariant* result); +bool scriptableSetProperty(NPObject* npobj, NPIdentifier name, const NPVariant* value); +bool scriptableRemoveProperty(NPObject* npobj, NPIdentifier name); +bool scriptableEnumerate(NPObject* npobj, NPIdentifier** identifier, uint32_t* count); +bool scriptableConstruct(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result); + +// +// npapi plugin functions +// + +#ifdef XP_UNIX +NP_EXPORT(char*) +NP_GetPluginVersion() +{ + return sPluginVersion; +} +#endif + +extern const char *sMimeDescription; + +#if defined(XP_UNIX) +NP_EXPORT(const char*) NP_GetMIMEDescription() +#elif defined(XP_WIN) +const char* NP_GetMIMEDescription() +#endif +{ + return sMimeDescription; +} + +#ifdef XP_UNIX +NP_EXPORT(NPError) +NP_GetValue(void* future, NPPVariable aVariable, void* aValue) { + switch (aVariable) { + case NPPVpluginNameString: + *((const char**)aValue) = sPluginName; + break; + case NPPVpluginDescriptionString: + *((const char**)aValue) = sPluginDescription; + break; + default: + return NPERR_INVALID_PARAM; + } + return NPERR_NO_ERROR; +} +#endif + +static bool fillPluginFunctionTable(NPPluginFuncs* pFuncs) +{ + // Check the size of the provided structure based on the offset of the + // last member we need. + if (pFuncs->size < (offsetof(NPPluginFuncs, getsiteswithdata) + sizeof(void*))) + return false; + + pFuncs->newp = NPP_New; + pFuncs->destroy = NPP_Destroy; + pFuncs->setwindow = NPP_SetWindow; + pFuncs->newstream = NPP_NewStream; + pFuncs->destroystream = NPP_DestroyStream; + pFuncs->asfile = NPP_StreamAsFile; + pFuncs->writeready = NPP_WriteReady; + pFuncs->write = NPP_Write; + pFuncs->print = NPP_Print; + pFuncs->event = NPP_HandleEvent; + pFuncs->urlnotify = NPP_URLNotify; + pFuncs->getvalue = NPP_GetValue; + pFuncs->setvalue = NPP_SetValue; + pFuncs->urlredirectnotify = NPP_URLRedirectNotify; + pFuncs->clearsitedata = NPP_ClearSiteData; + pFuncs->getsiteswithdata = NPP_GetSitesWithData; + + return true; +} + +#if defined(XP_MACOSX) +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs) +#elif defined(XP_WIN) +NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs) +#elif defined(XP_UNIX) +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs) +#endif +{ + sBrowserFuncs = bFuncs; + + initializeIdentifiers(); + + for (unsigned int i = 0; i < MOZ_ARRAY_LENGTH(sPluginPropertyValues); i++) { + VOID_TO_NPVARIANT(sPluginPropertyValues[i]); + } + + memset(&sNPClass, 0, sizeof(NPClass)); + sNPClass.structVersion = NP_CLASS_STRUCT_VERSION; + sNPClass.allocate = (NPAllocateFunctionPtr)scriptableAllocate; + sNPClass.deallocate = (NPDeallocateFunctionPtr)scriptableDeallocate; + sNPClass.invalidate = (NPInvalidateFunctionPtr)scriptableInvalidate; + sNPClass.hasMethod = (NPHasMethodFunctionPtr)scriptableHasMethod; + sNPClass.invoke = (NPInvokeFunctionPtr)scriptableInvoke; + sNPClass.invokeDefault = (NPInvokeDefaultFunctionPtr)scriptableInvokeDefault; + sNPClass.hasProperty = (NPHasPropertyFunctionPtr)scriptableHasProperty; + sNPClass.getProperty = (NPGetPropertyFunctionPtr)scriptableGetProperty; + sNPClass.setProperty = (NPSetPropertyFunctionPtr)scriptableSetProperty; + sNPClass.removeProperty = (NPRemovePropertyFunctionPtr)scriptableRemoveProperty; + sNPClass.enumerate = (NPEnumerationFunctionPtr)scriptableEnumerate; + sNPClass.construct = (NPConstructFunctionPtr)scriptableConstruct; + +#if defined(XP_UNIX) && !defined(XP_MACOSX) + if (!fillPluginFunctionTable(pFuncs)) { + return NPERR_INVALID_FUNCTABLE_ERROR; + } +#endif + + return NPERR_NO_ERROR; +} + +#if defined(XP_MACOSX) +NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs) +#elif defined(XP_WIN) +NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs) +#endif +#if defined(XP_MACOSX) || defined(XP_WIN) +{ + if (!fillPluginFunctionTable(pFuncs)) { + return NPERR_INVALID_FUNCTABLE_ERROR; + } + + return NPERR_NO_ERROR; +} +#endif + +#if defined(XP_UNIX) +NP_EXPORT(NPError) NP_Shutdown() +#elif defined(XP_WIN) +NPError OSCALL NP_Shutdown() +#endif +{ + clearIdentifiers(); + + for (unsigned int i = 0; i < MOZ_ARRAY_LENGTH(sPluginPropertyValues); i++) { + NPN_ReleaseVariantValue(&sPluginPropertyValues[i]); + } + + return NPERR_NO_ERROR; +} + +NPError +NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved) +{ + // Make sure our pdata field is nullptr at this point. If it isn't, that + // probably means the browser gave us uninitialized memory. + if (instance->pdata) { + printf("NPP_New called with non-NULL NPP->pdata pointer!\n"); + return NPERR_GENERIC_ERROR; + } + + // Make sure we can render this plugin + NPBool browserSupportsWindowless = false; + NPN_GetValue(instance, NPNVSupportsWindowless, &browserSupportsWindowless); + if (!browserSupportsWindowless && !pluginSupportsWindowMode()) { + printf("Windowless mode not supported by the browser, windowed mode not supported by the plugin!\n"); + return NPERR_GENERIC_ERROR; + } + + // set up our our instance data + InstanceData* instanceData = new InstanceData; + instanceData->npp = instance; + instanceData->streamMode = NP_ASFILEONLY; + instanceData->testFunction = FUNCTION_NONE; + instanceData->functionToFail = FUNCTION_NONE; + instanceData->failureCode = 0; + instanceData->callOnDestroy = nullptr; + instanceData->streamChunkSize = 1024; + instanceData->streamBuf = nullptr; + instanceData->streamBufSize = 0; + instanceData->fileBuf = nullptr; + instanceData->fileBufSize = 0; + instanceData->throwOnNextInvoke = false; + instanceData->runScriptOnPaint = false; + instanceData->dontTouchElement = false; + instanceData->testrange = nullptr; + instanceData->hasWidget = false; + instanceData->npnNewStream = false; + instanceData->invalidateDuringPaint = false; + instanceData->slowPaint = false; + instanceData->playingAudio = false; + instanceData->audioMuted = false; + instanceData->writeCount = 0; + instanceData->writeReadyCount = 0; + memset(&instanceData->window, 0, sizeof(instanceData->window)); + instanceData->crashOnDestroy = false; + instanceData->cleanupWidget = true; // only used by nptest_gtk + instanceData->topLevelWindowActivationState = ACTIVATION_STATE_UNKNOWN; + instanceData->topLevelWindowActivationEventCount = 0; + instanceData->focusState = ACTIVATION_STATE_UNKNOWN; + instanceData->focusEventCount = 0; + instanceData->eventModel = 0; + instanceData->closeStream = false; + instanceData->wantsAllStreams = false; + instanceData->mouseUpEventCount = 0; + instanceData->bugMode = -1; + instanceData->asyncDrawing = AD_NONE; + instanceData->frontBuffer = nullptr; + instanceData->backBuffer = nullptr; + instanceData->placeholderWnd = nullptr; + instanceData->cssZoomFactor = 1.0; + instance->pdata = instanceData; + + TestNPObject* scriptableObject = (TestNPObject*)NPN_CreateObject(instance, &sNPClass); + if (!scriptableObject) { + printf("NPN_CreateObject failed to create an object, can't create a plugin instance\n"); + delete instanceData; + return NPERR_GENERIC_ERROR; + } + scriptableObject->npp = instance; + scriptableObject->drawMode = DM_DEFAULT; + scriptableObject->drawColor = 0; + instanceData->scriptableObject = scriptableObject; + + instanceData->instanceCountWatchGeneration = sCurrentInstanceCountWatchGeneration; + + if (NP_FULL == mode) { + instanceData->streamMode = NP_SEEK; + instanceData->frame = "testframe"; + addRange(instanceData, "100,100"); + } + + AsyncDrawing requestAsyncDrawing = AD_NONE; + + bool requestWindow = false; + bool alreadyHasSalign = false; + // handle extra params + for (int i = 0; i < argc; i++) { + if (strcmp(argn[i], "drawmode") == 0) { + if (strcmp(argv[i], "solid") == 0) + scriptableObject->drawMode = DM_SOLID_COLOR; + } + else if (strcmp(argn[i], "color") == 0) { + scriptableObject->drawColor = parseHexColor(argv[i], strlen(argv[i])); + } + else if (strcmp(argn[i], "wmode") == 0) { + if (strcmp(argv[i], "window") == 0) { + requestWindow = true; + } + } + else if (strcmp(argn[i], "asyncmodel") == 0) { + if (strcmp(argv[i], "bitmap") == 0) { + requestAsyncDrawing = AD_BITMAP; + } else if (strcmp(argv[i], "dxgi") == 0) { + requestAsyncDrawing = AD_DXGI; + } + } + if (strcmp(argn[i], "streammode") == 0) { + if (strcmp(argv[i], "normal") == 0) { + instanceData->streamMode = NP_NORMAL; + } + else if ((strcmp(argv[i], "asfile") == 0) && + strlen(argv[i]) == strlen("asfile")) { + instanceData->streamMode = NP_ASFILE; + } + else if (strcmp(argv[i], "asfileonly") == 0) { + instanceData->streamMode = NP_ASFILEONLY; + } + else if (strcmp(argv[i], "seek") == 0) { + instanceData->streamMode = NP_SEEK; + } + } + if (strcmp(argn[i], "streamchunksize") == 0) { + instanceData->streamChunkSize = atoi(argv[i]); + } + if (strcmp(argn[i], "failurecode") == 0) { + instanceData->failureCode = atoi(argv[i]); + } + if (strcmp(argn[i], "functiontofail") == 0) { + instanceData->functionToFail = getFuncFromString(argv[i]); + } + if (strcmp(argn[i], "geturl") == 0) { + instanceData->testUrl = argv[i]; + instanceData->testFunction = FUNCTION_NPP_GETURL; + } + if (strcmp(argn[i], "posturl") == 0) { + instanceData->testUrl = argv[i]; + instanceData->testFunction = FUNCTION_NPP_POSTURL; + } + if (strcmp(argn[i], "geturlnotify") == 0) { + instanceData->testUrl = argv[i]; + instanceData->testFunction = FUNCTION_NPP_GETURLNOTIFY; + } + if (strcmp(argn[i], "postmode") == 0) { + if (strcmp(argv[i], "frame") == 0) { + instanceData->postMode = POSTMODE_FRAME; + } + else if (strcmp(argv[i], "stream") == 0) { + instanceData->postMode = POSTMODE_STREAM; + } + } + if (strcmp(argn[i], "frame") == 0) { + instanceData->frame = argv[i]; + } + if (strcmp(argn[i], "range") == 0) { + string range = argv[i]; + size_t semicolon = range.find(';'); + while (semicolon != string::npos) { + addRange(instanceData, range.substr(0, semicolon).c_str()); + if (semicolon == range.length()) { + range = ""; + break; + } + range = range.substr(semicolon + 1); + semicolon = range.find(';'); + } + if (range.length()) addRange(instanceData, range.c_str()); + } + if (strcmp(argn[i], "newstream") == 0 && + strcmp(argv[i], "true") == 0) { + instanceData->npnNewStream = true; + } + if (strcmp(argn[i], "newcrash") == 0) { + IntentionalCrash(); + } + if (strcmp(argn[i], "paintscript") == 0) { + instanceData->runScriptOnPaint = true; + } + + if (strcmp(argn[i], "donttouchelement") == 0) { + instanceData->dontTouchElement = true; + } + // "cleanupwidget" is only used with nptest_gtk, defaulting to true. It + // indicates whether the plugin should destroy its window in response to + // NPP_Destroy (or let the platform destroy the widget when the parent + // window gets destroyed). + if (strcmp(argn[i], "cleanupwidget") == 0 && + strcmp(argv[i], "false") == 0) { + instanceData->cleanupWidget = false; + } + if (!strcmp(argn[i], "closestream")) { + instanceData->closeStream = true; + } + if (strcmp(argn[i], "bugmode") == 0) { + instanceData->bugMode = atoi(argv[i]); + } + // Try to emulate java's codebase handling: Use the last seen codebase + // value, regardless of whether it is in attributes or params. + if (strcasecmp(argn[i], "codebase") == 0) { + instanceData->javaCodebase = argv[i]; + } + + // Bug 1307694 - There are two flash parameters that are order dependent for + // scaling/sizing the plugin. If they ever change from what is expected, it + // breaks flash on the web. In a test, if the scale tag ever happens + // with an salign before it, fail the plugin creation. + if (strcmp(argn[i], "scale") == 0) { + if (alreadyHasSalign) { + // If salign came before this parameter, error out now. + return NPERR_GENERIC_ERROR; + } + } + if (strcmp(argn[i], "salign") == 0) { + alreadyHasSalign = true; + } +} + + if (!browserSupportsWindowless || !pluginSupportsWindowlessMode()) { + requestWindow = true; + } else if (!pluginSupportsWindowMode()) { + requestWindow = false; + } + if (requestWindow) { + instanceData->hasWidget = true; + } else { + // NPPVpluginWindowBool should default to true, so we may as well + // test that by not setting it in the window case + NPN_SetValue(instance, NPPVpluginWindowBool, (void*)false); + } + + if (scriptableObject->drawMode == DM_SOLID_COLOR && + (scriptableObject->drawColor & 0xFF000000) != 0xFF000000) { + NPN_SetValue(instance, NPPVpluginTransparentBool, (void*)true); + } + + if (requestAsyncDrawing == AD_BITMAP) { + NPBool supportsAsyncBitmap = false; + if ((NPN_GetValue(instance, NPNVsupportsAsyncBitmapSurfaceBool, &supportsAsyncBitmap) == NPERR_NO_ERROR) && + supportsAsyncBitmap) { + if (NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncBitmapSurface) == NPERR_NO_ERROR) { + instanceData->asyncDrawing = AD_BITMAP; + } + } + } +#ifdef XP_WIN + else if (requestAsyncDrawing == AD_DXGI) { + NPBool supportsAsyncDXGI = false; + if ((NPN_GetValue(instance, NPNVsupportsAsyncWindowsDXGISurfaceBool, &supportsAsyncDXGI) == NPERR_NO_ERROR) && + supportsAsyncDXGI) { + if (NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncWindowsDXGISurface) == NPERR_NO_ERROR) { + instanceData->asyncDrawing = AD_DXGI; + } + } + } +#endif + + // If we can't get the right drawing mode, we fail, otherwise our tests might + // appear to be passing when they shouldn't. Real plugins should not do this. + if (instanceData->asyncDrawing != requestAsyncDrawing) { + return NPERR_GENERIC_ERROR; + } + + instanceData->lastReportedPrivateModeState = false; + instanceData->lastMouseX = instanceData->lastMouseY = -1; + instanceData->widthAtLastPaint = -1; + instanceData->paintCount = 0; + + // do platform-specific initialization + NPError err = pluginInstanceInit(instanceData); + if (err != NPERR_NO_ERROR) { + NPN_ReleaseObject(scriptableObject); + delete instanceData; + return err; + } + + NPVariant variantTrue; + BOOLEAN_TO_NPVARIANT(true, variantTrue); + NPObject* o = nullptr; + + // Set a property on NPNVPluginElementNPObject, unless the consumer explicitly + // opted out of this behavior. + if (!instanceData->dontTouchElement) { + err = NPN_GetValue(instance, NPNVPluginElementNPObject, &o); + if (err == NPERR_NO_ERROR) { + NPN_SetProperty(instance, o, + NPN_GetStringIdentifier("pluginFoundElement"), &variantTrue); + NPN_ReleaseObject(o); + o = nullptr; + } + } + + // Set a property on NPNVWindowNPObject + err = NPN_GetValue(instance, NPNVWindowNPObject, &o); + if (err == NPERR_NO_ERROR) { + NPN_SetProperty(instance, o, + NPN_GetStringIdentifier("pluginFoundWindow"), &variantTrue); + NPN_ReleaseObject(o); + o = nullptr; + } + + ++sInstanceCount; + + if (instanceData->testFunction == FUNCTION_NPP_GETURL) { + NPError err = NPN_GetURL(instance, instanceData->testUrl.c_str(), nullptr); + if (err != NPERR_NO_ERROR) { + instanceData->err << "NPN_GetURL returned " << err; + } + } + else if (instanceData->testFunction == FUNCTION_NPP_GETURLNOTIFY) { + NPError err = NPN_GetURLNotify(instance, instanceData->testUrl.c_str(), + nullptr, static_cast(&kNotifyData)); + if (err != NPERR_NO_ERROR) { + instanceData->err << "NPN_GetURLNotify returned " << err; + } + } + + if ((instanceData->bugMode == 813906) && instanceData->frame.length()) { + bug813906(instance, "f", "browser.xul", instanceData->frame.c_str()); + } + + return NPERR_NO_ERROR; +} + +NPError +NPP_Destroy(NPP instance, NPSavedData** save) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + + if (instanceData->crashOnDestroy) + IntentionalCrash(); + + if (instanceData->callOnDestroy) { + NPVariant result; + NPN_InvokeDefault(instance, instanceData->callOnDestroy, nullptr, 0, &result); + NPN_ReleaseVariantValue(&result); + NPN_ReleaseObject(instanceData->callOnDestroy); + } + + if (instanceData->streamBuf) { + free(instanceData->streamBuf); + } + if (instanceData->fileBuf) { + free(instanceData->fileBuf); + } + + TestRange* currentrange = instanceData->testrange; + TestRange* nextrange; + while (currentrange != nullptr) { + nextrange = reinterpret_cast(currentrange->next); + delete currentrange; + currentrange = nextrange; + } + + if (instanceData->frontBuffer) { + NPN_SetCurrentAsyncSurface(instance, nullptr, nullptr); + NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer); + NPN_MemFree(instanceData->frontBuffer); + } + if (instanceData->backBuffer) { + NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer); + NPN_MemFree(instanceData->backBuffer); + } + + pluginInstanceShutdown(instanceData); + NPN_ReleaseObject(instanceData->scriptableObject); + + if (sCurrentInstanceCountWatchGeneration == instanceData->instanceCountWatchGeneration) { + --sInstanceCount; + } + delete instanceData; + + return NPERR_NO_ERROR; +} + +NPError +NPP_SetWindow(NPP instance, NPWindow* window) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + + if (instanceData->scriptableObject->drawMode == DM_DEFAULT && + (instanceData->window.width != window->width || + instanceData->window.height != window->height)) { + NPRect r; + r.left = r.top = 0; + r.right = window->width; + r.bottom = window->height; + NPN_InvalidateRect(instance, &r); + } + + void* oldWindow = instanceData->window.window; + pluginDoSetWindow(instanceData, window); + if (instanceData->hasWidget && oldWindow != instanceData->window.window) { + pluginWidgetInit(instanceData, oldWindow); + } + + + if (instanceData->asyncDrawing != AD_NONE) { + if (instanceData->frontBuffer && + instanceData->frontBuffer->size.width >= 0 && + (uint32_t)instanceData->frontBuffer->size.width == window->width && + instanceData ->frontBuffer->size.height >= 0 && + (uint32_t)instanceData->frontBuffer->size.height == window->height) + { + return NPERR_NO_ERROR; + } + if (instanceData->frontBuffer) { + NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer); + NPN_MemFree(instanceData->frontBuffer); + } + if (instanceData->backBuffer) { + NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer); + NPN_MemFree(instanceData->backBuffer); + } + instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface)); + instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface)); + + NPSize size; + size.width = window->width; + size.height = window->height; + + memcpy(instanceData->backBuffer, instanceData->frontBuffer, sizeof(NPAsyncSurface)); + + NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, nullptr, instanceData->frontBuffer); + NPN_InitAsyncSurface(instance, &size, NPImageFormatBGRA32, nullptr, instanceData->backBuffer); + +#if defined(XP_WIN) + if (instanceData->asyncDrawing == AD_DXGI) { + if (!setupDxgiSurfaces(instance, instanceData)) { + return NPERR_GENERIC_ERROR; + } + } +#endif + } + + if (instanceData->asyncDrawing == AD_BITMAP) { + drawAsyncBitmapColor(instanceData); + } +#if defined(XP_WIN) + else if (instanceData->asyncDrawing == AD_DXGI) { + drawDxgiBitmapColor(instanceData); + } +#endif + + return NPERR_NO_ERROR; +} + +NPError +NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + + if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM && + instanceData->failureCode) { + instanceData->err << SUCCESS_STRING; + if (instanceData->frame.length() > 0) { + sendBufferToFrame(instance); + } + return instanceData->failureCode; + } + + if (stream->notifyData && + static_cast(stream->notifyData) != &kNotifyData) { + // stream from streamTest + *stype = NP_NORMAL; + } + else { + *stype = instanceData->streamMode; + + if (instanceData->streamBufSize) { + free(instanceData->streamBuf); + instanceData->streamBufSize = 0; + if (instanceData->testFunction == FUNCTION_NPP_POSTURL && + instanceData->postMode == POSTMODE_STREAM) { + instanceData->testFunction = FUNCTION_NPP_GETURL; + } + else { + // We already got a stream and didn't ask for another one. + instanceData->err << "Received unexpected multiple NPP_NewStream"; + } + } + } + return NPERR_NO_ERROR; +} + +NPError +NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + + if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) { + instanceData->err << "NPP_DestroyStream called"; + } + + if (instanceData->functionToFail == FUNCTION_NPP_WRITE) { + if (instanceData->writeCount == 1) + instanceData->err << SUCCESS_STRING; + else + instanceData->err << "NPP_Write called after returning -1"; + } + + if (instanceData->functionToFail == FUNCTION_NPP_DESTROYSTREAM && + instanceData->failureCode) { + instanceData->err << SUCCESS_STRING; + if (instanceData->frame.length() > 0) { + sendBufferToFrame(instance); + } + return instanceData->failureCode; + } + + URLNotifyData* nd = static_cast(stream->notifyData); + if (nd && nd != &kNotifyData) { + return NPERR_NO_ERROR; + } + + if (instanceData->streamMode == NP_ASFILE && + instanceData->functionToFail == FUNCTION_NONE) { + if (!instanceData->streamBuf) { + instanceData->err << + "Error: no data written with NPP_Write"; + return NPERR_GENERIC_ERROR; + } + + if (!instanceData->fileBuf) { + instanceData->err << + "Error: no data written with NPP_StreamAsFile"; + return NPERR_GENERIC_ERROR; + } + + if (strcmp(reinterpret_cast(instanceData->fileBuf), + reinterpret_cast(instanceData->streamBuf))) { + instanceData->err << + "Error: data passed to NPP_Write and NPP_StreamAsFile differed"; + } + } + if (instanceData->frame.length() > 0 && + instanceData->testFunction != FUNCTION_NPP_GETURLNOTIFY && + instanceData->testFunction != FUNCTION_NPP_POSTURL) { + sendBufferToFrame(instance); + } + if (instanceData->testFunction == FUNCTION_NPP_POSTURL) { + NPError err = NPN_PostURL(instance, instanceData->testUrl.c_str(), + instanceData->postMode == POSTMODE_FRAME ? instanceData->frame.c_str() : nullptr, + instanceData->streamBufSize, + reinterpret_cast(instanceData->streamBuf), false); + if (err != NPERR_NO_ERROR) + instanceData->err << "Error: NPN_PostURL returned error value " << err; + } + return NPERR_NO_ERROR; +} + +int32_t +NPP_WriteReady(NPP instance, NPStream* stream) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + instanceData->writeReadyCount++; + if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) { + instanceData->err << "NPP_WriteReady called"; + } + + // temporarily disabled per bug 519870 + //if (instanceData->writeReadyCount == 1) { + // return 0; + //} + + return instanceData->streamChunkSize; +} + +int32_t +NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + instanceData->writeCount++; + + // temporarily disabled per bug 519870 + //if (instanceData->writeReadyCount == 1) { + // instanceData->err << "NPP_Write called even though NPP_WriteReady " << + // "returned 0"; + //} + + if (instanceData->functionToFail == FUNCTION_NPP_WRITE_RPC) { + // Make an RPC call and pretend to consume the data + NPObject* windowObject = nullptr; + NPN_GetValue(instance, NPNVWindowNPObject, &windowObject); + if (windowObject) + NPN_ReleaseObject(windowObject); + + return len; + } + + if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) { + instanceData->err << "NPP_Write called"; + } + + if (instanceData->functionToFail == FUNCTION_NPP_WRITE) { + return -1; + } + + URLNotifyData* nd = static_cast(stream->notifyData); + + if (nd && nd->writeCallback) { + NPVariant args[1]; + STRINGN_TO_NPVARIANT(stream->url, strlen(stream->url), args[0]); + + NPVariant result; + NPN_InvokeDefault(instance, nd->writeCallback, args, 1, &result); + NPN_ReleaseVariantValue(&result); + } + + if (nd && nd != &kNotifyData) { + uint32_t newsize = nd->size + len; + nd->data = (char*) realloc(nd->data, newsize); + memcpy(nd->data + nd->size, buffer, len); + nd->size = newsize; + return len; + } + + if (instanceData->closeStream) { + instanceData->closeStream = false; + if (instanceData->testrange != nullptr) { + NPN_RequestRead(stream, instanceData->testrange); + } + NPN_DestroyStream(instance, stream, NPRES_USER_BREAK); + } + else if (instanceData->streamMode == NP_SEEK && + stream->end != 0 && + stream->end == ((uint32_t)instanceData->streamBufSize + len)) { + // If the complete stream has been written, and we're doing a seek test, + // then call NPN_RequestRead. + // prevent recursion + instanceData->streamMode = NP_NORMAL; + + if (instanceData->testrange != nullptr) { + NPError err = NPN_RequestRead(stream, instanceData->testrange); + if (err != NPERR_NO_ERROR) { + instanceData->err << "NPN_RequestRead returned error %d" << err; + } + printf("called NPN_RequestRead, return %d\n", err); + } + } + + char* streamBuf = reinterpret_cast(instanceData->streamBuf); + if (offset + len <= instanceData->streamBufSize) { + if (memcmp(buffer, streamBuf + offset, len)) { + instanceData->err << + "Error: data written from NPN_RequestRead doesn't match"; + } + else { + printf("data matches!\n"); + } + TestRange* range = instanceData->testrange; + bool stillwaiting = false; + while(range != nullptr) { + if (offset == range->offset && + (uint32_t)len == range->length) { + range->waiting = false; + } + if (range->waiting) stillwaiting = true; + range = reinterpret_cast(range->next); + } + if (!stillwaiting) { + NPError err = NPN_DestroyStream(instance, stream, NPRES_DONE); + if (err != NPERR_NO_ERROR) { + instanceData->err << "Error: NPN_DestroyStream returned " << err; + } + } + } + else { + if (instanceData->streamBufSize == 0) { + instanceData->streamBuf = malloc(len + 1); + streamBuf = reinterpret_cast(instanceData->streamBuf); + } + else { + instanceData->streamBuf = + realloc(reinterpret_cast(instanceData->streamBuf), + instanceData->streamBufSize + len + 1); + streamBuf = reinterpret_cast(instanceData->streamBuf); + } + memcpy(streamBuf + instanceData->streamBufSize, buffer, len); + instanceData->streamBufSize = instanceData->streamBufSize + len; + streamBuf[instanceData->streamBufSize] = '\0'; + } + return len; +} + +void +NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) +{ + size_t size; + + InstanceData* instanceData = (InstanceData*)(instance->pdata); + + if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM || + instanceData->functionToFail == FUNCTION_NPP_WRITE) { + instanceData->err << "NPP_StreamAsFile called"; + } + + if (!fname) + return; + + FILE *file = fopen(fname, "rb"); + if (file) { + fseek(file, 0, SEEK_END); + size = ftell(file); + instanceData->fileBuf = malloc((int32_t)size + 1); + char* buf = reinterpret_cast(instanceData->fileBuf); + fseek(file, 0, SEEK_SET); + size_t sizeRead = fread(instanceData->fileBuf, 1, size, file); + if (sizeRead != size) { + printf("Unable to read data from file\n"); + instanceData->err << "Unable to read data from file " << fname; + } + fclose(file); + buf[size] = '\0'; + instanceData->fileBufSize = (int32_t)size; + } + else { + printf("Unable to open file\n"); + instanceData->err << "Unable to open file " << fname; + } +} + +void +NPP_Print(NPP instance, NPPrint* platformPrint) +{ +} + +int16_t +NPP_HandleEvent(NPP instance, void* event) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + return pluginHandleEvent(instanceData, event); +} + +void +NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) +{ + InstanceData* instanceData = (InstanceData*)(instance->pdata); + URLNotifyData* ndata = static_cast(notifyData); + + if (&kNotifyData == ndata) { + if (instanceData->frame.length() > 0) { + sendBufferToFrame(instance); + } + } + else if (!strcmp(ndata->cookie, "dynamic-cookie")) { + if (ndata->notifyCallback) { + NPVariant args[2]; + INT32_TO_NPVARIANT(reason, args[0]); + if (ndata->data) { + STRINGN_TO_NPVARIANT(ndata->data, ndata->size, args[1]); + } + else { + STRINGN_TO_NPVARIANT("", 0, args[1]); + } + + NPVariant result; + NPN_InvokeDefault(instance, ndata->notifyCallback, args, 2, &result); + NPN_ReleaseVariantValue(&result); + } + + // clean up the URLNotifyData + if (ndata->writeCallback) { + NPN_ReleaseObject(ndata->writeCallback); + } + if (ndata->notifyCallback) { + NPN_ReleaseObject(ndata->notifyCallback); + } + if (ndata->redirectCallback) { + NPN_ReleaseObject(ndata->redirectCallback); + } + free(ndata->data); + delete ndata; + } + else { + printf("ERROR! NPP_URLNotify called with wrong cookie\n"); + instanceData->err << "Error: NPP_URLNotify called with wrong cookie"; + } +} + +NPError +NPP_GetValue(NPP instance, NPPVariable variable, void* value) +{ + InstanceData* instanceData = (InstanceData*)instance->pdata; + if (variable == NPPVpluginScriptableNPObject) { + NPObject* object = instanceData->scriptableObject; + NPN_RetainObject(object); + *((NPObject**)value) = object; + return NPERR_NO_ERROR; + } + if (variable == NPPVpluginNeedsXEmbed) { + // Only relevant for X plugins + // use 4-byte writes like some plugins may do + *(uint32_t*)value = instanceData->hasWidget; + return NPERR_NO_ERROR; + } + if (variable == NPPVpluginWantsAllNetworkStreams) { + // use 4-byte writes like some plugins may do + *(uint32_t*)value = instanceData->wantsAllStreams; + return NPERR_NO_ERROR; + } + + return NPERR_GENERIC_ERROR; +} + +NPError +NPP_SetValue(NPP instance, NPNVariable variable, void* value) +{ + if (variable == NPNVprivateModeBool) { + InstanceData* instanceData = (InstanceData*)(instance->pdata); + instanceData->lastReportedPrivateModeState = bool(*static_cast(value)); + return NPERR_NO_ERROR; + } + if (variable == NPNVmuteAudioBool) { + InstanceData* instanceData = (InstanceData*)(instance->pdata); + instanceData->audioMuted = bool(*static_cast(value)); + return NPERR_NO_ERROR; + } + if (variable == NPNVCSSZoomFactor) { + InstanceData* instanceData = (InstanceData*)(instance->pdata); + instanceData->cssZoomFactor = *static_cast(value); + return NPERR_NO_ERROR; + } + return NPERR_GENERIC_ERROR; +} + +void +NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData) +{ + if (notifyData) { + URLNotifyData* nd = static_cast(notifyData); + if (nd->redirectCallback) { + NPVariant args[2]; + STRINGN_TO_NPVARIANT(url, strlen(url), args[0]); + INT32_TO_NPVARIANT(status, args[1]); + + NPVariant result; + NPN_InvokeDefault(instance, nd->redirectCallback, args, 2, &result); + NPN_ReleaseVariantValue(&result); + } + NPN_URLRedirectResponse(instance, notifyData, nd->allowRedirects); + return; + } + NPN_URLRedirectResponse(instance, notifyData, true); +} + +NPError +NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge) +{ + if (!sSitesWithData) + return NPERR_NO_ERROR; + + // Error condition: no support for clear-by-age + if (!sClearByAgeSupported && maxAge != uint64_t(int64_t(-1))) + return NPERR_TIME_RANGE_NOT_SUPPORTED; + + // Iterate over list and remove matches + list::iterator iter = sSitesWithData->begin(); + list::iterator end = sSitesWithData->end(); + while (iter != end) { + const siteData& data = *iter; + list::iterator next = iter; + ++next; + if ((!site || data.site.compare(site) == 0) && + (flags == NP_CLEAR_ALL || data.flags & flags) && + data.age <= maxAge) { + sSitesWithData->erase(iter); + } + iter = next; + } + + return NPERR_NO_ERROR; +} + +char** +NPP_GetSitesWithData() +{ + int length = 0; + char** result; + + if (sSitesWithData) + length = sSitesWithData->size(); + + // Allocate the maximum possible size the list could be. + result = static_cast(NPN_MemAlloc((length + 1) * sizeof(char*))); + result[length] = nullptr; + + if (length == 0) { + // Represent the no site data case as an array of length 1 with a nullptr + // entry. + return result; + } + + // Iterate the list of stored data, and build a list of strings. + list sites; + { + list::iterator iter = sSitesWithData->begin(); + list::iterator end = sSitesWithData->end(); + for (; iter != end; ++iter) { + const siteData& data = *iter; + sites.push_back(data.site); + } + } + + // Remove duplicate strings. + sites.sort(); + sites.unique(); + + // Add strings to the result array, and null terminate. + { + int i = 0; + list::iterator iter = sites.begin(); + list::iterator end = sites.end(); + for (; iter != end; ++iter, ++i) { + const string& site = *iter; + result[i] = static_cast(NPN_MemAlloc(site.length() + 1)); + memcpy(result[i], site.c_str(), site.length() + 1); + } + } + result[sites.size()] = nullptr; + + return result; +} + +// +// npapi browser functions +// + +bool +NPN_SetProperty(NPP instance, NPObject* obj, NPIdentifier propertyName, const NPVariant* value) +{ + return sBrowserFuncs->setproperty(instance, obj, propertyName, value); +} + +NPIdentifier +NPN_GetIntIdentifier(int32_t intid) +{ + return sBrowserFuncs->getintidentifier(intid); +} + +NPIdentifier +NPN_GetStringIdentifier(const NPUTF8* name) +{ + return sBrowserFuncs->getstringidentifier(name); +} + +void +NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers) +{ + return sBrowserFuncs->getstringidentifiers(names, nameCount, identifiers); +} + +bool +NPN_IdentifierIsString(NPIdentifier identifier) +{ + return sBrowserFuncs->identifierisstring(identifier); +} + +NPUTF8* +NPN_UTF8FromIdentifier(NPIdentifier identifier) +{ + return sBrowserFuncs->utf8fromidentifier(identifier); +} + +int32_t +NPN_IntFromIdentifier(NPIdentifier identifier) +{ + return sBrowserFuncs->intfromidentifier(identifier); +} + +NPError +NPN_GetValue(NPP instance, NPNVariable variable, void* value) +{ + return sBrowserFuncs->getvalue(instance, variable, value); +} + +NPError +NPN_SetValue(NPP instance, NPPVariable variable, void* value) +{ + return sBrowserFuncs->setvalue(instance, variable, value); +} + +void +NPN_InvalidateRect(NPP instance, NPRect* rect) +{ + sBrowserFuncs->invalidaterect(instance, rect); +} + +bool +NPN_HasProperty(NPP instance, NPObject* obj, NPIdentifier propertyName) +{ + return sBrowserFuncs->hasproperty(instance, obj, propertyName); +} + +NPObject* +NPN_CreateObject(NPP instance, NPClass* aClass) +{ + return sBrowserFuncs->createobject(instance, aClass); +} + +bool +NPN_Invoke(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result) +{ + return sBrowserFuncs->invoke(npp, obj, methodName, args, argCount, result); +} + +bool +NPN_InvokeDefault(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result) +{ + return sBrowserFuncs->invokeDefault(npp, obj, args, argCount, result); +} + +bool +NPN_Construct(NPP npp, NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + return sBrowserFuncs->construct(npp, npobj, args, argCount, result); +} + +const char* +NPN_UserAgent(NPP instance) +{ + return sBrowserFuncs->uagent(instance); +} + +NPObject* +NPN_RetainObject(NPObject* obj) +{ + return sBrowserFuncs->retainobject(obj); +} + +void +NPN_ReleaseObject(NPObject* obj) +{ + return sBrowserFuncs->releaseobject(obj); +} + +void* +NPN_MemAlloc(uint32_t size) +{ + return sBrowserFuncs->memalloc(size); +} + +char* +NPN_StrDup(const char* str) +{ + return strcpy((char*)sBrowserFuncs->memalloc(strlen(str) + 1), str); +} + +void +NPN_MemFree(void* ptr) +{ + return sBrowserFuncs->memfree(ptr); +} + +uint32_t +NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)) +{ + return sBrowserFuncs->scheduletimer(instance, interval, repeat, timerFunc); +} + +void +NPN_UnscheduleTimer(NPP instance, uint32_t timerID) +{ + return sBrowserFuncs->unscheduletimer(instance, timerID); +} + +void +NPN_ReleaseVariantValue(NPVariant *variant) +{ + return sBrowserFuncs->releasevariantvalue(variant); +} + +NPError +NPN_GetURLNotify(NPP instance, const char* url, const char* target, void* notifyData) +{ + return sBrowserFuncs->geturlnotify(instance, url, target, notifyData); +} + +NPError +NPN_GetURL(NPP instance, const char* url, const char* target) +{ + return sBrowserFuncs->geturl(instance, url, target); +} + +NPError +NPN_RequestRead(NPStream* stream, NPByteRange* rangeList) +{ + return sBrowserFuncs->requestread(stream, rangeList); +} + +NPError +NPN_PostURLNotify(NPP instance, const char* url, + const char* target, uint32_t len, + const char* buf, NPBool file, void* notifyData) +{ + return sBrowserFuncs->posturlnotify(instance, url, target, len, buf, file, notifyData); +} + +NPError +NPN_PostURL(NPP instance, const char *url, + const char *target, uint32_t len, + const char *buf, NPBool file) +{ + return sBrowserFuncs->posturl(instance, url, target, len, buf, file); +} + +NPError +NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason) +{ + return sBrowserFuncs->destroystream(instance, stream, reason); +} + +NPError +NPN_NewStream(NPP instance, + NPMIMEType type, + const char* target, + NPStream** stream) +{ + return sBrowserFuncs->newstream(instance, type, target, stream); +} + +int32_t +NPN_Write(NPP instance, + NPStream* stream, + int32_t len, + void* buf) +{ + return sBrowserFuncs->write(instance, stream, len, buf); +} + +bool +NPN_Enumerate(NPP instance, + NPObject *npobj, + NPIdentifier **identifiers, + uint32_t *identifierCount) +{ + return sBrowserFuncs->enumerate(instance, npobj, identifiers, + identifierCount); +} + +bool +NPN_GetProperty(NPP instance, + NPObject *npobj, + NPIdentifier propertyName, + NPVariant *result) +{ + return sBrowserFuncs->getproperty(instance, npobj, propertyName, result); +} + +bool +NPN_Evaluate(NPP instance, NPObject *npobj, NPString *script, NPVariant *result) +{ + return sBrowserFuncs->evaluate(instance, npobj, script, result); +} + +void +NPN_SetException(NPObject *npobj, const NPUTF8 *message) +{ + return sBrowserFuncs->setexception(npobj, message); +} + +NPBool +NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace) +{ + return sBrowserFuncs->convertpoint(instance, sourceX, sourceY, sourceSpace, destX, destY, destSpace); +} + +NPError +NPN_SetValueForURL(NPP instance, NPNURLVariable variable, const char *url, const char *value, uint32_t len) +{ + return sBrowserFuncs->setvalueforurl(instance, variable, url, value, len); +} + +NPError +NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char *url, char **value, uint32_t *len) +{ + return sBrowserFuncs->getvalueforurl(instance, variable, url, value, len); +} + +NPError +NPN_GetAuthenticationInfo(NPP instance, + const char *protocol, + const char *host, int32_t port, + const char *scheme, + const char *realm, + char **username, uint32_t *ulen, + char **password, + uint32_t *plen) +{ + return sBrowserFuncs->getauthenticationinfo(instance, protocol, host, port, scheme, realm, + username, ulen, password, plen); +} + +void +NPN_PluginThreadAsyncCall(NPP plugin, void (*func)(void*), void* userdata) +{ + return sBrowserFuncs->pluginthreadasynccall(plugin, func, userdata); +} + +void +NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow) +{ + return sBrowserFuncs->urlredirectresponse(instance, notifyData, allow); +} + +NPError +NPN_InitAsyncSurface(NPP instance, NPSize *size, NPImageFormat format, + void *initData, NPAsyncSurface *surface) +{ + return sBrowserFuncs->initasyncsurface(instance, size, format, initData, surface); +} + +NPError +NPN_FinalizeAsyncSurface(NPP instance, NPAsyncSurface *surface) +{ + return sBrowserFuncs->finalizeasyncsurface(instance, surface); +} + +void +NPN_SetCurrentAsyncSurface(NPP instance, NPAsyncSurface *surface, NPRect *changed) +{ + sBrowserFuncs->setcurrentasyncsurface(instance, surface, changed); +} + +// +// npruntime object functions +// + +NPObject* +scriptableAllocate(NPP npp, NPClass* aClass) +{ + TestNPObject* object = (TestNPObject*)NPN_MemAlloc(sizeof(TestNPObject)); + if (!object) + return nullptr; + memset(object, 0, sizeof(TestNPObject)); + return object; +} + +void +scriptableDeallocate(NPObject* npobj) +{ + NPN_MemFree(npobj); +} + +void +scriptableInvalidate(NPObject* npobj) +{ +} + +bool +scriptableHasMethod(NPObject* npobj, NPIdentifier name) +{ + for (int i = 0; i < int(MOZ_ARRAY_LENGTH(sPluginMethodIdentifiers)); i++) { + if (name == sPluginMethodIdentifiers[i]) + return true; + } + return false; +} + +bool +scriptableInvoke(NPObject* npobj, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + if (id->throwOnNextInvoke) { + id->throwOnNextInvoke = false; + if (argCount == 0) { + NPN_SetException(npobj, nullptr); + } + else { + for (uint32_t i = 0; i < argCount; i++) { + const NPString* argstr = &NPVARIANT_TO_STRING(args[i]); + NPN_SetException(npobj, argstr->UTF8Characters); + } + } + return false; + } + + for (int i = 0; i < int(MOZ_ARRAY_LENGTH(sPluginMethodIdentifiers)); i++) { + if (name == sPluginMethodIdentifiers[i]) + return sPluginMethodFunctions[i](npobj, args, argCount, result); + } + return false; +} + +bool +scriptableInvokeDefault(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + if (id->throwOnNextInvoke) { + id->throwOnNextInvoke = false; + if (argCount == 0) { + NPN_SetException(npobj, nullptr); + } + else { + for (uint32_t i = 0; i < argCount; i++) { + const NPString* argstr = &NPVARIANT_TO_STRING(args[i]); + NPN_SetException(npobj, argstr->UTF8Characters); + } + } + return false; + } + + ostringstream value; + value << sPluginName; + for (uint32_t i = 0; i < argCount; i++) { + switch(args[i].type) { + case NPVariantType_Int32: + value << ";" << NPVARIANT_TO_INT32(args[i]); + break; + case NPVariantType_String: { + const NPString* argstr = &NPVARIANT_TO_STRING(args[i]); + value << ";" << argstr->UTF8Characters; + break; + } + case NPVariantType_Void: + value << ";undefined"; + break; + case NPVariantType_Null: + value << ";null"; + break; + default: + value << ";other"; + } + } + + char *outval = NPN_StrDup(value.str().c_str()); + STRINGZ_TO_NPVARIANT(outval, *result); + return true; +} + +bool +scriptableHasProperty(NPObject* npobj, NPIdentifier name) +{ + if (NPN_IdentifierIsString(name)) { + NPUTF8 *asUTF8 = NPN_UTF8FromIdentifier(name); + if (NPN_GetStringIdentifier(asUTF8) != name) { + Crash(); + } + NPN_MemFree(asUTF8); + } + else { + if (NPN_GetIntIdentifier(NPN_IntFromIdentifier(name)) != name) { + Crash(); + } + } + for (int i = 0; i < int(MOZ_ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) { + if (name == sPluginPropertyIdentifiers[i]) { + return true; + } + } + return false; +} + +bool +scriptableGetProperty(NPObject* npobj, NPIdentifier name, NPVariant* result) +{ + for (int i = 0; i < int(MOZ_ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) { + if (name == sPluginPropertyIdentifiers[i]) { + DuplicateNPVariant(*result, sPluginPropertyValues[i]); + return true; + } + } + return false; +} + +bool +scriptableSetProperty(NPObject* npobj, NPIdentifier name, const NPVariant* value) +{ + for (int i = 0; i < int(MOZ_ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) { + if (name == sPluginPropertyIdentifiers[i]) { + NPN_ReleaseVariantValue(&sPluginPropertyValues[i]); + DuplicateNPVariant(sPluginPropertyValues[i], *value); + return true; + } + } + return false; +} + +bool +scriptableRemoveProperty(NPObject* npobj, NPIdentifier name) +{ + for (int i = 0; i < int(MOZ_ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) { + if (name == sPluginPropertyIdentifiers[i]) { + NPN_ReleaseVariantValue(&sPluginPropertyValues[i]); + + // Avoid double frees (see test_propertyAndMethod.html, which deletes a + // property that doesn't exist). + VOID_TO_NPVARIANT(sPluginPropertyValues[i]); + return true; + } + } + return false; +} + +bool +scriptableEnumerate(NPObject* npobj, NPIdentifier** identifier, uint32_t* count) +{ + const int bufsize = sizeof(NPIdentifier) * MOZ_ARRAY_LENGTH(sPluginMethodIdentifierNames); + NPIdentifier* ids = (NPIdentifier*) NPN_MemAlloc(bufsize); + if (!ids) + return false; + + memcpy(ids, sPluginMethodIdentifiers, bufsize); + *identifier = ids; + *count = MOZ_ARRAY_LENGTH(sPluginMethodIdentifierNames); + return true; +} + +bool +scriptableConstruct(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + return false; +} + +// +// test functions +// + +static bool +compareVariants(NPP instance, const NPVariant* var1, const NPVariant* var2) +{ + bool success = true; + InstanceData* id = static_cast(instance->pdata); + if (var1->type != var2->type) { + id->err << "Variant types don't match; got " << var1->type << + " expected " << var2->type; + return false; + } + + // Cast var1->type from NPVariantType to int to avoid compiler warnings about + // not needing a default case when we have cases for every enum value. + switch (static_cast(var1->type)) { + case NPVariantType_Int32: { + int32_t result = NPVARIANT_TO_INT32(*var1); + int32_t expected = NPVARIANT_TO_INT32(*var2); + if (result != expected) { + id->err << "Variant values don't match; got " << result << + " expected " << expected; + success = false; + } + break; + } + case NPVariantType_Double: { + double result = NPVARIANT_TO_DOUBLE(*var1); + double expected = NPVARIANT_TO_DOUBLE(*var2); + if (result != expected) { + id->err << "Variant values don't match (double)"; + success = false; + } + break; + } + case NPVariantType_Void: { + // void values are always equivalent + break; + } + case NPVariantType_Null: { + // null values are always equivalent + break; + } + case NPVariantType_Bool: { + bool result = NPVARIANT_TO_BOOLEAN(*var1); + bool expected = NPVARIANT_TO_BOOLEAN(*var2); + if (result != expected) { + id->err << "Variant values don't match (bool)"; + success = false; + } + break; + } + case NPVariantType_String: { + const NPString* result = &NPVARIANT_TO_STRING(*var1); + const NPString* expected = &NPVARIANT_TO_STRING(*var2); + if (strcmp(result->UTF8Characters, expected->UTF8Characters) || + strlen(result->UTF8Characters) != strlen(expected->UTF8Characters)) { + id->err << "Variant values don't match; got " << + result->UTF8Characters << " expected " << + expected->UTF8Characters; + success = false; + } + break; + } + case NPVariantType_Object: { + uint32_t i, identifierCount = 0; + NPIdentifier* identifiers; + NPObject* result = NPVARIANT_TO_OBJECT(*var1); + NPObject* expected = NPVARIANT_TO_OBJECT(*var2); + bool enumerate_result = NPN_Enumerate(instance, expected, + &identifiers, &identifierCount); + if (!enumerate_result) { + id->err << "NPN_Enumerate failed"; + success = false; + } + for (i = 0; i < identifierCount; i++) { + NPVariant resultVariant, expectedVariant; + if (!NPN_GetProperty(instance, expected, identifiers[i], + &expectedVariant)) { + id->err << "NPN_GetProperty returned false"; + success = false; + } + else { + if (!NPN_HasProperty(instance, result, identifiers[i])) { + id->err << "NPN_HasProperty returned false"; + success = false; + } + else { + if (!NPN_GetProperty(instance, result, identifiers[i], + &resultVariant)) { + id->err << "NPN_GetProperty 2 returned false"; + success = false; + } + else { + success = compareVariants(instance, &resultVariant, + &expectedVariant); + NPN_ReleaseVariantValue(&expectedVariant); + } + } + NPN_ReleaseVariantValue(&resultVariant); + } + } + NPN_MemFree(identifiers); + break; + } + default: + id->err << "Unknown variant type"; + success = false; + MOZ_ASSERT_UNREACHABLE("Unknown variant type?!"); + } + + return success; +} + +static bool +throwExceptionNextInvoke(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + id->throwOnNextInvoke = true; + BOOLEAN_TO_NPVARIANT(true, *result); + return true; +} + +static bool +npnInvokeDefaultTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + bool success = false; + NPP npp = static_cast(npobj)->npp; + + NPObject* windowObject; + NPN_GetValue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return false; + + NPIdentifier objectIdentifier = variantToIdentifier(args[0]); + if (!objectIdentifier) + return false; + + NPVariant objectVariant; + if (NPN_GetProperty(npp, windowObject, objectIdentifier, + &objectVariant)) { + if (NPVARIANT_IS_OBJECT(objectVariant)) { + NPObject* selfObject = NPVARIANT_TO_OBJECT(objectVariant); + if (selfObject != nullptr) { + NPVariant resultVariant; + if (NPN_InvokeDefault(npp, selfObject, argCount > 1 ? &args[1] : nullptr, + argCount - 1, &resultVariant)) { + *result = resultVariant; + success = true; + } + } + } + NPN_ReleaseVariantValue(&objectVariant); + } + + NPN_ReleaseObject(windowObject); + return success; +} + +static bool +npnInvokeTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + id->err.str(""); + if (argCount < 2) + return false; + + NPIdentifier function = variantToIdentifier(args[0]); + if (!function) + return false; + + NPObject* windowObject; + NPN_GetValue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return false; + + NPVariant invokeResult; + bool invokeReturn = NPN_Invoke(npp, windowObject, function, + argCount > 2 ? &args[2] : nullptr, argCount - 2, &invokeResult); + + bool compareResult = compareVariants(npp, &invokeResult, &args[1]); + + NPN_ReleaseObject(windowObject); + NPN_ReleaseVariantValue(&invokeResult); + BOOLEAN_TO_NPVARIANT(invokeReturn && compareResult, *result); + return true; +} + +static bool +npnEvaluateTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + bool success = false; + NPP npp = static_cast(npobj)->npp; + + if (argCount != 1) + return false; + + if (!NPVARIANT_IS_STRING(args[0])) + return false; + + NPObject* windowObject; + NPN_GetValue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return false; + + success = NPN_Evaluate(npp, windowObject, (NPString*)&NPVARIANT_TO_STRING(args[0]), result); + + NPN_ReleaseObject(windowObject); + return success; +} + +static bool +setUndefinedValueTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + NPError err = NPN_SetValue(npp, (NPPVariable)0x0, 0x0); + BOOLEAN_TO_NPVARIANT((err == NPERR_NO_ERROR), *result); + return true; +} + +static bool +identifierToStringTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1) + return false; + NPIdentifier identifier = variantToIdentifier(args[0]); + if (!identifier) + return false; + + NPUTF8* utf8String = NPN_UTF8FromIdentifier(identifier); + if (!utf8String) + return false; + STRINGZ_TO_NPVARIANT(utf8String, *result); + return true; +} + +static bool +queryPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPBool pms = false; + NPN_GetValue(static_cast(npobj)->npp, NPNVprivateModeBool, &pms); + BOOLEAN_TO_NPVARIANT(pms, *result); + return true; +} + +static bool +lastReportedPrivateModeState(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + InstanceData* id = static_cast(static_cast(npobj)->npp->pdata); + BOOLEAN_TO_NPVARIANT(id->lastReportedPrivateModeState, *result); + return true; +} + +static bool +hasWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + InstanceData* id = static_cast(static_cast(npobj)->npp->pdata); + BOOLEAN_TO_NPVARIANT(id->hasWidget, *result); + return true; +} + +static bool +getEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1) + return false; + if (!NPVARIANT_IS_INT32(args[0])) + return false; + int32_t edge = NPVARIANT_TO_INT32(args[0]); + if (edge < EDGE_LEFT || edge > EDGE_BOTTOM) + return false; + + InstanceData* id = static_cast(static_cast(npobj)->npp->pdata); + int32_t r = pluginGetEdge(id, RectEdge(edge)); + if (r == NPTEST_INT32_ERROR) + return false; + INT32_TO_NPVARIANT(r, *result); + return true; +} + +static bool +getClipRegionRectCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + InstanceData* id = static_cast(static_cast(npobj)->npp->pdata); + int32_t r = pluginGetClipRegionRectCount(id); + if (r == NPTEST_INT32_ERROR) + return false; + INT32_TO_NPVARIANT(r, *result); + return true; +} + +static bool +getClipRegionRectEdge(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 2) + return false; + if (!NPVARIANT_IS_INT32(args[0])) + return false; + int32_t rectIndex = NPVARIANT_TO_INT32(args[0]); + if (rectIndex < 0) + return false; + if (!NPVARIANT_IS_INT32(args[1])) + return false; + int32_t edge = NPVARIANT_TO_INT32(args[1]); + if (edge < EDGE_LEFT || edge > EDGE_BOTTOM) + return false; + + InstanceData* id = static_cast(static_cast(npobj)->npp->pdata); + int32_t r = pluginGetClipRegionRectEdge(id, rectIndex, RectEdge(edge)); + if (r == NPTEST_INT32_ERROR) + return false; + INT32_TO_NPVARIANT(r, *result); + return true; +} + +static bool +startWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + if (sWatchingInstanceCount) + return false; + + sWatchingInstanceCount = true; + sInstanceCount = 0; + ++sCurrentInstanceCountWatchGeneration; + return true; +} + +static bool +getInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + if (!sWatchingInstanceCount) + return false; + + INT32_TO_NPVARIANT(sInstanceCount, *result); + return true; +} + +static bool +stopWatchingInstanceCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + if (!sWatchingInstanceCount) + return false; + + sWatchingInstanceCount = false; + return true; +} + +static bool +getLastMouseX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + INT32_TO_NPVARIANT(id->lastMouseX, *result); + return true; +} + +static bool +getLastMouseY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + INT32_TO_NPVARIANT(id->lastMouseY, *result); + return true; +} + +static bool +getPaintCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + INT32_TO_NPVARIANT(id->paintCount, *result); + return true; +} + +static bool +resetPaintCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + id->paintCount = 0; + return true; +} + +static bool +getWidthAtLastPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + INT32_TO_NPVARIANT(id->widthAtLastPaint, *result); + return true; +} + +static bool +setInvalidateDuringPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1) + return false; + + if (!NPVARIANT_IS_BOOLEAN(args[0])) + return false; + bool doInvalidate = NPVARIANT_TO_BOOLEAN(args[0]); + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + id->invalidateDuringPaint = doInvalidate; + return true; +} + +static bool +setSlowPaint(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1) + return false; + + if (!NPVARIANT_IS_BOOLEAN(args[0])) + return false; + bool slow = NPVARIANT_TO_BOOLEAN(args[0]); + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + id->slowPaint = slow; + return true; +} + +static bool +getError(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + if (id->err.str().length() == 0) { + char *outval = NPN_StrDup(SUCCESS_STRING); + STRINGZ_TO_NPVARIANT(outval, *result); + } else { + char *outval = NPN_StrDup(id->err.str().c_str()); + STRINGZ_TO_NPVARIANT(outval, *result); + } + return true; +} + +static bool +doInternalConsistencyCheck(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + string error; + pluginDoInternalConsistencyCheck(id, error); + NPUTF8* utf8String = (NPUTF8*)NPN_MemAlloc(error.length() + 1); + if (!utf8String) { + return false; + } + memcpy(utf8String, error.c_str(), error.length() + 1); + STRINGZ_TO_NPVARIANT(utf8String, *result); + return true; +} + +static bool +convertPointX(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 4) + return false; + + NPP npp = static_cast(npobj)->npp; + + if (!NPVARIANT_IS_INT32(args[0])) + return false; + int32_t sourceSpace = NPVARIANT_TO_INT32(args[0]); + + if (!NPVARIANT_IS_INT32(args[1])) + return false; + double sourceX = static_cast(NPVARIANT_TO_INT32(args[1])); + + if (!NPVARIANT_IS_INT32(args[2])) + return false; + double sourceY = static_cast(NPVARIANT_TO_INT32(args[2])); + + if (!NPVARIANT_IS_INT32(args[3])) + return false; + int32_t destSpace = NPVARIANT_TO_INT32(args[3]); + + double resultX, resultY; + NPN_ConvertPoint(npp, sourceX, sourceY, (NPCoordinateSpace)sourceSpace, &resultX, &resultY, (NPCoordinateSpace)destSpace); + + DOUBLE_TO_NPVARIANT(resultX, *result); + return true; +} + +static bool +convertPointY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 4) + return false; + + NPP npp = static_cast(npobj)->npp; + + if (!NPVARIANT_IS_INT32(args[0])) + return false; + int32_t sourceSpace = NPVARIANT_TO_INT32(args[0]); + + if (!NPVARIANT_IS_INT32(args[1])) + return false; + double sourceX = static_cast(NPVARIANT_TO_INT32(args[1])); + + if (!NPVARIANT_IS_INT32(args[2])) + return false; + double sourceY = static_cast(NPVARIANT_TO_INT32(args[2])); + + if (!NPVARIANT_IS_INT32(args[3])) + return false; + int32_t destSpace = NPVARIANT_TO_INT32(args[3]); + + double resultX, resultY; + NPN_ConvertPoint(npp, sourceX, sourceY, (NPCoordinateSpace)sourceSpace, &resultX, &resultY, (NPCoordinateSpace)destSpace); + + DOUBLE_TO_NPVARIANT(resultY, *result); + return true; +} + +static bool +streamTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + // .streamTest(url, doPost, doNull, writeCallback, notifyCallback, redirectCallback, allowRedirects) + if (7 != argCount) + return false; + + NPP npp = static_cast(npobj)->npp; + + if (!NPVARIANT_IS_STRING(args[0])) + return false; + NPString url = NPVARIANT_TO_STRING(args[0]); + + if (!NPVARIANT_IS_BOOLEAN(args[1])) + return false; + bool doPost = NPVARIANT_TO_BOOLEAN(args[1]); + + NPString postData = { nullptr, 0 }; + if (NPVARIANT_IS_STRING(args[2])) { + postData = NPVARIANT_TO_STRING(args[2]); + } + else { + if (!NPVARIANT_IS_NULL(args[2])) { + return false; + } + } + + NPObject* writeCallback = nullptr; + if (NPVARIANT_IS_OBJECT(args[3])) { + writeCallback = NPVARIANT_TO_OBJECT(args[3]); + } + else { + if (!NPVARIANT_IS_NULL(args[3])) { + return false; + } + } + + NPObject* notifyCallback = nullptr; + if (NPVARIANT_IS_OBJECT(args[4])) { + notifyCallback = NPVARIANT_TO_OBJECT(args[4]); + } + else { + if (!NPVARIANT_IS_NULL(args[4])) { + return false; + } + } + + NPObject* redirectCallback = nullptr; + if (NPVARIANT_IS_OBJECT(args[5])) { + redirectCallback = NPVARIANT_TO_OBJECT(args[5]); + } + else { + if (!NPVARIANT_IS_NULL(args[5])) { + return false; + } + } + + if (!NPVARIANT_IS_BOOLEAN(args[6])) + return false; + bool allowRedirects = NPVARIANT_TO_BOOLEAN(args[6]); + + URLNotifyData* ndata = new URLNotifyData; + ndata->cookie = "dynamic-cookie"; + ndata->writeCallback = writeCallback; + ndata->notifyCallback = notifyCallback; + ndata->redirectCallback = redirectCallback; + ndata->size = 0; + ndata->data = nullptr; + ndata->allowRedirects = allowRedirects; + + /* null-terminate "url" */ + char* urlstr = (char*) malloc(url.UTF8Length + 1); + strncpy(urlstr, url.UTF8Characters, url.UTF8Length); + urlstr[url.UTF8Length] = '\0'; + + NPError err; + if (doPost) { + err = NPN_PostURLNotify(npp, urlstr, nullptr, + postData.UTF8Length, postData.UTF8Characters, + false, ndata); + } + else { + err = NPN_GetURLNotify(npp, urlstr, nullptr, ndata); + } + + free(urlstr); + + if (NPERR_NO_ERROR == err) { + if (ndata->writeCallback) { + NPN_RetainObject(ndata->writeCallback); + } + if (ndata->notifyCallback) { + NPN_RetainObject(ndata->notifyCallback); + } + if (ndata->redirectCallback) { + NPN_RetainObject(ndata->redirectCallback); + } + BOOLEAN_TO_NPVARIANT(true, *result); + } + else { + delete ndata; + BOOLEAN_TO_NPVARIANT(false, *result); + } + + return true; +} + +static bool +setPluginWantsAllStreams(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (1 != argCount) + return false; + + if (!NPVARIANT_IS_BOOLEAN(args[0])) + return false; + bool wantsAllStreams = NPVARIANT_TO_BOOLEAN(args[0]); + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + id->wantsAllStreams = wantsAllStreams; + + return true; +} + +static bool +crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + IntentionalCrash(); + VOID_TO_NPVARIANT(*result); + return true; +} + +static bool +crashOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + id->crashOnDestroy = true; + VOID_TO_NPVARIANT(*result); + return true; +} + +static bool +setColor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1) + return false; + if (!NPVARIANT_IS_STRING(args[0])) + return false; + const NPString* str = &NPVARIANT_TO_STRING(args[0]); + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + id->scriptableObject->drawColor = + parseHexColor(str->UTF8Characters, str->UTF8Length); + + NPRect r; + r.left = 0; + r.top = 0; + r.right = id->window.width; + r.bottom = id->window.height; + if (id->asyncDrawing == AD_NONE) { + NPN_InvalidateRect(npp, &r); + } else if (id->asyncDrawing == AD_BITMAP) { + drawAsyncBitmapColor(id); + } + + VOID_TO_NPVARIANT(*result); + return true; +} + +void notifyDidPaint(InstanceData* instanceData) +{ + ++instanceData->paintCount; + instanceData->widthAtLastPaint = instanceData->window.width; + + if (instanceData->invalidateDuringPaint) { + NPRect r; + r.left = 0; + r.top = 0; + r.right = instanceData->window.width; + r.bottom = instanceData->window.height; + NPN_InvalidateRect(instanceData->npp, &r); + } + + if (instanceData->slowPaint) { + XPSleep(1); + } + + if (instanceData->runScriptOnPaint) { + NPObject* o = nullptr; + NPN_GetValue(instanceData->npp, NPNVPluginElementNPObject, &o); + if (o) { + NPVariant param; + STRINGZ_TO_NPVARIANT("paintscript", param); + NPVariant result; + NPN_Invoke(instanceData->npp, o, NPN_GetStringIdentifier("getAttribute"), + ¶m, 1, &result); + + if (NPVARIANT_IS_STRING(result)) { + NPObject* windowObject; + NPN_GetValue(instanceData->npp, NPNVWindowNPObject, &windowObject); + if (windowObject) { + NPVariant evalResult; + NPN_Evaluate(instanceData->npp, windowObject, + (NPString*)&NPVARIANT_TO_STRING(result), &evalResult); + NPN_ReleaseVariantValue(&evalResult); + NPN_ReleaseObject(windowObject); + } + } + + NPN_ReleaseVariantValue(&result); + NPN_ReleaseObject(o); + } + } +} + +static const NPClass kTestSharedNPClass = { + NP_CLASS_STRUCT_VERSION, + // Everything else is nullptr +}; + +static bool getJavaCodebase(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) { + return false; + } + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + char *outval = NPN_StrDup(id->javaCodebase.c_str()); + STRINGZ_TO_NPVARIANT(outval, *result); + return true; +} + +static bool getObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + + NPObject* o = NPN_CreateObject(npp, + const_cast(&kTestSharedNPClass)); + if (!o) + return false; + + OBJECT_TO_NPVARIANT(o, *result); + return true; +} + +static bool checkObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + VOID_TO_NPVARIANT(*result); + + if (1 != argCount) + return false; + + if (!NPVARIANT_IS_OBJECT(args[0])) + return false; + + NPObject* o = NPVARIANT_TO_OBJECT(args[0]); + + BOOLEAN_TO_NPVARIANT(o->_class == &kTestSharedNPClass, *result); + return true; +} + +static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + VOID_TO_NPVARIANT(*result); + +#if defined(XP_WIN) && defined(_M_IX86) + _control87(0, _MCW_EM); + return true; +#else + return false; +#endif +} + +// caller is responsible for freeing return buffer +static char* URLForInstanceWindow(NPP instance) { + char *outString = nullptr; + + NPObject* windowObject = nullptr; + NPError err = NPN_GetValue(instance, NPNVWindowNPObject, &windowObject); + if (err != NPERR_NO_ERROR || !windowObject) + return nullptr; + + NPIdentifier locationIdentifier = NPN_GetStringIdentifier("location"); + NPVariant locationVariant; + if (NPN_GetProperty(instance, windowObject, locationIdentifier, &locationVariant)) { + NPObject *locationObject = locationVariant.value.objectValue; + if (locationObject) { + NPIdentifier hrefIdentifier = NPN_GetStringIdentifier("href"); + NPVariant hrefVariant; + if (NPN_GetProperty(instance, locationObject, hrefIdentifier, &hrefVariant)) { + const NPString* hrefString = &NPVARIANT_TO_STRING(hrefVariant); + if (hrefString) { + outString = (char *)malloc(hrefString->UTF8Length + 1); + if (outString) { + strcpy(outString, hrefString->UTF8Characters); + outString[hrefString->UTF8Length] = '\0'; + } + } + NPN_ReleaseVariantValue(&hrefVariant); + } + } + NPN_ReleaseVariantValue(&locationVariant); + } + + NPN_ReleaseObject(windowObject); + + return outString; +} + +static bool +setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1) + return false; + if (!NPVARIANT_IS_STRING(args[0])) + return false; + const NPString* cookie = &NPVARIANT_TO_STRING(args[0]); + + NPP npp = static_cast(npobj)->npp; + + char* url = URLForInstanceWindow(npp); + if (!url) + return false; + NPError err = NPN_SetValueForURL(npp, NPNURLVCookie, url, cookie->UTF8Characters, cookie->UTF8Length); + free(url); + + return (err == NPERR_NO_ERROR); +} + +static bool +getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + + char* url = URLForInstanceWindow(npp); + if (!url) + return false; + char* cookie = nullptr; + unsigned int length = 0; + NPError err = NPN_GetValueForURL(npp, NPNURLVCookie, url, &cookie, &length); + free(url); + if (err != NPERR_NO_ERROR || !cookie) + return false; + + STRINGZ_TO_NPVARIANT(cookie, *result); + return true; +} + +static bool +getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 5) + return false; + + NPP npp = static_cast(npobj)->npp; + + if (!NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]) || + !NPVARIANT_IS_INT32(args[2]) || !NPVARIANT_IS_STRING(args[3]) || + !NPVARIANT_IS_STRING(args[4])) + return false; + + const NPString* protocol = &NPVARIANT_TO_STRING(args[0]); + const NPString* host = &NPVARIANT_TO_STRING(args[1]); + uint32_t port = NPVARIANT_TO_INT32(args[2]); + const NPString* scheme = &NPVARIANT_TO_STRING(args[3]); + const NPString* realm = &NPVARIANT_TO_STRING(args[4]); + + char* username = nullptr; + char* password = nullptr; + uint32_t ulen = 0, plen = 0; + + NPError err = NPN_GetAuthenticationInfo(npp, + protocol->UTF8Characters, + host->UTF8Characters, + port, + scheme->UTF8Characters, + realm->UTF8Characters, + &username, + &ulen, + &password, + &plen); + + if (err != NPERR_NO_ERROR) { + return false; + } + + char* outstring = (char*)NPN_MemAlloc(ulen + plen + 2); + memset(outstring, 0, ulen + plen + 2); + strncpy(outstring, username, ulen); + strcat(outstring, "|"); + strncat(outstring, password, plen); + + STRINGZ_TO_NPVARIANT(outstring, *result); + + NPN_MemFree(username); + NPN_MemFree(password); + + return true; +} + +static void timerCallback(NPP npp, uint32_t timerID) +{ + InstanceData* id = static_cast(npp->pdata); + currentTimerEventCount++; + timerEvent event = timerEvents[currentTimerEventCount]; + + NPObject* windowObject; + NPN_GetValue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return; + + NPVariant rval; + if (timerID != id->timerID[event.timerIdReceive]) { + id->timerTestResult = false; + } + + if (currentTimerEventCount == totalTimerEvents - 1) { + NPVariant arg; + BOOLEAN_TO_NPVARIANT(id->timerTestResult, arg); + NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->timerTestScriptCallback.c_str()), &arg, 1, &rval); + NPN_ReleaseVariantValue(&arg); + } + + NPN_ReleaseObject(windowObject); + + if (event.timerIdSchedule > -1) { + id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback); + } + if (event.timerIdUnschedule > -1) { + NPN_UnscheduleTimer(npp, id->timerID[event.timerIdUnschedule]); + } +} + +static bool +timerTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + currentTimerEventCount = 0; + + if (argCount < 1 || !NPVARIANT_IS_STRING(args[0])) + return false; + const NPString* argstr = &NPVARIANT_TO_STRING(args[0]); + id->timerTestScriptCallback = argstr->UTF8Characters; + + id->timerTestResult = true; + timerEvent event = timerEvents[currentTimerEventCount]; + + id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback); + + return id->timerID[event.timerIdSchedule] != 0; +} + +#ifdef XP_WIN +void +ThreadProc(void* cookie) +#else +void* +ThreadProc(void* cookie) +#endif +{ + NPObject* npobj = (NPObject*)cookie; + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + id->asyncTestPhase = 1; + NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj); +#ifndef XP_WIN + return nullptr; +#endif +} + +void +asyncCallback(void* cookie) +{ + NPObject* npobj = (NPObject*)cookie; + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + switch (id->asyncTestPhase) { + // async callback triggered from same thread + case 0: +#ifdef XP_WIN + if (_beginthread(ThreadProc, 0, (void*)npobj) == -1) + id->asyncCallbackResult = false; +#else + pthread_t tid; + if (pthread_create(&tid, 0, ThreadProc, (void*)npobj)) + id->asyncCallbackResult = false; +#endif + break; + + // async callback triggered from different thread + default: + NPObject* windowObject; + NPN_GetValue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return; + NPVariant arg, rval; + BOOLEAN_TO_NPVARIANT(id->asyncCallbackResult, arg); + NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->asyncTestScriptCallback.c_str()), &arg, 1, &rval); + NPN_ReleaseVariantValue(&arg); + NPN_ReleaseObject(windowObject); + break; + } +} + +static bool +asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + if (argCount < 1 || !NPVARIANT_IS_STRING(args[0])) + return false; + const NPString* argstr = &NPVARIANT_TO_STRING(args[0]); + id->asyncTestScriptCallback = argstr->UTF8Characters; + + id->asyncTestPhase = 0; + id->asyncCallbackResult = true; + NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj); + + return true; +} + +static bool +GCRaceInvoke(NPObject*, NPIdentifier, const NPVariant*, uint32_t, NPVariant*) +{ + return false; +} + +static bool +GCRaceInvokeDefault(NPObject* o, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (1 != argCount || !NPVARIANT_IS_INT32(args[0]) || + 35 != NPVARIANT_TO_INT32(args[0])) + return false; + + return true; +} + +static const NPClass kGCRaceClass = { + NP_CLASS_STRUCT_VERSION, + nullptr, + nullptr, + nullptr, + nullptr, + GCRaceInvoke, + GCRaceInvokeDefault, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr +}; + +struct GCRaceData +{ + GCRaceData(NPP npp, NPObject* callback, NPObject* localFunc) + : npp_(npp) + , callback_(callback) + , localFunc_(localFunc) + { + NPN_RetainObject(callback_); + NPN_RetainObject(localFunc_); + } + + ~GCRaceData() + { + NPN_ReleaseObject(callback_); + NPN_ReleaseObject(localFunc_); + } + + NPP npp_; + NPObject* callback_; + NPObject* localFunc_; +}; + +static void +FinishGCRace(void* closure) +{ + GCRaceData* rd = static_cast(closure); + + XPSleep(5); + + NPVariant arg; + OBJECT_TO_NPVARIANT(rd->localFunc_, arg); + + NPVariant result; + bool ok = NPN_InvokeDefault(rd->npp_, rd->callback_, &arg, 1, &result); + if (!ok) + return; + + NPN_ReleaseVariantValue(&result); + delete rd; +} + +bool +checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0])) + return false; + + NPP npp = static_cast(npobj)->npp; + + NPObject* localFunc = + NPN_CreateObject(npp, const_cast(&kGCRaceClass)); + + GCRaceData* rd = + new GCRaceData(npp, NPVARIANT_TO_OBJECT(args[0]), localFunc); + NPN_PluginThreadAsyncCall(npp, FinishGCRace, rd); + + OBJECT_TO_NPVARIANT(localFunc, *result); + return true; +} + +bool +hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + mozilla::NoteIntentionalCrash("plugin"); + + bool busyHang = false; + if ((argCount == 1) && NPVARIANT_IS_BOOLEAN(args[0])) { + busyHang = NPVARIANT_TO_BOOLEAN(args[0]); + } + + if (busyHang) { + const time_t start = std::time(nullptr); + while ((std::time(nullptr) - start) < 100000) { + volatile int dummy = 0; + for (int i=0; i<1000; ++i) { + dummy++; + } + } + } else { +#ifdef XP_WIN + Sleep(100000000); + Sleep(100000000); +#else + pause(); + pause(); +#endif + } + + // NB: returning true here means that we weren't terminated, and + // thus the hang detection/handling didn't work correctly. The + // test harness will succeed in calling this function, and the + // test will fail. + return true; +} + +bool +stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + uint32_t stallTimeSeconds = 0; + if ((argCount == 1) && NPVARIANT_IS_INT32(args[0])) { + stallTimeSeconds = (uint32_t) NPVARIANT_TO_INT32(args[0]); + } + +#ifdef XP_WIN + Sleep(stallTimeSeconds * 1000U); +#else + sleep(stallTimeSeconds); +#endif + + return true; +} + +#if defined(MOZ_WIDGET_GTK) +bool +getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + string sel = pluginGetClipboardText(id); + + uint32_t len = sel.size(); + char* selCopy = static_cast(NPN_MemAlloc(1 + len)); + if (!selCopy) + return false; + + memcpy(selCopy, sel.c_str(), len); + selCopy[len] = '\0'; + + STRINGN_TO_NPVARIANT(selCopy, len, *result); + // *result owns str now + + return true; +} + +bool +crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + return pluginCrashInNestedLoop(id); +} + +bool +triggerXError(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + return pluginTriggerXError(id); +} + +bool +destroySharedGfxStuff(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + return pluginDestroySharedGfxStuff(id); +} + +#else +bool +getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + // XXX Not implemented! + return false; +} + +bool +crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + // XXX Not implemented! + return false; +} + +bool +triggerXError(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + // XXX Not implemented! + return false; +} + +bool +destroySharedGfxStuff(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + // XXX Not implemented! + return false; +} +#endif + +#if defined(XP_WIN) +bool +nativeWidgetIsVisible(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + bool visible = pluginNativeWidgetIsVisible(id); + BOOLEAN_TO_NPVARIANT(visible, *result); + return true; +} +#else +bool +nativeWidgetIsVisible(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ + // XXX Not implemented! + return false; +} +#endif + +bool +getLastCompositionText(NPObject* npobj, const NPVariant* args, + uint32_t argCount, NPVariant* result) +{ +#ifdef XP_WIN + if (argCount != 0) { + return false; + } + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + char *outval = NPN_StrDup(id->lastComposition.c_str()); + STRINGZ_TO_NPVARIANT(outval, *result); + return true; +#else + // XXX not implemented + return false; +#endif +} + +bool +callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + if (id->callOnDestroy) + return false; + + if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0])) + return false; + + id->callOnDestroy = NPVARIANT_TO_OBJECT(args[0]); + NPN_RetainObject(id->callOnDestroy); + + return true; +} + +// On Linux at least, a windowed plugin resize causes Flash Player to +// reconnect to the browser window. This method simulates that. +bool +reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + if (!id->hasWidget) + return false; + + pluginWidgetInit(id, id->window.window); + return true; +} + +bool +propertyAndMethod(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + INT32_TO_NPVARIANT(5, *result); + return true; +} + +// Returns top-level window activation state as indicated by Cocoa NPAPI's +// NPCocoaEventWindowFocusChanged events - 'true' if active, 'false' if not. +// Throws an exception if no events have been received and thus this state +// is unknown. +bool +getTopLevelWindowActivationState(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + // Throw an exception for unknown state. + if (id->topLevelWindowActivationState == ACTIVATION_STATE_UNKNOWN) { + return false; + } + + if (id->topLevelWindowActivationState == ACTIVATION_STATE_ACTIVATED) { + BOOLEAN_TO_NPVARIANT(true, *result); + } else if (id->topLevelWindowActivationState == ACTIVATION_STATE_DEACTIVATED) { + BOOLEAN_TO_NPVARIANT(false, *result); + } + + return true; +} + +bool +getTopLevelWindowActivationEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + INT32_TO_NPVARIANT(id->topLevelWindowActivationEventCount, *result); + + return true; +} + +// Returns top-level window activation state as indicated by Cocoa NPAPI's +// NPCocoaEventFocusChanged events - 'true' if active, 'false' if not. +// Throws an exception if no events have been received and thus this state +// is unknown. +bool +getFocusState(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + // Throw an exception for unknown state. + if (id->focusState == ACTIVATION_STATE_UNKNOWN) { + return false; + } + + if (id->focusState == ACTIVATION_STATE_ACTIVATED) { + BOOLEAN_TO_NPVARIANT(true, *result); + } else if (id->focusState == ACTIVATION_STATE_DEACTIVATED) { + BOOLEAN_TO_NPVARIANT(false, *result); + } + + return true; +} + +bool +getFocusEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + INT32_TO_NPVARIANT(id->focusEventCount, *result); + + return true; +} + +bool +getEventModel(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + INT32_TO_NPVARIANT(id->eventModel, *result); + + return true; +} + +static bool +ReflectorHasMethod(NPObject* npobj, NPIdentifier name) +{ + return false; +} + +static bool +ReflectorHasProperty(NPObject* npobj, NPIdentifier name) +{ + return true; +} + +static bool +ReflectorGetProperty(NPObject* npobj, NPIdentifier name, NPVariant* result) +{ + if (NPN_IdentifierIsString(name)) { + char* s = NPN_UTF8FromIdentifier(name); + STRINGZ_TO_NPVARIANT(s, *result); + return true; + } + + INT32_TO_NPVARIANT(NPN_IntFromIdentifier(name), *result); + return true; +} + +static const NPClass kReflectorNPClass = { + NP_CLASS_STRUCT_VERSION, + nullptr, + nullptr, + nullptr, + ReflectorHasMethod, + nullptr, + nullptr, + ReflectorHasProperty, + ReflectorGetProperty, + nullptr, + nullptr, + nullptr, + nullptr +}; + +bool +getReflector(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (0 != argCount) + return false; + + NPP npp = static_cast(npobj)->npp; + + NPObject* reflector = + NPN_CreateObject(npp, + const_cast(&kReflectorNPClass)); // retains + OBJECT_TO_NPVARIANT(reflector, *result); + return true; +} + +bool isVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + BOOLEAN_TO_NPVARIANT(id->window.clipRect.top != 0 || + id->window.clipRect.left != 0 || + id->window.clipRect.bottom != 0 || + id->window.clipRect.right != 0, *result); + return true; +} + +bool getWindowPosition(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + NPObject* window = nullptr; + NPError err = NPN_GetValue(npp, NPNVWindowNPObject, &window); + if (NPERR_NO_ERROR != err || !window) + return false; + + NPIdentifier arrayID = NPN_GetStringIdentifier("Array"); + NPVariant arrayFunctionV; + bool ok = NPN_GetProperty(npp, window, arrayID, &arrayFunctionV); + + NPN_ReleaseObject(window); + + if (!ok) + return false; + + if (!NPVARIANT_IS_OBJECT(arrayFunctionV)) { + NPN_ReleaseVariantValue(&arrayFunctionV); + return false; + } + NPObject* arrayFunction = NPVARIANT_TO_OBJECT(arrayFunctionV); + + NPVariant elements[4]; + INT32_TO_NPVARIANT(id->window.x, elements[0]); + INT32_TO_NPVARIANT(id->window.y, elements[1]); + INT32_TO_NPVARIANT(id->window.width, elements[2]); + INT32_TO_NPVARIANT(id->window.height, elements[3]); + + ok = NPN_InvokeDefault(npp, arrayFunction, elements, 4, result); + + NPN_ReleaseObject(arrayFunction); + + return ok; +} + +bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount == 0 || !NPVARIANT_IS_OBJECT(args[0])) + return false; + + NPObject* ctor = NPVARIANT_TO_OBJECT(args[0]); + + NPP npp = static_cast(npobj)->npp; + + return NPN_Construct(npp, ctor, args + 1, argCount - 1, result); +} + +bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1 || !NPVARIANT_IS_STRING(args[0])) + return false; + + // Clear existing data. + delete sSitesWithData; + + const NPString* str = &NPVARIANT_TO_STRING(args[0]); + if (str->UTF8Length == 0) + return true; + + // Parse the comma-delimited string into a vector. + sSitesWithData = new list; + const char* iterator = str->UTF8Characters; + const char* end = iterator + str->UTF8Length; + while (1) { + const char* next = strchr(iterator, ','); + if (!next) + next = end; + + // Parse out the three tokens into a siteData struct. + const char* siteEnd = strchr(iterator, ':'); + *((char*) siteEnd) = '\0'; + const char* flagsEnd = strchr(siteEnd + 1, ':'); + *((char*) flagsEnd) = '\0'; + *((char*) next) = '\0'; + + siteData data; + data.site = string(iterator); + data.flags = atoi(siteEnd + 1); + data.age = atoi(flagsEnd + 1); + + sSitesWithData->push_back(data); + + if (next == end) + break; + + iterator = next + 1; + } + + return true; +} + +bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1 || !NPVARIANT_IS_BOOLEAN(args[0])) + return false; + + sClearByAgeSupported = NPVARIANT_TO_BOOLEAN(args[0]); + return true; +} + +bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) { + return false; + } + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + + char *outval = NPN_StrDup(id->lastKeyText.c_str()); + STRINGZ_TO_NPVARIANT(outval, *result); + return true; +} + +bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount, + NPVariant* result) +{ + if (argCount != 0) { + return false; + } + + NPP npp = static_cast(npobj)->npp; + + char *origin = nullptr; + NPError err = NPN_GetValue(npp, NPNVdocumentOrigin, &origin); + if (err != NPERR_NO_ERROR) { + return false; + } + + STRINGZ_TO_NPVARIANT(origin, *result); + return true; +} + +bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) { + return false; + } + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + INT32_TO_NPVARIANT(id->mouseUpEventCount, *result); + return true; +} + +bool queryContentsScaleFactor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + double scaleFactor = 1.0; +#if defined(XP_MACOSX) || defined(XP_WIN) + NPError err = NPN_GetValue(static_cast(npobj)->npp, + NPNVcontentsScaleFactor, &scaleFactor); + if (err != NPERR_NO_ERROR) { + return false; + } +#endif + DOUBLE_TO_NPVARIANT(scaleFactor, *result); + return true; +} + +bool queryCSSZoomFactorSetValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + NPP npp = static_cast(npobj)->npp; + if (!npp) { + return false; + } + InstanceData* id = static_cast(npp->pdata); + if (!id) { + return false; + } + DOUBLE_TO_NPVARIANT(id->cssZoomFactor, *result); + return true; +} + +bool queryCSSZoomFactorGetValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) + return false; + + double zoomFactor = 1.0; + NPError err = NPN_GetValue(static_cast(npobj)->npp, + NPNVCSSZoomFactor, &zoomFactor); + if (err != NPERR_NO_ERROR) { + return false; + } + DOUBLE_TO_NPVARIANT(zoomFactor, *result); + return true; +} + +bool echoString(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 1) { + return false; + } + + if (!NPVARIANT_IS_STRING(args[0])) { + return false; + } + + const NPString& arg = NPVARIANT_TO_STRING(args[0]); + NPUTF8* buffer = static_cast(NPN_MemAlloc(sizeof(NPUTF8) * arg.UTF8Length)); + if (!buffer) { + return false; + } + + std::copy(arg.UTF8Characters, arg.UTF8Characters + arg.UTF8Length, buffer); + STRINGN_TO_NPVARIANT(buffer, arg.UTF8Length, *result); + + return true; +} + +static bool +toggleAudioPlayback(NPObject* npobj, uint32_t argCount, bool playingAudio, NPVariant* result) +{ + if (argCount != 0) { + return false; + } + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + id->playingAudio = playingAudio; + + NPN_SetValue(npp, NPPVpluginIsPlayingAudio, (void*)playingAudio); + + VOID_TO_NPVARIANT(*result); + return true; +} + +static bool +startAudioPlayback(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + return toggleAudioPlayback(npobj, argCount, true, result); +} + +static bool +stopAudioPlayback(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + return toggleAudioPlayback(npobj, argCount, false, result); +} + +static bool +getAudioMuted(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result) +{ + if (argCount != 0) { + return false; + } + + NPP npp = static_cast(npobj)->npp; + InstanceData* id = static_cast(npp->pdata); + BOOLEAN_TO_NPVARIANT(id->audioMuted, *result); + return true; +} diff --git a/dom/plugins/test/testplugin/nptest.def b/dom/plugins/test/testplugin/nptest.def new file mode 100644 index 0000000000..4c543d5b9f --- /dev/null +++ b/dom/plugins/test/testplugin/nptest.def @@ -0,0 +1,7 @@ +LIBRARY NPTEST + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 + NP_GetMIMEDescription @4 diff --git a/dom/plugins/test/testplugin/nptest.h b/dom/plugins/test/testplugin/nptest.h new file mode 100644 index 0000000000..e77d636a4f --- /dev/null +++ b/dom/plugins/test/testplugin/nptest.h @@ -0,0 +1,171 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (c) 2008, Mozilla Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Mozilla Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Josh Aas + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nptest_h_ +#define nptest_h_ + +#include "mozilla-config.h" + +#include "npapi.h" +#include "npfunctions.h" +#include "npruntime.h" +#include +#include +#include + +typedef enum { + DM_DEFAULT, + DM_SOLID_COLOR +} DrawMode; + +typedef enum { + FUNCTION_NONE, + FUNCTION_NPP_GETURL, + FUNCTION_NPP_GETURLNOTIFY, + FUNCTION_NPP_POSTURL, + FUNCTION_NPP_POSTURLNOTIFY, + FUNCTION_NPP_NEWSTREAM, + FUNCTION_NPP_WRITEREADY, + FUNCTION_NPP_WRITE, + FUNCTION_NPP_DESTROYSTREAM, + FUNCTION_NPP_WRITE_RPC +} TestFunction; + +typedef enum { + AD_NONE, + AD_BITMAP, + AD_DXGI +} AsyncDrawing; + +typedef enum { + ACTIVATION_STATE_UNKNOWN, + ACTIVATION_STATE_ACTIVATED, + ACTIVATION_STATE_DEACTIVATED +} ActivationState; + +typedef struct FunctionTable { + TestFunction funcId; + const char* funcName; +} FunctionTable; + +typedef enum { + POSTMODE_FRAME, + POSTMODE_STREAM +} PostMode; + +typedef struct TestNPObject : NPObject { + NPP npp; + DrawMode drawMode; + uint32_t drawColor; // 0xAARRGGBB +} TestNPObject; + +typedef struct _PlatformData PlatformData; + +typedef struct TestRange : NPByteRange { + bool waiting; +} TestRange; + +typedef struct InstanceData { + NPP npp; + NPWindow window; + TestNPObject* scriptableObject; + PlatformData* platformData; + int32_t instanceCountWatchGeneration; + bool lastReportedPrivateModeState; + bool hasWidget; + bool npnNewStream; + bool throwOnNextInvoke; + bool runScriptOnPaint; + bool dontTouchElement; + uint32_t timerID[2]; + bool timerTestResult; + bool asyncCallbackResult; + bool invalidateDuringPaint; + bool slowPaint; + bool playingAudio; + bool audioMuted; + int32_t winX; + int32_t winY; + int32_t lastMouseX; + int32_t lastMouseY; + int32_t widthAtLastPaint; + int32_t paintCount; + int32_t writeCount; + int32_t writeReadyCount; + int32_t asyncTestPhase; + TestFunction testFunction; + TestFunction functionToFail; + NPError failureCode; + NPObject* callOnDestroy; + PostMode postMode; + std::string testUrl; + std::string frame; + std::string timerTestScriptCallback; + std::string asyncTestScriptCallback; + std::ostringstream err; + uint16_t streamMode; + int32_t streamChunkSize; + int32_t streamBufSize; + int32_t fileBufSize; + TestRange* testrange; + void* streamBuf; + void* fileBuf; + bool crashOnDestroy; + bool cleanupWidget; + ActivationState topLevelWindowActivationState; + int32_t topLevelWindowActivationEventCount; + ActivationState focusState; + int32_t focusEventCount; + int32_t eventModel; + bool closeStream; + std::string lastKeyText; + bool wantsAllStreams; + int32_t mouseUpEventCount; + int32_t bugMode; + std::string javaCodebase; + AsyncDrawing asyncDrawing; + NPAsyncSurface *frontBuffer; + NPAsyncSurface *backBuffer; + std::string lastComposition; + void* placeholderWnd; + double cssZoomFactor; +} InstanceData; + +void notifyDidPaint(InstanceData* instanceData); + +#if defined(XP_WIN) +bool setupDxgiSurfaces(NPP npp, InstanceData* instanceData); +void drawDxgiBitmapColor(InstanceData* instanceData); +#endif + +#endif // nptest_h_ diff --git a/dom/plugins/test/testplugin/nptest.rc b/dom/plugins/test/testplugin/nptest.rc new file mode 100644 index 0000000000..948fb846ef --- /dev/null +++ b/dom/plugins/test/testplugin/nptest.rc @@ -0,0 +1,42 @@ +#include + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "mozilla.org" + VALUE "FileDescription", L"Plug-in for testing purposes.\x2122 (\x0939\x093f\x0928\x094d\x0926\x0940 \x4e2d\x6587 \x0627\x0644\x0639\x0631\x0628\x064a\x0629)" + VALUE "FileExtents", "tst" + VALUE "FileOpenName", L"Test \x2122 mimetype" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "nptest" + VALUE "MIMEType", "application/x-test" + VALUE "OriginalFilename", "nptest.dll" + VALUE "ProductName", "Test Plug-in" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/dom/plugins/test/testplugin/nptest_droid.cpp b/dom/plugins/test/testplugin/nptest_droid.cpp new file mode 100644 index 0000000000..9b062e0c2f --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_droid.cpp @@ -0,0 +1,105 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (c) 2010, Mozilla Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Mozilla Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Brad Lassey + * + * ***** END LICENSE BLOCK ***** */ +#include "nptest_platform.h" +#include "npapi.h" + +struct _PlatformData { +}; + using namespace std; + +bool +pluginSupportsWindowMode() +{ + return false; +} + +bool +pluginSupportsWindowlessMode() +{ + return true; +} + +NPError +pluginInstanceInit(InstanceData* instanceData) +{ + printf("NPERR_INCOMPATIBLE_VERSION_ERROR\n"); + return NPERR_INCOMPATIBLE_VERSION_ERROR; +} + +void +pluginInstanceShutdown(InstanceData* instanceData) +{ + NPN_MemFree(instanceData->platformData); + instanceData->platformData = 0; +} + +void +pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow) +{ + instanceData->window = *newWindow; +} + +void +pluginWidgetInit(InstanceData* instanceData, void* oldWindow) +{ + // XXX nothing here yet since we don't support windowed plugins +} + +int16_t +pluginHandleEvent(InstanceData* instanceData, void* event) +{ + return 0; +} + +int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge) +{ + // XXX nothing here yet since we don't support windowed plugins + return NPTEST_INT32_ERROR; +} + +int32_t pluginGetClipRegionRectCount(InstanceData* instanceData) +{ + // XXX nothing here yet since we don't support windowed plugins + return NPTEST_INT32_ERROR; +} + +int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData, + int32_t rectIndex, RectEdge edge) +{ + // XXX nothing here yet since we don't support windowed plugins + return NPTEST_INT32_ERROR; +} + +void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error) +{ +} diff --git a/dom/plugins/test/testplugin/nptest_gtk2.cpp b/dom/plugins/test/testplugin/nptest_gtk2.cpp new file mode 100644 index 0000000000..500db35d24 --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_gtk2.cpp @@ -0,0 +1,774 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (c) 2008, Mozilla Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Mozilla Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Josh Aas + * Michael Ventnor + * + * ***** END LICENSE BLOCK ***** */ + +#include "nptest_platform.h" +#include "npapi.h" +#include +#include +#ifdef MOZ_X11 +#include +#include +#endif +#include +#include +#include + +#include "mozilla/IntentionalCrash.h" + + using namespace std; + +struct _PlatformData { +#ifdef MOZ_X11 + Display* display; + Visual* visual; + Colormap colormap; +#endif + GtkWidget* plug; +}; + +bool +pluginSupportsWindowMode() +{ + return true; +} + +bool +pluginSupportsWindowlessMode() +{ + return true; +} + +NPError +pluginInstanceInit(InstanceData* instanceData) +{ +#ifdef MOZ_X11 + instanceData->platformData = static_cast + (NPN_MemAlloc(sizeof(PlatformData))); + if (!instanceData->platformData) + return NPERR_OUT_OF_MEMORY_ERROR; + + instanceData->platformData->display = nullptr; + instanceData->platformData->visual = nullptr; + instanceData->platformData->colormap = X11None; + instanceData->platformData->plug = nullptr; + + return NPERR_NO_ERROR; +#else + // we only support X11 here, since thats what the plugin system uses + return NPERR_INCOMPATIBLE_VERSION_ERROR; +#endif +} + +void +pluginInstanceShutdown(InstanceData* instanceData) +{ + if (instanceData->hasWidget) { + Window window = reinterpret_cast(instanceData->window.window); + + if (window != X11None) { + // This window XID should still be valid. + // See bug 429604 and bug 454756. + XWindowAttributes attributes; + if (!XGetWindowAttributes(instanceData->platformData->display, window, + &attributes)) + g_error("XGetWindowAttributes failed at plugin instance shutdown"); + } + } + + GtkWidget* plug = instanceData->platformData->plug; + if (plug) { + instanceData->platformData->plug = 0; + if (instanceData->cleanupWidget) { + // Default/tidy behavior + gtk_widget_destroy(plug); + } else { + // Flash Player style: let the GtkPlug destroy itself on disconnect. + g_signal_handlers_disconnect_matched(plug, G_SIGNAL_MATCH_DATA, 0, 0, + nullptr, nullptr, instanceData); + } + } + + NPN_MemFree(instanceData->platformData); + instanceData->platformData = 0; +} + +static void +SetCairoRGBA(cairo_t* cairoWindow, uint32_t rgba) +{ + float b = (rgba & 0xFF) / 255.0; + float g = ((rgba & 0xFF00) >> 8) / 255.0; + float r = ((rgba & 0xFF0000) >> 16) / 255.0; + float a = ((rgba & 0xFF000000) >> 24) / 255.0; + + cairo_set_source_rgba(cairoWindow, r, g, b, a); +} + +static void +pluginDrawSolid(InstanceData* instanceData, GdkDrawable* gdkWindow, + int x, int y, int width, int height) +{ + cairo_t* cairoWindow = gdk_cairo_create(gdkWindow); + + if (!instanceData->hasWidget) { + NPRect* clip = &instanceData->window.clipRect; + cairo_rectangle(cairoWindow, clip->left, clip->top, + clip->right - clip->left, clip->bottom - clip->top); + cairo_clip(cairoWindow); + } + + GdkRectangle windowRect = { x, y, width, height }; + gdk_cairo_rectangle(cairoWindow, &windowRect); + SetCairoRGBA(cairoWindow, instanceData->scriptableObject->drawColor); + + cairo_fill(cairoWindow); + cairo_destroy(cairoWindow); +} + +static void +pluginDrawWindow(InstanceData* instanceData, GdkDrawable* gdkWindow, + const GdkRectangle& invalidRect) +{ + NPWindow& window = instanceData->window; + // When we have a widget, window.x/y are meaningless since our + // widget is always positioned correctly and we just draw into it at 0,0 + int x = instanceData->hasWidget ? 0 : window.x; + int y = instanceData->hasWidget ? 0 : window.y; + int width = window.width; + int height = window.height; + + notifyDidPaint(instanceData); + + if (instanceData->scriptableObject->drawMode == DM_SOLID_COLOR) { + // drawing a solid color for reftests + pluginDrawSolid(instanceData, gdkWindow, + invalidRect.x, invalidRect.y, + invalidRect.width, invalidRect.height); + return; + } + + NPP npp = instanceData->npp; + if (!npp) + return; + + const char* uaString = NPN_UserAgent(npp); + if (!uaString) + return; + + GdkGC* gdkContext = gdk_gc_new(gdkWindow); + if (!gdkContext) + return; + + if (!instanceData->hasWidget) { + NPRect* clip = &window.clipRect; + GdkRectangle gdkClip = { clip->left, clip->top, clip->right - clip->left, + clip->bottom - clip->top }; + gdk_gc_set_clip_rectangle(gdkContext, &gdkClip); + } + + // draw a grey background for the plugin frame + GdkColor grey; + grey.red = grey.blue = grey.green = 32767; + gdk_gc_set_rgb_fg_color(gdkContext, &grey); + gdk_draw_rectangle(gdkWindow, gdkContext, TRUE, x, y, width, height); + + // draw a 3-pixel-thick black frame around the plugin + GdkColor black; + black.red = black.green = black.blue = 0; + gdk_gc_set_rgb_fg_color(gdkContext, &black); + gdk_gc_set_line_attributes(gdkContext, 3, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_MITER); + gdk_draw_rectangle(gdkWindow, gdkContext, FALSE, x + 1, y + 1, + width - 3, height - 3); + + // paint the UA string + PangoContext* pangoContext = gdk_pango_context_get(); + PangoLayout* pangoTextLayout = pango_layout_new(pangoContext); + pango_layout_set_width(pangoTextLayout, (width - 10) * PANGO_SCALE); + pango_layout_set_text(pangoTextLayout, uaString, -1); + gdk_draw_layout(gdkWindow, gdkContext, x + 5, y + 5, pangoTextLayout); + g_object_unref(pangoTextLayout); + + g_object_unref(gdkContext); +} + +static gboolean +ExposeWidget(GtkWidget* widget, GdkEventExpose* event, + gpointer user_data) +{ + InstanceData* instanceData = static_cast(user_data); + pluginDrawWindow(instanceData, event->window, event->area); + return TRUE; +} + +static gboolean +MotionEvent(GtkWidget* widget, GdkEventMotion* event, + gpointer user_data) +{ + InstanceData* instanceData = static_cast(user_data); + instanceData->lastMouseX = event->x; + instanceData->lastMouseY = event->y; + return TRUE; +} + +static gboolean +ButtonEvent(GtkWidget* widget, GdkEventButton* event, + gpointer user_data) +{ + InstanceData* instanceData = static_cast(user_data); + instanceData->lastMouseX = event->x; + instanceData->lastMouseY = event->y; + if (event->type == GDK_BUTTON_RELEASE) { + instanceData->mouseUpEventCount++; + } + return TRUE; +} + +static gboolean +DeleteWidget(GtkWidget* widget, GdkEvent* event, gpointer user_data) +{ + InstanceData* instanceData = static_cast(user_data); + // Some plugins do not expect the plug to be removed from the socket before + // the plugin instance is destroyed. e.g. bug 485125 + if (instanceData->platformData->plug) + g_error("plug removed"); // this aborts + + return FALSE; +} + +void +pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow) +{ + instanceData->window = *newWindow; + +#ifdef MOZ_X11 + NPSetWindowCallbackStruct *ws_info = + static_cast(newWindow->ws_info); + instanceData->platformData->display = ws_info->display; + instanceData->platformData->visual = ws_info->visual; + instanceData->platformData->colormap = ws_info->colormap; +#endif +} + +void +pluginWidgetInit(InstanceData* instanceData, void* oldWindow) +{ +#ifdef MOZ_X11 + GtkWidget* oldPlug = instanceData->platformData->plug; + if (oldPlug) { + instanceData->platformData->plug = 0; + gtk_widget_destroy(oldPlug); + } + + GdkNativeWindow nativeWinId = + reinterpret_cast(instanceData->window.window); + + /* create a GtkPlug container */ + GtkWidget* plug = gtk_plug_new(nativeWinId); + + // Test for bugs 539138 and 561308 + if (!plug->window) + g_error("Plug has no window"); // aborts + + /* make sure the widget is capable of receiving focus */ + GTK_WIDGET_SET_FLAGS (GTK_WIDGET(plug), GTK_CAN_FOCUS); + + /* all the events that our widget wants to receive */ + gtk_widget_add_events(plug, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + g_signal_connect(plug, "expose-event", G_CALLBACK(ExposeWidget), + instanceData); + g_signal_connect(plug, "motion_notify_event", G_CALLBACK(MotionEvent), + instanceData); + g_signal_connect(plug, "button_press_event", G_CALLBACK(ButtonEvent), + instanceData); + g_signal_connect(plug, "button_release_event", G_CALLBACK(ButtonEvent), + instanceData); + g_signal_connect(plug, "delete-event", G_CALLBACK(DeleteWidget), + instanceData); + gtk_widget_show(plug); + + instanceData->platformData->plug = plug; +#endif +} + +int16_t +pluginHandleEvent(InstanceData* instanceData, void* event) +{ +#ifdef MOZ_X11 + XEvent* nsEvent = (XEvent*)event; + + switch (nsEvent->type) { + case GraphicsExpose: { + const XGraphicsExposeEvent& expose = nsEvent->xgraphicsexpose; + NPWindow& window = instanceData->window; + window.window = (void*)(expose.drawable); + + GdkNativeWindow nativeWinId = reinterpret_cast(window.window); + + GdkDisplay* gdkDisplay = gdk_x11_lookup_xdisplay(expose.display); + if (!gdkDisplay) { + g_warning("Display not opened by GDK"); + return 0; + } + // gdk_pixmap_foreign_new() doesn't check whether a GdkPixmap already + // exists, so check first. + // https://bugzilla.gnome.org/show_bug.cgi?id=590690 + GdkPixmap* gdkDrawable = + GDK_DRAWABLE(gdk_pixmap_lookup_for_display(gdkDisplay, nativeWinId)); + // If there is no existing GdkPixmap or it doesn't have a colormap then + // create our own. + if (gdkDrawable) { + GdkColormap* gdkColormap = gdk_drawable_get_colormap(gdkDrawable); + if (!gdkColormap) { + g_warning("No GdkColormap on GdkPixmap"); + return 0; + } + if (gdk_x11_colormap_get_xcolormap(gdkColormap) + != instanceData->platformData->colormap) { + g_warning("wrong Colormap"); + return 0; + } + if (gdk_x11_visual_get_xvisual(gdk_colormap_get_visual(gdkColormap)) + != instanceData->platformData->visual) { + g_warning("wrong Visual"); + return 0; + } + g_object_ref(gdkDrawable); + } else { + gdkDrawable = + GDK_DRAWABLE(gdk_pixmap_foreign_new_for_display(gdkDisplay, + nativeWinId)); + VisualID visualID = instanceData->platformData->visual->visualid; + GdkVisual* gdkVisual = + gdk_x11_screen_lookup_visual(gdk_drawable_get_screen(gdkDrawable), + visualID); + GdkColormap* gdkColormap = + gdk_x11_colormap_foreign_new(gdkVisual, + instanceData->platformData->colormap); + gdk_drawable_set_colormap(gdkDrawable, gdkColormap); + g_object_unref(gdkColormap); + } + + const NPRect& clip = window.clipRect; + if (expose.x < clip.left || expose.y < clip.top || + expose.x + expose.width > clip.right || + expose.y + expose.height > clip.bottom) { + g_warning("expose rectangle (x=%d,y=%d,w=%d,h=%d) not in clip rectangle (l=%d,t=%d,r=%d,b=%d)", + expose.x, expose.y, expose.width, expose.height, + clip.left, clip.top, clip.right, clip.bottom); + return 0; + } + if (expose.x < window.x || expose.y < window.y || + expose.x + expose.width > window.x + int32_t(window.width) || + expose.y + expose.height > window.y + int32_t(window.height)) { + g_warning("expose rectangle (x=%d,y=%d,w=%d,h=%d) not in plugin rectangle (x=%d,y=%d,w=%d,h=%d)", + expose.x, expose.y, expose.width, expose.height, + window.x, window.y, window.width, window.height); + return 0; + } + + GdkRectangle invalidRect = + { expose.x, expose.y, expose.width, expose.height }; + pluginDrawWindow(instanceData, gdkDrawable, invalidRect); + g_object_unref(gdkDrawable); + break; + } + case MotionNotify: { + XMotionEvent* motion = &nsEvent->xmotion; + instanceData->lastMouseX = motion->x; + instanceData->lastMouseY = motion->y; + break; + } + case ButtonPress: + case ButtonRelease: { + XButtonEvent* button = &nsEvent->xbutton; + instanceData->lastMouseX = button->x; + instanceData->lastMouseY = button->y; + if (nsEvent->type == ButtonRelease) { + instanceData->mouseUpEventCount++; + } + break; + } + default: + break; + } +#endif + + return 0; +} + +int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge) +{ + if (!instanceData->hasWidget) + return NPTEST_INT32_ERROR; + GtkWidget* plug = instanceData->platformData->plug; + if (!plug) + return NPTEST_INT32_ERROR; + GdkWindow* plugWnd = plug->window; + if (!plugWnd) + return NPTEST_INT32_ERROR; + + GdkWindow* toplevelGdk = 0; +#ifdef MOZ_X11 + Window toplevel = 0; + NPN_GetValue(instanceData->npp, NPNVnetscapeWindow, &toplevel); + if (!toplevel) + return NPTEST_INT32_ERROR; + toplevelGdk = gdk_window_foreign_new(toplevel); +#endif + if (!toplevelGdk) + return NPTEST_INT32_ERROR; + + GdkRectangle toplevelFrameExtents; + gdk_window_get_frame_extents(toplevelGdk, &toplevelFrameExtents); + g_object_unref(toplevelGdk); + + gint pluginWidth, pluginHeight; + gdk_drawable_get_size(GDK_DRAWABLE(plugWnd), &pluginWidth, &pluginHeight); + gint pluginOriginX, pluginOriginY; + gdk_window_get_origin(plugWnd, &pluginOriginX, &pluginOriginY); + gint pluginX = pluginOriginX - toplevelFrameExtents.x; + gint pluginY = pluginOriginY - toplevelFrameExtents.y; + + switch (edge) { + case EDGE_LEFT: + return pluginX; + case EDGE_TOP: + return pluginY; + case EDGE_RIGHT: + return pluginX + pluginWidth; + case EDGE_BOTTOM: + return pluginY + pluginHeight; + } + MOZ_CRASH("Unexpected RectEdge?!"); +} + +#ifdef MOZ_X11 +static void intersectWithShapeRects(Display* display, Window window, + int kind, GdkRegion* region) +{ + int count = -1, order; + XRectangle* shapeRects = + XShapeGetRectangles(display, window, kind, &count, &order); + // The documentation says that shapeRects will be nullptr when the + // extension is not supported. Unfortunately XShapeGetRectangles + // also returns nullptr when the region is empty, so we can't treat + // nullptr as failure. I hope this way is OK. + if (count < 0) + return; + + GdkRegion* shapeRegion = gdk_region_new(); + if (!shapeRegion) { + XFree(shapeRects); + return; + } + + for (int i = 0; i < count; ++i) { + XRectangle* r = &shapeRects[i]; + GdkRectangle rect = { r->x, r->y, r->width, r->height }; + gdk_region_union_with_rect(shapeRegion, &rect); + } + XFree(shapeRects); + + gdk_region_intersect(region, shapeRegion); + gdk_region_destroy(shapeRegion); +} +#endif + +static GdkRegion* computeClipRegion(InstanceData* instanceData) +{ + if (!instanceData->hasWidget) + return 0; + + GtkWidget* plug = instanceData->platformData->plug; + if (!plug) + return 0; + GdkWindow* plugWnd = plug->window; + if (!plugWnd) + return 0; + + gint plugWidth, plugHeight; + gdk_drawable_get_size(GDK_DRAWABLE(plugWnd), &plugWidth, &plugHeight); + GdkRectangle pluginRect = { 0, 0, plugWidth, plugHeight }; + GdkRegion* region = gdk_region_rectangle(&pluginRect); + if (!region) + return 0; + + int pluginX = 0, pluginY = 0; + +#ifdef MOZ_X11 + Display* display = GDK_WINDOW_XDISPLAY(plugWnd); + Window window = GDK_WINDOW_XWINDOW(plugWnd); + + Window toplevel = 0; + NPN_GetValue(instanceData->npp, NPNVnetscapeWindow, &toplevel); + if (!toplevel) + return 0; + + for (;;) { + Window root; + int x, y; + unsigned int width, height, border_width, depth; + if (!XGetGeometry(display, window, &root, &x, &y, &width, &height, + &border_width, &depth)) { + gdk_region_destroy(region); + return 0; + } + + GdkRectangle windowRect = { 0, 0, static_cast(width), + static_cast(height) }; + GdkRegion* windowRgn = gdk_region_rectangle(&windowRect); + if (!windowRgn) { + gdk_region_destroy(region); + return 0; + } + intersectWithShapeRects(display, window, ShapeBounding, windowRgn); + intersectWithShapeRects(display, window, ShapeClip, windowRgn); + gdk_region_offset(windowRgn, -pluginX, -pluginY); + gdk_region_intersect(region, windowRgn); + gdk_region_destroy(windowRgn); + + // Stop now if we've reached the toplevel. Stopping here means + // clipping performed by the toplevel window is taken into account. + if (window == toplevel) + break; + + Window parent; + Window* children; + unsigned int nchildren; + if (!XQueryTree(display, window, &root, &parent, &children, &nchildren)) { + gdk_region_destroy(region); + return 0; + } + XFree(children); + + pluginX += x; + pluginY += y; + + window = parent; + } +#endif + // pluginX and pluginY are now relative to the toplevel. Make them + // relative to the window frame top-left. + GdkWindow* toplevelGdk = gdk_window_foreign_new(window); + if (!toplevelGdk) + return 0; + GdkRectangle toplevelFrameExtents; + gdk_window_get_frame_extents(toplevelGdk, &toplevelFrameExtents); + gint toplevelOriginX, toplevelOriginY; + gdk_window_get_origin(toplevelGdk, &toplevelOriginX, &toplevelOriginY); + g_object_unref(toplevelGdk); + + pluginX += toplevelOriginX - toplevelFrameExtents.x; + pluginY += toplevelOriginY - toplevelFrameExtents.y; + + gdk_region_offset(region, pluginX, pluginY); + return region; +} + +int32_t pluginGetClipRegionRectCount(InstanceData* instanceData) +{ + GdkRegion* region = computeClipRegion(instanceData); + if (!region) + return NPTEST_INT32_ERROR; + + GdkRectangle* rects; + gint nrects; + gdk_region_get_rectangles(region, &rects, &nrects); + gdk_region_destroy(region); + g_free(rects); + return nrects; +} + +int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData, + int32_t rectIndex, RectEdge edge) +{ + GdkRegion* region = computeClipRegion(instanceData); + if (!region) + return NPTEST_INT32_ERROR; + + GdkRectangle* rects; + gint nrects; + gdk_region_get_rectangles(region, &rects, &nrects); + gdk_region_destroy(region); + if (rectIndex >= nrects) { + g_free(rects); + return NPTEST_INT32_ERROR; + } + + GdkRectangle rect = rects[rectIndex]; + g_free(rects); + + switch (edge) { + case EDGE_LEFT: + return rect.x; + case EDGE_TOP: + return rect.y; + case EDGE_RIGHT: + return rect.x + rect.width; + case EDGE_BOTTOM: + return rect.y + rect.height; + } + return NPTEST_INT32_ERROR; +} + +void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error) +{ +} + +string +pluginGetClipboardText(InstanceData* instanceData) +{ + GtkClipboard* cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + // XXX this is a BAD WAY to interact with GtkClipboard. We use this + // deprecated interface only to test nested event loop handling. + gchar* text = gtk_clipboard_wait_for_text(cb); + string retText = text ? text : ""; + + g_free(text); + + return retText; +} + +//----------------------------------------------------------------------------- +// NB: this test is quite gross in that it's not only +// nondeterministic, but dependent on the guts of the nested glib +// event loop handling code in PluginModule. We first sleep long +// enough to make sure that the "detection timer" will be pending when +// we enter the nested glib loop, then similarly for the "process browser +// events" timer. Then we "schedule" the crasher thread to run at about the +// same time we expect that the PluginModule "process browser events" task +// will run. If all goes well, the plugin process will crash and generate the +// XPCOM "plugin crashed" task, and the browser will run that task while still +// in the "process some events" loop. + +static void* +CrasherThread(void* data) +{ + // Give the parent thread a chance to send the message. + usleep(200); + + // Exit (without running atexit hooks) rather than crashing with a signal + // so as to make timing more reliable. The process terminates immediately + // rather than waiting for a thread in the parent process to attach and + // generate a minidump. + _exit(1); + + // not reached + return(nullptr); +} + +bool +pluginCrashInNestedLoop(InstanceData* instanceData) +{ + // wait at least long enough for nested loop detector task to be pending ... + sleep(1); + + // Run the nested loop detector by processing all events that are waiting. + bool found_event = false; + while (g_main_context_iteration(nullptr, FALSE)) { + found_event = true; + } + if (!found_event) { + g_warning("DetectNestedEventLoop did not fire"); + return true; // trigger a test failure + } + + // wait at least long enough for the "process browser events" task to be + // pending ... + sleep(1); + + // we'll be crashing soon, note that fact now to avoid messing with + // timing too much + mozilla::NoteIntentionalCrash("plugin"); + + // schedule the crasher thread ... + pthread_t crasherThread; + if (0 != pthread_create(&crasherThread, nullptr, CrasherThread, nullptr)) { + g_warning("Failed to create thread"); + return true; // trigger a test failure + } + + // .. and hope it crashes at about the same time as the "process browser + // events" task (that should run in this loop) is being processed in the + // parent. + found_event = false; + while (g_main_context_iteration(nullptr, FALSE)) { + found_event = true; + } + if (found_event) { + g_warning("Should have crashed in ProcessBrowserEvents"); + } else { + g_warning("ProcessBrowserEvents did not fire"); + } + + // if we get here without crashing, then we'll trigger a test failure + return true; +} + +bool +pluginTriggerXError(InstanceData* instanceData) +{ + mozilla::NoteIntentionalCrash("plugin"); + int num_prop_return; + // Window parameter is None to generate a fatal error, and this function + // should not return. + XListProperties(GDK_DISPLAY(), X11None, &num_prop_return); + + // if we get here without crashing, then we'll trigger a test failure + return true; +} + +static int +SleepThenDie(Display* display) +{ + mozilla::NoteIntentionalCrash("plugin"); + fprintf(stderr, "[testplugin:%d] SleepThenDie: sleeping\n", getpid()); + sleep(1); + + fprintf(stderr, "[testplugin:%d] SleepThenDie: dying\n", getpid()); + _exit(1); +} + +bool +pluginDestroySharedGfxStuff(InstanceData* instanceData) +{ + // Closing the X socket results in the gdk error handler being + // invoked, which exit()s us. We want to give the parent process a + // little while to do whatever it wanted to do, so steal the IO + // handler from gdk and set up our own that delays seppuku. + XSetIOErrorHandler(SleepThenDie); + close(ConnectionNumber(GDK_DISPLAY())); + return true; +} diff --git a/dom/plugins/test/testplugin/nptest_macosx.mm b/dom/plugins/test/testplugin/nptest_macosx.mm new file mode 100644 index 0000000000..c38da31dc8 --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_macosx.mm @@ -0,0 +1,312 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (c) 2008, Mozilla Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Mozilla Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Josh Aas + * + * ***** END LICENSE BLOCK ***** */ + +#include "nptest_platform.h" +#include "nsAlgorithm.h" +#include +#include + +using namespace std; + +bool +pluginSupportsWindowMode() +{ + return false; +} + +bool +pluginSupportsWindowlessMode() +{ + return true; +} + +NPError +pluginInstanceInit(InstanceData* instanceData) +{ + NPP npp = instanceData->npp; + + NPBool supportsCoreGraphics = false; + if ((NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR) && + supportsCoreGraphics) { + NPN_SetValue(npp, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics); + } else { + printf("CoreGraphics drawing model not supported, can't create a plugin instance.\n"); + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } + + NPBool supportsCocoaEvents = false; + if ((NPN_GetValue(npp, NPNVsupportsCocoaBool, &supportsCocoaEvents) == NPERR_NO_ERROR) && + supportsCocoaEvents) { + NPN_SetValue(npp, NPPVpluginEventModel, (void*)NPEventModelCocoa); + instanceData->eventModel = NPEventModelCocoa; + } else { + printf("Cocoa event model not supported, can't create a plugin instance.\n"); + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } + + return NPERR_NO_ERROR; +} + +void +pluginInstanceShutdown(InstanceData* instanceData) +{ +} + +static bool +RectEquals(const NPRect& r1, const NPRect& r2) +{ + return r1.left == r2.left && r1.top == r2.top && + r1.right == r2.right && r1.bottom == r2.bottom; +} + +void +pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow) +{ + // Ugh. Due to a terrible Gecko bug, we have to ignore position changes + // when the clip rect doesn't change; the position can be wrong + // when set by a path other than nsPluginFrame::FixUpPluginWindow. + int32_t oldX = instanceData->window.x; + int32_t oldY = instanceData->window.y; + bool clipChanged = + !RectEquals(instanceData->window.clipRect, newWindow->clipRect); + instanceData->window = *newWindow; + if (!clipChanged) { + instanceData->window.x = oldX; + instanceData->window.y = oldY; + } +} + +void +pluginWidgetInit(InstanceData* instanceData, void* oldWindow) +{ + // Should never be called since we don't support window mode +} + +static void +GetColorsFromRGBA(uint32_t rgba, float* r, float* g, float* b, float* a) +{ + *b = (rgba & 0xFF) / 255.0; + *g = ((rgba & 0xFF00) >> 8) / 255.0; + *r = ((rgba & 0xFF0000) >> 16) / 255.0; + *a = ((rgba & 0xFF000000) >> 24) / 255.0; +} + +static void +pluginDraw(InstanceData* instanceData, NPCocoaEvent* event) +{ + if (!instanceData) + return; + + notifyDidPaint(instanceData); + + NPP npp = instanceData->npp; + if (!npp) + return; + + const char* uaString = NPN_UserAgent(npp); + if (!uaString) + return; + + NPWindow window = instanceData->window; + + CGContextRef cgContext = event->data.draw.context; + + float windowWidth = window.width; + float windowHeight = window.height; + + switch(instanceData->scriptableObject->drawMode) { + case DM_DEFAULT: { + CFStringRef uaCFString = CFStringCreateWithCString(kCFAllocatorDefault, uaString, kCFStringEncodingASCII); + // save the cgcontext gstate + CGContextSaveGState(cgContext); + + // we get a flipped context + CGContextTranslateCTM(cgContext, 0.0, windowHeight); + CGContextScaleCTM(cgContext, 1.0, -1.0); + + // draw a gray background for the plugin + CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight)); + CGContextSetGrayFillColor(cgContext, 0.5, 1.0); + CGContextDrawPath(cgContext, kCGPathFill); + + // draw a black frame around the plugin + CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight)); + CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0); + CGContextSetLineWidth(cgContext, 6.0); + CGContextStrokePath(cgContext); + + // draw the UA string using Core Text + CGContextSetTextMatrix(cgContext, CGAffineTransformIdentity); + + // Initialize a rectangular path. + CGMutablePathRef path = CGPathCreateMutable(); + CGRect bounds = CGRectMake(10.0, 10.0, std::max(0.0, windowWidth - 20.0), + std::max(0.0, windowHeight - 20.0)); + CGPathAddRect(path, NULL, bounds); + + // Initialize an attributed string. + CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); + CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), uaCFString); + + // Create a color and add it as an attribute to the string. + CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); + CGFloat components[] = { 0.0, 0.0, 0.0, 1.0 }; + CGColorRef red = CGColorCreate(rgbColorSpace, components); + CGColorSpaceRelease(rgbColorSpace); + CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 50), kCTForegroundColorAttributeName, red); + + // Create the framesetter with the attributed string. + CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString); + CFRelease(attrString); + + // Create the frame and draw it into the graphics context + CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); + CFRelease(framesetter); + if (frame) { + CTFrameDraw(frame, cgContext); + CFRelease(frame); + } + + // restore the cgcontext gstate + CGContextRestoreGState(cgContext); + break; + } + case DM_SOLID_COLOR: { + // save the cgcontext gstate + CGContextSaveGState(cgContext); + + // we get a flipped context + CGContextTranslateCTM(cgContext, 0.0, windowHeight); + CGContextScaleCTM(cgContext, 1.0, -1.0); + + // draw a solid background for the plugin + CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight)); + + float r,g,b,a; + GetColorsFromRGBA(instanceData->scriptableObject->drawColor, &r, &g, &b, &a); + CGContextSetRGBFillColor(cgContext, r, g, b, a); + CGContextDrawPath(cgContext, kCGPathFill); + + // restore the cgcontext gstate + CGContextRestoreGState(cgContext); + break; + } + } +} + +int16_t +pluginHandleEvent(InstanceData* instanceData, void* event) +{ + NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event; + if (!cocoaEvent) + return kNPEventNotHandled; + + switch (cocoaEvent->type) { + case NPCocoaEventDrawRect: + pluginDraw(instanceData, cocoaEvent); + break; + case NPCocoaEventMouseDown: + case NPCocoaEventMouseUp: + case NPCocoaEventMouseMoved: + case NPCocoaEventMouseDragged: + instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX; + instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY; + if (cocoaEvent->type == NPCocoaEventMouseUp) { + instanceData->mouseUpEventCount++; + } + break; + case NPCocoaEventWindowFocusChanged: + instanceData->topLevelWindowActivationState = cocoaEvent->data.focus.hasFocus ? + ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED; + instanceData->topLevelWindowActivationEventCount = instanceData->topLevelWindowActivationEventCount + 1; + break; + case NPCocoaEventFocusChanged: + instanceData->focusState = cocoaEvent->data.focus.hasFocus ? + ACTIVATION_STATE_ACTIVATED : ACTIVATION_STATE_DEACTIVATED; + instanceData->focusEventCount = instanceData->focusEventCount + 1; + break; + default: + return kNPEventNotHandled; + } + + return kNPEventHandled; +} + +int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge) +{ + NPWindow* w = &instanceData->window; + switch (edge) { + case EDGE_LEFT: + return w->x; + case EDGE_TOP: + return w->y; + case EDGE_RIGHT: + return w->x + w->width; + case EDGE_BOTTOM: + return w->y + w->height; + } + MOZ_CRASH("Unexpected RectEdge?!"); +} + +int32_t pluginGetClipRegionRectCount(InstanceData* instanceData) +{ + return 1; +} + +int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData, + int32_t rectIndex, RectEdge edge) +{ + if (rectIndex != 0) + return NPTEST_INT32_ERROR; + + // We have to add the Cocoa titlebar height here since the clip rect + // is being returned relative to that + static const int COCOA_TITLEBAR_HEIGHT = 22; + + NPWindow* w = &instanceData->window; + switch (edge) { + case EDGE_LEFT: + return w->clipRect.left; + case EDGE_TOP: + return w->clipRect.top + COCOA_TITLEBAR_HEIGHT; + case EDGE_RIGHT: + return w->clipRect.right; + case EDGE_BOTTOM: + return w->clipRect.bottom + COCOA_TITLEBAR_HEIGHT; + } + MOZ_CRASH("Unexpected RectEdge?!"); +} + +void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error) +{ +} diff --git a/dom/plugins/test/testplugin/nptest_name.cpp b/dom/plugins/test/testplugin/nptest_name.cpp new file mode 100644 index 0000000000..f9b57dfa8f --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_name.cpp @@ -0,0 +1,6 @@ +const char *sPluginName = "Test Plug-in"; +const char *sPluginDescription = "Plug-in for testing purposes.\xE2\x84\xA2 " \ + "(\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\xa8\xe0\xa5\x8d\xe0\xa4\xa6\xe0\xa5\x80 " \ + "\xe4\xb8\xad\xe6\x96\x87 " \ + "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a\xd8\xa9)"; +const char *sMimeDescription = "application/x-test:tst:Test \xE2\x84\xA2 mimetype"; diff --git a/dom/plugins/test/testplugin/nptest_platform.h b/dom/plugins/test/testplugin/nptest_platform.h new file mode 100644 index 0000000000..c9542c78bb --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_platform.h @@ -0,0 +1,160 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (c) 2008, Mozilla Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Mozilla Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Josh Aas + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nptest_platform_h_ +#define nptest_platform_h_ + +#include "nptest.h" + +/** + * Returns true if the plugin supports windowed mode + */ +bool pluginSupportsWindowMode(); + +/** + * Returns true if the plugin supports windowless mode. At least one of + * "pluginSupportsWindowMode" and "pluginSupportsWindowlessMode" must + * return true. + */ +bool pluginSupportsWindowlessMode(); + +/** + * Initialize the plugin instance. Returning an error here will cause the + * plugin instantiation to fail. + */ +NPError pluginInstanceInit(InstanceData* instanceData); + +/** + * Shutdown the plugin instance. + */ +void pluginInstanceShutdown(InstanceData* instanceData); + +/** + * Set the instanceData's window to newWindow. + */ +void pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow); + +/** + * Initialize the window for a windowed plugin. oldWindow is the old + * native window value. This will never be called for windowless plugins. + */ +void pluginWidgetInit(InstanceData* instanceData, void* oldWindow); + +/** + * Handle an event for a windowless plugin. (Windowed plugins are + * responsible for listening for their own events.) + */ +int16_t pluginHandleEvent(InstanceData* instanceData, void* event); + +enum RectEdge { + EDGE_LEFT = 0, + EDGE_TOP = 1, + EDGE_RIGHT = 2, + EDGE_BOTTOM = 3 +}; + +enum { + NPTEST_INT32_ERROR = 0x7FFFFFFF +}; + +/** + * Return the coordinate of the given edge of the plugin's area, relative + * to the top-left corner of the toplevel window containing the plugin, + * including window decorations. Only works for window-mode plugins + * and Mac plugins. + * Returns NPTEST_ERROR on error. + */ +int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge); + +/** + * Return the number of rectangles in the plugin's clip region. Only + * works for window-mode plugins and Mac plugins. + * Returns NPTEST_ERROR on error. + */ +int32_t pluginGetClipRegionRectCount(InstanceData* instanceData); + +/** + * Return the coordinate of the given edge of a rectangle in the plugin's + * clip region, relative to the top-left corner of the toplevel window + * containing the plugin, including window decorations. Only works for + * window-mode plugins and Mac plugins. + * Returns NPTEST_ERROR on error. + */ +int32_t pluginGetClipRegionRectEdge(InstanceData* instanceData, + int32_t rectIndex, RectEdge edge); + +/** + * Check that the platform-specific plugin state is internally consistent. + * Just return if everything is OK, otherwise append error messages + * to 'error' separated by \n. + */ +void pluginDoInternalConsistencyCheck(InstanceData* instanceData, std::string& error); + +/** + * Get the current clipboard item as text. If the clipboard item + * isn't text, the returned value is undefined. + */ +std::string pluginGetClipboardText(InstanceData* instanceData); + +/** + * Crash while in a nested event loop. The goal is to catch the + * browser processing the XPCOM event generated from the plugin's + * crash while other plugin code is still on the stack. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=550026. + */ +bool pluginCrashInNestedLoop(InstanceData* instanceData); + +/** + * Generate an X11 protocol error to terminate the plugin process. + */ +bool pluginTriggerXError(InstanceData* instanceData); + +/** + * Destroy gfx things that might be shared with the parent process + * when we're run out-of-process. It's not expected that this + * function will be called when the test plugin is loaded in-process, + * and bad things will happen if it is called. + * + * This call leaves the plugin subprocess in an undefined state. It + * must not be used after this call or weird things will happen. + */ +bool pluginDestroySharedGfxStuff(InstanceData* instanceData); + +/** + * Checks to see if the native widget is marked as visible. Works + * in e10s and non-e10s. Useful in testing e10s related compositor + * plugin window functionality. Supported on Windows. + */ +bool pluginNativeWidgetIsVisible(InstanceData* instanceData); + +#endif // nptest_platform_h_ diff --git a/dom/plugins/test/testplugin/nptest_utils.cpp b/dom/plugins/test/testplugin/nptest_utils.cpp new file mode 100644 index 0000000000..d33603143a --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_utils.cpp @@ -0,0 +1,113 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Josh Aas + * + * ***** END LICENSE BLOCK ***** */ + +#include "nptest_utils.h" + +#include +#include +#include + +NPUTF8* +createCStringFromNPVariant(const NPVariant* variant) +{ + size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length; + NPUTF8* result = (NPUTF8*)malloc(length + 1); + memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length); + result[length] = '\0'; + return result; +} + +NPIdentifier +variantToIdentifier(NPVariant variant) +{ + if (NPVARIANT_IS_STRING(variant)) + return stringVariantToIdentifier(variant); + else if (NPVARIANT_IS_INT32(variant)) + return int32VariantToIdentifier(variant); + else if (NPVARIANT_IS_DOUBLE(variant)) + return doubleVariantToIdentifier(variant); + return 0; +} + +NPIdentifier +stringVariantToIdentifier(NPVariant variant) +{ + assert(NPVARIANT_IS_STRING(variant)); + NPUTF8* utf8String = createCStringFromNPVariant(&variant); + NPIdentifier identifier = NPN_GetStringIdentifier(utf8String); + free(utf8String); + return identifier; +} + +NPIdentifier +int32VariantToIdentifier(NPVariant variant) +{ + assert(NPVARIANT_IS_INT32(variant)); + int32_t integer = NPVARIANT_TO_INT32(variant); + return NPN_GetIntIdentifier(integer); +} + +NPIdentifier +doubleVariantToIdentifier(NPVariant variant) +{ + assert(NPVARIANT_IS_DOUBLE(variant)); + double value = NPVARIANT_TO_DOUBLE(variant); + // sadly there is no "getdoubleidentifier" + int32_t integer = static_cast(value); + return NPN_GetIntIdentifier(integer); +} + +/* + * Parse a color in hex format, #AARRGGBB or AARRGGBB. + */ +uint32_t +parseHexColor(const char* color, int len) +{ + uint8_t bgra[4] = { 0, 0, 0, 0xFF }; + int i = 0; + + // Ignore unsupported formats. + if (len != 9 && len != 8) + return 0; + + // start from the right and work to the left + while (len >= 2) { // we have at least #AA or AA left. + char byte[3]; + // parse two hex digits + byte[0] = color[len - 2]; + byte[1] = color[len - 1]; + byte[2] = '\0'; + + bgra[i] = (uint8_t)(strtoul(byte, nullptr, 16) & 0xFF); + i++; + len -= 2; + } + return (bgra[3] << 24) | (bgra[2] << 16) | (bgra[1] << 8) | bgra[0]; +} diff --git a/dom/plugins/test/testplugin/nptest_utils.h b/dom/plugins/test/testplugin/nptest_utils.h new file mode 100644 index 0000000000..78228841eb --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_utils.h @@ -0,0 +1,45 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Josh Aas + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nptest_utils_h_ +#define nptest_utils_h_ + +#include "nptest.h" + +NPUTF8* createCStringFromNPVariant(const NPVariant* variant); + +NPIdentifier variantToIdentifier(NPVariant variant); +NPIdentifier stringVariantToIdentifier(NPVariant variant); +NPIdentifier int32VariantToIdentifier(NPVariant variant); +NPIdentifier doubleVariantToIdentifier(NPVariant variant); + +uint32_t parseHexColor(const char* color, int len); + +#endif // nptest_utils_h_ diff --git a/dom/plugins/test/testplugin/nptest_windows.cpp b/dom/plugins/test/testplugin/nptest_windows.cpp new file mode 100644 index 0000000000..8b02872e95 --- /dev/null +++ b/dom/plugins/test/testplugin/nptest_windows.cpp @@ -0,0 +1,878 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * + * Copyright (c) 2008, Mozilla Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Mozilla Corporation nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributor(s): + * Josh Aas + * Jim Mathies + * + * ***** END LICENSE BLOCK ***** */ + +#include "nptest_platform.h" + +#include +#include +#include + +#include +#include + +using namespace std; + +void SetSubclass(HWND hWnd, InstanceData* instanceData); +void ClearSubclass(HWND hWnd); +LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +struct _PlatformData { + HWND childWindow; + IDXGIAdapter1 *adapter; + ID3D10Device1 *device; + ID3D10Texture2D *frontBuffer; + ID3D10Texture2D *backBuffer; + ID2D1Factory *d2d1Factory; +}; + +bool +pluginSupportsWindowMode() +{ + return true; +} + +bool +pluginSupportsWindowlessMode() +{ + return true; +} + +NPError +pluginInstanceInit(InstanceData* instanceData) +{ + NPP npp = instanceData->npp; + + instanceData->platformData = static_cast + (NPN_MemAlloc(sizeof(PlatformData))); + if (!instanceData->platformData) + return NPERR_OUT_OF_MEMORY_ERROR; + + instanceData->platformData->childWindow = nullptr; + instanceData->platformData->device = nullptr; + instanceData->platformData->frontBuffer = nullptr; + instanceData->platformData->backBuffer = nullptr; + instanceData->platformData->adapter = nullptr; + instanceData->platformData->d2d1Factory = nullptr; + return NPERR_NO_ERROR; +} + +static inline bool +openSharedTex2D(ID3D10Device* device, HANDLE handle, ID3D10Texture2D** out) +{ + HRESULT hr = device->OpenSharedResource(handle, __uuidof(ID3D10Texture2D), (void**)out); + if (FAILED(hr) || !*out) { + return false; + } + return true; +} + +// This is overloaded in d2d1.h so we can't use decltype(). +typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)( + D2D1_FACTORY_TYPE factoryType, + REFIID iid, + CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, + void **factory +); + +static IDXGIAdapter1* +FindDXGIAdapter(NPP npp, IDXGIFactory1* factory) +{ + DXGI_ADAPTER_DESC preferred; + if (NPN_GetValue(npp, NPNVpreferredDXGIAdapter, &preferred) != NPERR_NO_ERROR) { + return nullptr; + } + + UINT index = 0; + for (;;) { + IDXGIAdapter1* adapter = nullptr; + if (FAILED(factory->EnumAdapters1(index, &adapter)) || !adapter) { + return nullptr; + } + + DXGI_ADAPTER_DESC desc; + if (SUCCEEDED(adapter->GetDesc(&desc)) && + desc.AdapterLuid.LowPart == preferred.AdapterLuid.LowPart && + desc.AdapterLuid.HighPart == preferred.AdapterLuid.HighPart && + desc.VendorId == preferred.VendorId && + desc.DeviceId == preferred.DeviceId) + { + return adapter; + } + + adapter->Release(); + index++; + } +} + +// Note: we leak modules since we need them anyway. +bool +setupDxgiSurfaces(NPP npp, InstanceData* instanceData) +{ + HMODULE dxgi = LoadLibraryA("dxgi.dll"); + if (!dxgi) { + return false; + } + decltype(CreateDXGIFactory1)* createDXGIFactory1 = + (decltype(CreateDXGIFactory1)*)GetProcAddress(dxgi, "CreateDXGIFactory1"); + if (!createDXGIFactory1) { + return false; + } + + IDXGIFactory1* factory1 = nullptr; + HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&factory1); + if (FAILED(hr) || !factory1) { + return false; + } + + instanceData->platformData->adapter = FindDXGIAdapter(npp, factory1); + if (!instanceData->platformData->adapter) { + return false; + } + + HMODULE d3d10 = LoadLibraryA("d3d10_1.dll"); + if (!d3d10) { + return false; + } + + decltype(D3D10CreateDevice1)* createDevice = + (decltype(D3D10CreateDevice1)*)GetProcAddress(d3d10, "D3D10CreateDevice1"); + if (!createDevice) { + return false; + } + + + hr = createDevice( + instanceData->platformData->adapter, + D3D10_DRIVER_TYPE_HARDWARE, nullptr, + D3D10_CREATE_DEVICE_BGRA_SUPPORT | + D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS, + D3D10_FEATURE_LEVEL_10_1, + D3D10_1_SDK_VERSION, &instanceData->platformData->device); + if (FAILED(hr) || !instanceData->platformData->device) { + return false; + } + + if (!openSharedTex2D(instanceData->platformData->device, + instanceData->frontBuffer->sharedHandle, + &instanceData->platformData->frontBuffer)) + { + return false; + } + if (!openSharedTex2D(instanceData->platformData->device, + instanceData->backBuffer->sharedHandle, + &instanceData->platformData->backBuffer)) + { + return false; + } + + HMODULE d2d1 = LoadLibraryA("D2d1.dll"); + if (!d2d1) { + return false; + } + auto d2d1CreateFactory = (D2D1CreateFactoryFunc)GetProcAddress(d2d1, "D2D1CreateFactory"); + if (!d2d1CreateFactory) { + return false; + } + + D2D1_FACTORY_OPTIONS options; + options.debugLevel = D2D1_DEBUG_LEVEL_NONE; + + hr = d2d1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, + __uuidof(ID2D1Factory), + &options, + (void**)&instanceData->platformData->d2d1Factory); + if (FAILED(hr) || !instanceData->platformData->d2d1Factory) { + return false; + } + + return true; +} + +void +drawDxgiBitmapColor(InstanceData* instanceData) +{ + NPP npp = instanceData->npp; + + HRESULT hr; + + IDXGISurface* surface = nullptr; + hr = instanceData->platformData->backBuffer->QueryInterface( + __uuidof(IDXGISurface), (void **)&surface); + if (FAILED(hr) || !surface) { + return; + } + + D2D1_RENDER_TARGET_PROPERTIES props = + D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT, + D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)); + + ID2D1RenderTarget* target = nullptr; + hr = instanceData->platformData->d2d1Factory->CreateDxgiSurfaceRenderTarget( + surface, + &props, + &target); + if (FAILED(hr) || !target) { + surface->Release(); + return; + } + + IDXGIKeyedMutex* mutex = nullptr; + hr = instanceData->platformData->backBuffer->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&mutex); + if (mutex) { + mutex->AcquireSync(0, 0); + } + + target->BeginDraw(); + + unsigned char subpixels[4]; + memcpy(subpixels, + &instanceData->scriptableObject->drawColor, + sizeof(subpixels)); + + auto rect = D2D1::RectF( + 0, 0, + instanceData->backBuffer->size.width, + instanceData->backBuffer->size.height); + auto color = D2D1::ColorF( + float(subpixels[3] * subpixels[2]) / 0xFF, + float(subpixels[3] * subpixels[1]) / 0xFF, + float(subpixels[3] * subpixels[0]) / 0xFF, + float(subpixels[3]) / 0xff); + + ID2D1SolidColorBrush* brush = nullptr; + hr = target->CreateSolidColorBrush(color, &brush); + if (SUCCEEDED(hr) && brush) { + target->FillRectangle(rect, brush); + brush->Release(); + brush = nullptr; + } + hr = target->EndDraw(); + + if (mutex) { + mutex->ReleaseSync(0); + mutex->Release(); + mutex = nullptr; + } + + target->Release(); + surface->Release(); + target = nullptr; + surface = nullptr; + + NPN_SetCurrentAsyncSurface(npp, instanceData->backBuffer, NULL); + std::swap(instanceData->backBuffer, instanceData->frontBuffer); + std::swap(instanceData->platformData->backBuffer, + instanceData->platformData->frontBuffer); +} + +void +pluginInstanceShutdown(InstanceData* instanceData) +{ + PlatformData *pd = instanceData->platformData; + if (pd->frontBuffer) { + pd->frontBuffer->Release(); + } + if (pd->backBuffer) { + pd->backBuffer->Release(); + } + if (pd->d2d1Factory) { + pd->d2d1Factory->Release(); + } + if (pd->device) { + pd->device->Release(); + } + if (pd->adapter) { + pd->adapter->Release(); + } + NPN_MemFree(instanceData->platformData); + instanceData->platformData = 0; +} + +void +pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow) +{ + instanceData->window = *newWindow; +} + +#define CHILD_WIDGET_SIZE 10 + +void +pluginWidgetInit(InstanceData* instanceData, void* oldWindow) +{ + HWND hWnd = (HWND)instanceData->window.window; + if (oldWindow) { + // chrashtests/539897-1.html excercises this code + HWND hWndOld = (HWND)oldWindow; + ClearSubclass(hWndOld); + if (instanceData->platformData->childWindow) { + ::DestroyWindow(instanceData->platformData->childWindow); + } + } + + SetSubclass(hWnd, instanceData); + + instanceData->platformData->childWindow = + ::CreateWindowW(L"SCROLLBAR", L"Dummy child window", + WS_CHILD, 0, 0, CHILD_WIDGET_SIZE, CHILD_WIDGET_SIZE, hWnd, nullptr, + nullptr, nullptr); +} + +static void +drawToDC(InstanceData* instanceData, HDC dc, + int x, int y, int width, int height) +{ + switch (instanceData->scriptableObject->drawMode) { + case DM_DEFAULT: + { + const RECT fill = { x, y, x + width, y + height }; + + int oldBkMode = ::SetBkMode(dc, TRANSPARENT); + HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0)); + if (brush) { + ::FillRect(dc, &fill, brush); + ::DeleteObject(brush); + } + if (width > 6 && height > 6) { + brush = ::CreateSolidBrush(RGB(192, 192, 192)); + if (brush) { + RECT inset = { x + 3, y + 3, x + width - 3, y + height - 3 }; + ::FillRect(dc, &inset, brush); + ::DeleteObject(brush); + } + } + + const char* uaString = NPN_UserAgent(instanceData->npp); + if (uaString && width > 10 && height > 10) { + HFONT font = + ::CreateFontA(20, 0, 0, 0, 400, FALSE, FALSE, FALSE, + DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, 5, // CLEARTYPE_QUALITY + DEFAULT_PITCH, "Arial"); + if (font) { + HFONT oldFont = (HFONT)::SelectObject(dc, font); + RECT inset = { x + 5, y + 5, x + width - 5, y + height - 5 }; + ::DrawTextA(dc, uaString, -1, &inset, + DT_LEFT | DT_TOP | DT_NOPREFIX | DT_WORDBREAK); + ::SelectObject(dc, oldFont); + ::DeleteObject(font); + } + } + ::SetBkMode(dc, oldBkMode); + } + break; + + case DM_SOLID_COLOR: + { + HDC offscreenDC = ::CreateCompatibleDC(dc); + if (!offscreenDC) + return; + + const BITMAPV4HEADER bitmapheader = { + sizeof(BITMAPV4HEADER), + width, + height, + 1, // planes + 32, // bits + BI_BITFIELDS, + 0, // unused size + 0, 0, // unused metrics + 0, 0, // unused colors used/important + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000, // ARGB masks + }; + uint32_t *pixelData; + HBITMAP offscreenBitmap = + ::CreateDIBSection(dc, reinterpret_cast(&bitmapheader), + 0, reinterpret_cast(&pixelData), 0, 0); + if (!offscreenBitmap) + return; + + uint32_t rgba = instanceData->scriptableObject->drawColor; + unsigned int alpha = ((rgba & 0xFF000000) >> 24); + BYTE r = ((rgba & 0xFF0000) >> 16); + BYTE g = ((rgba & 0xFF00) >> 8); + BYTE b = (rgba & 0xFF); + + // Windows expects premultiplied + r = BYTE(float(alpha * r) / 0xFF); + g = BYTE(float(alpha * g) / 0xFF); + b = BYTE(float(alpha * b) / 0xFF); + uint32_t premultiplied = + (alpha << 24) + (r << 16) + (g << 8) + b; + + for (uint32_t* lastPixel = pixelData + width * height; + pixelData < lastPixel; + ++pixelData) + *pixelData = premultiplied; + + ::SelectObject(offscreenDC, offscreenBitmap); + BLENDFUNCTION blendFunc; + blendFunc.BlendOp = AC_SRC_OVER; + blendFunc.BlendFlags = 0; + blendFunc.SourceConstantAlpha = 255; + blendFunc.AlphaFormat = AC_SRC_ALPHA; + ::AlphaBlend(dc, x, y, width, height, offscreenDC, 0, 0, width, height, + blendFunc); + + ::DeleteObject(offscreenDC); + ::DeleteObject(offscreenBitmap); + } + break; + } +} + +void +pluginDraw(InstanceData* instanceData) +{ + NPP npp = instanceData->npp; + if (!npp) + return; + + HDC hdc = nullptr; + PAINTSTRUCT ps; + + notifyDidPaint(instanceData); + + if (instanceData->hasWidget) + hdc = ::BeginPaint((HWND)instanceData->window.window, &ps); + else + hdc = (HDC)instanceData->window.window; + + if (hdc == nullptr) + return; + + // Push the browser's hdc on the resource stack. If this test plugin is windowless, + // we share the drawing surface with the rest of the browser. + int savedDCID = SaveDC(hdc); + + // When we have a widget, window.x/y are meaningless since our widget + // is always positioned correctly and we just draw into it at 0,0. + int x = instanceData->hasWidget ? 0 : instanceData->window.x; + int y = instanceData->hasWidget ? 0 : instanceData->window.y; + int width = instanceData->window.width; + int height = instanceData->window.height; + drawToDC(instanceData, hdc, x, y, width, height); + + // Pop our hdc changes off the resource stack + RestoreDC(hdc, savedDCID); + + if (instanceData->hasWidget) + ::EndPaint((HWND)instanceData->window.window, &ps); +} + +/* script interface */ + +int32_t +pluginGetEdge(InstanceData* instanceData, RectEdge edge) +{ + if (!instanceData || !instanceData->hasWidget) + return NPTEST_INT32_ERROR; + + // Get the plugin client rect in screen coordinates + RECT rect = {0}; + if (!::GetClientRect((HWND)instanceData->window.window, &rect)) + return NPTEST_INT32_ERROR; + ::MapWindowPoints((HWND)instanceData->window.window, nullptr, + (LPPOINT)&rect, 2); + + // Get the toplevel window frame rect in screen coordinates + HWND rootWnd = ::GetAncestor((HWND)instanceData->window.window, GA_ROOT); + if (!rootWnd) + return NPTEST_INT32_ERROR; + RECT rootRect; + if (!::GetWindowRect(rootWnd, &rootRect)) + return NPTEST_INT32_ERROR; + + switch (edge) { + case EDGE_LEFT: + return rect.left - rootRect.left; + case EDGE_TOP: + return rect.top - rootRect.top; + case EDGE_RIGHT: + return rect.right - rootRect.left; + case EDGE_BOTTOM: + return rect.bottom - rootRect.top; + } + + return NPTEST_INT32_ERROR; +} + +static BOOL +getWindowRegion(HWND wnd, HRGN rgn) +{ + if (::GetWindowRgn(wnd, rgn) != ERROR) + return TRUE; + + RECT clientRect; + if (!::GetClientRect(wnd, &clientRect)) + return FALSE; + return ::SetRectRgn(rgn, 0, 0, clientRect.right, clientRect.bottom); +} + +static RGNDATA* +computeClipRegion(InstanceData* instanceData) +{ + HWND wnd = (HWND)instanceData->window.window; + HRGN rgn = ::CreateRectRgn(0, 0, 0, 0); + if (!rgn) + return nullptr; + HRGN ancestorRgn = ::CreateRectRgn(0, 0, 0, 0); + if (!ancestorRgn) { + ::DeleteObject(rgn); + return nullptr; + } + if (!getWindowRegion(wnd, rgn)) { + ::DeleteObject(ancestorRgn); + ::DeleteObject(rgn); + return nullptr; + } + + HWND ancestor = wnd; + for (;;) { + ancestor = ::GetAncestor(ancestor, GA_PARENT); + if (!ancestor || ancestor == ::GetDesktopWindow()) { + ::DeleteObject(ancestorRgn); + + DWORD size = ::GetRegionData(rgn, 0, nullptr); + if (!size) { + ::DeleteObject(rgn); + return nullptr; + } + + HANDLE heap = ::GetProcessHeap(); + RGNDATA* data = static_cast(::HeapAlloc(heap, 0, size)); + if (!data) { + ::DeleteObject(rgn); + return nullptr; + } + DWORD result = ::GetRegionData(rgn, size, data); + ::DeleteObject(rgn); + if (!result) { + ::HeapFree(heap, 0, data); + return nullptr; + } + + return data; + } + + if (!getWindowRegion(ancestor, ancestorRgn)) { + ::DeleteObject(ancestorRgn); + ::DeleteObject(rgn); + return 0; + } + + POINT pt = { 0, 0 }; + ::MapWindowPoints(ancestor, wnd, &pt, 1); + if (::OffsetRgn(ancestorRgn, pt.x, pt.y) == ERROR || + ::CombineRgn(rgn, rgn, ancestorRgn, RGN_AND) == ERROR) { + ::DeleteObject(ancestorRgn); + ::DeleteObject(rgn); + return 0; + } + } +} + +int32_t +pluginGetClipRegionRectCount(InstanceData* instanceData) +{ + RGNDATA* data = computeClipRegion(instanceData); + if (!data) + return NPTEST_INT32_ERROR; + + int32_t result = data->rdh.nCount; + ::HeapFree(::GetProcessHeap(), 0, data); + return result; +} + +static int32_t +addOffset(LONG coord, int32_t offset) +{ + if (offset == NPTEST_INT32_ERROR) + return NPTEST_INT32_ERROR; + return coord + offset; +} + +int32_t +pluginGetClipRegionRectEdge(InstanceData* instanceData, + int32_t rectIndex, RectEdge edge) +{ + RGNDATA* data = computeClipRegion(instanceData); + if (!data) + return NPTEST_INT32_ERROR; + + HANDLE heap = ::GetProcessHeap(); + if (rectIndex >= int32_t(data->rdh.nCount)) { + ::HeapFree(heap, 0, data); + return NPTEST_INT32_ERROR; + } + + RECT rect = reinterpret_cast(data->Buffer)[rectIndex]; + ::HeapFree(heap, 0, data); + + switch (edge) { + case EDGE_LEFT: + return addOffset(rect.left, pluginGetEdge(instanceData, EDGE_LEFT)); + case EDGE_TOP: + return addOffset(rect.top, pluginGetEdge(instanceData, EDGE_TOP)); + case EDGE_RIGHT: + return addOffset(rect.right, pluginGetEdge(instanceData, EDGE_LEFT)); + case EDGE_BOTTOM: + return addOffset(rect.bottom, pluginGetEdge(instanceData, EDGE_TOP)); + } + + return NPTEST_INT32_ERROR; +} + +static +void +createDummyWindowForIME(InstanceData* instanceData) +{ + WNDCLASSW wndClass; + wndClass.style = 0; + wndClass.lpfnWndProc = DefWindowProcW; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = GetModuleHandleW(NULL); + wndClass.hIcon = nullptr; + wndClass.hCursor = nullptr; + wndClass.hbrBackground = (HBRUSH)COLOR_WINDOW; + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = L"SWFlash_PlaceholderX"; + RegisterClassW(&wndClass); + + instanceData->placeholderWnd = + static_cast(CreateWindowW(L"SWFlash_PlaceholderX", L"", WS_CHILD, 0, + 0, 0, 0, HWND_MESSAGE, NULL, + GetModuleHandleW(NULL), NULL)); +} + +/* windowless plugin events */ + +static bool +handleEventInternal(InstanceData* instanceData, NPEvent* pe, LRESULT* result) +{ + switch ((UINT)pe->event) { + case WM_PAINT: + pluginDraw(instanceData); + return true; + + case WM_MOUSEACTIVATE: + if (instanceData->hasWidget) { + ::SetFocus((HWND)instanceData->window.window); + *result = MA_ACTIVATEANDEAT; + return true; + } + return false; + + case WM_MOUSEWHEEL: + return true; + + case WM_WINDOWPOSCHANGED: { + WINDOWPOS* pPos = (WINDOWPOS*)pe->lParam; + instanceData->winX = instanceData->winY = 0; + if (pPos) { + instanceData->winX = pPos->x; + instanceData->winY = pPos->y; + return true; + } + return false; + } + + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: { + int x = instanceData->hasWidget ? 0 : instanceData->winX; + int y = instanceData->hasWidget ? 0 : instanceData->winY; + instanceData->lastMouseX = GET_X_LPARAM(pe->lParam) - x; + instanceData->lastMouseY = GET_Y_LPARAM(pe->lParam) - y; + if ((UINT)pe->event == WM_LBUTTONUP) { + instanceData->mouseUpEventCount++; + } + return true; + } + + case WM_KEYDOWN: + instanceData->lastKeyText.erase(); + *result = 0; + return true; + + case WM_CHAR: { + *result = 0; + wchar_t uniChar = static_cast(pe->wParam); + if (!uniChar) { + return true; + } + char utf8Char[6]; + int len = + ::WideCharToMultiByte(CP_UTF8, 0, &uniChar, 1, utf8Char, 6, + nullptr, nullptr); + if (len == 0 || len > 6) { + return true; + } + instanceData->lastKeyText.append(utf8Char, len); + return true; + } + + case WM_IME_STARTCOMPOSITION: + instanceData->lastComposition.erase(); + if (!instanceData->placeholderWnd) { + createDummyWindowForIME(instanceData); + } + return true; + + case WM_IME_ENDCOMPOSITION: + instanceData->lastComposition.erase(); + return true; + + case WM_IME_COMPOSITION: { + if (pe->lParam & GCS_COMPSTR) { + HIMC hIMC = ImmGetContext((HWND)instanceData->placeholderWnd); + if (!hIMC) { + return false; + } + WCHAR compStr[256]; + LONG len = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, compStr, + 256 * sizeof(WCHAR)); + CHAR buffer[256]; + len = ::WideCharToMultiByte(CP_UTF8, 0, compStr, len / sizeof(WCHAR), + buffer, 256, nullptr, nullptr); + instanceData->lastComposition.append(buffer, len); + ::ImmReleaseContext((HWND)instanceData->placeholderWnd, hIMC); + } + return true; + } + + default: + return false; + } +} + +int16_t +pluginHandleEvent(InstanceData* instanceData, void* event) +{ + NPEvent* pe = (NPEvent*)event; + + if (pe == nullptr || instanceData == nullptr || + instanceData->window.type != NPWindowTypeDrawable) + return 0; + + LRESULT result = 0; + return handleEventInternal(instanceData, pe, &result); +} + +/* windowed plugin events */ + +LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC wndProc = (WNDPROC)GetProp(hWnd, "MozillaWndProc"); + if (!wndProc) + return 0; + InstanceData* pInstance = (InstanceData*)GetProp(hWnd, "InstanceData"); + if (!pInstance) + return 0; + + NPEvent event = { static_cast(uMsg), wParam, lParam }; + + LRESULT result = 0; + if (handleEventInternal(pInstance, &event, &result)) + return result; + + if (uMsg == WM_CLOSE) { + ClearSubclass((HWND)pInstance->window.window); + } + + return CallWindowProc(wndProc, hWnd, uMsg, wParam, lParam); +} + +void +ClearSubclass(HWND hWnd) +{ + if (GetProp(hWnd, "MozillaWndProc")) { + ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)GetProp(hWnd, "MozillaWndProc")); + RemoveProp(hWnd, "MozillaWndProc"); + RemoveProp(hWnd, "InstanceData"); + } +} + +void +SetSubclass(HWND hWnd, InstanceData* instanceData) +{ + // Subclass the plugin window so we can handle our own windows events. + SetProp(hWnd, "InstanceData", (HANDLE)instanceData); + WNDPROC origProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PluginWndProc); + SetProp(hWnd, "MozillaWndProc", (HANDLE)origProc); +} + +static void checkEquals(int a, int b, const char* msg, string& error) +{ + if (a == b) { + return; + } + + error.append(msg); + char buf[100]; + sprintf(buf, " (got %d, expected %d)\n", a, b); + error.append(buf); +} + +void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error) +{ + if (instanceData->platformData->childWindow) { + RECT childRect; + ::GetWindowRect(instanceData->platformData->childWindow, &childRect); + RECT ourRect; + HWND hWnd = (HWND)instanceData->window.window; + ::GetWindowRect(hWnd, &ourRect); + checkEquals(childRect.left, ourRect.left, "Child widget left", error); + checkEquals(childRect.top, ourRect.top, "Child widget top", error); + checkEquals(childRect.right, childRect.left + CHILD_WIDGET_SIZE, "Child widget width", error); + checkEquals(childRect.bottom, childRect.top + CHILD_WIDGET_SIZE, "Child widget height", error); + } +} + +bool pluginNativeWidgetIsVisible(InstanceData* instanceData) +{ + HWND hWnd = (HWND)instanceData->window.window; + wchar_t className[60]; + if (::GetClassNameW(hWnd, className, sizeof(className) / sizeof(char16_t)) && + !wcsicmp(className, L"GeckoPluginWindow")) { + return ::IsWindowVisible(hWnd); + } + // something isn't right, fail the check + return false; +} diff --git a/dom/plugins/test/testplugin/secondplugin/Info.plist b/dom/plugins/test/testplugin/secondplugin/Info.plist new file mode 100644 index 0000000000..afa83a63ce --- /dev/null +++ b/dom/plugins/test/testplugin/secondplugin/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + libnpsecondtest.dylib + CFBundleIdentifier + org.mozilla.SecondTestPlugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0.0.0 + CFBundleSignature + SECONDTEST + CFBundleVersion + 1.0.0.0 + WebPluginName + Second Test Plug-in + WebPluginDescription + Second plug-in for testing purposes. + WebPluginMIMETypes + + application/x-Second-Test + + WebPluginExtensions + + ts2 + + WebPluginTypeDescription + Second test type + + + + diff --git a/dom/plugins/test/testplugin/secondplugin/moz.build b/dom/plugins/test/testplugin/secondplugin/moz.build new file mode 100644 index 0000000000..f95ed4190e --- /dev/null +++ b/dom/plugins/test/testplugin/secondplugin/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SharedLibrary('npsecondtest') + +relative_path = 'secondplugin' +cocoa_name = 'SecondTest' +include('../testplugin.mozbuild') diff --git a/dom/plugins/test/testplugin/secondplugin/nptest.def b/dom/plugins/test/testplugin/secondplugin/nptest.def new file mode 100644 index 0000000000..c6584387d2 --- /dev/null +++ b/dom/plugins/test/testplugin/secondplugin/nptest.def @@ -0,0 +1,7 @@ +LIBRARY NPSECONDTEST + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 + NP_GetMIMEDescription @4 diff --git a/dom/plugins/test/testplugin/secondplugin/nptest.rc b/dom/plugins/test/testplugin/secondplugin/nptest.rc new file mode 100644 index 0000000000..835906d0cb --- /dev/null +++ b/dom/plugins/test/testplugin/secondplugin/nptest.rc @@ -0,0 +1,42 @@ +#include + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "mozilla.org" + VALUE "FileDescription", L"Second plug-in for testing purposes." + VALUE "FileExtents", "ts2" + VALUE "FileOpenName", "Second test type" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "npsecondtest" + VALUE "MIMEType", "application/x-Second-Test" + VALUE "OriginalFilename", "npsecondtest.dll" + VALUE "ProductName", "Second Test Plug-in" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/dom/plugins/test/testplugin/secondplugin/nptest_name.cpp b/dom/plugins/test/testplugin/secondplugin/nptest_name.cpp new file mode 100644 index 0000000000..12cc68b694 --- /dev/null +++ b/dom/plugins/test/testplugin/secondplugin/nptest_name.cpp @@ -0,0 +1,7 @@ +/* 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/. */ + +const char *sPluginName = "Second Test Plug-in"; +const char *sPluginDescription = "Second plug-in for testing purposes."; +const char *sMimeDescription = "application/x-Second-Test:ts2:Second test type"; diff --git a/dom/plugins/test/testplugin/silverlightplugin/Info.plist b/dom/plugins/test/testplugin/silverlightplugin/Info.plist new file mode 100644 index 0000000000..7a8094b83c --- /dev/null +++ b/dom/plugins/test/testplugin/silverlightplugin/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + libnpctrltest.dylib + CFBundleIdentifier + org.mozilla.SilverlightTestPlugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0.0.0 + CFBundleSignature + SILVERLIGHTTEST + CFBundleVersion + 1.0.0.0 + WebPluginName + Silverlight Test Plug-in + WebPluginDescription + Silverlight plug-in for testing purposes. + WebPluginMIMETypes + + application/x-silverlight-test + + WebPluginExtensions + + xaml + + WebPluginTypeDescription + Silverlight test type + + + + diff --git a/dom/plugins/test/testplugin/silverlightplugin/moz.build b/dom/plugins/test/testplugin/silverlightplugin/moz.build new file mode 100644 index 0000000000..6050e04734 --- /dev/null +++ b/dom/plugins/test/testplugin/silverlightplugin/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SharedLibrary('npctrltest') + +relative_path = 'silverlightplugin' +cocoa_name = 'npctrltest' +include('../testplugin.mozbuild') diff --git a/dom/plugins/test/testplugin/silverlightplugin/nptest.def b/dom/plugins/test/testplugin/silverlightplugin/nptest.def new file mode 100644 index 0000000000..b25c6c8c52 --- /dev/null +++ b/dom/plugins/test/testplugin/silverlightplugin/nptest.def @@ -0,0 +1,7 @@ +LIBRARY NPCTRLTEST + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 + NP_GetMIMEDescription @4 diff --git a/dom/plugins/test/testplugin/silverlightplugin/nptest.rc b/dom/plugins/test/testplugin/silverlightplugin/nptest.rc new file mode 100644 index 0000000000..a48654bc56 --- /dev/null +++ b/dom/plugins/test/testplugin/silverlightplugin/nptest.rc @@ -0,0 +1,42 @@ +#include + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "mozilla.org" + VALUE "FileDescription", L"Silverlight plug-in for testing purposes." + VALUE "FileExtents", "xaml" + VALUE "FileOpenName", "Silverlight test type" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "npctrltest" + VALUE "MIMEType", "application/x-silverlight-test" + VALUE "OriginalFilename", "npctrltest.dll" + VALUE "ProductName", "Silverlight Test Plug-in" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/dom/plugins/test/testplugin/silverlightplugin/nptest_name.cpp b/dom/plugins/test/testplugin/silverlightplugin/nptest_name.cpp new file mode 100644 index 0000000000..2cdfaa5f1c --- /dev/null +++ b/dom/plugins/test/testplugin/silverlightplugin/nptest_name.cpp @@ -0,0 +1,7 @@ +/* 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/. */ + +const char *sPluginName = "Silverlight Test Plug-in"; +const char *sPluginDescription = "Silverlight plug-in for testing purposes."; +const char *sMimeDescription = "application/x-silverlight-test:xaml:Silverlight test type"; diff --git a/dom/plugins/test/testplugin/testplugin.mozbuild b/dom/plugins/test/testplugin/testplugin.mozbuild new file mode 100644 index 0000000000..9ed4f89663 --- /dev/null +++ b/dom/plugins/test/testplugin/testplugin.mozbuild @@ -0,0 +1,72 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +UNIFIED_SOURCES += [ + 'nptest.cpp', + 'nptest_utils.cpp', +] + +UNIFIED_SOURCES += [ + '%s/nptest_name.cpp' % relative_path, +] + +toolkit = CONFIG['MOZ_WIDGET_TOOLKIT'] +if toolkit == 'cocoa': + UNIFIED_SOURCES += [ + 'nptest_macosx.mm' + ] +elif toolkit in ('gtk2', 'gtk3'): + UNIFIED_SOURCES += [ + 'nptest_gtk2.cpp', + ] +elif toolkit == 'android': + UNIFIED_SOURCES += [ + 'nptest_droid.cpp', + ] +elif toolkit == 'windows': + UNIFIED_SOURCES += [ + 'nptest_windows.cpp', + ] + OS_LIBS += [ + 'msimg32', + 'imm32' + ] + +# must link statically with the CRT; nptest isn't Gecko code +USE_STATIC_LIBS = True + +# Don't use STL wrappers; nptest isn't Gecko code +DISABLE_STL_WRAPPING = True + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + RCFILE = 'nptest.rc' + RESFILE = 'nptest.res' + DEFFILE = SRCDIR + '/nptest.def' + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' and '64' in CONFIG['OS_TEST']: + OS_LIBS += ['-framework Carbon'] + +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): + CXXFLAGS += CONFIG['MOZ_GTK2_CFLAGS'] + CFLAGS += CONFIG['MOZ_GTK2_CFLAGS'] + OS_LIBS += CONFIG['MOZ_GTK2_LIBS'] + OS_LIBS += CONFIG['XLDFLAGS'] + OS_LIBS += CONFIG['XLIBS'] + OS_LIBS += CONFIG['XEXT_LIBS'] + +if CONFIG['_MSC_VER']: + # This is intended as a temporary hack to support building with VS2015. + # conversion from 'X' to 'Y' requires a narrowing conversion + CXXFLAGS += ['-wd4838'] + +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + FINAL_TARGET = 'dist/plugins/%s.plugin/Contents/MacOS' % cocoa_name + OBJDIR_FILES.dist.plugins['%s.plugin' % cocoa_name].Contents += ['%s/Info.plist' % relative_path] +else: + FINAL_TARGET = 'dist/plugins' + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] diff --git a/dom/plugins/test/testplugin/thirdplugin/Info.plist b/dom/plugins/test/testplugin/thirdplugin/Info.plist new file mode 100644 index 0000000000..96e18ba755 --- /dev/null +++ b/dom/plugins/test/testplugin/thirdplugin/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + libnpthirdtest.dylib + CFBundleIdentifier + org.mozilla.ThirdTestPlugin + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BRPL + CFBundleShortVersionString + 1.0.0.0 + CFBundleSignature + THIRDTEST + CFBundleVersion + 1.0.0.0 + WebPluginName + Third Test Plug-in + WebPluginDescription + Third plug-in for testing purposes. + WebPluginMIMETypes + + application/x-Third-Test + + WebPluginExtensions + + ts2 + + WebPluginTypeDescription + Third test type + + + + diff --git a/dom/plugins/test/testplugin/thirdplugin/moz.build b/dom/plugins/test/testplugin/thirdplugin/moz.build new file mode 100644 index 0000000000..f0d7b1a5b9 --- /dev/null +++ b/dom/plugins/test/testplugin/thirdplugin/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SharedLibrary('npthirdtest') + +relative_path = 'thirdplugin' +cocoa_name = 'ThirdTest' +include('../testplugin.mozbuild') diff --git a/dom/plugins/test/testplugin/thirdplugin/nptest.def b/dom/plugins/test/testplugin/thirdplugin/nptest.def new file mode 100644 index 0000000000..8ea68ba410 --- /dev/null +++ b/dom/plugins/test/testplugin/thirdplugin/nptest.def @@ -0,0 +1,7 @@ +LIBRARY NPTHIRDTEST + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 + NP_GetMIMEDescription @4 diff --git a/dom/plugins/test/testplugin/thirdplugin/nptest.rc b/dom/plugins/test/testplugin/thirdplugin/nptest.rc new file mode 100644 index 0000000000..de1576920e --- /dev/null +++ b/dom/plugins/test/testplugin/thirdplugin/nptest.rc @@ -0,0 +1,42 @@ +#include + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "mozilla.org" + VALUE "FileDescription", L"Third plug-in for testing purposes." + VALUE "FileExtents", "ts2" + VALUE "FileOpenName", "Third test type" + VALUE "FileVersion", "1.0" + VALUE "InternalName", "npthirdtest" + VALUE "MIMEType", "application/x-Third-Test" + VALUE "OriginalFilename", "npthirdtest.dll" + VALUE "ProductName", "Third Test Plug-in" + VALUE "ProductVersion", "1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END diff --git a/dom/plugins/test/testplugin/thirdplugin/nptest_name.cpp b/dom/plugins/test/testplugin/thirdplugin/nptest_name.cpp new file mode 100644 index 0000000000..34eb5973d4 --- /dev/null +++ b/dom/plugins/test/testplugin/thirdplugin/nptest_name.cpp @@ -0,0 +1,7 @@ +/* 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/. */ + +const char *sPluginName = "Third Test Plug-in"; +const char *sPluginDescription = "Third plug-in for testing purposes."; +const char *sMimeDescription = "application/x-Third-Test:ts3:Third test type"; diff --git a/dom/plugins/test/unit/head_plugins.js b/dom/plugins/test/unit/head_plugins.js new file mode 100644 index 0000000000..4d32a52bf7 --- /dev/null +++ b/dom/plugins/test/unit/head_plugins.js @@ -0,0 +1,195 @@ +/* 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/. + */ + +var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +const gIsWindows = mozinfo.os == "win"; +const gIsOSX = mozinfo.os == "mac"; +const gIsLinux = mozinfo.os == "linux"; +const gDirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); + +function allow_all_plugins() { + Services.prefs.setBoolPref("plugin.load_flash_only", false); +} + +// Finds the test plugin library +function get_test_plugin(secondplugin=false) { + var pluginEnum = gDirSvc.get("APluginsDL", Ci.nsISimpleEnumerator); + while (pluginEnum.hasMoreElements()) { + let dir = pluginEnum.getNext().QueryInterface(Ci.nsILocalFile); + let name = get_platform_specific_plugin_name(secondplugin); + let plugin = dir.clone(); + plugin.append(name); + if (plugin.exists()) { + plugin.normalize(); + return plugin; + } + } + return null; +} + +// Finds the test nsIPluginTag +function get_test_plugintag(aName="Test Plug-in") { + const Cc = Components.classes; + const Ci = Components.interfaces; + + var name = aName || "Test Plug-in"; + var host = Cc["@mozilla.org/plugin/host;1"]. + getService(Ci.nsIPluginHost); + var tags = host.getPluginTags(); + + for (var i = 0; i < tags.length; i++) { + if (tags[i].name == name) + return tags[i]; + } + return null; +} + +// Creates a fake ProfDS directory key, copied from do_get_profile +function do_get_profile_startup() { + let env = Components.classes["@mozilla.org/process/environment;1"] + .getService(Components.interfaces.nsIEnvironment); + // the python harness sets this in the environment for us + let profd = env.get("XPCSHELL_TEST_PROFILE_DIR"); + let file = Components.classes["@mozilla.org/file/local;1"] + .createInstance(Components.interfaces.nsILocalFile); + file.initWithPath(profd); + + let dirSvc = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties); + let provider = { + getFile: function(prop, persistent) { + persistent.value = true; + if (prop == "ProfDS") { + return file.clone(); + } + throw Components.results.NS_ERROR_FAILURE; + }, + QueryInterface: function(iid) { + if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) || + iid.equals(Components.interfaces.nsISupports)) { + return this; + } + throw Components.results.NS_ERROR_NO_INTERFACE; + } + }; + dirSvc.QueryInterface(Components.interfaces.nsIDirectoryService) + .registerProvider(provider); + return file.clone(); +} + +function get_platform_specific_plugin_name(secondplugin=false) { + if (secondplugin) { + if (gIsWindows) return "npsecondtest.dll"; + if (gIsOSX) return "SecondTest.plugin"; + if (gIsLinux) return "libnpsecondtest.so"; + } else { + if (gIsWindows) return "nptest.dll"; + if (gIsOSX) return "Test.plugin"; + if (gIsLinux) return "libnptest.so"; + } + return null; +} + +function get_platform_specific_plugin_suffix() { + if (gIsWindows) return ".dll"; + else if (gIsOSX) return ".plugin"; + else if (gIsLinux) return ".so"; + else return null; +} + +function get_test_plugin_no_symlink() { + let dirSvc = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties); + let pluginEnum = dirSvc.get("APluginsDL", Ci.nsISimpleEnumerator); + while (pluginEnum.hasMoreElements()) { + let dir = pluginEnum.getNext().QueryInterface(Ci.nsILocalFile); + let plugin = dir.clone(); + plugin.append(get_platform_specific_plugin_name()); + if (plugin.exists()) { + return plugin; + } + } + return null; +} + +var gGlobalScope = this; +function loadAddonManager() { + let ns = {}; + Cu.import("resource://gre/modules/Services.jsm", ns); + let head = "../../../../toolkit/mozapps/extensions/test/xpcshell/head_addons.js"; + let file = do_get_file(head); + let uri = ns.Services.io.newFileURI(file); + ns.Services.scriptloader.loadSubScript(uri.spec, gGlobalScope); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + startupManager(); +} + +// Install addon and return a Promise that is +// resolve with true on success, false otherwise. +function installAddon(relativePath) { + let deferred = Promise.defer(); + let success = () => deferred.resolve(true); + let fail = () => deferred.resolve(false); + let listener = { + onDownloadCancelled: fail, + onDownloadFailed: fail, + onInstallCancelled: fail, + onInstallFailed: fail, + onInstallEnded: success, + }; + + let installCallback = install => { + install.addListener(listener); + install.install(); + }; + + let file = do_get_file(relativePath, false); + AddonManager.getInstallForFile(file, installCallback, + "application/x-xpinstall"); + + return deferred.promise; +} + +// Uninstall addon and return a Promise that is +// resolve with true on success, false otherwise. +function uninstallAddon(id) { + let deferred = Promise.defer(); + + AddonManager.getAddonByID(id, addon => { + if (!addon) { + deferred.resolve(false); + } + + let listener = {}; + let handler = addon => { + if (addon.id !== id) { + return; + } + + AddonManager.removeAddonListener(listener); + deferred.resolve(true); + }; + + listener.onUninstalled = handler; + listener.onDisabled = handler; + + AddonManager.addAddonListener(listener); + addon.uninstall(); + }); + + return deferred.promise; +} + +// Returns a Promise that is resolved with +// the corresponding addon or rejected. +function getAddonByID(id) { + let deferred = Promise.defer(); + AddonManager.getAddonByID(id, addon => deferred.resolve(addon)); + return deferred.promise; +} diff --git a/dom/plugins/test/unit/test_allowed_types.js b/dom/plugins/test/unit/test_allowed_types.js new file mode 100644 index 0000000000..09b30b31af --- /dev/null +++ b/dom/plugins/test/unit/test_allowed_types.js @@ -0,0 +1,142 @@ +/* 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/. + */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +function run_test() { + const pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); + const pluginDefaultState = Services.prefs.getIntPref("plugin.default.state"); + + Services.prefs.setBoolPref("plugin.load_flash_only", false); + + function reload_plugins_with_allowed_types(allowed_types) { + if (typeof allowed_types === "undefined") { + // If we didn't get an allowed_types string, then unset the pref, + // so the caller can test the behavior when the pref isn't set. + Services.prefs.clearUserPref("plugin.allowed_types"); + } else { + Services.prefs.setCharPref("plugin.allowed_types", allowed_types); + } + pluginHost.reloadPlugins(); + } + + function get_status_for_type(type) { + try { + return pluginHost.getStateForType(type); + } catch(ex) { + // If the type is not allowed, then nsIPluginHost.getStateForType throws + // NS_ERROR_NOT_AVAILABLE, for which we return undefined to make it easier + // to write assertions about the API. + if (ex.result === Cr.NS_ERROR_NOT_AVAILABLE) { + return undefined; + } + throw ex; + } + } + + // If allowed_types isn't set, then all plugin types are enabled. + reload_plugins_with_allowed_types(); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + // If allowed_types is set to the empty string, then all plugin types are enabled. + reload_plugins_with_allowed_types(""); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + // If allowed_types is set to anything other than the empty string, + // then only types that exactly match its comma-separated entries are enabled, + // so a single space disables all types. + reload_plugins_with_allowed_types(" "); + do_check_eq(get_status_for_type("application/x-test"), undefined); + do_check_eq(get_status_for_type("application/x-Second-Test"), undefined); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + // The rest of the assertions test various values of allowed_types to ensure + // that the correct types are enabled. + + reload_plugins_with_allowed_types("application/x-test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), undefined); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-Second-Test"); + do_check_eq(get_status_for_type("application/x-test"), undefined); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-nonexistent"); + do_check_eq(get_status_for_type("application/x-test"), undefined); + do_check_eq(get_status_for_type("application/x-Second-Test"), undefined); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-test,application/x-Second-Test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-Second-Test,application/x-test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-test,application/x-nonexistent"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), undefined); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-nonexistent,application/x-test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), undefined); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-test,application/x-Second-Test,application/x-nonexistent"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-test,application/x-nonexistent,application/x-Second-Test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-Second-Test,application/x-test,application/x-nonexistent"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-Second-Test,application/x-nonexistent,application/x-test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-nonexistent,application/x-test,application/x-Second-Test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + reload_plugins_with_allowed_types("application/x-nonexistent,application/x-Second-Test,application/x-test"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState); + do_check_eq(get_status_for_type("application/x-nonexistent"), undefined); + + // Plugin types are case-insensitive, so matching should be too. + reload_plugins_with_allowed_types("APPLICATION/X-TEST"); + do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState); + reload_plugins_with_allowed_types("application/x-test"); + do_check_eq(get_status_for_type("APPLICATION/X-TEST"), pluginDefaultState); + + // Types must match exactly, so supersets should not enable subset types. + reload_plugins_with_allowed_types("application/x-test-superset"); + do_check_eq(get_status_for_type("application/x-test"), undefined); + reload_plugins_with_allowed_types("superset-application/x-test"); + do_check_eq(get_status_for_type("application/x-test"), undefined); + + // Clean up. + Services.prefs.clearUserPref("plugin.allowed_types"); + Services.prefs.clearUserPref("plugin.importedState"); +} diff --git a/dom/plugins/test/unit/test_bug471245.js b/dom/plugins/test/unit/test_bug471245.js new file mode 100644 index 0000000000..8e38afcdc7 --- /dev/null +++ b/dom/plugins/test/unit/test_bug471245.js @@ -0,0 +1,23 @@ +/* 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/. + */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +function run_test() { + allow_all_plugins(); + do_get_profile_startup(); + + var plugin = get_test_plugintag(); + do_check_true(plugin == null); + + // Initialises a profile folder + do_get_profile(); + + var plugin = get_test_plugintag(); + do_check_false(plugin == null); + + // Clean up + Services.prefs.clearUserPref("plugin.importedState"); +} diff --git a/dom/plugins/test/unit/test_bug813245.js b/dom/plugins/test/unit/test_bug813245.js new file mode 100644 index 0000000000..069e4a0146 --- /dev/null +++ b/dom/plugins/test/unit/test_bug813245.js @@ -0,0 +1,87 @@ +/* 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/. + */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Plugin registry uses different field delimeters on different platforms +var DELIM = mozinfo.os == "win" ? "|" : ":"; + +var gProfD = do_get_profile_startup(); + +// Writes out some plugin registry to the profile +function write_registry(version, info) { + let runtime = Cc["@mozilla.org/xre/runtime;1"].getService(Ci.nsIXULRuntime); + + var header = "Generated File. Do not edit.\n\n"; + header += "[HEADER]\n"; + header += "Version" + DELIM + version + DELIM + "$\n"; + header += "Arch" + DELIM + runtime.XPCOMABI + DELIM + "$\n"; + header += "\n"; + header += "[PLUGINS]\n"; + + var registry = gProfD.clone(); + registry.append("pluginreg.dat"); + var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"] + .createInstance(Components.interfaces.nsIFileOutputStream); + // write, create, truncate + foStream.init(registry, 0x02 | 0x08 | 0x20, 0o666, 0); + + var charset = "UTF-8"; // Can be any character encoding name that Mozilla supports + var os = Cc["@mozilla.org/intl/converter-output-stream;1"]. + createInstance(Ci.nsIConverterOutputStream); + os.init(foStream, charset, 0, 0x0000); + + os.writeString(header); + os.writeString(info); + os.close(); +} + +function run_test() { + allow_all_plugins(); + var plugin = get_test_plugintag(); + do_check_true(plugin == null); + + var file = get_test_plugin(); + if (!file) { + do_throw("Plugin library not found"); + } + + // write plugin registry data + let registry = ""; + + if (gIsOSX) { + registry += file.leafName + DELIM + "$\n"; + registry += file.path + DELIM + "$\n"; + } else { + registry += file.path + DELIM + "$\n"; + registry += DELIM + "$\n"; + } + registry += "0.0.0.0" + DELIM + "$\n"; + registry += "16725225600" + DELIM + "0" + DELIM + "5" + DELIM + "$\n"; + registry += "Plug-in for testing purposes." + DELIM + "$\n"; + registry += "Test Plug-in" + DELIM + "$\n"; + registry += "999999999999999999999999999999999999999999999999|0|5|$\n"; + registry += "0" + DELIM + "application/x-test" + DELIM + "Test mimetype" + + DELIM + "tst" + DELIM + "$\n"; + + registry += "\n"; + registry += "[INVALID]\n"; + registry += "\n"; + write_registry("0.15", registry); + + // Initialise profile folder + do_get_profile(); + + var plugin = get_test_plugintag(); + if (!plugin) + do_throw("Plugin tag not found"); + + // The plugin registry should have been rejected. + // If not, the test plugin version would be 0.0.0.0 + do_check_eq(plugin.version, "1.0.0.0"); + + // Clean up + Services.prefs.clearUserPref("plugin.importedState"); +} diff --git a/dom/plugins/test/unit/test_bug854467.js b/dom/plugins/test/unit/test_bug854467.js new file mode 100644 index 0000000000..0487dffc65 --- /dev/null +++ b/dom/plugins/test/unit/test_bug854467.js @@ -0,0 +1,40 @@ +/* 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/. + */ + +function check_state(aTag, aExpectedClicktoplay, aExpectedDisabled) { + do_check_eq(aTag.clicktoplay, aExpectedClicktoplay); + do_check_eq(aTag.disabled, aExpectedDisabled); +} + +function run_test() { + allow_all_plugins(); + let tag = get_test_plugintag(); + tag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; + check_state(tag, false, false); + + /* test going to click-to-play from always enabled and back */ + tag.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; + check_state(tag, true, false); + tag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; + check_state(tag, false, false); + + /* test going to disabled from always enabled and back */ + tag.enabledState = Ci.nsIPluginTag.STATE_DISABLED; + check_state(tag, false, true); + tag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; + check_state(tag, false, false); + + /* test going to click-to-play from disabled and back */ + tag.enabledState = Ci.nsIPluginTag.STATE_DISABLED; + check_state(tag, false, true); + tag.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY; + check_state(tag, true, false); + tag.enabledState = Ci.nsIPluginTag.STATE_DISABLED; + check_state(tag, false, true); + + /* put everything back to normal and check that that succeeded */ + tag.enabledState = Ci.nsIPluginTag.STATE_ENABLED; + check_state(tag, false, false); +} diff --git a/dom/plugins/test/unit/test_nice_plugin_name.js b/dom/plugins/test/unit/test_nice_plugin_name.js new file mode 100644 index 0000000000..32d2870af0 --- /dev/null +++ b/dom/plugins/test/unit/test_nice_plugin_name.js @@ -0,0 +1,80 @@ +/* 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/. + */ + +const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1"; +const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}"); + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +var gAppInfo = null; + +function createAppInfo(ID, name, version, platformVersion="1.0") { + let tmp = {}; + Cu.import("resource://testing-common/AppInfo.jsm", tmp); + tmp.updateAppInfo({ + ID, name, version, platformVersion, + crashReporter: true + }); + gAppInfo = tmp.getAppInfo(); +} + +var gPluginHost = null; + +function test_expected_permission_string(aPermString) { + gPluginHost.reloadPlugins(false); + let plugin = get_test_plugintag(); + do_check_false(plugin == null); + do_check_eq(gPluginHost.getPermissionStringForType("application/x-test"), + aPermString); +} + +function run_test() { + allow_all_plugins(); + do_check_true(gIsWindows || gIsOSX || gIsLinux); + do_check_true(!(gIsWindows && gIsOSX) && !(gIsWindows && gIsLinux) && + !(gIsOSX && gIsLinux)); + + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9"); + gPluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); + + let expectedDefaultPermissionString = null; + if (gIsWindows) expectedDefaultPermissionString = "plugin:nptest"; + if (gIsOSX) expectedDefaultPermissionString = "plugin:test"; + if (gIsLinux) expectedDefaultPermissionString = "plugin:libnptest"; + test_expected_permission_string(expectedDefaultPermissionString); + + let suffix = get_platform_specific_plugin_suffix(); + let pluginFile = get_test_plugin_no_symlink(); + let pluginDir = pluginFile.parent; + pluginFile.copyTo(null, "npblah235" + suffix); + let pluginCopy = pluginDir.clone(); + pluginCopy.append("npblah235" + suffix); + let tempDir = do_get_tempdir(); + pluginFile.moveTo(tempDir, null); + test_expected_permission_string("plugin:npblah"); + + pluginCopy.moveTo(null, "npasdf-3.2.2" + suffix); + test_expected_permission_string("plugin:npasdf"); + + pluginCopy.moveTo(null, "npasdf_##29387!{}{[][" + suffix); + test_expected_permission_string("plugin:npasdf"); + + pluginCopy.moveTo(null, "npqtplugin7" + suffix); + test_expected_permission_string("plugin:npqtplugin"); + + pluginCopy.moveTo(null, "npFoo3d" + suffix); + test_expected_permission_string("plugin:npfoo3d"); + + pluginCopy.moveTo(null, "NPSWF32_11_5_502_146" + suffix); + test_expected_permission_string("plugin:npswf"); + + pluginCopy.remove(true); + pluginFile.moveTo(pluginDir, null); + test_expected_permission_string(expectedDefaultPermissionString); + + // Clean up + Services.prefs.clearUserPref("plugin.importedState"); +} diff --git a/dom/plugins/test/unit/test_persist_in_prefs.js b/dom/plugins/test/unit/test_persist_in_prefs.js new file mode 100644 index 0000000000..ede0074d39 --- /dev/null +++ b/dom/plugins/test/unit/test_persist_in_prefs.js @@ -0,0 +1,76 @@ +/* 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/. + */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +// Plugin registry uses different field delimeters on different platforms +var DELIM = mozinfo.os == "win" ? "|" : ":"; + +var gProfD = do_get_profile_startup(); + +function run_test() { + allow_all_plugins(); + + do_check_true(gIsWindows || gIsOSX || gIsLinux); + + let file = get_test_plugin_no_symlink(); + if (!file) + do_throw("Plugin library not found"); + + const pluginDir = file.parent; + const tempDir = do_get_tempdir(); + const suffix = get_platform_specific_plugin_suffix(); + const pluginName = file.leafName.substring(0, file.leafName.length - suffix.length).toLowerCase(); + const pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); + const statePref = "plugin.state." + pluginName; + + // Initialise profile folder + do_get_profile(); + + let plugin = get_test_plugintag(); + if (!plugin) + do_throw("Plugin tag not found"); + + plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED; + + // prepare a copy of the plugin and backup the original + file.copyTo(null, "nptestcopy" + suffix); + let copy = pluginDir.clone(); + copy.append("nptestcopy" + suffix); + file.moveTo(tempDir, null); + + // test that the settings persist through a few variations of test-plugin names + let testNames = [ + pluginName + "2", + pluginName.toUpperCase() + "_11_5_42_2323", + pluginName + "-5.2.7" + ]; + testNames.forEach(function(leafName) { + dump("Checking " + leafName + ".\n"); + copy.moveTo(null, leafName + suffix); + pluginHost.reloadPlugins(false); + plugin = get_test_plugintag(); + do_check_false(plugin == null); + do_check_true(plugin.disabled); + do_check_false(plugin.clicktoplay); + }); + + // check that the state persists even if the plugin is not always present + copy.moveTo(tempDir, null); + pluginHost.reloadPlugins(false); + copy.moveTo(pluginDir, null); + pluginHost.reloadPlugins(false); + + plugin = get_test_plugintag(); + do_check_false(plugin == null); + do_check_true(plugin.disabled); + do_check_false(plugin.clicktoplay); + + // clean up + Services.prefs.clearUserPref(statePref); + Services.prefs.clearUserPref("plugin.importedState"); + copy.remove(true); + file.moveTo(pluginDir, null); +} diff --git a/dom/plugins/test/unit/test_plugin_default_state.js b/dom/plugins/test/unit/test_plugin_default_state.js new file mode 100644 index 0000000000..cb68c61e7e --- /dev/null +++ b/dom/plugins/test/unit/test_plugin_default_state.js @@ -0,0 +1,31 @@ +Components.utils.import("resource://gre/modules/Services.jsm"); + +function run_test() { + allow_all_plugins(); + let pluginDefaultState = Services.prefs.getIntPref("plugin.default.state"); + // if this fails, we just have to switch around the values we're testing + do_check_neq(pluginDefaultState, Ci.nsIPluginTag.STATE_DISABLED); + let nonDefaultState = (pluginDefaultState != Ci.nsIPluginTag.STATE_ENABLED ? + Ci.nsIPluginTag.STATE_ENABLED : + Ci.nsIPluginTag.STATE_CLICKTOPLAY); + let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); + let testPlugin = get_test_plugintag(); + // the test plugin should have the default enabledState + do_check_eq(testPlugin.enabledState, pluginDefaultState); + + let secondTestPlugin = get_test_plugintag("Second Test Plug-in"); + // set an enabledState for the second test plugin + secondTestPlugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED; + // change what the default enabledState is + Services.prefs.setIntPref("plugin.default.state", nonDefaultState); + // the test plugin should follow the default (it has no individual pref yet) + do_check_eq(testPlugin.enabledState, nonDefaultState); + // the second test plugin should retain its preferred state + do_check_eq(secondTestPlugin.enabledState, Ci.nsIPluginTag.STATE_DISABLED); + + // clean up + testPlugin.enabledState = pluginDefaultState; + secondTestPlugin.enabledState = pluginDefaultState; + Services.prefs.clearUserPref("plugin.default.state"); + Services.prefs.clearUserPref("plugin.importedState"); +} diff --git a/dom/plugins/test/unit/test_plugin_default_state_xpi.js b/dom/plugins/test/unit/test_plugin_default_state_xpi.js new file mode 100644 index 0000000000..f1aeb3ac9e --- /dev/null +++ b/dom/plugins/test/unit/test_plugin_default_state_xpi.js @@ -0,0 +1,118 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/Promise.jsm"); + +const ADDON_ID = "test-plugin-from-xpi@tests.mozilla.org"; +const XRE_EXTENSIONS_DIR_LIST = "XREExtDL"; +const NS_APP_PLUGINS_DIR_LIST = "APluginsDL"; + +const gPluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); +const gXPCOMABI = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).XPCOMABI; +var gProfileDir = null; + +function getAddonRoot(profileDir, id) { + let dir = profileDir.clone(); + dir.append("extensions"); + Assert.ok(dir.exists(), "Extensions dir should exist: " + dir.path); + dir.append(id); + return dir; +} + +function getTestaddonFilename() { + let abiPart = ""; + if (gIsOSX) { + abiPart = "_" + gXPCOMABI; + } + return "testaddon" + abiPart + ".xpi"; +} + +function run_test() { + allow_all_plugins(); + loadAddonManager(); + gProfileDir = do_get_profile(); + do_register_cleanup(() => shutdownManager()); + run_next_test(); +} + +add_task(function* test_state() { + // Remove test so we will have only one "Test Plug-in" registered. + // xpcshell tests have plugins in per-test profiles, so that's fine. + let file = get_test_plugin(); + file.remove(true); + file = get_test_plugin(true); + file.remove(true); + + Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_CLICKTOPLAY); + Services.prefs.setIntPref("plugin.defaultXpi.state", Ci.nsIPluginTag.STATE_ENABLED); + + let success = yield installAddon(getTestaddonFilename()); + Assert.ok(success, "Should have installed addon."); + let addonDir = getAddonRoot(gProfileDir, ADDON_ID); + + let provider = { + classID: Components.ID("{0af6b2d7-a06c-49b7-babc-636d292b0dbb}"), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider, + Ci.nsIDirectoryServiceProvider2]), + + getFile: function (prop, persistant) { + throw Cr.NS_ERROR_FAILURE; + }, + + getFiles: function (prop) { + let result = []; + + switch (prop) { + case XRE_EXTENSIONS_DIR_LIST: + result.push(addonDir); + break; + case NS_APP_PLUGINS_DIR_LIST: + let pluginDir = addonDir.clone(); + pluginDir.append("plugins"); + result.push(pluginDir); + break; + default: + throw Cr.NS_ERROR_FAILURE; + } + + return { + QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), + hasMoreElements: () => result.length > 0, + getNext: () => result.shift(), + }; + }, + }; + + let dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); + dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider); + + // We installed a non-restartless addon, need to restart the manager. + restartManager(); + gPluginHost.reloadPlugins(); + + Assert.ok(addonDir.exists(), "Addon path should exist: " + addonDir.path); + Assert.ok(addonDir.isDirectory(), "Addon path should be a directory: " + addonDir.path); + let pluginDir = addonDir.clone(); + pluginDir.append("plugins"); + Assert.ok(pluginDir.exists(), "Addon plugins path should exist: " + pluginDir.path); + Assert.ok(pluginDir.isDirectory(), "Addon plugins path should be a directory: " + pluginDir.path); + + let addon = yield getAddonByID(ADDON_ID); + Assert.ok(!addon.appDisabled, "Addon should not be appDisabled"); + Assert.ok(addon.isActive, "Addon should be active"); + Assert.ok(addon.isCompatible, "Addon should be compatible"); + Assert.ok(!addon.userDisabled, "Addon should not be user disabled"); + + let testPlugin = get_test_plugintag(); + Assert.notEqual(testPlugin, null, "Test plugin should have been found"); + Assert.equal(testPlugin.enabledState, Ci.nsIPluginTag.STATE_ENABLED, "Test plugin from addon should have state enabled"); + + pluginDir.append(testPlugin.filename); + Assert.ok(pluginDir.exists(), "Plugin file should exist in addon directory: " + pluginDir.path); + + testPlugin = get_test_plugintag("Second Test Plug-in"); + Assert.notEqual(testPlugin, null, "Second test plugin should have been found"); + Assert.equal(testPlugin.enabledState, Ci.nsIPluginTag.STATE_ENABLED, "Second test plugin from addon should have state enabled"); +}); diff --git a/dom/plugins/test/unit/xpcshell.ini b/dom/plugins/test/unit/xpcshell.ini new file mode 100644 index 0000000000..8dae66b208 --- /dev/null +++ b/dom/plugins/test/unit/xpcshell.ini @@ -0,0 +1,29 @@ +[DEFAULT] +skip-if = toolkit == 'android' +head = head_plugins.js +tail = +tags = addons +firefox-appdir = browser +support-files = + !/toolkit/mozapps/extensions/test/xpcshell/head_addons.js + +[test_allowed_types.js] +skip-if = appname == "thunderbird" +reason = plugins are disabled by default in Thunderbird +[test_bug471245.js] +# Bug 676953: test fails consistently on Android +fail-if = os == "android" +[test_bug813245.js] +# Bug 676953: test fails consistently on Android +fail-if = os == "android" +[test_nice_plugin_name.js] +# Bug 676953: test fails consistently on Android +fail-if = os == "android" +[test_persist_in_prefs.js] +skip-if = appname == "thunderbird" +reason = plugins are disabled by default in Thunderbird +[test_bug854467.js] +[test_plugin_default_state.js] +skip-if = appname == "thunderbird" +reason = plugins are disabled by default in Thunderbird +[test_plugin_default_state_xpi.js] -- cgit v1.2.3