diff --git a/CLOBBER b/CLOBBER index d788c5f8a68..864c1c57542 100644 --- a/CLOBBER +++ b/CLOBBER @@ -22,4 +22,4 @@ # changes to stick? As of bug 928195, this shouldn't be necessary! Please # don't change CLOBBER for WebIDL changes any more. -Bug 1178892 requires clobber for profiler file moves. +Bug 1178850 requires clobber for Android JNI header changes diff --git a/b2g/config/mozconfigs/common.override b/b2g/config/mozconfigs/common.override index b94b773c003..abe73b4605d 100644 --- a/b2g/config/mozconfigs/common.override +++ b/b2g/config/mozconfigs/common.override @@ -5,3 +5,4 @@ # This file is included at the bottom of all b2g mozconfigs . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/b2g/config/mozconfigs/ics_armv7a_gecko/debug b/b2g/config/mozconfigs/ics_armv7a_gecko/debug index 494df42c02b..1cacb8a7551 100644 --- a/b2g/config/mozconfigs/ics_armv7a_gecko/debug +++ b/b2g/config/mozconfigs/ics_armv7a_gecko/debug @@ -12,7 +12,6 @@ export GONK_PRODUCT=generic ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-" ac_add_options --enable-debug-symbols ac_add_options --enable-debug -#. "$topsrcdir/build/mozconfig.cache" ENABLE_MARIONETTE=1 # Enable dump() from JS. diff --git a/b2g/config/mozconfigs/ics_armv7a_gecko/nightly b/b2g/config/mozconfigs/ics_armv7a_gecko/nightly index ece18271d8a..c2f1ae0fa99 100644 --- a/b2g/config/mozconfigs/ics_armv7a_gecko/nightly +++ b/b2g/config/mozconfigs/ics_armv7a_gecko/nightly @@ -13,7 +13,6 @@ export GONK_PRODUCT=generic ac_add_options --with-gonk-toolchain-prefix="$topsrcdir/gonk-toolchain/prebuilt/$TOOLCHAIN_HOST/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-" ac_add_options --enable-debug-symbols # ac_add_options --enable-profiling -#. "$topsrcdir/build/mozconfig.cache" ENABLE_MARIONETTE=1 # Enable dump() from JS. diff --git a/b2g/config/mozconfigs/linux32_gecko/debug b/b2g/config/mozconfigs/linux32_gecko/debug index ec6476cd27f..917f4a5f09a 100644 --- a/b2g/config/mozconfigs/linux32_gecko/debug +++ b/b2g/config/mozconfigs/linux32_gecko/debug @@ -9,9 +9,6 @@ ac_add_options --enable-update-packaging ac_add_options --enable-signmar ac_add_options --enable-debug -# Nightlies only since this has a cost in performance -#ac_add_options --enable-js-diagnostics - # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. @@ -27,7 +24,6 @@ ac_add_options --enable-warnings-as-errors # Use sccache no_sccache= -. "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g diff --git a/b2g/config/mozconfigs/linux32_gecko/nightly b/b2g/config/mozconfigs/linux32_gecko/nightly index 7b38c318933..8f41f9609f5 100644 --- a/b2g/config/mozconfigs/linux32_gecko/nightly +++ b/b2g/config/mozconfigs/linux32_gecko/nightly @@ -9,9 +9,6 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-signmar -# Nightlies only since this has a cost in performance -#ac_add_options --enable-js-diagnostics - # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. @@ -27,7 +24,6 @@ ac_add_options --enable-warnings-as-errors # Use sccache no_sccache= -. "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g diff --git a/b2g/config/mozconfigs/linux64_gecko/debug b/b2g/config/mozconfigs/linux64_gecko/debug index 31b818e15d9..4fa78e29e11 100644 --- a/b2g/config/mozconfigs/linux64_gecko/debug +++ b/b2g/config/mozconfigs/linux64_gecko/debug @@ -9,9 +9,6 @@ ac_add_options --enable-update-packaging ac_add_options --enable-signmar ac_add_options --enable-debug -# Nightlies only since this has a cost in performance -#ac_add_options --enable-js-diagnostics - # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. @@ -27,7 +24,6 @@ ac_add_options --enable-warnings-as-errors # Use sccache no_sccache= -. "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g diff --git a/b2g/config/mozconfigs/linux64_gecko/nightly b/b2g/config/mozconfigs/linux64_gecko/nightly index f098f711065..25fd0e75689 100644 --- a/b2g/config/mozconfigs/linux64_gecko/nightly +++ b/b2g/config/mozconfigs/linux64_gecko/nightly @@ -9,9 +9,6 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-signmar -# Nightlies only since this has a cost in performance -#ac_add_options --enable-js-diagnostics - # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. @@ -27,7 +24,6 @@ ac_add_options --enable-warnings-as-errors # Use sccache no_sccache= -. "$topsrcdir/build/mozconfig.cache" #B2G options ac_add_options --enable-application=b2g diff --git a/b2g/config/mozconfigs/macosx64_gecko/debug b/b2g/config/mozconfigs/macosx64_gecko/debug index 876475decf4..a3d19eb395c 100644 --- a/b2g/config/mozconfigs/macosx64_gecko/debug +++ b/b2g/config/mozconfigs/macosx64_gecko/debug @@ -11,9 +11,6 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-signmar -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 diff --git a/b2g/config/mozconfigs/macosx64_gecko/nightly b/b2g/config/mozconfigs/macosx64_gecko/nightly index 05eb3c9e877..a1b5b061a07 100644 --- a/b2g/config/mozconfigs/macosx64_gecko/nightly +++ b/b2g/config/mozconfigs/macosx64_gecko/nightly @@ -12,9 +12,6 @@ ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --enable-signmar -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 diff --git a/b2g/config/mozconfigs/win32_gecko/debug b/b2g/config/mozconfigs/win32_gecko/debug index fc12dc7bcd1..e67d627e2fe 100644 --- a/b2g/config/mozconfigs/win32_gecko/debug +++ b/b2g/config/mozconfigs/win32_gecko/debug @@ -9,9 +9,6 @@ ac_add_options --enable-jemalloc ac_add_options --enable-signmar ac_add_options --enable-debug -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 diff --git a/b2g/config/mozconfigs/win32_gecko/nightly b/b2g/config/mozconfigs/win32_gecko/nightly index 7fc27a5f831..9bb1203ae91 100644 --- a/b2g/config/mozconfigs/win32_gecko/nightly +++ b/b2g/config/mozconfigs/win32_gecko/nightly @@ -9,9 +9,6 @@ ac_add_options --enable-update-packaging ac_add_options --enable-jemalloc ac_add_options --enable-signmar -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 diff --git a/b2g/config/tooltool-manifests/linux32/releng.manifest b/b2g/config/tooltool-manifests/linux32/releng.manifest index 174251d80bf..4b9f7ad4ed1 100644 --- a/b2g/config/tooltool-manifests/linux32/releng.manifest +++ b/b2g/config/tooltool-manifests/linux32/releng.manifest @@ -1,28 +1,23 @@ [ { -"size": 51, -"digest": "c8e40edb314eeabfb92c77cf5ff9a7857033f15dd65a00349bcf9e3e5b75624afc71f733b2ff7e029c20a78313038409c2bd022bf7e5a7e0c487fc2c2d640986", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", -"unpack": "True" +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true }, { "size": 31057326, "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", "algorithm": "sha512", "filename": "moztt.tar.bz2", -"unpack": "True" +"unpack": true } ] diff --git a/b2g/config/tooltool-manifests/linux64/releng.manifest b/b2g/config/tooltool-manifests/linux64/releng.manifest index 174251d80bf..4b9f7ad4ed1 100644 --- a/b2g/config/tooltool-manifests/linux64/releng.manifest +++ b/b2g/config/tooltool-manifests/linux64/releng.manifest @@ -1,28 +1,23 @@ [ { -"size": 51, -"digest": "c8e40edb314eeabfb92c77cf5ff9a7857033f15dd65a00349bcf9e3e5b75624afc71f733b2ff7e029c20a78313038409c2bd022bf7e5a7e0c487fc2c2d640986", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", -"unpack": "True" +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true }, { "size": 31057326, "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", "algorithm": "sha512", "filename": "moztt.tar.bz2", -"unpack": "True" +"unpack": true } ] diff --git a/b2g/config/tooltool-manifests/macosx64/releng.manifest b/b2g/config/tooltool-manifests/macosx64/releng.manifest index 5e1cdaf2561..0867e800a5c 100644 --- a/b2g/config/tooltool-manifests/macosx64/releng.manifest +++ b/b2g/config/tooltool-manifests/macosx64/releng.manifest @@ -3,28 +3,24 @@ "clang_version": "r183744" }, { -"size": 88, -"digest": "0d2ae9bcd7cea34ec0b768270725e98410dbb3bc150c7381e0dcf3eb5dbb3e69ac76dbb0f46b056151d6a6fa8681cab06da68173ae8598f3397b8f7628e67381", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 59602619, "digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true }, { "size": 31057326, "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", "algorithm": "sha512", "filename": "moztt.tar.bz2", -"unpack": "True" +"unpack": true } ] diff --git a/b2g/config/tooltool-manifests/win32/releng.manifest b/b2g/config/tooltool-manifests/win32/releng.manifest index b0768e4bd55..8cbd9fcee38 100644 --- a/b2g/config/tooltool-manifests/win32/releng.manifest +++ b/b2g/config/tooltool-manifests/win32/releng.manifest @@ -10,6 +10,13 @@ "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", "algorithm": "sha512", "filename": "moztt.tar.bz2", -"unpack": "True" +"unpack": true +}, +{ +"size": 167175, +"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", +"algorithm": "sha512", +"filename": "sccache.tar.bz2", +"unpack": true } ] diff --git a/b2g/dev/config/mozconfigs/macosx64/mulet b/b2g/dev/config/mozconfigs/macosx64/mulet index 2d459a23278..93bbf41eebd 100644 --- a/b2g/dev/config/mozconfigs/macosx64/mulet +++ b/b2g/dev/config/mozconfigs/macosx64/mulet @@ -12,9 +12,6 @@ ac_add_options --enable-profiling ac_add_options --enable-instruments ac_add_options --enable-dtrace -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 @@ -30,3 +27,4 @@ export MOZ_PACKAGE_JSSHELL=1 MOZTTDIR=$topsrcdir/moztt . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/b2g/dev/config/tooltool-manifests/linux64/releng.manifest b/b2g/dev/config/tooltool-manifests/linux64/releng.manifest index aee1d62d60f..4b9f7ad4ed1 100644 --- a/b2g/dev/config/tooltool-manifests/linux64/releng.manifest +++ b/b2g/dev/config/tooltool-manifests/linux64/releng.manifest @@ -1,27 +1,23 @@ [ { -"size": 82, -"digest": "70a6126249e40aa1da32248bf6bfe45e0d8c87334579ec0cf69403e61b635e27c766d9bf08d530978286552f158ee24c74b0168a57cc6b734dcfed4fc5e09cff", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", -"filename": "gcc.tar.xz" +"filename": "gcc.tar.xz", +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true }, { "size": 31057326, "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", "algorithm": "sha512", "filename": "moztt.tar.bz2", -"unpack": "True" +"unpack": true } ] diff --git a/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest b/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest index 5e1cdaf2561..0867e800a5c 100644 --- a/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest +++ b/b2g/dev/config/tooltool-manifests/macosx64/releng.manifest @@ -3,28 +3,24 @@ "clang_version": "r183744" }, { -"size": 88, -"digest": "0d2ae9bcd7cea34ec0b768270725e98410dbb3bc150c7381e0dcf3eb5dbb3e69ac76dbb0f46b056151d6a6fa8681cab06da68173ae8598f3397b8f7628e67381", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 59602619, "digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true }, { "size": 31057326, "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", "algorithm": "sha512", "filename": "moztt.tar.bz2", -"unpack": "True" +"unpack": true } ] diff --git a/b2g/dev/config/tooltool-manifests/win32/releng.manifest b/b2g/dev/config/tooltool-manifests/win32/releng.manifest index cbd38cec879..a01b7781244 100644 --- a/b2g/dev/config/tooltool-manifests/win32/releng.manifest +++ b/b2g/dev/config/tooltool-manifests/win32/releng.manifest @@ -6,22 +6,17 @@ "filename": "mozmake.exe" }, { -"size": 51, -"digest": "c8e40edb314eeabfb92c77cf5ff9a7857033f15dd65a00349bcf9e3e5b75624afc71f733b2ff7e029c20a78313038409c2bd022bf7e5a7e0c487fc2c2d640986", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true }, { "size": 31057326, "digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51", "algorithm": "sha512", "filename": "moztt.tar.bz2", -"unpack": "True" +"unpack": true } ] diff --git a/browser/config/mozconfigs/linux32/debug b/browser/config/mozconfigs/linux32/debug index 97d6210b236..a8f90546f30 100644 --- a/browser/config/mozconfigs/linux32/debug +++ b/browser/config/mozconfigs/linux32/debug @@ -11,7 +11,6 @@ MOZ_AUTOMATION_L10N_CHECK=0 export MOZILLA_OFFICIAL=1 #Use ccache -. "$topsrcdir/build/mozconfig.cache" # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors @@ -22,3 +21,4 @@ export MOZ_PACKAGE_JSSHELL=1 ac_add_options --with-branding=browser/branding/nightly . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/linux32/nightly b/browser/config/mozconfigs/linux32/nightly index 3fe67cbe2fc..05ab10e63b3 100644 --- a/browser/config/mozconfigs/linux32/nightly +++ b/browser/config/mozconfigs/linux32/nightly @@ -3,9 +3,6 @@ ac_add_options --enable-signmar ac_add_options --enable-profiling -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. @@ -13,7 +10,5 @@ STRIP_FLAGS="--strip-debug" ac_add_options --with-branding=browser/branding/nightly -# Use ccache -. "$topsrcdir/build/mozconfig.cache" - . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/linux64/debug b/browser/config/mozconfigs/linux64/debug index 8f1f458ff21..ef5aa0dc549 100644 --- a/browser/config/mozconfigs/linux64/debug +++ b/browser/config/mozconfigs/linux64/debug @@ -10,9 +10,6 @@ MOZ_AUTOMATION_L10N_CHECK=0 # Needed to enable breakpad in application.ini export MOZILLA_OFFICIAL=1 -# Use ccache -. "$topsrcdir/build/mozconfig.cache" - # Treat warnings as errors in directories with FAIL_ON_WARNINGS. ac_add_options --enable-warnings-as-errors @@ -22,3 +19,4 @@ export MOZ_PACKAGE_JSSHELL=1 ac_add_options --with-branding=browser/branding/nightly . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/linux64/nightly b/browser/config/mozconfigs/linux64/nightly index 6f7812f131c..b6b9c998527 100644 --- a/browser/config/mozconfigs/linux64/nightly +++ b/browser/config/mozconfigs/linux64/nightly @@ -3,9 +3,6 @@ ac_add_options --enable-signmar ac_add_options --enable-profiling -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - # This will overwrite the default of stripping everything and keep the symbol table. # This is useful for profiling and debugging and only increases the package size # by 2 MBs. @@ -13,7 +10,5 @@ STRIP_FLAGS="--strip-debug" ac_add_options --with-branding=browser/branding/nightly -# Use ccache -. "$topsrcdir/build/mozconfig.cache" - . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx-universal/beta b/browser/config/mozconfigs/macosx-universal/beta index cc2f44d0ef0..80c77b484d0 100644 --- a/browser/config/mozconfigs/macosx-universal/beta +++ b/browser/config/mozconfigs/macosx-universal/beta @@ -3,3 +3,4 @@ ac_add_options --enable-official-branding . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx-universal/l10n-mozconfig b/browser/config/mozconfigs/macosx-universal/l10n-mozconfig index dd400d2b64f..a9ff62c8eed 100644 --- a/browser/config/mozconfigs/macosx-universal/l10n-mozconfig +++ b/browser/config/mozconfigs/macosx-universal/l10n-mozconfig @@ -10,8 +10,7 @@ if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then ac_add_options --with-macbundlename-prefix=Firefox fi -. "$topsrcdir/build/mozconfig.cache" - export MOZILLA_OFFICIAL=1 . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx-universal/nightly b/browser/config/mozconfigs/macosx-universal/nightly index 33fdfa98dc5..19cf57cce91 100644 --- a/browser/config/mozconfigs/macosx-universal/nightly +++ b/browser/config/mozconfigs/macosx-universal/nightly @@ -6,9 +6,6 @@ ac_add_options --enable-profiling ac_add_options --enable-instruments ac_add_options --enable-dtrace -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - if test "${MOZ_UPDATE_CHANNEL}" = "nightly"; then ac_add_options --with-macbundlename-prefix=Firefox fi @@ -16,3 +13,4 @@ fi ac_add_options --with-branding=browser/branding/nightly . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx-universal/release b/browser/config/mozconfigs/macosx-universal/release index ab8a4698c96..d5e493341ac 100644 --- a/browser/config/mozconfigs/macosx-universal/release +++ b/browser/config/mozconfigs/macosx-universal/release @@ -9,3 +9,4 @@ ac_add_options --enable-official-branding export BUILDING_RELEASE=1 . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx64/debug b/browser/config/mozconfigs/macosx64/debug index 148c1909913..bf387ff0755 100644 --- a/browser/config/mozconfigs/macosx64/debug +++ b/browser/config/mozconfigs/macosx64/debug @@ -21,3 +21,4 @@ export MOZ_PACKAGE_JSSHELL=1 ac_add_options --with-branding=browser/branding/nightly . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx64/debug-static-analysis b/browser/config/mozconfigs/macosx64/debug-static-analysis index d451e78c99a..d55de955908 100644 --- a/browser/config/mozconfigs/macosx64/debug-static-analysis +++ b/browser/config/mozconfigs/macosx64/debug-static-analysis @@ -13,3 +13,4 @@ ac_add_options --enable-warnings-as-errors ac_add_options --enable-clang-plugin . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx64/l10n-mozconfig b/browser/config/mozconfigs/macosx64/l10n-mozconfig index 7c15cb01997..952ab3da3dc 100644 --- a/browser/config/mozconfigs/macosx64/l10n-mozconfig +++ b/browser/config/mozconfigs/macosx64/l10n-mozconfig @@ -4,6 +4,6 @@ ac_add_options --with-l10n-base=../../l10n ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} ac_add_options --enable-update-packaging ac_add_options --with-branding=browser/branding/nightly -. "$topsrcdir/build/mozconfig.cache" . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/macosx64/nightly b/browser/config/mozconfigs/macosx64/nightly index 087a17d7740..ceb1ba33f22 100644 --- a/browser/config/mozconfigs/macosx64/nightly +++ b/browser/config/mozconfigs/macosx64/nightly @@ -19,3 +19,4 @@ export MOZ_PACKAGE_JSSHELL=1 ac_add_options --with-branding=browser/branding/nightly . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/whitelist b/browser/config/mozconfigs/whitelist index db3c5a1ce91..8e41fe6c5e0 100644 --- a/browser/config/mozconfigs/whitelist +++ b/browser/config/mozconfigs/whitelist @@ -22,7 +22,6 @@ for platform in ['linux32', 'linux64', 'macosx-universal']: for platform in ['linux32', 'linux64', 'macosx-universal', 'win32', 'win64']: whitelist['nightly'][platform] += ['ac_add_options --enable-signmar'] - whitelist['nightly'][platform] += ['ac_add_options --enable-js-diagnostics'] whitelist['nightly']['linux32'] += [ 'CXX=$REAL_CXX', diff --git a/browser/config/mozconfigs/win32/debug b/browser/config/mozconfigs/win32/debug index 5eabdd8952a..118cb5256c0 100644 --- a/browser/config/mozconfigs/win32/debug +++ b/browser/config/mozconfigs/win32/debug @@ -28,6 +28,5 @@ export MOZ_PACKAGE_JSSHELL=1 ac_add_options --with-branding=browser/branding/nightly -. "$topsrcdir/build/mozconfig.cache" - . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/win32/nightly b/browser/config/mozconfigs/win32/nightly index 398478980ff..de440c2c7d5 100644 --- a/browser/config/mozconfigs/win32/nightly +++ b/browser/config/mozconfigs/win32/nightly @@ -4,11 +4,7 @@ ac_add_options --enable-signmar ac_add_options --enable-profiling -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - ac_add_options --with-branding=browser/branding/nightly -. "$topsrcdir/build/mozconfig.cache" - . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/win64/debug b/browser/config/mozconfigs/win64/debug index 40905ae9c9e..b22f1891011 100644 --- a/browser/config/mozconfigs/win64/debug +++ b/browser/config/mozconfigs/win64/debug @@ -30,6 +30,5 @@ ac_add_options --with-branding=browser/branding/nightly . $topsrcdir/build/win64/mozconfig.vs2013 -. "$topsrcdir/build/mozconfig.cache" - . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/mozconfigs/win64/nightly b/browser/config/mozconfigs/win64/nightly index 9464437b316..76054cf5e7d 100644 --- a/browser/config/mozconfigs/win64/nightly +++ b/browser/config/mozconfigs/win64/nightly @@ -5,11 +5,7 @@ ac_add_options --enable-signmar ac_add_options --enable-profiling -# Nightlies only since this has a cost in performance -ac_add_options --enable-js-diagnostics - ac_add_options --with-branding=browser/branding/nightly -. "$topsrcdir/build/mozconfig.cache" - . "$topsrcdir/build/mozconfig.common.override" +. "$topsrcdir/build/mozconfig.cache" diff --git a/browser/config/tooltool-manifests/linux32/asan.manifest b/browser/config/tooltool-manifests/linux32/asan.manifest index 304afbc1345..87ce925a9bd 100644 --- a/browser/config/tooltool-manifests/linux32/asan.manifest +++ b/browser/config/tooltool-manifests/linux32/asan.manifest @@ -3,15 +3,10 @@ "clang_version": "r185949" }, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 72573411, "digest": "491753968f34d1bd3c58280688349499a92f31a118eb6f28e86746be62615004370394b8e1b10d48dc3fba4bc6d4fbb4ce6c7dbc4fadb39447de9aa55573c58e", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/linux32/clang.manifest b/browser/config/tooltool-manifests/linux32/clang.manifest index 7685c443f07..6d75f637c11 100644 --- a/browser/config/tooltool-manifests/linux32/clang.manifest +++ b/browser/config/tooltool-manifests/linux32/clang.manifest @@ -3,15 +3,10 @@ "clang_version": "r183744" }, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 70206124, "digest": "a6b8046bd9485f9387dcb1c14b8d442822f02b1caa61b653e8b6cfd96906deadfb4b29809f2cd2b71f919b321d97dd2ebec6020c15f6d485f1641c0f710a762f", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true, } ] diff --git a/browser/config/tooltool-manifests/linux32/releng.manifest b/browser/config/tooltool-manifests/linux32/releng.manifest index a419d505fa0..80c50dfaea9 100644 --- a/browser/config/tooltool-manifests/linux32/releng.manifest +++ b/browser/config/tooltool-manifests/linux32/releng.manifest @@ -1,20 +1,16 @@ [ { -"size": 82, -"digest": "70a6126249e40aa1da32248bf6bfe45e0d8c87334579ec0cf69403e61b635e27c766d9bf08d530978286552f158ee24c74b0168a57cc6b734dcfed4fc5e09cff", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", -"filename": "gcc.tar.xz" +"filename": "gcc.tar.xz", +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/linux64/asan.manifest b/browser/config/tooltool-manifests/linux64/asan.manifest index bf0aee6fe6d..820177316a8 100644 --- a/browser/config/tooltool-manifests/linux64/asan.manifest +++ b/browser/config/tooltool-manifests/linux64/asan.manifest @@ -3,15 +3,10 @@ "clang_version": "r200213" }, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 71282740, "digest": "ee9edb1ef3afd9ab29e39565145545ad57e8d8d2538be4d822d7dbd64038f4529b0b287cecf48bf83def52a26ac2c6faa331686c3ad5e8b4ba4c22686ee0808f", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/linux64/clang.manifest b/browser/config/tooltool-manifests/linux64/clang.manifest index 05bb628280e..2bad4b994b9 100644 --- a/browser/config/tooltool-manifests/linux64/clang.manifest +++ b/browser/config/tooltool-manifests/linux64/clang.manifest @@ -3,15 +3,10 @@ "clang_version": "r183744" }, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 70350828, "digest": "6cd04e8ec44c6fef159349c22bd0476891e4a2d46479f9586283eaf3305e42f79c720d40dfec0e78d8899c1651189b12e285de60862ffd0612b0dac7a0c336c6", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/linux64/releng.manifest b/browser/config/tooltool-manifests/linux64/releng.manifest index a419d505fa0..80c50dfaea9 100644 --- a/browser/config/tooltool-manifests/linux64/releng.manifest +++ b/browser/config/tooltool-manifests/linux64/releng.manifest @@ -1,20 +1,16 @@ [ { -"size": 82, -"digest": "70a6126249e40aa1da32248bf6bfe45e0d8c87334579ec0cf69403e61b635e27c766d9bf08d530978286552f158ee24c74b0168a57cc6b734dcfed4fc5e09cff", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", -"filename": "gcc.tar.xz" +"filename": "gcc.tar.xz", +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/macosx64/asan.manifest b/browser/config/tooltool-manifests/macosx64/asan.manifest index e675b7de927..a9edd97de77 100644 --- a/browser/config/tooltool-manifests/macosx64/asan.manifest +++ b/browser/config/tooltool-manifests/macosx64/asan.manifest @@ -3,15 +3,10 @@ "clang_version": "r200213" }, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 58997296, "digest": "9757d142142442c881b8d1eb31c2fe80e1979a858e6133473b5574a5a3b9cdaf9abed32b2e246b715c9f0eb0969103337918215fc491feae196219e8fb03f0b1", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/macosx64/clang.manifest b/browser/config/tooltool-manifests/macosx64/clang.manifest index c4e4a942cc5..aa1ef98af6c 100644 --- a/browser/config/tooltool-manifests/macosx64/clang.manifest +++ b/browser/config/tooltool-manifests/macosx64/clang.manifest @@ -3,21 +3,17 @@ "clang_version": "r183744" }, { -"size": 88, -"digest": "0d2ae9bcd7cea34ec0b768270725e98410dbb3bc150c7381e0dcf3eb5dbb3e69ac76dbb0f46b056151d6a6fa8681cab06da68173ae8598f3397b8f7628e67381", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 59602619, "digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/macosx64/releng.manifest b/browser/config/tooltool-manifests/macosx64/releng.manifest index c4e4a942cc5..aa1ef98af6c 100644 --- a/browser/config/tooltool-manifests/macosx64/releng.manifest +++ b/browser/config/tooltool-manifests/macosx64/releng.manifest @@ -3,21 +3,17 @@ "clang_version": "r183744" }, { -"size": 88, -"digest": "0d2ae9bcd7cea34ec0b768270725e98410dbb3bc150c7381e0dcf3eb5dbb3e69ac76dbb0f46b056151d6a6fa8681cab06da68173ae8598f3397b8f7628e67381", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 59602619, "digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"unpack": true }, { "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/win32/releng.manifest b/browser/config/tooltool-manifests/win32/releng.manifest index 726819f1678..6343fb6d816 100644 --- a/browser/config/tooltool-manifests/win32/releng.manifest +++ b/browser/config/tooltool-manifests/win32/releng.manifest @@ -6,15 +6,10 @@ "filename": "mozmake.exe" }, { -"size": 176, -"digest": "2809058907ac5eefdc394113d2e4fe76ba559ac61c2eca2f88e7a12a74bdf44a15d9039fa8aa229f7362a14b67d67395063f68147ae098beac5dfcc78aff98da", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true } ] diff --git a/browser/config/tooltool-manifests/win64/releng.manifest b/browser/config/tooltool-manifests/win64/releng.manifest index 726819f1678..6343fb6d816 100644 --- a/browser/config/tooltool-manifests/win64/releng.manifest +++ b/browser/config/tooltool-manifests/win64/releng.manifest @@ -6,15 +6,10 @@ "filename": "mozmake.exe" }, { -"size": 176, -"digest": "2809058907ac5eefdc394113d2e4fe76ba559ac61c2eca2f88e7a12a74bdf44a15d9039fa8aa229f7362a14b67d67395063f68147ae098beac5dfcc78aff98da", -"algorithm": "sha512", -"filename": "setup.sh" -}, -{ "size": 167175, "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831", "algorithm": "sha512", -"filename": "sccache.tar.bz2" +"filename": "sccache.tar.bz2", +"unpack": true } ] diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 42710fc079c..6c71497278a 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -436,7 +436,8 @@ @RESPATH@/components/addoncompat.manifest @RESPATH@/components/multiprocessShims.js @RESPATH@/components/defaultShims.js -@RESPATH@/components/remoteTagService.js +@RESPATH@/components/utils.manifest +@RESPATH@/components/simpleServices.js @RESPATH@/components/pluginGlue.manifest @RESPATH@/components/ProcessSingleton.manifest @RESPATH@/components/MainProcessSingleton.js @@ -888,6 +889,8 @@ bin/libfreebl_32int64_3.so @RESPATH@/components/DataStoreImpl.js @RESPATH@/components/dom_datastore.xpt +@RESPATH@/components/dom_audiochannel.xpt + ; Shutdown Terminator @RESPATH@/components/nsTerminatorTelemetry.js @RESPATH@/components/terminator.manifest diff --git a/build/annotationProcessors/AnnotationProcessor.java b/build/annotationProcessors/AnnotationProcessor.java index 1408891a1df..3c0d2c5e224 100644 --- a/build/annotationProcessors/AnnotationProcessor.java +++ b/build/annotationProcessors/AnnotationProcessor.java @@ -15,14 +15,15 @@ import java.util.Arrays; import java.util.Iterator; public class AnnotationProcessor { - public static final String OUTFILE = "GeneratedJNIWrappers.cpp"; - public static final String HEADERFILE = "GeneratedJNIWrappers.h"; + public static final String SOURCE_FILE = "GeneratedJNIWrappers.cpp"; + public static final String HEADER_FILE = "GeneratedJNIWrappers.h"; + public static final String NATIVES_FILE = "GeneratedJNINatives.h"; public static final String GENERATED_COMMENT = "// GENERATED CODE\n" + "// Generated by the Java program at /build/annotationProcessors at compile time\n" + "// from annotations on Java methods. To update, change the annotations on the\n" + - "// corresponding Javamethods and rerun the build. Manually updating this file\n" + + "// corresponding Java methods and rerun the build. Manually updating this file\n" + "// will cause your build to fail.\n" + "\n"; @@ -47,8 +48,8 @@ public class AnnotationProcessor { StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT); headerFile.append( - "#ifndef GeneratedJNIWrappers_h__\n" + - "#define GeneratedJNIWrappers_h__\n" + + "#ifndef " + getHeaderGuardName(HEADER_FILE) + "\n" + + "#define " + getHeaderGuardName(HEADER_FILE) + "\n" + "\n" + "#include \"mozilla/jni/Refs.h\"\n" + "\n" + @@ -65,6 +66,18 @@ public class AnnotationProcessor { "namespace widget {\n" + "\n"); + StringBuilder nativesFile = new StringBuilder(GENERATED_COMMENT); + nativesFile.append( + "#ifndef " + getHeaderGuardName(NATIVES_FILE) + "\n" + + "#define " + getHeaderGuardName(NATIVES_FILE) + "\n" + + "\n" + + "#include \"GeneratedJNIWrappers.h\"\n" + + "#include \"mozilla/jni/Natives.h\"\n" + + "\n" + + "namespace mozilla {\n" + + "namespace widget {\n" + + "\n"); + while (jarClassIterator.hasNext()) { ClassWithOptions aClassTuple = jarClassIterator.next(); @@ -85,6 +98,9 @@ public class AnnotationProcessor { case METHOD: generatorInstance.generateMethod(aElementTuple); break; + case NATIVE: + generatorInstance.generateNative(aElementTuple); + break; case FIELD: generatorInstance.generateField(aElementTuple); break; @@ -96,6 +112,7 @@ public class AnnotationProcessor { headerFile.append(generatorInstance.getHeaderFileContents()); implementationFile.append(generatorInstance.getWrapperFileContents()); + nativesFile.append(generatorInstance.getNativesFileContents()); } implementationFile.append( @@ -107,38 +124,33 @@ public class AnnotationProcessor { "\n" + "} /* widget */\n" + "} /* mozilla */\n" + - "#endif // GeneratedJNIWrappers_h__\n"); + "#endif // " + getHeaderGuardName(HEADER_FILE) + "\n"); - writeOutputFiles(headerFile, implementationFile); + nativesFile.append( + "\n" + + "} /* widget */\n" + + "} /* mozilla */\n" + + "#endif // " + getHeaderGuardName(NATIVES_FILE) + "\n"); + + writeOutputFile(SOURCE_FILE, implementationFile); + writeOutputFile(HEADER_FILE, headerFile); + writeOutputFile(NATIVES_FILE, nativesFile); long e = System.currentTimeMillis(); System.out.println("Annotation processing complete in " + (e - s) + "ms"); } - private static void writeOutputFiles(StringBuilder aHeaderFile, StringBuilder aImplementationFile) { - FileOutputStream headerStream = null; - try { - headerStream = new FileOutputStream(OUTFILE); - headerStream.write(aImplementationFile.toString().getBytes()); - } catch (IOException e) { - System.err.println("Unable to write " + OUTFILE + ". Perhaps a permissions issue?"); - e.printStackTrace(System.err); - } finally { - if (headerStream != null) { - try { - headerStream.close(); - } catch (IOException e) { - System.err.println("Unable to close headerStream due to "+e); - e.printStackTrace(System.err); - } - } - } + private static String getHeaderGuardName(final String name) { + return name.replaceAll("\\W", "_"); + } + private static void writeOutputFile(final String name, + final StringBuilder content) { FileOutputStream outStream = null; try { - outStream = new FileOutputStream(HEADERFILE); - outStream.write(aHeaderFile.toString().getBytes()); + outStream = new FileOutputStream(name); + outStream.write(content.toString().getBytes()); } catch (IOException e) { - System.err.println("Unable to write " + HEADERFILE + ". Perhaps a permissions issue?"); + System.err.println("Unable to write " + name + ". Perhaps a permissions issue?"); e.printStackTrace(System.err); } finally { if (outStream != null) { diff --git a/build/annotationProcessors/CodeGenerator.java b/build/annotationProcessors/CodeGenerator.java index 9b965f1bc3d..702e1beebad 100644 --- a/build/annotationProcessors/CodeGenerator.java +++ b/build/annotationProcessors/CodeGenerator.java @@ -22,6 +22,8 @@ public class CodeGenerator { // Buffers holding the strings to ultimately be written to the output files. private final StringBuilder cpp = new StringBuilder(); private final StringBuilder header = new StringBuilder(); + private final StringBuilder natives = new StringBuilder(); + private final StringBuilder nativesInits = new StringBuilder(); private final Class cls; private final String clsName; @@ -33,13 +35,13 @@ public class CodeGenerator { this.clsName = annotatedClass.generatedName; header.append( - "class " + clsName + " : public mozilla::jni::Class<" + clsName + "> {\n" + - "\n" + + "class " + clsName + " : public mozilla::jni::Class<" + clsName + ">\n" + + "{\n" + "public:\n" + " typedef mozilla::jni::Ref<" + clsName + "> Ref;\n" + " typedef mozilla::jni::LocalRef<" + clsName + "> LocalRef;\n" + " typedef mozilla::jni::GlobalRef<" + clsName + "> GlobalRef;\n" + - " typedef const typename mozilla::jni::Param<" + clsName + ">::Type& Param;\n" + + " typedef const mozilla::jni::Param<" + clsName + ">& Param;\n" + "\n" + " static constexpr char name[] =\n" + " \"" + cls.getName().replace('.', '/') + "\";\n" + @@ -51,6 +53,12 @@ public class CodeGenerator { cpp.append( "constexpr char " + clsName + "::name[];\n" + "\n"); + + natives.append( + "template\n" + + "class " + clsName + "::Natives : " + + "public mozilla::jni::NativeImpl<" + clsName + ", Impl>\n" + + "{\n"); } private String getTraitsName(String uniqueName, boolean includeScope) { @@ -72,20 +80,30 @@ public class CodeGenerator { } private void generateMember(AnnotationInfo info, Member member, - String uniqueName, Class type) { + String uniqueName, Class type, Class[] argTypes) { + final StringBuilder args = new StringBuilder(); + for (Class argType : argTypes) { + args.append("\n " + getNativeParameterType(argType, info) + ","); + } + if (args.length() > 0) { + args.setLength(args.length() - 1); + } + header.append( "public:\n" + " struct " + getTraitsName(uniqueName, /* includeScope */ false) + " {\n" + " typedef " + clsName + " Owner;\n" + " typedef " + getNativeReturnType(type, info) + " ReturnType;\n" + " typedef " + getNativeParameterType(type, info) + " SetterType;\n" + + " typedef mozilla::jni::Args<" + args + "> Args;\n" + " static constexpr char name[] = \"" + Utils.getMemberName(member) + "\";\n" + " static constexpr char signature[] =\n" + " \"" + Utils.getSignature(member) + "\";\n" + " static const bool isStatic = " + Utils.isStatic(member) + ";\n" + " static const bool isMultithreaded = " + info.isMultithreaded + ";\n" + - " static const mozilla::jni::ExceptionMode exceptionMode = " + ( + " static const mozilla::jni::ExceptionMode exceptionMode =\n" + + " " + ( info.catchException ? "mozilla::jni::ExceptionMode::NSRESULT" : info.noThrow ? "mozilla::jni::ExceptionMode::IGNORE" : "mozilla::jni::ExceptionMode::ABORT") + ";\n" + @@ -248,15 +266,15 @@ public class CodeGenerator { final Method method = annotatedMethod.getMethod(); final AnnotationInfo info = annotatedMethod.mAnnotationInfo; final String uniqueName = getUniqueMethodName(info.wrapperName); + final Class[] argTypes = method.getParameterTypes(); final Class returnType = method.getReturnType(); if (method.isSynthetic()) { return; } - generateMember(info, method, uniqueName, returnType); + generateMember(info, method, uniqueName, returnType, argTypes); - final Class[] argTypes = method.getParameterTypes(); final boolean isStatic = Utils.isStatic(method); header.append( @@ -272,6 +290,35 @@ public class CodeGenerator { "\n"); } + /** + * Append the appropriate generated code to the buffers for the native method provided. + * + * @param annotatedMethod The Java native method, plus annotation data. + */ + public void generateNative(AnnotatableEntity annotatedMethod) { + // Unpack the tuple and extract some useful fields from the Method.. + final Method method = annotatedMethod.getMethod(); + final AnnotationInfo info = annotatedMethod.mAnnotationInfo; + final String uniqueName = getUniqueMethodName(info.wrapperName); + final Class[] argTypes = method.getParameterTypes(); + final Class returnType = method.getReturnType(); + + generateMember(info, method, uniqueName, returnType, argTypes); + + final String traits = getTraitsName(uniqueName, /* includeScope */ true); + + if (nativesInits.length() > 0) { + nativesInits.append(','); + } + + nativesInits.append( + "\n" + + "\n" + + " mozilla::jni::MakeNativeMethod<" + traits + ">(\n" + + " mozilla::jni::NativeStub<" + traits + ", Impl>\n" + + " ::template Wrap<&Impl::" + info.wrapperName + ">)"); + } + private String getLiteral(Object val, AnnotationInfo info) { final Class type = val.getClass(); @@ -348,7 +395,7 @@ public class CodeGenerator { // Fall back to using accessors if we encounter an exception. } - generateMember(info, field, uniqueName, type); + generateMember(info, field, uniqueName, type, EMPTY_CLASS_ARRAY); final Class[] getterArgs = EMPTY_CLASS_ARRAY; @@ -389,15 +436,14 @@ public class CodeGenerator { final AnnotationInfo info = annotatedConstructor.mAnnotationInfo; final String wrapperName = "New"; final String uniqueName = getUniqueMethodName(wrapperName); + final Class[] argTypes = method.getParameterTypes(); final Class returnType = cls; if (method.isSynthetic()) { return; } - generateMember(info, method, uniqueName, returnType); - - final Class[] argTypes = method.getParameterTypes(); + generateMember(info, method, uniqueName, returnType, argTypes); header.append( " " + generateDeclaration(wrapperName, argTypes, @@ -454,9 +500,34 @@ public class CodeGenerator { * @return The bytes to be written to the header file. */ public String getHeaderFileContents() { + if (nativesInits.length() > 0) { + header.append( + "public:\n" + + " template class Natives;\n"); + } header.append( "};\n" + "\n"); return header.toString(); } + + /** + * Get the finalised bytes to go into the generated natives header file. + * + * @return The bytes to be written to the header file. + */ + public String getNativesFileContents() { + if (nativesInits.length() == 0) { + return ""; + } + natives.append( + "public:\n" + + " static constexpr JNINativeMethod methods[] = {" + nativesInits + '\n' + + " };\n" + + "};\n" + + "\n" + + "template\n" + + "constexpr JNINativeMethod " + clsName + "::Natives::methods[];\n"); + return natives.toString(); + } } diff --git a/build/annotationProcessors/classloader/AnnotatableEntity.java b/build/annotationProcessors/classloader/AnnotatableEntity.java index 9dffe6033be..b11a6c49a6c 100644 --- a/build/annotationProcessors/classloader/AnnotatableEntity.java +++ b/build/annotationProcessors/classloader/AnnotatableEntity.java @@ -10,13 +10,14 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; /** * Union type to hold either a method, field, or ctor. Allows us to iterate "The generatable stuff", despite * the fact that such things can be of either flavour. */ public class AnnotatableEntity { - public enum ENTITY_TYPE {METHOD, FIELD, CONSTRUCTOR} + public enum ENTITY_TYPE {METHOD, NATIVE, FIELD, CONSTRUCTOR} private final Member mMember; public final ENTITY_TYPE mEntityType; @@ -28,7 +29,11 @@ public class AnnotatableEntity { mAnnotationInfo = aAnnotationInfo; if (aObject instanceof Method) { - mEntityType = ENTITY_TYPE.METHOD; + if (Modifier.isNative(aObject.getModifiers())) { + mEntityType = ENTITY_TYPE.NATIVE; + } else { + mEntityType = ENTITY_TYPE.METHOD; + } } else if (aObject instanceof Field) { mEntityType = ENTITY_TYPE.FIELD; } else { @@ -37,7 +42,7 @@ public class AnnotatableEntity { } public Method getMethod() { - if (mEntityType != ENTITY_TYPE.METHOD) { + if (mEntityType != ENTITY_TYPE.METHOD && mEntityType != ENTITY_TYPE.NATIVE) { throw new UnsupportedOperationException("Attempt to cast to unsupported member type."); } return (Method) mMember; diff --git a/build/macosx/mozconfig.common b/build/macosx/mozconfig.common index 8bfd65b5d53..a36cf895d43 100644 --- a/build/macosx/mozconfig.common +++ b/build/macosx/mozconfig.common @@ -34,6 +34,4 @@ if [ -z "$CXX" ]; then export CXX=clang++ fi -. "$topsrcdir/build/mozconfig.cache" - export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token diff --git a/build/mozconfig.cache b/build/mozconfig.cache index c003f5f6ea4..b965ee0712e 100644 --- a/build/mozconfig.cache +++ b/build/mozconfig.cache @@ -51,6 +51,10 @@ if test -z "$bucket"; then ac_add_options --with-ccache esac else + if ! test -e $topsrcdir/sccache/sccache.py; then + echo "Sccache missing in the tooltool manifest" >&2 + exit 1 + fi mk_add_options "export SCCACHE_BUCKET=$bucket" case "$master" in *use1.mozilla.com*|*usw2.mozilla.com*) diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp index 3b19dfc9933..eaf70867fd3 100644 --- a/caps/BasePrincipal.cpp +++ b/caps/BasePrincipal.cpp @@ -6,6 +6,7 @@ #include "mozilla/BasePrincipal.h" +#include "nsIAddonPolicyService.h" #include "nsIContentSecurityPolicy.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" @@ -15,6 +16,7 @@ #include "nsIURIWithPrincipal.h" #include "nsNullPrincipal.h" #include "nsScriptSecurityManager.h" +#include "nsServiceManagerUtils.h" #include "mozilla/dom/CSPDictionariesBinding.h" #include "mozilla/dom/ToJSValue.h" @@ -41,6 +43,10 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const params->Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1")); } + if (!mAddonId.IsEmpty()) { + params->Set(NS_LITERAL_STRING("addonId"), mAddonId); + } + aStr.Truncate(); params->Serialize(value); @@ -88,6 +94,12 @@ public: return true; } + if (aName.EqualsLiteral("addonId")) { + MOZ_RELEASE_ASSERT(mOriginAttributes->mAddonId.IsEmpty()); + mOriginAttributes->mAddonId.Assign(aValue); + return true; + } + // No other attributes are supported. return false; } @@ -346,4 +358,19 @@ BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs) return codebase.forget(); } +bool +BasePrincipal::AddonAllowsLoad(nsIURI* aURI) +{ + if (mOriginAttributes.mAddonId.IsEmpty()) { + return false; + } + + nsCOMPtr aps = do_GetService("@mozilla.org/addons/policy-service;1"); + NS_ENSURE_TRUE(aps, false); + + bool allowed = false; + nsresult rv = aps->AddonMayLoadURI(mOriginAttributes.mAddonId, aURI, &allowed); + return NS_SUCCEEDED(rv) && allowed; +} + } // namespace mozilla diff --git a/caps/BasePrincipal.h b/caps/BasePrincipal.h index 425b94a29c1..406ffe99b10 100644 --- a/caps/BasePrincipal.h +++ b/caps/BasePrincipal.h @@ -34,7 +34,8 @@ public: bool operator==(const OriginAttributes& aOther) const { return mAppId == aOther.mAppId && - mInBrowser == aOther.mInBrowser; + mInBrowser == aOther.mInBrowser && + mAddonId == aOther.mAddonId; } bool operator!=(const OriginAttributes& aOther) const { @@ -106,6 +107,10 @@ protected: virtual nsresult GetOriginInternal(nsACString& aOrigin) = 0; virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0; + // Helper to check whether this principal is associated with an addon that + // allows unprivileged code to load aURI. + bool AddonAllowsLoad(nsIURI* aURI); + nsCOMPtr mCSP; OriginAttributes mOriginAttributes; }; diff --git a/caps/moz.build b/caps/moz.build index b8005c506ae..b2e4f1be80a 100644 --- a/caps/moz.build +++ b/caps/moz.build @@ -9,6 +9,7 @@ MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini'] XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini'] XPIDL_SOURCES += [ + 'nsIAddonPolicyService.idl', 'nsIDomainPolicy.idl', 'nsIPrincipal.idl', 'nsIScriptSecurityManager.idl', diff --git a/caps/nsIAddonPolicyService.idl b/caps/nsIAddonPolicyService.idl new file mode 100644 index 00000000000..f858b1484f7 --- /dev/null +++ b/caps/nsIAddonPolicyService.idl @@ -0,0 +1,22 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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 "nsISupports.idl" +#include "nsIURI.idl" + +/** + * This interface allows the security manager to query custom per-addon security + * policy. + */ +[scriptable,uuid(fedf126c-988e-42df-82c9-f2ac99cd65f3)] +interface nsIAddonPolicyService : nsISupports +{ + /** + * Returns true if unprivileged code associated with the given addon may load + * data from |aURI|. + */ + boolean addonMayLoadURI(in AString aAddonId, in nsIURI aURI); +}; diff --git a/caps/nsNullPrincipal.h b/caps/nsNullPrincipal.h index 9d267e12fbf..6590ee21147 100644 --- a/caps/nsNullPrincipal.h +++ b/caps/nsNullPrincipal.h @@ -23,8 +23,8 @@ class nsIURI; #define NS_NULLPRINCIPAL_CID \ -{ 0xe502ffb8, 0x5d95, 0x48e8, \ - { 0x82, 0x3c, 0x0d, 0x29, 0xd8, 0x3a, 0x59, 0x33 } } +{ 0x34a19ab6, 0xca47, 0x4098, \ + { 0xa7, 0xb8, 0x4a, 0xfc, 0xdd, 0xcd, 0x8f, 0x88 } } #define NS_NULLPRINCIPAL_CONTRACTID "@mozilla.org/nullprincipal;1" #define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal" diff --git a/caps/nsPrincipal.cpp b/caps/nsPrincipal.cpp index 33cc4d7fedc..ed3b6b017a0 100644 --- a/caps/nsPrincipal.cpp +++ b/caps/nsPrincipal.cpp @@ -236,6 +236,12 @@ nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrinc return NS_OK; } + // If this principal is associated with an addon, check whether that addon + // has been given permission to load from this domain. + if (AddonAllowsLoad(aURI)) { + return NS_OK; + } + if (nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) { return NS_OK; } diff --git a/caps/nsPrincipal.h b/caps/nsPrincipal.h index 53803122848..e5f4f5576f3 100644 --- a/caps/nsPrincipal.h +++ b/caps/nsPrincipal.h @@ -112,12 +112,12 @@ private: #define NS_PRINCIPAL_CONTRACTID "@mozilla.org/principal;1" #define NS_PRINCIPAL_CID \ - { 0xb7c8505e, 0xc56d, 0x4191, \ - { 0xa1, 0x5e, 0x5d, 0xcb, 0x88, 0x9b, 0xa0, 0x94 }} +{ 0xb02c3023, 0x5b37, 0x472a, \ + { 0xa2, 0xcd, 0x35, 0xaa, 0x5e, 0xe2, 0xa8, 0x19 } } #define NS_EXPANDEDPRINCIPAL_CONTRACTID "@mozilla.org/expandedprincipal;1" #define NS_EXPANDEDPRINCIPAL_CID \ - { 0x38539471, 0x68cc, 0x4a6f, \ - { 0x81, 0x20, 0xdb, 0xd5, 0x4a, 0x22, 0x0a, 0x13 }} +{ 0xe8ee88b0, 0x5571, 0x4086, \ + { 0xa4, 0x5b, 0x39, 0xa7, 0x16, 0x90, 0x6b, 0xdb } } #endif // nsPrincipal_h__ diff --git a/caps/tests/mochitest/chrome.ini b/caps/tests/mochitest/chrome.ini index 71b166f6595..818638f2da1 100644 --- a/caps/tests/mochitest/chrome.ini +++ b/caps/tests/mochitest/chrome.ini @@ -1,9 +1,10 @@ [DEFAULT] -skip-if = buildapp == 'b2g' +skip-if = buildapp == 'b2g' || os == 'android' support-files = file_disableScript.html [test_bug995943.xul] +[test_addonMayLoad.html] [test_disableScript.xul] [test_principal_jarprefix_origin_appid_appstatus.html] # jarPrefix test doesn't work on Windows, see bug 776296. diff --git a/caps/tests/mochitest/file_data.txt b/caps/tests/mochitest/file_data.txt new file mode 100644 index 00000000000..26d7bd84885 --- /dev/null +++ b/caps/tests/mochitest/file_data.txt @@ -0,0 +1 @@ +server data fetched over XHR diff --git a/caps/tests/mochitest/mochitest.ini b/caps/tests/mochitest/mochitest.ini index 187150a05c4..b6529ef5e8c 100644 --- a/caps/tests/mochitest/mochitest.ini +++ b/caps/tests/mochitest/mochitest.ini @@ -1,5 +1,6 @@ [DEFAULT] support-files = + file_data.txt file_disableScript.html [test_app_principal_equality.html] diff --git a/caps/tests/mochitest/test_addonMayLoad.html b/caps/tests/mochitest/test_addonMayLoad.html new file mode 100644 index 00000000000..286284bfe8c --- /dev/null +++ b/caps/tests/mochitest/test_addonMayLoad.html @@ -0,0 +1,97 @@ + + + + + + Test for Bug 1180921 + + + + + + +Mozilla Bug 1180921 +

+ +
+
+ + diff --git a/caps/tests/unit/test_origin.js b/caps/tests/unit/test_origin.js index 33fed1395a6..ef462719e7c 100644 --- a/caps/tests/unit/test_origin.js +++ b/caps/tests/unit/test_origin.js @@ -25,9 +25,10 @@ function checkCrossOrigin(a, b) { a.originAttributes.inBrowser == b.originAttributes.inBrowser); } -function checkOriginAttributes(prin, appId, inBrowser, suffix) { - do_check_eq(prin.originAttributes.appId, appId || 0); - do_check_eq(prin.originAttributes.inBrowser, inBrowser || false); +function checkOriginAttributes(prin, attrs, suffix) { + attrs = attrs || {}; + do_check_eq(prin.originAttributes.appId, attrs.appId || 0); + do_check_eq(prin.originAttributes.inBrowser, attrs.inBrowser || false); do_check_eq(prin.originSuffix, suffix || ''); if (!prin.isNullPrincipal && !prin.origin.startsWith('[')) { do_check_true(BrowserUtils.principalFromOrigin(prin.origin).equals(prin)); @@ -67,29 +68,34 @@ function run_test() { // Just app. var exampleOrg_app = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 42}); var nullPrin_app = ssm.createNullPrincipal({appId: 42}); - checkOriginAttributes(exampleOrg_app, 42, false, '!appId=42'); - checkOriginAttributes(nullPrin_app, 42, false, '!appId=42'); + checkOriginAttributes(exampleOrg_app, {appId: 42}, '!appId=42'); + checkOriginAttributes(nullPrin_app, {appId: 42}, '!appId=42'); do_check_eq(exampleOrg_app.origin, 'http://example.org!appId=42'); // Just browser. var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true}); var nullPrin_browser = ssm.createNullPrincipal({inBrowser: true}); - checkOriginAttributes(exampleOrg_browser, 0, true, '!inBrowser=1'); - checkOriginAttributes(nullPrin_browser, 0, true, '!inBrowser=1'); + checkOriginAttributes(exampleOrg_browser, {inBrowser: true}, '!inBrowser=1'); + checkOriginAttributes(nullPrin_browser, {inBrowser: true}, '!inBrowser=1'); do_check_eq(exampleOrg_browser.origin, 'http://example.org!inBrowser=1'); // App and browser. var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true, appId: 42}); var nullPrin_appBrowser = ssm.createNullPrincipal({inBrowser: true, appId: 42}); - checkOriginAttributes(exampleOrg_appBrowser, 42, true, '!appId=42&inBrowser=1'); - checkOriginAttributes(nullPrin_appBrowser, 42, true, '!appId=42&inBrowser=1'); + checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1'); + checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1'); do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org!appId=42&inBrowser=1'); // App and browser, different domain. var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inBrowser: true}); - checkOriginAttributes(exampleCom_appBrowser, 42, true, '!appId=42&inBrowser=1'); + checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inBrowser: true}, '!appId=42&inBrowser=1'); do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123!appId=42&inBrowser=1'); + // Addon. + var exampleOrg_addon = ssm.createCodebasePrincipal(makeURI('http://example.org'), {addonId: 'dummy'}); + checkOriginAttributes(exampleOrg_addon, { addonId: "dummy" }, '!addonId=dummy'); + do_check_eq(exampleOrg_addon.origin, 'http://example.org!addonId=dummy'); + // Check that all of the above are cross-origin. checkCrossOrigin(exampleOrg_app, exampleOrg); checkCrossOrigin(exampleOrg_app, nullPrin_app); @@ -98,4 +104,5 @@ function run_test() { checkCrossOrigin(exampleOrg_appBrowser, exampleOrg_app); checkCrossOrigin(exampleOrg_appBrowser, nullPrin_appBrowser); checkCrossOrigin(exampleOrg_appBrowser, exampleCom_appBrowser); + checkCrossOrigin(exampleOrg_addon, exampleOrg); } diff --git a/config/external/lgpllibs/lgpllibs.def b/config/external/lgpllibs/lgpllibs.def new file mode 100644 index 00000000000..359d97e714e --- /dev/null +++ b/config/external/lgpllibs/lgpllibs.def @@ -0,0 +1,10 @@ +; 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/. + +LIBRARY lgpllibs.dll + +EXPORTS + av_rdft_init + av_rdft_calc + av_rdft_end diff --git a/config/external/lgpllibs/moz.build b/config/external/lgpllibs/moz.build index b1cc9420fbe..9812b79c36e 100644 --- a/config/external/lgpllibs/moz.build +++ b/config/external/lgpllibs/moz.build @@ -12,3 +12,7 @@ SharedLibrary('lgpllibs') SHARED_LIBRARY_NAME = 'lgpllibs' + +if CONFIG['MOZ_LIBAV_FFT']: + DIRS += ['/media/libav'] + DEFFILE = SRCDIR + '/lgpllibs.def' diff --git a/config/system-headers b/config/system-headers index 8e73df2f6ff..bee35daf39a 100644 --- a/config/system-headers +++ b/config/system-headers @@ -1258,6 +1258,9 @@ X11/Xutil.h zmouse.h soundtouch/SoundTouch.h soundtouch/SoundTouchFactory.h +#if MOZ_LIBAV_FFT==1 +libavcodec/avfft.h +#endif #if MOZ_NATIVE_PNG==1 png.h #endif diff --git a/configure.in b/configure.in index bd5da05aa3b..fe01b26b839 100644 --- a/configure.in +++ b/configure.in @@ -6274,6 +6274,74 @@ elif test -n "$MOZ_LIBJPEG_TURBO"; then AC_MSG_WARN([No assembler or assembly support for libjpeg-turbo. Using unoptimized C routines.]) fi +dnl ======================================================== +dnl = libav-fft configuration +dnl ======================================================== + +MOZ_LIBAV_FFT= + +dnl Turn on libav-fft for 32-bit windows, and all 64-bit supported platforms. +dnl 32-bit linux/os x have text relocation issues. + +case "$OS_ARCH:$CPU_ARCH" in + WINNT:x86) + MOZ_LIBAV_FFT=1 + ;; + *:x86_64) + MOZ_LIBAV_FFT=1 + ;; +esac + +dnl Detect if we can use yasm to compile libav's assembly + +if test -n "$MOZ_LIBAV_FFT"; then + AC_DEFINE(MOZ_LIBAV_FFT) + dnl Do we support libav-fft on this platform? + case "$OS_ARCH:$CPU_ARCH" in + Darwin:x86_64) + LIBAV_FFT_ASFLAGS="-f macho64 -rnasm -pnasm -D__x86_64__ -DPIC -DMACHO" + ;; + WINNT:x86) + LIBAV_FFT_ASFLAGS="-f win32 -rnasm -pnasm -DPIC -DWIN32" + ;; + WINNT:x86_64) + LIBAV_FFT_ASFLAGS="-f win64 -rnasm -pnasm -D__x86_64__ -DPIC -DWIN64 -DMSVC" + ;; + *:x86_64) + if $CC -E -dM - pWindow = do_QueryInterface(aWindow); - if (!pWindow->IsInnerWindow()) { - pWindow = pWindow->GetCurrentInnerWindow(); + nsCOMPtr topWindow; + aWindow->GetScriptableTop(getter_AddRefs(topWindow)); + MOZ_ASSERT(topWindow); + + mWindow = do_QueryInterface(topWindow); + if (!mWindow) { + return NS_ERROR_FAILURE; } - mWindow = pWindow.forget(); + mWindow = mWindow->GetOuterWindow(); } mAudioChannelType = aChannelType; @@ -116,65 +106,45 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType, mCallback = aCallback; } - mWithVideo = aWithVideo; - return NS_OK; } -/* boolean startPlaying (); */ -NS_IMETHODIMP AudioChannelAgent::StartPlaying(int32_t *_retval) +/* boolean notifyStartedPlaying (); */ +NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(float *aVolume, + bool* aMuted) { - AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService(); + MOZ_ASSERT(aVolume); + MOZ_ASSERT(aMuted); + + nsRefPtr service = AudioChannelService::GetOrCreate(); if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR || service == nullptr || mIsRegToService) { return NS_ERROR_FAILURE; } service->RegisterAudioChannelAgent(this, - static_cast(mAudioChannelType), mWithVideo); - *_retval = service->GetState(this, !mVisible); + static_cast(mAudioChannelType)); + + service->GetState(mWindow, mAudioChannelType, aVolume, aMuted); + mIsRegToService = true; return NS_OK; } -/* void stopPlaying (); */ -NS_IMETHODIMP AudioChannelAgent::StopPlaying(void) +/* void notifyStoppedPlaying (); */ +NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying(void) { if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR || !mIsRegToService) { return NS_ERROR_FAILURE; } - AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService(); + nsRefPtr service = AudioChannelService::GetOrCreate(); service->UnregisterAudioChannelAgent(this); mIsRegToService = false; return NS_OK; } -/* void setVisibilityState (in boolean visible); */ -NS_IMETHODIMP AudioChannelAgent::SetVisibilityState(bool visible) -{ - bool oldVisibility = mVisible; - - nsCOMPtr callback = GetCallback(); - - mVisible = visible; - if (mIsRegToService && oldVisibility != mVisible && callback) { - AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService(); - callback->CanPlayChanged(service->GetState(this, !mVisible)); - } - return NS_OK; -} - -void AudioChannelAgent::NotifyAudioChannelStateChanged() -{ - nsCOMPtr callback = GetCallback(); - if (callback) { - AudioChannelService *service = AudioChannelService::GetOrCreateAudioChannelService(); - callback->CanPlayChanged(service->GetState(this, !mVisible)); - } -} - already_AddRefed AudioChannelAgent::GetCallback() { @@ -193,20 +163,17 @@ AudioChannelAgent::WindowVolumeChanged() return; } - callback->WindowVolumeChanged(); + float volume = 1.0; + bool muted = false; + + nsRefPtr service = AudioChannelService::GetOrCreate(); + service->GetState(mWindow, mAudioChannelType, &volume, &muted); + + callback->WindowVolumeChanged(volume, muted); } -NS_IMETHODIMP -AudioChannelAgent::GetWindowVolume(float* aVolume) +uint64_t +AudioChannelAgent::WindowID() const { - NS_ENSURE_ARG_POINTER(aVolume); - - nsCOMPtr win = do_QueryInterface(mWindow); - if (!win) { - *aVolume = 1.0f; - return NS_OK; - } - - *aVolume = win->GetAudioGlobalVolume(); - return NS_OK; + return mWindow ? mWindow->WindowID() : 0; } diff --git a/dom/audiochannel/AudioChannelAgent.h b/dom/audiochannel/AudioChannelAgent.h index f2259386f6d..3033ed44f83 100644 --- a/dom/audiochannel/AudioChannelAgent.h +++ b/dom/audiochannel/AudioChannelAgent.h @@ -17,7 +17,7 @@ #define NS_AUDIOCHANNELAGENT_CID {0xf27688e2, 0x3dd7, 0x11e2, \ {0x90, 0x4e, 0x10, 0xbf, 0x48, 0xd6, 0x4b, 0xd4}} -class nsIDOMWindow; +class nsPIDOMWindow; namespace mozilla { namespace dom { @@ -32,15 +32,16 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS(AudioChannelAgent) AudioChannelAgent(); - virtual void NotifyAudioChannelStateChanged(); void WindowVolumeChanged(); - nsIDOMWindow* Window() const + nsPIDOMWindow* Window() const { return mWindow; } + uint64_t WindowID() const; + private: virtual ~AudioChannelAgent(); @@ -50,18 +51,18 @@ private: nsresult InitInternal(nsIDOMWindow* aWindow, int32_t aAudioAgentType, nsIAudioChannelAgentCallback* aCallback, - bool aUseWeakRef, bool aWithVideo=false); + bool aUseWeakRef); - nsCOMPtr mWindow; + nsCOMPtr mWindow; nsCOMPtr mCallback; + nsWeakPtr mWeakCallback; + int32_t mAudioChannelType; bool mIsRegToService; - bool mVisible; - bool mWithVideo; }; } // namespace dom } // namespace mozilla -#endif +#endif diff --git a/dom/audiochannel/AudioChannelCommon.h b/dom/audiochannel/AudioChannelCommon.h deleted file mode 100644 index b0de2904140..00000000000 --- a/dom/audiochannel/AudioChannelCommon.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=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/. */ - -#ifndef mozilla_dom_audiochannelcommon_h__ -#define mozilla_dom_audiochannelcommon_h__ - -namespace mozilla { -namespace dom { - -enum AudioChannelState { - AUDIO_CHANNEL_STATE_NORMAL = 0, - AUDIO_CHANNEL_STATE_MUTED, - AUDIO_CHANNEL_STATE_FADED, - AUDIO_CHANNEL_STATE_LAST -}; - -} // namespace dom -} // namespace mozilla - -#endif - diff --git a/dom/audiochannel/AudioChannelService.cpp b/dom/audiochannel/AudioChannelService.cpp index 87eceb2a8ad..e55136797e1 100644 --- a/dom/audiochannel/AudioChannelService.cpp +++ b/dom/audiochannel/AudioChannelService.cpp @@ -5,7 +5,6 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AudioChannelService.h" -#include "AudioChannelServiceChild.h" #include "base/basictypes.h" @@ -13,9 +12,11 @@ #include "mozilla/StaticPtr.h" #include "mozilla/unused.h" +#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentParent.h" #include "nsContentUtils.h" +#include "nsIScriptSecurityManager.h" #include "nsISupportsPrimitives.h" #include "nsThreadUtils.h" #include "nsHashPropertyBag.h" @@ -37,19 +38,117 @@ using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::hal; -// When a inner-window is destroyed we have to mute all the related -// AudioChannelAgents. In order to do this we have to notify them after purging -// AudioChannelService::mAgents. -struct MOZ_STACK_CLASS WindowDestroyedEnumeratorData +namespace { + +// If true, any new AudioChannelAgent will be muted when created. +bool sAudioChannelMutedByDefault = false; + +class NotifyChannelActiveRunnable final : public nsRunnable { - explicit WindowDestroyedEnumeratorData(uint64_t aInnerID) - : mInnerID(aInnerID) +public: + NotifyChannelActiveRunnable(uint64_t aWindowID, AudioChannel aAudioChannel, + bool aActive) + : mWindowID(aWindowID) + , mAudioChannel(aAudioChannel) + , mActive(aActive) {} - nsTArray> mAgents; - uint64_t mInnerID; + NS_IMETHOD Run() override + { + nsCOMPtr observerService = + services::GetObserverService(); + if (NS_WARN_IF(!observerService)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr wrapper = + do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID); + if (NS_WARN_IF(!wrapper)) { + return NS_ERROR_FAILURE; + } + + wrapper->SetData(mWindowID); + + nsAutoString name; + AudioChannelService::GetAudioChannelString(mAudioChannel, name); + + nsAutoCString topic; + topic.Assign("audiochannel-activity-"); + topic.Append(NS_ConvertUTF16toUTF8(name)); + + observerService->NotifyObservers(wrapper, topic.get(), + mActive + ? MOZ_UTF16("active") + : MOZ_UTF16("inactive")); + return NS_OK; + } + +private: + const uint64_t mWindowID; + const AudioChannel mAudioChannel; + const bool mActive; }; +void +NotifyChannelActive(uint64_t aWindowID, AudioChannel aAudioChannel, + bool aActive) +{ + nsRefPtr runnable = + new NotifyChannelActiveRunnable(aWindowID, aAudioChannel, aActive); + NS_DispatchToCurrentThread(runnable); +} + +already_AddRefed +GetTopWindow(nsIDOMWindow* aWindow) +{ + MOZ_ASSERT(aWindow); + + nsCOMPtr topWindow; + aWindow->GetScriptableTop(getter_AddRefs(topWindow)); + MOZ_ASSERT(topWindow); + + nsCOMPtr window = do_QueryInterface(topWindow); + window = window->GetOuterWindow(); + + return window.forget(); +} + +bool +IsParentProcess() +{ + return XRE_GetProcessType() == GeckoProcessType_Default; +} + +class MediaPlaybackRunnable : public nsRunnable +{ +public: + MediaPlaybackRunnable(nsIDOMWindow* aWindow, bool aActive) + : mWindow(aWindow) + , mActive(aActive) + {} + + NS_IMETHOD Run() + { + nsCOMPtr observerService = + services::GetObserverService(); + if (observerService) { + observerService->NotifyObservers( + ToSupports(mWindow), + "media-playback", + mActive ? NS_LITERAL_STRING("active").get() + : NS_LITERAL_STRING("inactive").get()); + } + + return NS_OK; + } + +private: + nsCOMPtr mWindow; + bool mActive; +}; + +} // anonymous namespace + StaticRefPtr gAudioChannelService; // Mappings from 'mozaudiochannel' attribute strings to an enumeration. @@ -64,65 +163,57 @@ static const nsAttrValue::EnumTable kMozAudioChannelAttributeTable[] = { { nullptr } }; -// static -AudioChannelService* -AudioChannelService::GetAudioChannelService() +/* static */ already_AddRefed +AudioChannelService::GetOrCreate() { MOZ_ASSERT(NS_IsMainThread()); - if (!XRE_IsParentProcess()) { - return AudioChannelServiceChild::GetAudioChannelService(); + if (!gAudioChannelService) { + gAudioChannelService = new AudioChannelService(); } - return gAudioChannelService; - -} - -// static -AudioChannelService* -AudioChannelService::GetOrCreateAudioChannelService() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!XRE_IsParentProcess()) { - return AudioChannelServiceChild::GetOrCreateAudioChannelService(); - } - - // If we already exist, exit early - if (gAudioChannelService) { - return gAudioChannelService; - } - - // Create new instance, register, return - nsRefPtr service = new AudioChannelService(); - MOZ_ASSERT(service); - - gAudioChannelService = service; - return gAudioChannelService; + nsRefPtr service = gAudioChannelService.get(); + return service.forget(); } void AudioChannelService::Shutdown() { - if (!XRE_IsParentProcess()) { - return AudioChannelServiceChild::Shutdown(); - } - if (gAudioChannelService) { + if (IsParentProcess()) { + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(gAudioChannelService, "ipc:content-shutdown"); + obs->RemoveObserver(gAudioChannelService, "xpcom-shutdown"); + obs->RemoveObserver(gAudioChannelService, "inner-window-destroyed"); +#ifdef MOZ_WIDGET_GONK + // To monitor the volume settings based on audio channel. + obs->RemoveObserver(gAudioChannelService, "mozsettings-changed"); +#endif + } + } + gAudioChannelService = nullptr; } } -NS_IMPL_ISUPPORTS(AudioChannelService, nsIObserver, nsITimerCallback) +NS_INTERFACE_MAP_BEGIN(AudioChannelService) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAudioChannelService) + NS_INTERFACE_MAP_ENTRY(nsIAudioChannelService) + NS_INTERFACE_MAP_ENTRY(nsIObserver) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(AudioChannelService) +NS_IMPL_RELEASE(AudioChannelService) AudioChannelService::AudioChannelService() -: mCurrentHigherChannel(-1) -, mCurrentVisibleHigherChannel(-1) -, mPlayableHiddenContentChildID(CONTENT_PROCESS_ID_UNKNOWN) -, mDisabled(false) -, mDefChannelChildID(CONTENT_PROCESS_ID_UNKNOWN) + : mDisabled(false) + , mDefChannelChildID(CONTENT_PROCESS_ID_UNKNOWN) + , mTelephonyChannel(false) + , mContentOrNormalChannel(false) + , mAnyChannel(false) { - if (XRE_IsParentProcess()) { + if (IsParentProcess()) { nsCOMPtr obs = mozilla::services::GetObserverService(); if (obs) { obs->AddObserver(this, "ipc:content-shutdown", false); @@ -134,6 +225,9 @@ AudioChannelService::AudioChannelService() #endif } } + + Preferences::AddBoolVarCache(&sAudioChannelMutedByDefault, + "dom.audiochannel.mutedByDefault"); } AudioChannelService::~AudioChannelService() @@ -142,86 +236,37 @@ AudioChannelService::~AudioChannelService() void AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent, - AudioChannel aChannel, - bool aWithVideo) + AudioChannel aChannel) { if (mDisabled) { return; } - AudioChannelAgentData* data = new AudioChannelAgentData(aChannel, - true /* aElementHidden */, - AUDIO_CHANNEL_STATE_MUTED /* aState */, - aWithVideo); - mAgents.Put(aAgent, data); - RegisterType(aChannel, CONTENT_PROCESS_ID_MAIN, aWithVideo); + uint64_t windowID = aAgent->WindowID(); + AudioChannelWindow* winData = GetWindowData(windowID); + if (!winData) { + winData = new AudioChannelWindow(windowID); + mWindows.AppendElement(winData); + } + + MOZ_ASSERT(!winData->mAgents.Contains(aAgent)); + winData->mAgents.AppendElement(aAgent); + + ++winData->mChannels[(uint32_t)aChannel].mNumberOfAgents; + + // The first one, we must inform the BrowserElementAudioChannel. + if (winData->mChannels[(uint32_t)aChannel].mNumberOfAgents == 1) { + NotifyChannelActive(aAgent->WindowID(), aChannel, true); + } // If this is the first agent for this window, we must notify the observers. - uint32_t count = CountWindow(aAgent->Window()); - if (count == 1) { - nsCOMPtr observerService = - services::GetObserverService(); - if (observerService) { - observerService->NotifyObservers(ToSupports(aAgent->Window()), - "media-playback", - NS_LITERAL_STRING("active").get()); - } - } -} - -void -AudioChannelService::RegisterType(AudioChannel aChannel, uint64_t aChildID, - bool aWithVideo) -{ - if (mDisabled) { - return; + if (winData->mAgents.Length() == 1) { + nsRefPtr runnable = + new MediaPlaybackRunnable(aAgent->Window(), true /* active */); + NS_DispatchToCurrentThread(runnable); } - AudioChannelInternalType type = GetInternalType(aChannel, true); - mChannelCounters[type].AppendElement(aChildID); - - if (XRE_IsParentProcess()) { - - // We must keep the childIds in order to decide which app is allowed to play - // with then telephony channel. - if (aChannel == AudioChannel::Telephony) { - RegisterTelephonyChild(aChildID); - } - - // Since there is another telephony registered, we can unregister old one - // immediately. - if (mDeferTelChannelTimer && aChannel == AudioChannel::Telephony) { - mDeferTelChannelTimer->Cancel(); - mDeferTelChannelTimer = nullptr; - UnregisterTypeInternal(aChannel, mTimerElementHidden, mTimerChildID, - false); - } - - if (aWithVideo) { - mWithVideoChildIDs.AppendElement(aChildID); - } - - // No hidden content channel can be playable if there is a content channel - // in foreground (bug 855208), nor if there is a normal channel with video - // in foreground (bug 894249). - if (type == AUDIO_CHANNEL_INT_CONTENT || - (type == AUDIO_CHANNEL_INT_NORMAL && - mWithVideoChildIDs.Contains(aChildID))) { - mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN; - } - // One hidden content channel can be playable only when there is no any - // content channel in the foreground, and no normal channel with video in - // foreground. - else if (type == AUDIO_CHANNEL_INT_CONTENT_HIDDEN && - mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) { - mPlayableHiddenContentChildID = aChildID; - } - - // In order to avoid race conditions, it's safer to notify any existing - // agent any time a new one is registered. - SendAudioChannelChangedNotification(aChildID); - SendNotification(); - } + MaybeSendStatusUpdate(); } void @@ -231,12 +276,26 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent) return; } - nsAutoPtr data; - mAgents.RemoveAndForget(aAgent, data); + AudioChannelWindow* winData = GetWindowData(aAgent->WindowID()); + if (!winData) { + return; + } - if (data) { - UnregisterType(data->mChannel, data->mElementHidden, - CONTENT_PROCESS_ID_MAIN, data->mWithVideo); + if (winData->mAgents.Contains(aAgent)) { + int32_t channel = aAgent->AudioChannelType(); + uint64_t windowID = aAgent->WindowID(); + + // aAgent can be freed after this call. + winData->mAgents.RemoveElement(aAgent); + + MOZ_ASSERT(winData->mChannels[channel].mNumberOfAgents > 0); + + --winData->mChannels[channel].mNumberOfAgents; + + // The last one, we must inform the BrowserElementAudioChannel. + if (winData->mChannels[channel].mNumberOfAgents == 0) { + NotifyChannelActive(windowID, static_cast(channel), false); + } } #ifdef MOZ_WIDGET_GONK @@ -247,629 +306,168 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent) #endif // If this is the last agent for this window, we must notify the observers. - uint32_t count = CountWindow(aAgent->Window()); - if (count == 0) { - nsCOMPtr observerService = - services::GetObserverService(); - if (observerService) { - observerService->NotifyObservers(ToSupports(aAgent->Window()), - "media-playback", - NS_LITERAL_STRING("inactive").get()); - } + if (winData->mAgents.IsEmpty()) { + nsRefPtr runnable = + new MediaPlaybackRunnable(aAgent->Window(), false /* active */); + NS_DispatchToCurrentThread(runnable); } + + MaybeSendStatusUpdate(); } void -AudioChannelService::UnregisterType(AudioChannel aChannel, - bool aElementHidden, - uint64_t aChildID, - bool aWithVideo) +AudioChannelService::GetState(nsPIDOMWindow* aWindow, uint32_t aAudioChannel, + float* aVolume, bool* aMuted) { - if (mDisabled) { + MOZ_ASSERT(!aWindow || aWindow->IsOuterWindow()); + MOZ_ASSERT(aVolume && aMuted); + MOZ_ASSERT(aAudioChannel < NUMBER_OF_AUDIO_CHANNELS); + + *aVolume = 1.0; + *aMuted = false; + + if (!aWindow || !aWindow->IsOuterWindow()) { return; } - // There are two reasons to defer the decrease of telephony channel. - // 1. User can have time to remove device from his ear before music resuming. - // 2. Give BT SCO to be disconnected before starting to connect A2DP. - if (XRE_IsParentProcess()) { + AudioChannelWindow* winData = nullptr; + nsCOMPtr window = aWindow; - if (aChannel == AudioChannel::Telephony) { - UnregisterTelephonyChild(aChildID); + // The volume must be calculated based on the window hierarchy. Here we go up + // to the top window and we calculate the volume and the muted flag. + do { + winData = GetWindowData(window->WindowID()); + if (winData) { + *aVolume *= winData->mChannels[aAudioChannel].mVolume; + *aMuted = *aMuted || winData->mChannels[aAudioChannel].mMuted; } - if (aChannel == AudioChannel::Telephony && - (mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN].Length() + - mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY].Length()) == 1) { - mTimerElementHidden = aElementHidden; - mTimerChildID = aChildID; - mDeferTelChannelTimer = do_CreateInstance("@mozilla.org/timer;1"); - mDeferTelChannelTimer->InitWithCallback(this, 1500, nsITimer::TYPE_ONE_SHOT); - return; - } - } + *aVolume *= window->GetAudioVolume(); + *aMuted = *aMuted || window->GetAudioMuted(); - UnregisterTypeInternal(aChannel, aElementHidden, aChildID, aWithVideo); -} - -void -AudioChannelService::UnregisterTypeInternal(AudioChannel aChannel, - bool aElementHidden, - uint64_t aChildID, - bool aWithVideo) -{ - // The array may contain multiple occurrence of this appId but - // this should remove only the first one. - AudioChannelInternalType type = GetInternalType(aChannel, aElementHidden); - MOZ_ASSERT(mChannelCounters[type].Contains(aChildID)); - mChannelCounters[type].RemoveElement(aChildID); - - // In order to avoid race conditions, it's safer to notify any existing - // agent any time a new one is registered. - if (XRE_IsParentProcess()) { - // No hidden content channel is playable if the original playable hidden - // process does not need to play audio from background anymore. - if (aChannel == AudioChannel::Content && - mPlayableHiddenContentChildID == aChildID && - !mChannelCounters[AUDIO_CHANNEL_INT_CONTENT_HIDDEN].Contains(aChildID)) { - mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN; - } - - if (aWithVideo) { - MOZ_ASSERT(mWithVideoChildIDs.Contains(aChildID)); - mWithVideoChildIDs.RemoveElement(aChildID); - } - - SendAudioChannelChangedNotification(aChildID); - SendNotification(); - } -} - -void -AudioChannelService::UpdateChannelType(AudioChannel aChannel, - uint64_t aChildID, - bool aElementHidden, - bool aElementWasHidden) -{ - // Calculate the new and old internal type and update the hashtable if needed. - AudioChannelInternalType newType = GetInternalType(aChannel, aElementHidden); - AudioChannelInternalType oldType = GetInternalType(aChannel, aElementWasHidden); - - if (newType != oldType) { - mChannelCounters[newType].AppendElement(aChildID); - MOZ_ASSERT(mChannelCounters[oldType].Contains(aChildID)); - mChannelCounters[oldType].RemoveElement(aChildID); - } - - // No hidden content channel can be playable if there is a content channel - // in foreground (bug 855208), nor if there is a normal channel with video - // in foreground (bug 894249). - if (newType == AUDIO_CHANNEL_INT_CONTENT || - (newType == AUDIO_CHANNEL_INT_NORMAL && - mWithVideoChildIDs.Contains(aChildID))) { - mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN; - } - // If there is no content channel in foreground and no normal channel with - // video in foreground, the last content channel which goes from foreground - // to background can be playable. - else if (oldType == AUDIO_CHANNEL_INT_CONTENT && - newType == AUDIO_CHANNEL_INT_CONTENT_HIDDEN && - mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) { - mPlayableHiddenContentChildID = aChildID; - } -} - -AudioChannelState -AudioChannelService::GetState(AudioChannelAgent* aAgent, bool aElementHidden) -{ - AudioChannelAgentData* data; - if (!mAgents.Get(aAgent, &data)) { - return AUDIO_CHANNEL_STATE_MUTED; - } - - bool oldElementHidden = data->mElementHidden; - // Update visibility. - data->mElementHidden = aElementHidden; - - data->mState = GetStateInternal(data->mChannel, CONTENT_PROCESS_ID_MAIN, - aElementHidden, oldElementHidden); - #ifdef MOZ_WIDGET_GONK - /** Only modify the speaker status when - * (1) apps in the foreground. - * (2) apps in the backgrund and inactive. - * Notice : check the state when the visible status is stable, because there - * has lantency in passing the visibility events. - **/ - bool active = AnyAudioChannelIsActive(); - if (aElementHidden == oldElementHidden && - (!aElementHidden || (aElementHidden && !active))) { - for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) { - mSpeakerManager[i]->SetAudioChannelActive(active); - } - } - #endif - - return data->mState; -} - -AudioChannelState -AudioChannelService::GetStateInternal(AudioChannel aChannel, uint64_t aChildID, - bool aElementHidden, - bool aElementWasHidden) -{ - UpdateChannelType(aChannel, aChildID, aElementHidden, aElementWasHidden); - - // Calculating the new and old type and update the hashtable if needed. - AudioChannelInternalType newType = GetInternalType(aChannel, aElementHidden); - AudioChannelInternalType oldType = GetInternalType(aChannel, - aElementWasHidden); - - if (newType != oldType && - (aChannel == AudioChannel::Content || - (aChannel == AudioChannel::Normal && - mWithVideoChildIDs.Contains(aChildID)))) { - SendNotification(); - } - - SendAudioChannelChangedNotification(aChildID); - - // Let play any visible audio channel. - if (!aElementHidden) { - if (CheckVolumeFadedCondition(newType, aElementHidden)) { - return AUDIO_CHANNEL_STATE_FADED; - } - return CheckTelephonyPolicy(aChannel, aChildID); - } - - // We are not visible, maybe we have to mute. - if (newType == AUDIO_CHANNEL_INT_NORMAL_HIDDEN || - (newType == AUDIO_CHANNEL_INT_CONTENT_HIDDEN && - // One process can have multiple content channels; and during the - // transition from foreground to background, its content channels will be - // updated with correct visibility status one by one. All its content - // channels should remain playable until all of their visibility statuses - // have been updated as hidden. After all its content channels have been - // updated properly as hidden, mPlayableHiddenContentChildID is used to - // check whether this background process is playable or not. - !(mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID) || - (mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty() && - mPlayableHiddenContentChildID == aChildID)))) { - return AUDIO_CHANNEL_STATE_MUTED; - } - - // After checking the condition on normal & content channel, if the state - // is not on muted then checking other higher channels type here. - if (ChannelsActiveWithHigherPriorityThan(newType)) { - MOZ_ASSERT(newType != AUDIO_CHANNEL_INT_NORMAL_HIDDEN); - if (CheckVolumeFadedCondition(newType, aElementHidden)) { - return AUDIO_CHANNEL_STATE_FADED; - } - return AUDIO_CHANNEL_STATE_MUTED; - } - - return CheckTelephonyPolicy(aChannel, aChildID); -} - -AudioChannelState -AudioChannelService::CheckTelephonyPolicy(AudioChannel aChannel, - uint64_t aChildID) -{ - // Only the latest childID is allowed to play with telephony channel. - if (aChannel != AudioChannel::Telephony) { - return AUDIO_CHANNEL_STATE_NORMAL; - } - - MOZ_ASSERT(!mTelephonyChildren.IsEmpty()); - -#if DEBUG - bool found = false; - for (uint32_t i = 0, len = mTelephonyChildren.Length(); i < len; ++i) { - if (mTelephonyChildren[i].mChildID == aChildID) { - found = true; + nsCOMPtr win; + window->GetScriptableParent(getter_AddRefs(win)); + if (window == win) { break; } - } - MOZ_ASSERT(found); -#endif + window = do_QueryInterface(win); - return mTelephonyChildren.LastElement().mChildID == aChildID - ? AUDIO_CHANNEL_STATE_NORMAL : AUDIO_CHANNEL_STATE_MUTED; -} - -bool -AudioChannelService::CheckVolumeFadedCondition(AudioChannelInternalType aType, - bool aElementHidden) -{ - // Only normal & content channels are considered - if (aType > AUDIO_CHANNEL_INT_CONTENT_HIDDEN) { - return false; - } - - // Consider that audio from notification is with short duration - // so just fade the volume not pause it - if (mChannelCounters[AUDIO_CHANNEL_INT_NOTIFICATION].IsEmpty() && - mChannelCounters[AUDIO_CHANNEL_INT_NOTIFICATION_HIDDEN].IsEmpty()) { - return false; - } - - // Since this element is on the foreground, it can be allowed to play always. - // So return true directly when there is any notification channel alive. - if (aElementHidden == false) { - return true; - } - - // If element is on the background, it is possible paused by channels higher - // then notification. - for (int i = AUDIO_CHANNEL_INT_LAST - 1; - i != AUDIO_CHANNEL_INT_NOTIFICATION_HIDDEN; --i) { - if (!mChannelCounters[i].IsEmpty()) { - return false; - } - } - - return true; -} - -bool -AudioChannelService::ContentOrNormalChannelIsActive() -{ - return !mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty() || - !mChannelCounters[AUDIO_CHANNEL_INT_CONTENT_HIDDEN].IsEmpty() || - !mChannelCounters[AUDIO_CHANNEL_INT_NORMAL].IsEmpty(); + // If there is no parent, or we are the toplevel we don't continue. + } while (window && window != aWindow); } bool AudioChannelService::TelephonyChannelIsActive() { - return !mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY].IsEmpty() || - !mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN].IsEmpty(); + nsTObserverArray>::ForwardIterator iter(mWindows); + while (iter.HasMore()) { + AudioChannelWindow* next = iter.GetNext(); + if (next->mChannels[(uint32_t)AudioChannel::Telephony].mNumberOfAgents != 0 && + !next->mChannels[(uint32_t)AudioChannel::Telephony].mMuted) { + return true; + } + } + + if (IsParentProcess()) { + nsTObserverArray>::ForwardIterator + iter(mPlayingChildren); + while (iter.HasMore()) { + AudioChannelChildStatus* child = iter.GetNext(); + if (child->mActiveTelephonyChannel) { + return true; + } + } + } + + return false; +} + +bool +AudioChannelService::ContentOrNormalChannelIsActive() +{ + // This method is meant to be used just by the child to send status update. + MOZ_ASSERT(!IsParentProcess()); + + nsTObserverArray>::ForwardIterator iter(mWindows); + while (iter.HasMore()) { + AudioChannelWindow* next = iter.GetNext(); + if (next->mChannels[(uint32_t)AudioChannel::Content].mNumberOfAgents > 0 || + next->mChannels[(uint32_t)AudioChannel::Normal].mNumberOfAgents > 0) { + return true; + } + } + return false; +} + +AudioChannelService::AudioChannelChildStatus* +AudioChannelService::GetChildStatus(uint64_t aChildID) const +{ + nsTObserverArray>::ForwardIterator + iter(mPlayingChildren); + while (iter.HasMore()) { + AudioChannelChildStatus* child = iter.GetNext(); + if (child->mChildID == aChildID) { + return child; + } + } + + return nullptr; +} + +void +AudioChannelService::RemoveChildStatus(uint64_t aChildID) +{ + nsTObserverArray>::ForwardIterator + iter(mPlayingChildren); + while (iter.HasMore()) { + nsAutoPtr& child = iter.GetNext(); + if (child->mChildID == aChildID) { + mPlayingChildren.RemoveElement(child); + break; + } + } } bool AudioChannelService::ProcessContentOrNormalChannelIsActive(uint64_t aChildID) { - return mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].Contains(aChildID) || - mChannelCounters[AUDIO_CHANNEL_INT_CONTENT_HIDDEN].Contains(aChildID) || - mChannelCounters[AUDIO_CHANNEL_INT_NORMAL].Contains(aChildID); -} - -void -AudioChannelService::SetDefaultVolumeControlChannel(int32_t aChannel, - bool aVisible) -{ - SetDefaultVolumeControlChannelInternal(aChannel, aVisible, - CONTENT_PROCESS_ID_MAIN); -} - -void -AudioChannelService::SetDefaultVolumeControlChannelInternal(int32_t aChannel, - bool aVisible, - uint64_t aChildID) -{ - if (!XRE_IsParentProcess()) { - return; + AudioChannelChildStatus* child = GetChildStatus(aChildID); + if (!child) { + return false; } - // If this child is in the background and mDefChannelChildID is set to - // others then it means other child in the foreground already set it's - // own default channel already. - if (!aVisible && mDefChannelChildID != aChildID) { - return; - } - // Workaround for the call screen app. The call screen app is running on the - // main process, that will results in wrong visible state. Because we use the - // docshell's active state as visible state, the main process is always - // active. Therefore, we will see the strange situation that the visible - // state of the call screen is always true. If the mDefChannelChildID is set - // to others then it means other child in the foreground already set it's - // own default channel already. - // Summary : - // Child process : foreground app always can set type. - // Parent process : check the mDefChannelChildID. - else if (aChildID == CONTENT_PROCESS_ID_MAIN && - mDefChannelChildID != CONTENT_PROCESS_ID_UNKNOWN) { - return; - } - - mDefChannelChildID = aVisible ? aChildID : CONTENT_PROCESS_ID_UNKNOWN; - nsAutoString channelName; - if (aChannel == -1) { - channelName.AssignASCII("unknown"); - } else { - GetAudioChannelString(static_cast(aChannel), channelName); - } - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (obs) { - obs->NotifyObservers(nullptr, "default-volume-channel-changed", - channelName.get()); - } -} - -void -AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID) -{ - if (!XRE_IsParentProcess()) { - return; - } - - nsRefPtr props = new nsHashPropertyBag(); - props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), aChildID); - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (obs) { - obs->NotifyObservers(static_cast(props), - "audio-channel-process-changed", nullptr); - } - - // Calculating the most important active channel. - int32_t higher = -1; - - // Top-Down in the hierarchy for visible elements - if (!mChannelCounters[AUDIO_CHANNEL_INT_PUBLICNOTIFICATION].IsEmpty()) { - higher = static_cast(AudioChannel::Publicnotification); - } - - else if (!mChannelCounters[AUDIO_CHANNEL_INT_RINGER].IsEmpty()) { - higher = static_cast(AudioChannel::Ringer); - } - - else if (!mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY].IsEmpty()) { - higher = static_cast(AudioChannel::Telephony); - } - - else if (!mChannelCounters[AUDIO_CHANNEL_INT_ALARM].IsEmpty()) { - higher = static_cast(AudioChannel::Alarm); - } - - else if (!mChannelCounters[AUDIO_CHANNEL_INT_NOTIFICATION].IsEmpty()) { - higher = static_cast(AudioChannel::Notification); - } - - else if (!mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) { - higher = static_cast(AudioChannel::Content); - } - - else if (!mChannelCounters[AUDIO_CHANNEL_INT_NORMAL].IsEmpty()) { - higher = static_cast(AudioChannel::Normal); - } - - int32_t visibleHigher = higher; - - // Top-Down in the hierarchy for non-visible elements - // And we can ignore normal channel because it can't play in the background. - int32_t index; - for (index = 0; kMozAudioChannelAttributeTable[index].tag; ++index); - - for (--index; - kMozAudioChannelAttributeTable[index].value > higher && - kMozAudioChannelAttributeTable[index].value > (int16_t)AudioChannel::Normal; - --index) { - // Each channel type will be split to fg and bg for recording the state, - // so here need to do a translation. - if (mChannelCounters[index * 2 + 1].IsEmpty()) { - continue; - } - - if (kMozAudioChannelAttributeTable[index].value == (int16_t)AudioChannel::Content) { - if (mPlayableHiddenContentChildID != CONTENT_PROCESS_ID_UNKNOWN) { - higher = kMozAudioChannelAttributeTable[index].value; - break; - } - } else { - higher = kMozAudioChannelAttributeTable[index].value; - break; - } - } - - if (higher != mCurrentHigherChannel) { - mCurrentHigherChannel = higher; - - nsString channelName; - if (mCurrentHigherChannel != -1) { - GetAudioChannelString(static_cast(mCurrentHigherChannel), - channelName); - } else { - channelName.AssignLiteral("none"); - } - - if (obs) { - obs->NotifyObservers(nullptr, "audio-channel-changed", channelName.get()); - } - } - - if (visibleHigher != mCurrentVisibleHigherChannel) { - mCurrentVisibleHigherChannel = visibleHigher; - - nsString channelName; - if (mCurrentVisibleHigherChannel != -1) { - GetAudioChannelString(static_cast(mCurrentVisibleHigherChannel), - channelName); - } else { - channelName.AssignLiteral("none"); - } - - if (obs) { - obs->NotifyObservers(nullptr, "visible-audio-channel-changed", channelName.get()); - } - } -} - -PLDHashOperator -AudioChannelService::NotifyEnumerator(AudioChannelAgent* aAgent, - AudioChannelAgentData* aData, void* aUnused) -{ - MOZ_ASSERT(aAgent); - aAgent->NotifyAudioChannelStateChanged(); - return PL_DHASH_NEXT; -} - -class NotifyRunnable : public nsRunnable -{ -public: - explicit NotifyRunnable(AudioChannelService* aService) - : mService(aService) - {} - - NS_IMETHOD Run() - { - mService->Notify(); - return NS_OK; - } - -private: - nsRefPtr mService; -}; - -void -AudioChannelService::SendNotification() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (mRunnable) { - return; - } - - mRunnable = new NotifyRunnable(this); - NS_DispatchToCurrentThread(mRunnable); -} - -void -AudioChannelService::Notify() -{ - MOZ_ASSERT(NS_IsMainThread()); - mRunnable = nullptr; - - // Notify any agent for the main process. - mAgents.EnumerateRead(NotifyEnumerator, nullptr); - - // Notify for the child processes. - nsTArray children; - ContentParent::GetAll(children); - for (uint32_t i = 0; i < children.Length(); i++) { - unused << children[i]->SendAudioChannelNotify(); - } -} - -NS_IMETHODIMP -AudioChannelService::Notify(nsITimer* aTimer) -{ - UnregisterTypeInternal(AudioChannel::Telephony, mTimerElementHidden, - mTimerChildID, false); - mDeferTelChannelTimer = nullptr; - return NS_OK; + return child->mActiveContentOrNormalChannel; } bool AudioChannelService::AnyAudioChannelIsActive() { - for (int i = AUDIO_CHANNEL_INT_LAST - 1; - i >= AUDIO_CHANNEL_INT_NORMAL; --i) { - if (!mChannelCounters[i].IsEmpty()) { - return true; + nsTObserverArray>::ForwardIterator iter(mWindows); + while (iter.HasMore()) { + AudioChannelWindow* next = iter.GetNext(); + for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].tag; ++i) { + if (next->mChannels[kMozAudioChannelAttributeTable[i].value].mNumberOfAgents + != 0) { + return true; + } } } + if (IsParentProcess()) { + return !mPlayingChildren.IsEmpty(); + } + return false; } -bool -AudioChannelService::ChannelsActiveWithHigherPriorityThan( - AudioChannelInternalType aType) -{ - for (int i = AUDIO_CHANNEL_INT_LAST - 1; - i != AUDIO_CHANNEL_INT_CONTENT_HIDDEN; --i) { - if (i == aType) { - return false; - } - - if (!mChannelCounters[i].IsEmpty()) { - return true; - } - } - - return false; -} - -PLDHashOperator -AudioChannelService::WindowDestroyedEnumerator(AudioChannelAgent* aAgent, - nsAutoPtr& aData, - void* aPtr) -{ - auto* data = static_cast(aPtr); - MOZ_ASSERT(data); - - nsCOMPtr window = do_QueryInterface(aAgent->Window()); - if (window && !window->IsInnerWindow()) { - window = window->GetCurrentInnerWindow(); - } - - if (!window || window->WindowID() != data->mInnerID) { - return PL_DHASH_NEXT; - } - - AudioChannelService* service = AudioChannelService::GetAudioChannelService(); - MOZ_ASSERT(service); - - service->UnregisterType(aData->mChannel, aData->mElementHidden, - CONTENT_PROCESS_ID_MAIN, aData->mWithVideo); - data->mAgents.AppendElement(aAgent); - - return PL_DHASH_REMOVE; -} - NS_IMETHODIMP -AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) +AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { if (!strcmp(aTopic, "xpcom-shutdown")) { mDisabled = true; - } - - if (!strcmp(aTopic, "ipc:content-shutdown")) { - nsCOMPtr props = do_QueryInterface(aSubject); - if (!props) { - NS_WARNING("ipc:content-shutdown message without property bag as subject"); - return NS_OK; - } - - int32_t index; - uint64_t childID = 0; - nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), - &childID); - if (NS_SUCCEEDED(rv)) { - for (int32_t type = AUDIO_CHANNEL_INT_NORMAL; - type < AUDIO_CHANNEL_INT_LAST; - ++type) { - - while ((index = mChannelCounters[type].IndexOf(childID)) != -1) { - mChannelCounters[type].RemoveElementAt(index); - } - } - - // No hidden content channel is playable if the original playable hidden - // process shuts down. - if (mPlayableHiddenContentChildID == childID) { - mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN; - } - - while ((index = mWithVideoChildIDs.IndexOf(childID)) != -1) { - mWithVideoChildIDs.RemoveElementAt(index); - } - - // We don't have to remove the agents from the mAgents hashtable because if - // that table contains only agents running on the same process. - - SendAudioChannelChangedNotification(childID); - SendNotification(); - - if (mDefChannelChildID == childID) { - SetDefaultVolumeControlChannelInternal(-1, false, childID); - mDefChannelChildID = CONTENT_PROCESS_ID_UNKNOWN; - } - } else { - NS_WARNING("ipc:content-shutdown message without childID property"); - } + mWindows.Clear(); } #ifdef MOZ_WIDGET_GONK @@ -920,10 +518,27 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const ch return rv; } - WindowDestroyedEnumeratorData data(innerID); - mAgents.Enumerate(WindowDestroyedEnumerator, &data); - for (uint32_t i = 0, len = data.mAgents.Length(); i < len; ++i) { - data.mAgents[i]->NotifyAudioChannelStateChanged(); + nsAutoPtr winData; + { + nsTObserverArray>::ForwardIterator + iter(mWindows); + while (iter.HasMore()) { + nsAutoPtr& next = iter.GetNext(); + if (next->mWindowID == innerID) { + uint32_t pos = mWindows.IndexOf(next); + winData = next.forget(); + mWindows.RemoveElementAt(pos); + break; + } + } + } + + if (winData) { + nsTObserverArray::ForwardIterator + iter(winData->mAgents); + while (iter.HasMore()) { + iter.GetNext()->WindowVolumeChanged(); + } } #ifdef MOZ_WIDGET_GONK @@ -934,54 +549,29 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const ch #endif } - return NS_OK; -} + else if (!strcmp(aTopic, "ipc:content-shutdown")) { + nsCOMPtr props = do_QueryInterface(aSubject); + if (!props) { + NS_WARNING("ipc:content-shutdown message without property bag as subject"); + return NS_OK; + } -AudioChannelService::AudioChannelInternalType -AudioChannelService::GetInternalType(AudioChannel aChannel, - bool aElementHidden) -{ - switch (aChannel) { - case AudioChannel::Normal: - return aElementHidden - ? AUDIO_CHANNEL_INT_NORMAL_HIDDEN - : AUDIO_CHANNEL_INT_NORMAL; + uint64_t childID = 0; + nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), + &childID); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } - case AudioChannel::Content: - return aElementHidden - ? AUDIO_CHANNEL_INT_CONTENT_HIDDEN - : AUDIO_CHANNEL_INT_CONTENT; + if (mDefChannelChildID == childID) { + SetDefaultVolumeControlChannelInternal(-1, false, childID); + mDefChannelChildID = CONTENT_PROCESS_ID_UNKNOWN; + } - case AudioChannel::Notification: - return aElementHidden - ? AUDIO_CHANNEL_INT_NOTIFICATION_HIDDEN - : AUDIO_CHANNEL_INT_NOTIFICATION; - - case AudioChannel::Alarm: - return aElementHidden - ? AUDIO_CHANNEL_INT_ALARM_HIDDEN - : AUDIO_CHANNEL_INT_ALARM; - - case AudioChannel::Telephony: - return aElementHidden - ? AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN - : AUDIO_CHANNEL_INT_TELEPHONY; - - case AudioChannel::Ringer: - return aElementHidden - ? AUDIO_CHANNEL_INT_RINGER_HIDDEN - : AUDIO_CHANNEL_INT_RINGER; - - case AudioChannel::Publicnotification: - return aElementHidden - ? AUDIO_CHANNEL_INT_PUBLICNOTIFICATION_HIDDEN - : AUDIO_CHANNEL_INT_PUBLICNOTIFICATION; - - default: - break; + RemoveChildStatus(childID); } - MOZ_CRASH("unexpected audio channel"); + return NS_OK; } struct RefreshAgentsVolumeData @@ -994,69 +584,21 @@ struct RefreshAgentsVolumeData nsTArray> mAgents; }; -PLDHashOperator -AudioChannelService::RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent, - AudioChannelAgentData* aUnused, - void* aPtr) -{ - MOZ_ASSERT(aAgent); - RefreshAgentsVolumeData* data = static_cast(aPtr); - MOZ_ASSERT(data); - - nsCOMPtr window = do_QueryInterface(aAgent->Window()); - if (window && !window->IsInnerWindow()) { - window = window->GetCurrentInnerWindow(); - } - - if (window == data->mWindow) { - data->mAgents.AppendElement(aAgent); - } - - return PL_DHASH_NEXT; -} void AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow) { - RefreshAgentsVolumeData data(aWindow); - mAgents.EnumerateRead(RefreshAgentsVolumeEnumerator, &data); + MOZ_ASSERT(aWindow); - for (uint32_t i = 0; i < data.mAgents.Length(); ++i) { - data.mAgents[i]->WindowVolumeChanged(); - } -} - -struct CountWindowData -{ - explicit CountWindowData(nsIDOMWindow* aWindow) - : mWindow(aWindow) - , mCount(0) - {} - - nsIDOMWindow* mWindow; - uint32_t mCount; -}; - -PLDHashOperator -AudioChannelService::CountWindowEnumerator(AudioChannelAgent* aAgent, - AudioChannelAgentData* aUnused, - void* aPtr) -{ - CountWindowData* data = static_cast(aPtr); - MOZ_ASSERT(aAgent); - - if (aAgent->Window() == data->mWindow) { - ++data->mCount; + AudioChannelWindow* winData = GetWindowData(aWindow->WindowID()); + if (!winData) { + return; } - return PL_DHASH_NEXT; -} - -uint32_t -AudioChannelService::CountWindow(nsIDOMWindow* aWindow) -{ - CountWindowData data(aWindow); - mAgents.EnumerateRead(CountWindowEnumerator, &data); - return data.mCount; + nsTObserverArray::ForwardIterator + iter(winData->mAgents); + while (iter.HasMore()) { + iter.GetNext()->WindowVolumeChanged(); + } } /* static */ const nsAttrValue::EnumTable* @@ -1080,7 +622,7 @@ AudioChannelService::GetAudioChannel(const nsAString& aChannel) /* static */ AudioChannel AudioChannelService::GetDefaultAudioChannel() { - nsString audioChannel = Preferences::GetString("media.defaultAudioChannel"); + nsAutoString audioChannel(Preferences::GetString("media.defaultAudioChannel")); if (audioChannel.IsEmpty()) { return AudioChannel::Normal; } @@ -1114,7 +656,7 @@ AudioChannelService::GetDefaultAudioChannelString(nsAString& aString) { aString.AssignASCII("normal"); - nsString audioChannel = Preferences::GetString("media.defaultAudioChannel"); + nsAutoString audioChannel(Preferences::GetString("media.defaultAudioChannel")); if (!audioChannel.IsEmpty()) { for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].tag; ++i) { if (audioChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].tag)) { @@ -1125,38 +667,261 @@ AudioChannelService::GetDefaultAudioChannelString(nsAString& aString) } } -void -AudioChannelService::RegisterTelephonyChild(uint64_t aChildID) +AudioChannelService::AudioChannelWindow* +AudioChannelService::GetOrCreateWindowData(nsPIDOMWindow* aWindow) { - for (uint32_t i = 0, len = mTelephonyChildren.Length(); i < len; ++i) { - if (mTelephonyChildren[i].mChildID == aChildID) { - ++mTelephonyChildren[i].mInstances; + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsOuterWindow()); - if (i != len - 1) { - TelephonyChild child = mTelephonyChildren[i]; - mTelephonyChildren.RemoveElementAt(i); - mTelephonyChildren.AppendElement(child); - } + AudioChannelWindow* winData = GetWindowData(aWindow->WindowID()); + if (!winData) { + winData = new AudioChannelWindow(aWindow->WindowID()); + mWindows.AppendElement(winData); + } - return; + return winData; +} + +AudioChannelService::AudioChannelWindow* +AudioChannelService::GetWindowData(uint64_t aWindowID) const +{ + nsTObserverArray>::ForwardIterator + iter(mWindows); + while (iter.HasMore()) { + AudioChannelWindow* next = iter.GetNext(); + if (next->mWindowID == aWindowID) { + return next; } } - mTelephonyChildren.AppendElement(TelephonyChild(aChildID)); + return nullptr; +} + +float +AudioChannelService::GetAudioChannelVolume(nsPIDOMWindow* aWindow, + AudioChannel aAudioChannel) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsOuterWindow()); + + AudioChannelWindow* winData = GetOrCreateWindowData(aWindow); + return winData->mChannels[(uint32_t)aAudioChannel].mVolume; +} + +NS_IMETHODIMP +AudioChannelService::GetAudioChannelVolume(nsIDOMWindow* aWindow, + unsigned short aAudioChannel, + float* aVolume) +{ + nsCOMPtr window = GetTopWindow(aWindow); + *aVolume = GetAudioChannelVolume(window, (AudioChannel)aAudioChannel); + return NS_OK; } void -AudioChannelService::UnregisterTelephonyChild(uint64_t aChildID) +AudioChannelService::SetAudioChannelVolume(nsPIDOMWindow* aWindow, + AudioChannel aAudioChannel, + float aVolume) { - for (uint32_t i = 0, len = mTelephonyChildren.Length(); i < len; ++i) { - if (mTelephonyChildren[i].mChildID == aChildID) { - if (!--mTelephonyChildren[i].mInstances) { - mTelephonyChildren.RemoveElementAt(i); - } + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsOuterWindow()); - return; + AudioChannelWindow* winData = GetOrCreateWindowData(aWindow); + winData->mChannels[(uint32_t)aAudioChannel].mVolume = aVolume; + RefreshAgentsVolume(aWindow); +} + +NS_IMETHODIMP +AudioChannelService::SetAudioChannelVolume(nsIDOMWindow* aWindow, + unsigned short aAudioChannel, + float aVolume) +{ + nsCOMPtr window = GetTopWindow(aWindow); + SetAudioChannelVolume(window, (AudioChannel)aAudioChannel, aVolume); + return NS_OK; +} + +bool +AudioChannelService::GetAudioChannelMuted(nsPIDOMWindow* aWindow, + AudioChannel aAudioChannel) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsOuterWindow()); + + AudioChannelWindow* winData = GetOrCreateWindowData(aWindow); + return winData->mChannels[(uint32_t)aAudioChannel].mMuted; +} + +NS_IMETHODIMP +AudioChannelService::GetAudioChannelMuted(nsIDOMWindow* aWindow, + unsigned short aAudioChannel, + bool* aMuted) +{ + nsCOMPtr window = GetTopWindow(aWindow); + *aMuted = GetAudioChannelMuted(window, (AudioChannel)aAudioChannel); + return NS_OK; +} + +void +AudioChannelService::SetAudioChannelMuted(nsPIDOMWindow* aWindow, + AudioChannel aAudioChannel, + bool aMuted) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsOuterWindow()); + + AudioChannelWindow* winData = GetOrCreateWindowData(aWindow); + winData->mChannels[(uint32_t)aAudioChannel].mMuted = aMuted; + RefreshAgentsVolume(aWindow); +} + +NS_IMETHODIMP +AudioChannelService::SetAudioChannelMuted(nsIDOMWindow* aWindow, + unsigned short aAudioChannel, + bool aMuted) +{ + nsCOMPtr window = GetTopWindow(aWindow); + SetAudioChannelMuted(window, (AudioChannel)aAudioChannel, aMuted); + return NS_OK; +} + +bool +AudioChannelService::IsAudioChannelActive(nsPIDOMWindow* aWindow, + AudioChannel aAudioChannel) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aWindow); + MOZ_ASSERT(aWindow->IsOuterWindow()); + + AudioChannelWindow* winData = GetOrCreateWindowData(aWindow); + return !!winData->mChannels[(uint32_t)aAudioChannel].mNumberOfAgents; +} + +NS_IMETHODIMP +AudioChannelService::IsAudioChannelActive(nsIDOMWindow* aWindow, + unsigned short aAudioChannel, + bool* aActive) +{ + nsCOMPtr window = GetTopWindow(aWindow); + *aActive = IsAudioChannelActive(window, (AudioChannel)aAudioChannel); + return NS_OK; +} +void +AudioChannelService::SetDefaultVolumeControlChannel(int32_t aChannel, + bool aVisible) +{ + SetDefaultVolumeControlChannelInternal(aChannel, aVisible, + CONTENT_PROCESS_ID_MAIN); +} + +void +AudioChannelService::SetDefaultVolumeControlChannelInternal(int32_t aChannel, + bool aVisible, + uint64_t aChildID) +{ + if (!IsParentProcess()) { + ContentChild* cc = ContentChild::GetSingleton(); + if (cc) { + cc->SendAudioChannelChangeDefVolChannel(aChannel, aVisible); } + + return; } - MOZ_ASSERT(false, "This should not happen."); + // If this child is in the background and mDefChannelChildID is set to + // others then it means other child in the foreground already set it's + // own default channel. + if (!aVisible && mDefChannelChildID != aChildID) { + return; + } + + // Workaround for the call screen app. The call screen app is running on the + // main process, that will results in wrong visible state. Because we use the + // docshell's active state as visible state, the main process is always + // active. Therefore, we will see the strange situation that the visible + // state of the call screen is always true. If the mDefChannelChildID is set + // to others then it means other child in the foreground already set it's + // own default channel already. + // Summary : + // Child process : foreground app always can set type. + // Parent process : check the mDefChannelChildID. + else if (aChildID == CONTENT_PROCESS_ID_MAIN && + mDefChannelChildID != CONTENT_PROCESS_ID_UNKNOWN) { + return; + } + + mDefChannelChildID = aVisible ? aChildID : CONTENT_PROCESS_ID_UNKNOWN; + nsAutoString channelName; + + if (aChannel == -1) { + channelName.AssignASCII("unknown"); + } else { + GetAudioChannelString(static_cast(aChannel), channelName); + } + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + obs->NotifyObservers(nullptr, "default-volume-channel-changed", + channelName.get()); + } +} + +void +AudioChannelService::MaybeSendStatusUpdate() +{ + if (IsParentProcess()) { + return; + } + + bool telephonyChannel = TelephonyChannelIsActive(); + bool contentOrNormalChannel = ContentOrNormalChannelIsActive(); + bool anyChannel = AnyAudioChannelIsActive(); + + if (telephonyChannel == mTelephonyChannel && + contentOrNormalChannel == mContentOrNormalChannel && + anyChannel == mAnyChannel) { + return; + } + + mTelephonyChannel = telephonyChannel; + mContentOrNormalChannel = contentOrNormalChannel; + mAnyChannel = anyChannel; + + ContentChild* cc = ContentChild::GetSingleton(); + if (cc) { + cc->SendAudioChannelServiceStatus(telephonyChannel, contentOrNormalChannel, + anyChannel); + } +} + +void +AudioChannelService::ChildStatusReceived(uint64_t aChildID, + bool aTelephonyChannel, + bool aContentOrNormalChannel, + bool aAnyChannel) +{ + if (!aAnyChannel) { + RemoveChildStatus(aChildID); + return; + } + + AudioChannelChildStatus* data = GetChildStatus(aChildID); + if (!data) { + data = new AudioChannelChildStatus(aChildID); + mPlayingChildren.AppendElement(data); + } + + data->mActiveTelephonyChannel = aTelephonyChannel; + data->mActiveContentOrNormalChannel = aContentOrNormalChannel; +} + +/* static */ bool +AudioChannelService::IsAudioChannelMutedByDefault() +{ + return sAudioChannelMutedByDefault; } diff --git a/dom/audiochannel/AudioChannelService.h b/dom/audiochannel/AudioChannelService.h index 8e20c92b53e..65f312d236b 100644 --- a/dom/audiochannel/AudioChannelService.h +++ b/dom/audiochannel/AudioChannelService.h @@ -7,15 +7,14 @@ #ifndef mozilla_dom_audiochannelservice_h__ #define mozilla_dom_audiochannelservice_h__ +#include "nsIAudioChannelService.h" #include "nsAutoPtr.h" #include "nsIObserver.h" +#include "nsTObserverArray.h" #include "nsTArray.h" -#include "nsITimer.h" -#include "AudioChannelCommon.h" #include "AudioChannelAgent.h" #include "nsAttrValue.h" -#include "nsClassHashtable.h" #include "mozilla/dom/AudioChannelBinding.h" class nsIRunnable; @@ -26,71 +25,74 @@ namespace dom { #ifdef MOZ_WIDGET_GONK class SpeakerManagerService; #endif -class AudioChannelService -: public nsIObserver -, public nsITimerCallback + +#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::Publicnotification + 1 + +class AudioChannelService final : public nsIAudioChannelService + , public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER - NS_DECL_NSITIMERCALLBACK - - /** - * Returns the AudioChannelServce singleton or null if the process havn't create it before. - * Only to be called from main thread. - */ - static AudioChannelService* GetAudioChannelService(); + NS_DECL_NSIAUDIOCHANNELSERVICE /** * Returns the AudioChannelServce singleton. * If AudioChannelServce is not exist, create and return new one. * Only to be called from main thread. */ - static AudioChannelService* GetOrCreateAudioChannelService(); + static already_AddRefed GetOrCreate(); /** * Shutdown the singleton. */ static void Shutdown(); + static bool IsAudioChannelMutedByDefault(); + /** * Any audio channel agent that starts playing should register itself to * this service, sharing the AudioChannel. */ - virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent, - AudioChannel aChannel, - bool aWithVideo); + void RegisterAudioChannelAgent(AudioChannelAgent* aAgent, AudioChannel aChannel); /** * Any audio channel agent that stops playing should unregister itself to * this service. */ - virtual void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent); + void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent); /** - * Return the state to indicate this agent should keep playing/ - * fading volume/muted. + * Return the state to indicate this audioChannel for his window should keep + * playing/muted. */ - virtual AudioChannelState GetState(AudioChannelAgent* aAgent, - bool aElementHidden); + void GetState(nsPIDOMWindow* aWindow, uint32_t aChannel, + float* aVolume, bool* aMuted); - /** - * Return true if there is a content channel active in this process - * or one of its subprocesses. - */ - virtual bool ContentOrNormalChannelIsActive(); + /* Methods for the BrowserElementAudioChannel */ + float GetAudioChannelVolume(nsPIDOMWindow* aWindow, AudioChannel aChannel); + + void SetAudioChannelVolume(nsPIDOMWindow* aWindow, AudioChannel aChannel, + float aVolume); + + bool GetAudioChannelMuted(nsPIDOMWindow* aWindow, AudioChannel aChannel); + + void SetAudioChannelMuted(nsPIDOMWindow* aWindow, AudioChannel aChannel, + bool aMuted); + + bool IsAudioChannelActive(nsPIDOMWindow* aWindow, AudioChannel aChannel); /** * Return true if there is a telephony channel active in this process * or one of its subprocesses. */ - virtual bool TelephonyChannelIsActive(); + bool TelephonyChannelIsActive(); /** * Return true if a normal or content channel is active for the given * process ID. */ - virtual bool ProcessContentOrNormalChannelIsActive(uint64_t aChildID); + bool ProcessContentOrNormalChannelIsActive(uint64_t aChildID); /*** * AudioChannelManager calls this function to notify the default channel used @@ -125,163 +127,95 @@ public: static void GetAudioChannelString(AudioChannel aChannel, nsAString& aString); static void GetDefaultAudioChannelString(nsAString& aString); - void Notify(); + void Notify(uint64_t aWindowID); -protected: - void SendNotification(); + void ChildStatusReceived(uint64_t aChildID, bool aTelephonyChannel, + bool aContentOrNormalChannel, bool aAnyChannel); - /** - * Send the audio-channel-changed notification for the given process ID if - * needed. - */ - void SendAudioChannelChangedNotification(uint64_t aChildID); +private: + AudioChannelService(); + ~AudioChannelService(); - /* Register/Unregister IPC types: */ - void RegisterType(AudioChannel aChannel, uint64_t aChildID, bool aWithVideo); - void UnregisterType(AudioChannel aChannel, bool aElementHidden, - uint64_t aChildID, bool aWithVideo); - void UnregisterTypeInternal(AudioChannel aChannel, bool aElementHidden, - uint64_t aChildID, bool aWithVideo); + void MaybeSendStatusUpdate(); - AudioChannelState GetStateInternal(AudioChannel aChannel, uint64_t aChildID, - bool aElementHidden, - bool aElementWasHidden); - - /* Update the internal type value following the visibility changes */ - void UpdateChannelType(AudioChannel aChannel, uint64_t aChildID, - bool aElementHidden, bool aElementWasHidden); + bool ContentOrNormalChannelIsActive(); /* Send the default-volume-channel-changed notification */ void SetDefaultVolumeControlChannelInternal(int32_t aChannel, bool aVisible, uint64_t aChildID); - AudioChannelState CheckTelephonyPolicy(AudioChannel aChannel, - uint64_t aChildID); - void RegisterTelephonyChild(uint64_t aChildID); - void UnregisterTelephonyChild(uint64_t aChildID); - - AudioChannelService(); - virtual ~AudioChannelService(); - - enum AudioChannelInternalType { - AUDIO_CHANNEL_INT_NORMAL = 0, - AUDIO_CHANNEL_INT_NORMAL_HIDDEN, - AUDIO_CHANNEL_INT_CONTENT, - AUDIO_CHANNEL_INT_CONTENT_HIDDEN, - AUDIO_CHANNEL_INT_NOTIFICATION, - AUDIO_CHANNEL_INT_NOTIFICATION_HIDDEN, - AUDIO_CHANNEL_INT_ALARM, - AUDIO_CHANNEL_INT_ALARM_HIDDEN, - AUDIO_CHANNEL_INT_TELEPHONY, - AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN, - AUDIO_CHANNEL_INT_RINGER, - AUDIO_CHANNEL_INT_RINGER_HIDDEN, - AUDIO_CHANNEL_INT_PUBLICNOTIFICATION, - AUDIO_CHANNEL_INT_PUBLICNOTIFICATION_HIDDEN, - AUDIO_CHANNEL_INT_LAST - }; - - bool ChannelsActiveWithHigherPriorityThan(AudioChannelInternalType aType); - - bool CheckVolumeFadedCondition(AudioChannelInternalType aType, - bool aElementHidden); - - AudioChannelInternalType GetInternalType(AudioChannel aChannel, - bool aElementHidden); - - class AudioChannelAgentData { - public: - AudioChannelAgentData(AudioChannel aChannel, - bool aElementHidden, - AudioChannelState aState, - bool aWithVideo) - : mChannel(aChannel) - , mElementHidden(aElementHidden) - , mState(aState) - , mWithVideo(aWithVideo) + struct AudioChannelConfig final + { + AudioChannelConfig() + : mVolume(1.0) + , mMuted(IsAudioChannelMutedByDefault()) + , mNumberOfAgents(0) {} - AudioChannel mChannel; - bool mElementHidden; - AudioChannelState mState; - const bool mWithVideo; + float mVolume; + bool mMuted; + + uint32_t mNumberOfAgents; }; - static PLDHashOperator - NotifyEnumerator(AudioChannelAgent* aAgent, - AudioChannelAgentData* aData, void *aUnused); + struct AudioChannelWindow final + { + explicit AudioChannelWindow(uint64_t aWindowID) + : mWindowID(aWindowID) + {} - static PLDHashOperator - RefreshAgentsVolumeEnumerator(AudioChannelAgent* aAgent, - AudioChannelAgentData* aUnused, - void *aPtr); + uint64_t mWindowID; + AudioChannelConfig mChannels[NUMBER_OF_AUDIO_CHANNELS]; - static PLDHashOperator - CountWindowEnumerator(AudioChannelAgent* aAgent, - AudioChannelAgentData* aUnused, - void *aPtr); + // Raw pointer because the AudioChannelAgent must unregister itself. + nsTObserverArray mAgents; + }; - static PLDHashOperator - WindowDestroyedEnumerator(AudioChannelAgent* aAgent, - nsAutoPtr& aData, - void *aPtr); + AudioChannelWindow* + GetOrCreateWindowData(nsPIDOMWindow* aWindow); - // This returns the number of agents from this aWindow. - uint32_t CountWindow(nsIDOMWindow* aWindow); + AudioChannelWindow* + GetWindowData(uint64_t aWindowID) const; + + struct AudioChannelChildStatus final + { + explicit AudioChannelChildStatus(uint64_t aChildID) + : mChildID(aChildID) + , mActiveTelephonyChannel(false) + , mActiveContentOrNormalChannel(false) + {} + + uint64_t mChildID; + bool mActiveTelephonyChannel; + bool mActiveContentOrNormalChannel; + }; + + AudioChannelChildStatus* + GetChildStatus(uint64_t aChildID) const; + + void + RemoveChildStatus(uint64_t aChildID); + + nsTObserverArray> mWindows; + + nsTObserverArray> mPlayingChildren; - nsClassHashtable< nsPtrHashKey, AudioChannelAgentData > mAgents; #ifdef MOZ_WIDGET_GONK nsTArray mSpeakerManager; #endif - nsTArray mChannelCounters[AUDIO_CHANNEL_INT_LAST]; - - int32_t mCurrentHigherChannel; - int32_t mCurrentVisibleHigherChannel; - - nsTArray mWithVideoChildIDs; - - // Telephony Channel policy is "LIFO", the last app to require the resource is - // allowed to play. The others are muted. - struct TelephonyChild { - uint64_t mChildID; - uint32_t mInstances; - - explicit TelephonyChild(uint64_t aChildID) - : mChildID(aChildID) - , mInstances(1) - {} - }; - nsTArray mTelephonyChildren; - - // mPlayableHiddenContentChildID stores the ChildID of the process which can - // play content channel(s) in the background. - // A background process contained content channel(s) will become playable: - // 1. When this background process registers its content channel(s) in - // AudioChannelService and there is no foreground process with registered - // content channel(s). - // 2. When this process goes from foreground into background and there is - // no foreground process with registered content channel(s). - // A background process contained content channel(s) will become non-playable: - // 1. When there is a foreground process registering its content channel(s) - // in AudioChannelService. - // ps. Currently this condition is never satisfied because the default value - // of visibility status of each channel during registering is hidden = true. - // 2. When there is a process with registered content channel(s) goes from - // background into foreground. - // 3. When this process unregisters all hidden content channels. - // 4. When this process shuts down. - uint64_t mPlayableHiddenContentChildID; bool mDisabled; nsCOMPtr mRunnable; - nsCOMPtr mDeferTelChannelTimer; - bool mTimerElementHidden; - uint64_t mTimerChildID; - uint64_t mDefChannelChildID; + // These boolean are used to know if we have to send an status update to the + // service running in the main process. + bool mTelephonyChannel; + bool mContentOrNormalChannel; + bool mAnyChannel; + // This is needed for IPC comunication between // AudioChannelServiceChild and this class. friend class ContentParent; diff --git a/dom/audiochannel/AudioChannelServiceChild.cpp b/dom/audiochannel/AudioChannelServiceChild.cpp deleted file mode 100644 index ba23feb8ba7..00000000000 --- a/dom/audiochannel/AudioChannelServiceChild.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=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/. */ - -#include "AudioChannelServiceChild.h" - -#include "base/basictypes.h" - -#include "mozilla/Services.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/unused.h" -#include "mozilla/dom/ContentChild.h" -#include "mozilla/dom/ContentParent.h" -#include "nsIObserverService.h" -#include "nsThreadUtils.h" - -#ifdef MOZ_WIDGET_GONK -#include "SpeakerManagerService.h" -#endif - -using namespace mozilla; -using namespace mozilla::dom; -using namespace mozilla::hal; - -StaticRefPtr gAudioChannelServiceChild; - -// static -AudioChannelService* -AudioChannelServiceChild::GetAudioChannelService() -{ - MOZ_ASSERT(NS_IsMainThread()); - - return gAudioChannelServiceChild; - -} - -// static -AudioChannelService* -AudioChannelServiceChild::GetOrCreateAudioChannelService() -{ - MOZ_ASSERT(NS_IsMainThread()); - - // If we already exist, exit early - if (gAudioChannelServiceChild) { - return gAudioChannelServiceChild; - } - - // Create new instance, register, return - nsRefPtr service = new AudioChannelServiceChild(); - MOZ_ASSERT(service); - - gAudioChannelServiceChild = service; - return gAudioChannelServiceChild; -} - -void -AudioChannelServiceChild::Shutdown() -{ - if (gAudioChannelServiceChild) { - gAudioChannelServiceChild = nullptr; - } -} - -AudioChannelServiceChild::AudioChannelServiceChild() -{ -} - -AudioChannelServiceChild::~AudioChannelServiceChild() -{ -} - -AudioChannelState -AudioChannelServiceChild::GetState(AudioChannelAgent* aAgent, bool aElementHidden) -{ - AudioChannelAgentData* data; - if (!mAgents.Get(aAgent, &data)) { - return AUDIO_CHANNEL_STATE_MUTED; - } - - AudioChannelState state = AUDIO_CHANNEL_STATE_MUTED; - bool oldElementHidden = data->mElementHidden; - - UpdateChannelType(data->mChannel, CONTENT_PROCESS_ID_MAIN, aElementHidden, - oldElementHidden); - - // Update visibility. - data->mElementHidden = aElementHidden; - - ContentChild* cc = ContentChild::GetSingleton(); - cc->SendAudioChannelGetState(data->mChannel, aElementHidden, oldElementHidden, - &state); - data->mState = state; - cc->SendAudioChannelChangedNotification(); - - #ifdef MOZ_WIDGET_GONK - /** Only modify the speaker status when - * (1) apps in the foreground. - * (2) apps in the backgrund and inactive. - * Notice : modify only when the visible status is stable, because there - * has lantency in passing the visibility events. - **/ - bool active = AnyAudioChannelIsActive(); - if (aElementHidden == oldElementHidden && - (!aElementHidden || (aElementHidden && !active))) { - for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) { - mSpeakerManager[i]->SetAudioChannelActive(active); - } - } - #endif - - return state; -} - -void -AudioChannelServiceChild::RegisterAudioChannelAgent(AudioChannelAgent* aAgent, - AudioChannel aChannel, - bool aWithVideo) -{ - AudioChannelService::RegisterAudioChannelAgent(aAgent, aChannel, aWithVideo); - - ContentChild::GetSingleton()->SendAudioChannelRegisterType(aChannel, aWithVideo); - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (obs) { - obs->NotifyObservers(nullptr, "audio-channel-agent-changed", nullptr); - } -} - -void -AudioChannelServiceChild::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent) -{ - AudioChannelAgentData *pData; - if (!mAgents.Get(aAgent, &pData)) { - return; - } - - // We need to keep a copy because unregister will remove the - // AudioChannelAgentData object from the hashtable. - AudioChannelAgentData data(*pData); - - AudioChannelService::UnregisterAudioChannelAgent(aAgent); - - ContentChild::GetSingleton()->SendAudioChannelUnregisterType( - data.mChannel, data.mElementHidden, data.mWithVideo); - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (obs) { - obs->NotifyObservers(nullptr, "audio-channel-agent-changed", nullptr); - } -#ifdef MOZ_WIDGET_GONK - bool active = AnyAudioChannelIsActive(); - for (uint32_t i = 0; i < mSpeakerManager.Length(); i++) { - mSpeakerManager[i]->SetAudioChannelActive(active); - } -#endif -} - -void -AudioChannelServiceChild::SetDefaultVolumeControlChannel(int32_t aChannel, - bool aHidden) -{ - ContentChild *cc = ContentChild::GetSingleton(); - if (cc) { - cc->SendAudioChannelChangeDefVolChannel(aChannel, aHidden); - } -} diff --git a/dom/audiochannel/AudioChannelServiceChild.h b/dom/audiochannel/AudioChannelServiceChild.h deleted file mode 100644 index 503033495c5..00000000000 --- a/dom/audiochannel/AudioChannelServiceChild.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=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/. */ - -#ifndef mozilla_dom_audiochannelservicechild_h__ -#define mozilla_dom_audiochannelservicechild_h__ - -#include "nsAutoPtr.h" -#include "nsISupports.h" - -#include "AudioChannelService.h" -#include "AudioChannelCommon.h" - -namespace mozilla { -namespace dom { - -class AudioChannelServiceChild : public AudioChannelService -{ -public: - - /** - * Returns the AudioChannelServce singleton or null if the process havn't create it before. - * Only to be called from main thread. - */ - static AudioChannelService* GetAudioChannelService(); - - /** - * Returns the AudioChannelServce singleton. - * If AudioChannelServce is not exist, create and return new one. - * Only to be called from main thread. - */ - static AudioChannelService* GetOrCreateAudioChannelService(); - - static void Shutdown(); - - virtual void RegisterAudioChannelAgent(AudioChannelAgent* aAgent, - AudioChannel aChannel, - bool aWithVideo); - virtual void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent); - - /** - * Return the state to indicate this agent should keep playing/ - * fading volume/muted. - */ - virtual AudioChannelState GetState(AudioChannelAgent* aAgent, - bool aElementHidden); - - virtual void SetDefaultVolumeControlChannel(int32_t aChannel, - bool aHidden); - -protected: - AudioChannelServiceChild(); - virtual ~AudioChannelServiceChild(); -}; - -} // namespace dom -} // namespace mozilla - -#endif - diff --git a/dom/audiochannel/moz.build b/dom/audiochannel/moz.build index 00803501bc4..cc8b71ffd0c 100644 --- a/dom/audiochannel/moz.build +++ b/dom/audiochannel/moz.build @@ -4,25 +4,21 @@ # 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/. -TEST_DIRS += ['tests'] - XPIDL_SOURCES += [ 'nsIAudioChannelAgent.idl', + 'nsIAudioChannelService.idl', ] XPIDL_MODULE = 'dom_audiochannel' EXPORTS += [ 'AudioChannelAgent.h', - 'AudioChannelCommon.h', 'AudioChannelService.h', - 'AudioChannelServiceChild.h', ] UNIFIED_SOURCES += [ 'AudioChannelAgent.cpp', 'AudioChannelService.cpp', - 'AudioChannelServiceChild.cpp', ] FAIL_ON_WARNINGS = True diff --git a/dom/audiochannel/nsIAudioChannelAgent.idl b/dom/audiochannel/nsIAudioChannelAgent.idl index e990d3959ab..e344a6613c6 100644 --- a/dom/audiochannel/nsIAudioChannelAgent.idl +++ b/dom/audiochannel/nsIAudioChannelAgent.idl @@ -6,24 +6,13 @@ interface nsIDOMWindow; -[uuid(194b55d9-39c0-45c6-b8ef-b8049f978ea5)] +[uuid(4f537c88-3722-4946-9a09-ce559fa0591d)] interface nsIAudioChannelAgentCallback : nsISupports { - /** - * Notified when the playable status of channel is changed. - * - * @param canPlay - * Callback from agent to notify component of the playable status - * of the channel. If canPlay is muted state, component SHOULD stop - * playing media associated with this channel as soon as possible. if - * it is faded state then the volume of media should be reduced. - */ - void canPlayChanged(in long canPlay); - /** * Notified when the window volume/mute is changed */ - void windowVolumeChanged(); + void windowVolumeChanged(in float aVolume, in bool aMuted); }; /** @@ -40,7 +29,7 @@ interface nsIAudioChannelAgentCallback : nsISupports * 1. Changes to the playable status of this channel. */ -[uuid(2b0222a5-8f7b-49d2-9ab8-cd01b744b23e)] +[uuid(e28e1569-2a44-4f71-9cd0-216874b05d57)] interface nsIAudioChannelAgent : nsISupports { const long AUDIO_AGENT_CHANNEL_NORMAL = 0; @@ -62,6 +51,13 @@ interface nsIAudioChannelAgent : nsISupports */ readonly attribute long audioChannelType; + %{C++ + inline int32_t AudioChannelType() { + int32_t channel; + return NS_SUCCEEDED(GetAudioChannelType(&channel)) ? channel : AUDIO_AGENT_CHANNEL_ERROR; + } + %} + /** * Initialize the agent with a channel type. * Note: This function should only be called once. @@ -91,16 +87,6 @@ interface nsIAudioChannelAgent : nsISupports void initWithWeakCallback(in nsIDOMWindow window, in long channelType, in nsIAudioChannelAgentCallback callback); - /** - * This method is just like init(), and specify the channel is associated - * with video. - * - * @param weak - * true if weak reference should be hold. - */ - void initWithVideo(in nsIDOMWindow window, in long channelType, - in nsIAudioChannelAgentCallback callback, in boolean weak); - /** * Notify the agent that we want to start playing. * Note: Gecko component SHOULD call this function first then start to @@ -115,28 +101,15 @@ interface nsIAudioChannelAgent : nsISupports * faded state: the agent has registered with audio channel service the * component should start playback as well as reducing the volume. */ - long startPlaying(); + void notifyStartedPlaying(out float volume, out bool muted); /** * Notify the agent we no longer want to play. * - * Note : even if startPlaying() returned false, the agent would still be - * registered with the audio channel service and receive callbacks for status changes. - * So stopPlaying must still eventually be called to unregister the agent with the - * channel service. + * Note : even if notifyStartedPlaying() returned false, the agent would + * still be registered with the audio channel service and receive callbacks + * for status changes. So notifyStoppedPlaying must still eventually be + * called to unregister the agent with the channel service. */ - void stopPlaying(); - - /** - * Notify the agent of the visibility state of the window using this agent. - * @param visible - * True if the window associated with the agent is visible. - */ - void setVisibilityState(in boolean visible); - - /** - * Retrieve the volume from the window. - */ - readonly attribute float windowVolume; + void notifyStoppedPlaying(); }; - diff --git a/dom/audiochannel/nsIAudioChannelService.idl b/dom/audiochannel/nsIAudioChannelService.idl new file mode 100644 index 00000000000..8cdc0379d26 --- /dev/null +++ b/dom/audiochannel/nsIAudioChannelService.idl @@ -0,0 +1,29 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "nsISupports.idl" + +interface nsIDOMWindow; + +[scriptable, builtinclass, uuid(323e5472-b8f4-4288-b1b9-53c7c54bbbe8)] +interface nsIAudioChannelService : nsISupports +{ + float getAudioChannelVolume(in nsIDOMWindow window, + in unsigned short audioChannel); + + void setAudioChannelVolume(in nsIDOMWindow window, + in unsigned short audioChannel, + in float volume); + + boolean getAudioChannelMuted(in nsIDOMWindow window, + in unsigned short audioChannel); + + void setAudioChannelMuted(in nsIDOMWindow window, + in unsigned short audioChannel, + in boolean muted); + + boolean isAudioChannelActive(in nsIDOMWindow window, + in unsigned short audioChannel); +}; diff --git a/dom/audiochannel/tests/AudioChannelChromeScript.js b/dom/audiochannel/tests/AudioChannelChromeScript.js deleted file mode 100644 index 46bd7d30791..00000000000 --- a/dom/audiochannel/tests/AudioChannelChromeScript.js +++ /dev/null @@ -1,18 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; -const { Services } = Cu.import('resource://gre/modules/Services.jsm'); -const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm'); - -addMessageListener('init-chrome-event', function(message) { - // listen mozChromeEvent and forward to content process. - let type = message.type; - - SystemAppProxy.addEventListener('mozChromeEvent', function(event) { - let details = event.detail; - if (details.type === type) { - sendAsyncMessage('chrome-event', details); - } - }, true); -}); diff --git a/dom/audiochannel/tests/TestAudioChannelService.cpp b/dom/audiochannel/tests/TestAudioChannelService.cpp deleted file mode 100644 index 9d6a6d1a40d..00000000000 --- a/dom/audiochannel/tests/TestAudioChannelService.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=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/. */ -#ifdef XP_WIN -#include -#else -#include -#endif - -#include "TestHarness.h" - -#include "nsWeakReference.h" -#include "AudioChannelService.h" -#include "AudioChannelAgent.h" - -#include "nsThreadUtils.h" - -#define TEST_ENSURE_BASE(_test, _msg) \ - PR_BEGIN_MACRO \ - if (!(_test)) { \ - fail(_msg); \ - return NS_ERROR_FAILURE; \ - } else { \ - passed(_msg); \ - } \ - PR_END_MACRO - -using namespace mozilla::dom; - -void -spin_events_loop_until_false(const bool* const aCondition) -{ - nsCOMPtr thread(::do_GetCurrentThread()); - nsresult rv = NS_OK; - bool processed = true; - while (*aCondition && NS_SUCCEEDED(rv)) { - rv = thread->ProcessNextEvent(true, &processed); - } -} - -class Agent : public nsIAudioChannelAgentCallback, - public nsSupportsWeakReference -{ -protected: - virtual ~Agent() - { - if (mRegistered) { - StopPlaying(); - } - } - -public: - NS_DECL_ISUPPORTS - - explicit Agent(AudioChannel aChannel) - : mChannel(aChannel) - , mWaitCallback(false) - , mRegistered(false) - , mCanPlay(AUDIO_CHANNEL_STATE_MUTED) - { - mAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1"); - } - - nsresult Init(bool video=false) - { - nsresult rv = NS_OK; - if (video) { - rv = mAgent->InitWithVideo(nullptr, static_cast(mChannel), - this, true); - } - else { - rv = mAgent->InitWithWeakCallback(nullptr, static_cast(mChannel), - this); - } - NS_ENSURE_SUCCESS(rv, rv); - - return mAgent->SetVisibilityState(false); - } - - nsresult StartPlaying(AudioChannelState *_ret) - { - if (mRegistered) { - StopPlaying(); - } - - nsresult rv = mAgent->StartPlaying((int32_t *)_ret); - mRegistered = true; - return rv; - } - - nsresult StopPlaying() - { - mRegistered = false; - spin_events_loop_until_false(&mWaitCallback); - return mAgent->StopPlaying(); - } - - nsresult SetVisibilityState(bool visible) - { - if (mRegistered) { - mWaitCallback = true; - } - return mAgent->SetVisibilityState(visible); - } - - NS_IMETHODIMP CanPlayChanged(int32_t canPlay) override - { - mCanPlay = static_cast(canPlay); - mWaitCallback = false; - return NS_OK; - } - - NS_IMETHODIMP WindowVolumeChanged() override - { - return NS_OK; - } - - nsresult GetCanPlay(AudioChannelState *_ret, bool aWaitCallback = false) - { - if (aWaitCallback) { - mWaitCallback = true; - } - - spin_events_loop_until_false(&mWaitCallback); - *_ret = mCanPlay; - return NS_OK; - } - - nsCOMPtr mAgent; - AudioChannel mChannel; - bool mWaitCallback; - bool mRegistered; - AudioChannelState mCanPlay; -}; - -NS_IMPL_ISUPPORTS(Agent, nsIAudioChannelAgentCallback, - nsISupportsWeakReference) - -nsresult -TestDoubleStartPlaying() -{ - nsRefPtr agent = new Agent(AudioChannel::Normal); - - nsresult rv = agent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - AudioChannelState playable; - rv = agent->mAgent->StartPlaying((int32_t *)&playable); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent->mAgent->StartPlaying((int32_t *)&playable); - TEST_ENSURE_BASE(NS_FAILED(rv), - "Test0: StartPlaying calling twice must return error"); - - return NS_OK; -} - -nsresult -TestOneNormalChannel() -{ - nsRefPtr agent = new Agent(AudioChannel::Normal); - nsresult rv = agent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - AudioChannelState playable; - rv = agent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test1: A normal channel unvisible agent must be muted"); - - rv = agent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test1: A normal channel visible agent must be playable"); - - return rv; -} - -nsresult -TestTwoNormalChannels() -{ - nsRefPtr agent1 = new Agent(AudioChannel::Normal); - nsresult rv = agent1->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr agent2 = new Agent(AudioChannel::Normal); - rv = agent2->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - AudioChannelState playable; - rv = agent1->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test2: A normal channel unvisible agent1 must be muted"); - - rv = agent2->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test2: A normal channel unvisible agent2 must be muted"); - - rv = agent1->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent2->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent1->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test2: A normal channel visible agent1 must be playable"); - - rv = agent2->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test2: A normal channel visible agent2 must be playable"); - - return rv; -} - -nsresult -TestContentChannels() -{ - nsRefPtr agent1 = new Agent(AudioChannel::Content); - nsresult rv = agent1->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr agent2 = new Agent(AudioChannel::Content); - rv = agent2->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - // All content channels in the foreground can be allowed to play - rv = agent1->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent2->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - AudioChannelState playable; - rv = agent1->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test3: A content channel visible agent1 must be playable"); - - rv = agent2->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test3: A content channel visible agent2 must be playable"); - - // Test the transition state of one content channel tried to set non-visible - // state first when app is going to background. - rv = agent1->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent1->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test3: A content channel unvisible agent1 must be playable from " - "foreground to background"); - - // Test all content channels set non-visible already - rv = agent2->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent2->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test3: A content channel unvisible agent2 must be playable from " - "foreground to background"); - - // Clear the content channels & mActiveContentChildIDs in AudioChannelService. - // If agent stop playable in the background, we will reserve it's childID in - // mActiveContentChildIDs, then it can allow to play next song. So we set agents - // to foreground first then stopping to play - rv = agent1->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - rv = agent2->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - rv = agent1->StopPlaying(); - NS_ENSURE_SUCCESS(rv, rv); - rv = agent2->StopPlaying(); - NS_ENSURE_SUCCESS(rv, rv); - - // Test that content channels can be allow to play when they starts from - // the background state - rv = agent1->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - rv = agent2->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent1->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test3: A content channel unvisible agent1 must be playable " - "from background state"); - - rv = agent2->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test3: A content channel unvisible agent2 must be playable " - "from background state"); - - return rv; -} - -nsresult -TestFadedState() -{ - nsRefPtr normalAgent = new Agent(AudioChannel::Normal); - nsresult rv = normalAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr contentAgent = new Agent(AudioChannel::Content); - rv = contentAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr notificationAgent = new Agent(AudioChannel::Notification); - rv = notificationAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - rv = normalAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = contentAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = notificationAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - AudioChannelState playable; - rv = normalAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test4: A normal channel visible agent must be playable"); - - rv = contentAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test4: A content channel visible agent must be playable"); - - rv = notificationAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test4: A notification channel visible agent must be playable"); - - rv = contentAgent->GetCanPlay(&playable, true); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_FADED, - "Test4: A content channel unvisible agent must be faded because of " - "notification channel is playing"); - - rv = contentAgent->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - - rv = contentAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_FADED, - "Test4: A content channel unvisible agent must be faded because of " - "notification channel is playing"); - - rv = notificationAgent->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - - rv = notificationAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test4: A notification channel unvisible agent must be playable from " - "foreground to background"); - - rv = notificationAgent->StopPlaying(); - NS_ENSURE_SUCCESS(rv, rv); - - rv = contentAgent->GetCanPlay(&playable, true); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test4: A content channel unvisible agent must be playable " - "because of notification channel is stopped"); - - rv = contentAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - return rv; -} - -nsresult -TestPriorities() -{ - nsRefPtr normalAgent = new Agent(AudioChannel::Normal); - nsresult rv = normalAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr contentAgent = new Agent(AudioChannel::Content); - rv = contentAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr notificationAgent = new Agent(AudioChannel::Notification); - rv = notificationAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr alarmAgent = new Agent(AudioChannel::Alarm); - rv = alarmAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr telephonyAgent = new Agent(AudioChannel::Telephony); - rv = telephonyAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr ringerAgent = new Agent(AudioChannel::Ringer); - rv = ringerAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr pNotificationAgent = - new Agent(AudioChannel::Publicnotification); - rv = pNotificationAgent->Init(); - NS_ENSURE_SUCCESS(rv, rv); - - AudioChannelState playable; - - rv = normalAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test5: A normal channel unvisible agent must be muted"); - - rv = contentAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A content channel unvisible agent must be playable while " - "playing from background state"); - - rv = notificationAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A notification channel unvisible agent must be playable"); - - rv = alarmAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: An alarm channel unvisible agent must be playable"); - - rv = notificationAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test5: A notification channel unvisible agent must be muted when an " - "alarm is playing"); - - rv = telephonyAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A telephony channel unvisible agent must be playable"); - - rv = alarmAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test5: An alarm channel unvisible agent must be muted when a telephony " - "is playing"); - - rv = ringerAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A ringer channel unvisible agent must be playable"); - - rv = telephonyAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test5: A telephony channel unvisible agent must be muted when a ringer " - "is playing"); - - rv = pNotificationAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A pNotification channel unvisible agent must be playable"); - - rv = ringerAgent->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test5: A ringer channel unvisible agent must be muted when a public " - "notification is playing"); - - // Stop to play notification channel or normal/content will be faded. - // Which already be tested on Test 4. - rv = notificationAgent->StopPlaying(); - NS_ENSURE_SUCCESS(rv, rv); - - // Settings visible the normal channel. - rv = normalAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = normalAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A normal channel visible agent must be playable"); - - // Set the content channel as visible . - rv = contentAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - // Content must be playable because visible. - rv = contentAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A content channel visible agent must be playable"); - - // Set the alarm channel as visible. - rv = alarmAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = alarmAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: An alarm channel visible agent must be playable"); - - // Set the telephony channel as visible. - rv = telephonyAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = telephonyAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A telephony channel visible agent must be playable"); - - // Set the ringer channel as visible. - rv = ringerAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ringerAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A ringer channel visible agent must be playable"); - - // Set the public notification channel as visible. - rv = pNotificationAgent->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = pNotificationAgent->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test5: A pNotification channel visible agent must be playable"); - - return rv; -} - -nsresult -TestOneVideoNormalChannel() -{ - nsRefPtr agent1 = new Agent(AudioChannel::Normal); - nsresult rv = agent1->Init(true); - NS_ENSURE_SUCCESS(rv, rv); - - nsRefPtr agent2 = new Agent(AudioChannel::Content); - rv = agent2->Init(false); - NS_ENSURE_SUCCESS(rv, rv); - - AudioChannelState playable; - rv = agent1->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test6: A video normal channel invisible agent1 must be muted"); - - rv = agent2->StartPlaying(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test6: A content channel invisible agent2 must be playable"); - - // one video normal channel in foreground and one content channel in background - rv = agent1->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent1->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test6: A video normal channel visible agent1 must be playable"); - - rv = agent2->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test6: A content channel invisible agent2 must be muted"); - - // both one video normal channel and one content channel in foreground - rv = agent2->SetVisibilityState(true); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent1->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test6: A video normal channel visible agent1 must be playable"); - - rv = agent2->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test6: A content channel visible agent2 must be playable"); - - // one video normal channel in background and one content channel in foreground - rv = agent1->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent1->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test6: A video normal channel invisible agent1 must be muted"); - - rv = agent2->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test6: A content channel visible agent2 must be playable"); - - // both one video normal channel and one content channel in background - rv = agent2->SetVisibilityState(false); - NS_ENSURE_SUCCESS(rv, rv); - - rv = agent1->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED, - "Test6: A video normal channel invisible agent1 must be muted"); - - rv = agent2->GetCanPlay(&playable); - NS_ENSURE_SUCCESS(rv, rv); - TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL, - "Test6: A content channel invisible agent2 must be playable"); - - return rv; -} - -int main(int argc, char** argv) -{ - ScopedXPCOM xpcom("AudioChannelService"); - if (xpcom.failed()) { - return 1; - } - - if (NS_FAILED(TestDoubleStartPlaying())) { - return 1; - } - - if (NS_FAILED(TestOneNormalChannel())) { - return 1; - } - - if (NS_FAILED(TestTwoNormalChannels())) { - return 1; - } - - if (NS_FAILED(TestContentChannels())) { - return 1; - } - - if (NS_FAILED(TestFadedState())) { - return 1; - } - - // Channel type with AudioChannel::Telephony cannot be unregistered until the - // main thread has chances to process 1500 millisecond timer. In order to - // skip ambiguous return value of ChannelsActiveWithHigherPriorityThan(), new - // test cases are added before any test case that registers the channel type - // with AudioChannel::Telephony channel. - if (NS_FAILED(TestOneVideoNormalChannel())) { - return 1; - } - - if (NS_FAILED(TestPriorities())) { - return 1; - } - - return 0; -} - diff --git a/dom/audiochannel/tests/audio.ogg b/dom/audiochannel/tests/audio.ogg deleted file mode 100644 index d7f6a0ccf47..00000000000 Binary files a/dom/audiochannel/tests/audio.ogg and /dev/null differ diff --git a/dom/audiochannel/tests/file_audio.html b/dom/audiochannel/tests/file_audio.html deleted file mode 100644 index 11058a1ff11..00000000000 --- a/dom/audiochannel/tests/file_audio.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - Test audio-channel-changed & visible-audio-channel-changed mozChromeEvent - - -
- - - diff --git a/dom/audiochannel/tests/file_telephonyPolicy.html b/dom/audiochannel/tests/file_telephonyPolicy.html deleted file mode 100644 index f95b7d40ff8..00000000000 --- a/dom/audiochannel/tests/file_telephonyPolicy.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Test Telephony Channel Policy - - -
- - - diff --git a/dom/audiochannel/tests/mochitest.ini b/dom/audiochannel/tests/mochitest.ini deleted file mode 100644 index 45564d6dd46..00000000000 --- a/dom/audiochannel/tests/mochitest.ini +++ /dev/null @@ -1,11 +0,0 @@ -[DEFAULT] -support-files = - audio.ogg - file_audio.html - file_telephonyPolicy.html - AudioChannelChromeScript.js - -[test_telephonyPolicy.html] -skip-if = buildapp == 'mulet' || (toolkit == 'gonk' || e10s) || os == "android" -[test_audioChannelChange.html] -skip-if = (toolkit != 'gonk') diff --git a/dom/audiochannel/tests/test_audioChannelChange.html b/dom/audiochannel/tests/test_audioChannelChange.html deleted file mode 100644 index 1036018047f..00000000000 --- a/dom/audiochannel/tests/test_audioChannelChange.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - Test audio-channel-changed & visible-audio-channel-changed mozChromeEvent - - - - -
- - - diff --git a/dom/audiochannel/tests/test_telephonyPolicy.html b/dom/audiochannel/tests/test_telephonyPolicy.html deleted file mode 100644 index f0294ac3cf8..00000000000 --- a/dom/audiochannel/tests/test_telephonyPolicy.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Test the Telephony Channel Policy - - - - -
- - - diff --git a/dom/base/ResponsiveImageSelector.cpp b/dom/base/ResponsiveImageSelector.cpp index 609ef00a640..f0ec6c80004 100644 --- a/dom/base/ResponsiveImageSelector.cpp +++ b/dom/base/ResponsiveImageSelector.cpp @@ -703,8 +703,8 @@ ResponsiveImageCandidate::Density(int32_t aMatchingWidth) const if (mType == eCandidateType_Density) { return mValue.mDensity; } else if (mType == eCandidateType_ComputedFromWidth) { - if (aMatchingWidth <= 0) { - MOZ_ASSERT(false, "0 or negative matching width is invalid per spec"); + if (aMatchingWidth < 0) { + MOZ_ASSERT(false, "Don't expect to have a negative matching width at this point"); return 1.0; } double density = double(mValue.mWidth) / double(aMatchingWidth); diff --git a/dom/base/WebSocket.cpp b/dom/base/WebSocket.cpp index 9fbafe61974..9535fd85dee 100644 --- a/dom/base/WebSocket.cpp +++ b/dom/base/WebSocket.cpp @@ -13,6 +13,8 @@ #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/net/WebSocketChannel.h" #include "mozilla/dom/File.h" +#include "mozilla/dom/nsCSPContext.h" +#include "mozilla/dom/nsCSPUtils.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRunnable.h" @@ -1466,6 +1468,67 @@ WebSocketImpl::Init(JSContext* aCx, } } + nsCOMPtr uri; + { + nsresult rv = NS_NewURI(getter_AddRefs(uri), mURI); + + // We crash here because we are sure that mURI is a valid URI, so either we + // are OOM'ing or something else bad is happening. + if (NS_WARN_IF(NS_FAILED(rv))) { + MOZ_CRASH(); + } + } + + // Check content policy. + int16_t shouldLoad = nsIContentPolicy::ACCEPT; + nsCOMPtr originDoc = nsContentUtils::GetDocumentFromScriptContext(sc); + mOriginDocument = do_GetWeakReference(originDoc); + aRv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET, + uri, + aPrincipal, + originDoc, + EmptyCString(), + nullptr, + &shouldLoad, + nsContentUtils::GetContentPolicy(), + nsContentUtils::GetSecurityManager()); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + + if (NS_CP_REJECTED(shouldLoad)) { + // Disallowed by content policy. + aRv.Throw(NS_ERROR_CONTENT_BLOCKED); + return; + } + + // Potentially the page uses the CSP directive 'upgrade-insecure-requests'. + // In such a case we have to upgrade ws: to wss: and also update mSecure + // to reflect that upgrade. Please note that we can not upgrade from ws: + // to wss: before performing content policy checks because CSP needs to + // send reports in case the scheme is about to be upgraded. + if (!mSecure && originDoc && originDoc->GetUpgradeInsecureRequests()) { + // let's use the old specification before the upgrade for logging + NS_ConvertUTF8toUTF16 reportSpec(mURI); + + // upgrade the request from ws:// to wss:// and mark as secure + mURI.ReplaceSubstring("ws://", "wss://"); + if (NS_WARN_IF(mURI.Find("wss://") != 0)) { + return; + } + mSecure = true; + + const char16_t* params[] = { reportSpec.get(), NS_LITERAL_STRING("wss").get() }; + CSP_LogLocalizedStr(NS_LITERAL_STRING("upgradeInsecureRequest").get(), + params, ArrayLength(params), + EmptyString(), // aSourceFile + EmptyString(), // aScriptSample + 0, // aLineNumber + 0, // aColumnNumber + nsIScriptError::warningFlag, "CSP", + mInnerWindowID); + } + // Don't allow https:// to open ws:// if (!mSecure && !Preferences::GetBool("network.websocket.allowInsecureFromHTTPS", @@ -1512,40 +1575,6 @@ WebSocketImpl::Init(JSContext* aCx, AppendUTF16toUTF8(aProtocolArray[index], mRequestedProtocolList); } - nsCOMPtr uri; - { - nsresult rv = NS_NewURI(getter_AddRefs(uri), mURI); - - // We crash here because we are sure that mURI is a valid URI, so either we - // are OOM'ing or something else bad is happening. - if (NS_FAILED(rv)) { - MOZ_CRASH(); - } - } - - // Check content policy. - int16_t shouldLoad = nsIContentPolicy::ACCEPT; - nsCOMPtr originDoc = nsContentUtils::GetDocumentFromScriptContext(sc); - mOriginDocument = do_GetWeakReference(originDoc); - aRv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET, - uri, - aPrincipal, - originDoc, - EmptyCString(), - nullptr, - &shouldLoad, - nsContentUtils::GetContentPolicy(), - nsContentUtils::GetSecurityManager()); - if (NS_WARN_IF(aRv.Failed())) { - return; - } - - if (NS_CP_REJECTED(shouldLoad)) { - // Disallowed by content policy. - aRv.Throw(NS_ERROR_CONTENT_BLOCKED); - return; - } - // the constructor should throw a SYNTAX_ERROR only if it fails to parse the // url parameter, so don't throw if InitializeConnection fails, and call // onerror/onclose asynchronously diff --git a/dom/base/nsCCUncollectableMarker.cpp b/dom/base/nsCCUncollectableMarker.cpp index 5c4be26523f..d21d8aa1ce1 100644 --- a/dom/base/nsCCUncollectableMarker.cpp +++ b/dom/base/nsCCUncollectableMarker.cpp @@ -30,6 +30,7 @@ #include "nsFrameLoader.h" #include "mozilla/EventListenerManager.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/ProcessGlobal.h" #include "xpcpublic.h" #include "nsObserverService.h" #include "nsFocusManager.h" @@ -140,6 +141,14 @@ MarkChildMessageManagers(nsIMessageBroadcaster* aMM) static void MarkMessageManagers() { + if (nsFrameMessageManager::GetChildProcessManager()) { + // ProcessGlobal's MarkForCC marks also ChildProcessManager. + ProcessGlobal* pg = ProcessGlobal::Get(); + if (pg) { + pg->MarkForCC(); + } + } + // The global message manager only exists in the root process. if (!XRE_IsParentProcess()) { return; @@ -172,9 +181,6 @@ MarkMessageManagers() if (nsFrameMessageManager::sSameProcessParentManager) { nsFrameMessageManager::sSameProcessParentManager->MarkForCC(); } - if (nsFrameMessageManager::GetChildProcessManager()) { - nsFrameMessageManager::GetChildProcessManager()->MarkForCC(); - } } void diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 231a2ea24f3..308b74bbf31 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -1552,6 +1552,7 @@ nsIDocument::nsIDocument() : nsINode(nullNodeInfo), mReferrerPolicySet(false), mReferrerPolicy(mozilla::net::RP_Default), + mUpgradeInsecureRequests(false), mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")), mNodeInfoManager(nullptr), mCompatMode(eCompatibility_FullStandards), @@ -2706,6 +2707,19 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, WarnIfSandboxIneffective(docShell, mSandboxFlags, GetChannel()); } + // The CSP directive upgrade-insecure-requests not only applies to the + // toplevel document, but also to nested documents. Let's propagate that + // flag from the parent to the nested document. + nsCOMPtr treeItem = this->GetDocShell(); + if (treeItem) { + nsCOMPtr sameTypeParent; + treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent)); + if (sameTypeParent) { + mUpgradeInsecureRequests = + sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(); + } + } + // If this is not a data document, set CSP. if (!mLoadedAsData) { nsresult rv = InitCSP(aChannel); @@ -2978,6 +2992,13 @@ nsDocument::InitCSP(nsIChannel* aChannel) // speculative loads. } + // ------ Set flag for 'upgrade-insecure-requests' if not already + // inherited from the parent context. + if (!mUpgradeInsecureRequests) { + rv = csp->GetUpgradeInsecureRequests(&mUpgradeInsecureRequests); + NS_ENSURE_SUCCESS(rv, rv); + } + rv = principal->SetCsp(csp); NS_ENSURE_SUCCESS(rv, rv); MOZ_LOG(gCspPRLog, LogLevel::Debug, diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 816a4cfadf0..30de73cac69 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -2055,6 +2055,7 @@ GK_ATOM(onwarning, "onwarning") GK_ATOM(onstart, "onstart") GK_ATOM(onstop, "onstop") GK_ATOM(onphoto, "onphoto") +GK_ATOM(onactivestatechanged, "onactivestatechanged") #ifdef MOZ_GAMEPAD GK_ATOM(ongamepadbuttondown, "ongamepadbuttondown") GK_ATOM(ongamepadbuttonup, "ongamepadbuttonup") diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 3a76b314b7c..25679f0e796 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -3735,39 +3735,10 @@ nsPIDOMWindow::SetAudioVolume(float aVolume) return NS_OK; } -float -nsPIDOMWindow::GetAudioGlobalVolume() -{ - float globalVolume = 1.0; - nsCOMPtr window = this; - - do { - if (window->GetAudioMuted()) { - return 0; - } - - globalVolume *= window->GetAudioVolume(); - - nsCOMPtr win; - window->GetParent(getter_AddRefs(win)); - if (window == win) { - break; - } - - window = do_QueryInterface(win); - - // If there is not parent, or we are the toplevel or the volume is - // already 0.0, we don't continue. - } while (window && window != this && globalVolume); - - return globalVolume; -} - void nsPIDOMWindow::RefreshMediaElements() { - nsRefPtr service = - AudioChannelService::GetOrCreateAudioChannelService(); + nsRefPtr service = AudioChannelService::GetOrCreate(); service->RefreshAgentsVolume(GetCurrentInnerWindow()); } diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index dec96156309..1b519857b54 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -308,6 +308,18 @@ public: return GetReferrerPolicy(); } + /** + * If true, this flag indicates that all subresource loads for this + * document need to be upgraded from http to https. + * This flag becomes true if the CSP of the document itself, or any + * of the document's ancestors up to the toplevel document makes use + * of the CSP directive 'upgrade-insecure-requests'. + */ + bool GetUpgradeInsecureRequests() const + { + return mUpgradeInsecureRequests; + } + /** * Set the principal responsible for this document. */ @@ -2631,6 +2643,8 @@ protected: bool mReferrerPolicySet; ReferrerPolicyEnum mReferrerPolicy; + bool mUpgradeInsecureRequests; + mozilla::WeakPtr mDocumentContainer; nsCString mCharacterSet; diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index ccedbae83b4..6d12a7e7208 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -422,6 +422,36 @@ nsINode::IsInAnonymousSubtree() const return AsContent()->IsInAnonymousSubtree(); } +std::ostream& +operator<<(std::ostream& aStream, const nsINode& aNode) +{ + nsAutoString elemDesc; + const nsINode* curr = &aNode; + while (curr) { + const nsString& localName = curr->LocalName(); + nsString id; + if (curr->IsElement()) { + curr->AsElement()->GetId(id); + } + + if (!elemDesc.IsEmpty()) { + elemDesc = elemDesc + NS_LITERAL_STRING("."); + } + + elemDesc = elemDesc + localName; + + if (!id.IsEmpty()) { + elemDesc = elemDesc + NS_LITERAL_STRING("['") + id + + NS_LITERAL_STRING("']"); + } + + curr = curr->GetParentNode(); + } + + NS_ConvertUTF16toUTF8 str(elemDesc); + return aStream << str.get(); +} + bool nsINode::IsAnonymousContentInSVGUseSubtree() const { diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h index bd808fa7c36..7a18242c48f 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -22,6 +22,7 @@ #include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext #include "mozilla/dom/DOMString.h" #include "mozilla/dom/BindingDeclarations.h" +#include // Including 'windows.h' will #define GetClassInfo to something else. #ifdef XP_WIN @@ -582,6 +583,12 @@ public: return mNodeInfo->NamespaceID() == aNamespace; } + /** + * Print a debugger friendly descriptor of this element. This will describe + * the position of this element in the document. + */ + friend std::ostream& operator<<(std::ostream& aStream, const nsINode& aNode); + protected: // These 2 methods are useful for the recursive templates IsHTMLElement, // IsSVGElement, etc. @@ -1722,7 +1729,7 @@ public: mNodeInfo->GetPrefix(aPrefix); } #endif - void GetLocalName(mozilla::dom::DOMString& aLocalName) + void GetLocalName(mozilla::dom::DOMString& aLocalName) const { const nsString& localName = LocalName(); if (localName.IsVoid()) { diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index fd4593d580e..3f7b1b220fd 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -185,8 +185,6 @@ public: float GetAudioVolume() const; nsresult SetAudioVolume(float aVolume); - float GetAudioGlobalVolume(); - virtual void SetServiceWorkersTestingEnabled(bool aEnabled) { MOZ_ASSERT(IsOuterWindow()); diff --git a/dom/base/test/chrome.ini b/dom/base/test/chrome.ini index 9684ee8dba5..f129293efd9 100644 --- a/dom/base/test/chrome.ini +++ b/dom/base/test/chrome.ini @@ -1,5 +1,5 @@ [DEFAULT] -skip-if = buildapp == 'b2g' +skip-if = buildapp == 'b2g' || os == 'android' support-files = file_url.jsm file_empty.html diff --git a/dom/base/test/chrome/chrome.ini b/dom/base/test/chrome/chrome.ini index 3e223aed598..173f424292e 100644 --- a/dom/base/test/chrome/chrome.ini +++ b/dom/base/test/chrome/chrome.ini @@ -1,5 +1,5 @@ [DEFAULT] -skip-if = buildapp == 'b2g' +skip-if = buildapp == 'b2g' || os == 'android' support-files = blockNoPlugins.xml blockPluginHard.xml diff --git a/dom/base/test/file_audioLoop.html b/dom/base/test/file_audioLoop.html new file mode 100644 index 00000000000..d680c9a58f6 --- /dev/null +++ b/dom/base/test/file_audioLoop.html @@ -0,0 +1,2 @@ + +