author | Wes Kocher <wkocher@mozilla.com> |
Wed, 10 Jun 2015 18:38:28 -0700 | |
changeset 248193 | 39e638ed06bf0fe1123d8d2f424117dd0d1d73a7 |
parent 248192 | fa788695c8fc8dc1cb42ee162d49f20ce95ee22a (current diff) |
parent 248113 | 54942e3f878087156d18983dd119af1640e50354 (diff) |
child 248194 | 5b73b6e079e0fdf2017e9700862a14119c79fe22 |
push id | 28893 |
push user | kwierso@gmail.com |
push date | Fri, 12 Jun 2015 00:02:58 +0000 |
treeherder | autoland@8cf9d3e497f9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 41.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -347,20 +347,20 @@ pref("image.onload.decode.limit", 24); / // we don't really have a better one at the moment. // enable touch events interfaces pref("dom.w3c_touch_events.enabled", 1); pref("dom.w3c_touch_events.safetyX", 0); // escape borders in units of 1/240" pref("dom.w3c_touch_events.safetyY", 120); // escape borders in units of 1/240" #ifdef MOZ_SAFE_BROWSING // Safe browsing does nothing unless this pref is set -pref("browser.safebrowsing.enabled", false); +pref("browser.safebrowsing.enabled", true); // Prevent loading of pages identified as malware -pref("browser.safebrowsing.malware.enabled", false); +pref("browser.safebrowsing.malware.enabled", true); pref("browser.safebrowsing.debug", false); pref("browser.safebrowsing.updateURL", "https://safebrowsing.google.com/safebrowsing/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2&key=%GOOGLE_API_KEY%"); pref("browser.safebrowsing.gethashURL", "https://safebrowsing.google.com/safebrowsing/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2"); pref("browser.safebrowsing.reportURL", "https://safebrowsing.google.com/safebrowsing/report?"); pref("browser.safebrowsing.reportGenericURL", "http://%LOCALE%.phish-generic.mozilla.com/?hl=%LOCALE%"); pref("browser.safebrowsing.reportErrorURL", "http://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%"); pref("browser.safebrowsing.reportPhishURL", "http://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%"); @@ -400,16 +400,21 @@ pref("urlclassifier.gethash.timeout_ms", // If an urlclassifier table has not been updated in this number of seconds, // a gethash request will be forced to check that the result is still in // the database. pref("urlclassifier.max-complete-age", 2700); // URL for checking the reason for a malware warning. pref("browser.safebrowsing.malware.reportURL", "https://safebrowsing.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site="); + +// Tracking protection +pref("privacy.trackingprotection.enabled", true); +pref("privacy.trackingprotection.pbmode.enabled", false); + #endif // True if this is the first time we are showing about:firstrun pref("browser.firstrun.show.uidiscovery", true); pref("browser.firstrun.show.localepicker", true); // initiated by a user pref("content.ime.strict_policy", true);
--- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
--- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
--- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -14,20 +14,20 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> - <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/> + <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/> <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/> <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/> <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/> <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
--- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/> @@ -127,14 +127,14 @@ <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/> <default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/> <!-- Emulator specific things --> <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/> <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f390788a00706c06e5248edfd8d27b365387e84a"/> <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="4bebbe8d92368befc31e8b4a99da2d29cc26bfbc"/> <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/> <project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/> - <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="de4bfffbbc2aabe5b5eca485e459da75e49097e2"/> + <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2b62676f02abb7633aac619e0f92c7fd70216860"/> <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d82e00fb6380b4f6cea7a96213913ee9eb441239"/> <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/> <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/> <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/> </manifest>
--- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
--- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -14,20 +14,20 @@ <!--original fetch url was git://github.com/apitrace/--> <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/> <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/> <!-- Gonk specific things and forks --> <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/> - <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> - <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/> + <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/> <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/> <!-- Stock Android things --> <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/> <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/> <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/> <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
--- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
--- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9", + "git_revision": "d2f31eb85837aae6eca04d022d1f5b2023bc778c", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "c33bf7766d1b19c407c3bbab943403ddee172915", + "revision": "2e9a1e5808b983fe4aa50a169b0e36fb3f0b43a3", "repo_path": "integration/gaia-central" }
--- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -12,17 +12,17 @@ <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd"> <copyfile dest="Makefile" src="core/root.mk"/> </project> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <!-- Stock Android things --> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/> <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -10,17 +10,17 @@ <!--original fetch url was git://codeaurora.org/--> <remote fetch="https://git.mozilla.org/external/caf" name="caf"/> <!--original fetch url was https://git.mozilla.org/releases--> <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/> <!-- B2G specific things. --> <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33"> <copyfile dest="Makefile" src="core/root.mk"/> </project> - <project name="gaia" path="gaia" remote="mozillaorg" revision="e3eaf72ccd1bfe6d60d37efde6d3b92c1dbc5ff9"/> + <project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/> <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/> <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/> <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/> <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/> <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/> <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/> <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/> <project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -265,17 +265,17 @@ pref("general.smoothScroll", true); pref("general.autoScroll", false); #else pref("general.autoScroll", true); #endif // At startup, check if we're the default browser and prompt user if not. pref("browser.shell.checkDefaultBrowser", true); pref("browser.shell.shortcutFavicons",true); -pref("browser.shell.isSetAsDefaultBrowser", false); +pref("browser.shell.mostRecentDateSetAsDefault", ""); // 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session // The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore pref("browser.startup.page", 1); pref("browser.startup.homepage", "chrome://branding/locale/browserconfig.properties"); pref("browser.slowStartup.notificationDisabled", false); pref("browser.slowStartup.timeThreshold", 40000); @@ -1457,16 +1457,17 @@ pref("devtools.performance.timeline.hidd pref("devtools.performance.profiler.buffer-size", 10000000); pref("devtools.performance.profiler.sample-frequency-khz", 1); pref("devtools.performance.ui.invert-call-tree", true); pref("devtools.performance.ui.invert-flame-graph", false); pref("devtools.performance.ui.flatten-tree-recursion", true); pref("devtools.performance.ui.show-platform-data", false); pref("devtools.performance.ui.show-idle-blocks", true); pref("devtools.performance.ui.enable-memory", false); +pref("devtools.performance.ui.enable-allocations", false); pref("devtools.performance.ui.enable-framerate", true); pref("devtools.performance.ui.show-jit-optimizations", false); // Enable experimental options in the UI only in Nightly #if defined(NIGHTLY_BUILD) pref("devtools.performance.ui.experimental", true); #else pref("devtools.performance.ui.experimental", false); @@ -1482,16 +1483,25 @@ pref("devtools.serviceWorkers.testing.en pref("devtools.netmonitor.enabled", true); // The default Network Monitor UI settings pref("devtools.netmonitor.panes-network-details-width", 550); pref("devtools.netmonitor.panes-network-details-height", 450); pref("devtools.netmonitor.statistics", true); pref("devtools.netmonitor.filters", "[\"all\"]"); +// The default Network monitor HAR export setting +pref("devtools.netmonitor.har.defaultLogDir", ""); +pref("devtools.netmonitor.har.defaultFileName", "archive"); +pref("devtools.netmonitor.har.jsonp", false); +pref("devtools.netmonitor.har.jsonpCallback", ""); +pref("devtools.netmonitor.har.includeResponseBodies", true); +pref("devtools.netmonitor.har.compress", false); +pref("devtools.netmonitor.har.forceExport", false); + // Enable the Tilt inspector pref("devtools.tilt.enabled", true); pref("devtools.tilt.intro_transition", true); pref("devtools.tilt.outro_transition", true); // Scratchpad settings // - recentFileMax: The maximum number of recently-opened files // stored. Setting this preference to 0 will not
--- a/browser/base/content/browser-doctype.inc +++ b/browser/base/content/browser-doctype.inc @@ -1,15 +1,13 @@ <!DOCTYPE window [ <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" > %brandDTD; <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" > %browserDTD; -<!ENTITY % browserPocketDTD SYSTEM "chrome://browser/content/browser-pocket.dtd" > -%browserPocketDTD; <!ENTITY % baseMenuDTD SYSTEM "chrome://browser/locale/baseMenuOverlay.dtd" > %baseMenuDTD; <!ENTITY % charsetDTD SYSTEM "chrome://global/locale/charsetMenu.dtd" > %charsetDTD; <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" > %textcontextDTD; <!ENTITY % customizeToolbarDTD SYSTEM "chrome://global/locale/customizeToolbar.dtd"> %customizeToolbarDTD;
--- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -538,17 +538,18 @@ accesskey="&devAppMgrMenu.accesskey;"/> <menuitem id="menu_webide" observes="devtoolsMenuBroadcaster_webide" accesskey="&webide.accesskey;"/> <menuitem id="menu_browserToolbox" observes="devtoolsMenuBroadcaster_BrowserToolbox" accesskey="&browserToolboxMenu.accesskey;"/> <menuitem id="menu_browserContentToolbox" - observes="devtoolsMenuBroadcaster_BrowserContentToolbox"/> + observes="devtoolsMenuBroadcaster_BrowserContentToolbox" + accesskey="&browserContentToolboxMenu.accesskey;" /> <menuitem id="menu_browserConsole" observes="devtoolsMenuBroadcaster_BrowserConsole" accesskey="&browserConsoleCmd.accesskey;"/> <menuitem id="menu_responsiveUI" observes="devtoolsMenuBroadcaster_ResponsiveUI" accesskey="&responsiveDesignTool.accesskey;"/> <menuitem id="menu_eyedropper" observes="devtoolsMenuBroadcaster_Eyedropper"
--- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -1558,35 +1558,16 @@ let BookmarkingUI = { onMainMenuPopupShowing: function BUI_onMainMenuPopupShowing(event) { this._updateBookmarkPageMenuItem(); PlacesCommandHook.updateBookmarkAllTabsCommand(); }, updatePocketItemVisibility: function BUI_updatePocketItemVisibility(prefix) { let hidden = !CustomizableUI.getPlacementOfWidget("pocket-button"); - if (!hidden) { - let locale = Cc["@mozilla.org/chrome/chrome-registry;1"]. - getService(Ci.nsIXULChromeRegistry). - getSelectedLocale("browser"); - if (locale != "en-US") { - if (locale == "ja-JP-mac") - locale = "ja"; - let url = "chrome://browser/content/browser-pocket-" + locale + ".properties"; - let bundle = Services.strings.createBundle(url); - let item = document.getElementById(prefix + "pocket"); - try { - item.setAttribute("label", bundle.GetStringFromName("pocketMenuitem.label")); - } catch (err) { - // GetStringFromName throws when the bundle doesn't exist. In that - // case, the item will retain the browser-pocket.dtd en-US string that - // it has in the markup. - } - } - } document.getElementById(prefix + "pocket").hidden = hidden; document.getElementById(prefix + "pocketSeparator").hidden = hidden; }, _showBookmarkedNotification: function BUI_showBookmarkedNotification() { function getCenteringTransformForRects(rectToPosition, referenceRect) { let topDiff = referenceRect.top - rectToPosition.top; let leftDiff = referenceRect.left - rectToPosition.left;
deleted file mode 100644 --- a/browser/base/content/browser-pocket-de.properties +++ /dev/null @@ -1,16 +0,0 @@ -# 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/. - -# This is a temporary file, later versions of Firefox will use -# browser.properties in the usual L10N location. - -pocket-button.label = Pocket -pocket-button.tooltiptext = Bei Pocket speichern - -# From browser-pocket.dtd -saveToPocketCmd.label = Seite bei Pocket speichern -saveToPocketCmd.accesskey = k -saveLinkToPocketCmd.label = Link bei Pocket speichern -saveLinkToPocketCmd.accesskey = o -pocketMenuitem.label = Pocket-Liste anzeigen
deleted file mode 100644 --- a/browser/base/content/browser-pocket-en-US.properties +++ /dev/null @@ -1,9 +0,0 @@ -# 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/. - -# This is a temporary file, later versions of Firefox will use -# browser.properties in the usual L10N location. - -pocket-button.label = Pocket -pocket-button.tooltiptext = Save to Pocket
deleted file mode 100644 --- a/browser/base/content/browser-pocket-es-ES.properties +++ /dev/null @@ -1,16 +0,0 @@ -# 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/. - -# This is a temporary file, later versions of Firefox will use -# browser.properties in the usual L10N location. - -pocket-button.label = Pocket -pocket-button.tooltiptext = Guardar en Pocket - -# From browser-pocket.dtd -saveToPocketCmd.label = Guardar página en Pocket -saveToPocketCmd.accesskey = k -saveLinkToPocketCmd.label = Guardar enlace en Pocket -saveLinkToPocketCmd.accesskey = k -pocketMenuitem.label = Ver lista de Pocket
deleted file mode 100644 --- a/browser/base/content/browser-pocket-ja.properties +++ /dev/null @@ -1,16 +0,0 @@ -# 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/. - -# This is a temporary file, later versions of Firefox will use -# browser.properties in the usual L10N location. - -pocket-button.label = Pocket -pocket-button.tooltiptext = Pocket に保存 - -# From browser-pocket.dtd -saveToPocketCmd.label = Pocket にページを保存 -saveToPocketCmd.accesskey = k -saveLinkToPocketCmd.label = Pocket にリンクを保存 -saveLinkToPocketCmd.accesskey = o -pocketMenuitem.label = Pocket のマイリストを表示
deleted file mode 100644 --- a/browser/base/content/browser-pocket-ru.properties +++ /dev/null @@ -1,16 +0,0 @@ -# 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/. - -# This is a temporary file, later versions of Firefox will use -# browser.properties in the usual L10N location. - -pocket-button.label = Pocket -pocket-button.tooltiptext = Сохранить в Pocket - -# From browser-pocket.dtd -saveToPocketCmd.label = Сохранить страницу в Pocket -saveToPocketCmd.accesskey = х -saveLinkToPocketCmd.label = Сохранить ссылку в Pocket -saveLinkToPocketCmd.accesskey = а -pocketMenuitem.label = Показать список Pocket
deleted file mode 100644 --- a/browser/base/content/browser-pocket.dtd +++ /dev/null @@ -1,12 +0,0 @@ -<!-- 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/. --> - -<!-- This is a temporary file and not meant for localization; later versions - - of Firefox include these strings in browser.dtd --> - -<!ENTITY saveToPocketCmd.label "Save Page to Pocket"> -<!ENTITY saveToPocketCmd.accesskey "k"> -<!ENTITY saveLinkToPocketCmd.label "Save Link to Pocket"> -<!ENTITY saveLinkToPocketCmd.accesskey "o"> -<!ENTITY pocketMenuitem.label "View Pocket List">
--- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -1286,8 +1286,12 @@ toolbarpaletteitem[place="palette"][hidd .popup-notification-footer[popupid="bad-content"] { display: none; } .popup-notification-footer[popupid="bad-content"][mixedblockdisabled], .popup-notification-footer[popupid="bad-content"][trackingblockdisabled] { display: block; } + +#login-fill-doorhanger:not([inDetailView]) > #login-fill-clickcapturer { + pointer-events: none; +}
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -215,19 +215,16 @@ XPCOMUtils.defineLazyModuleGetter(this, "resource:///modules/translation/Translation.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "SitePermissions", "resource:///modules/SitePermissions.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "SessionStore", "resource:///modules/sessionstore/SessionStore.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "TabState", - "resource:///modules/sessionstore/TabState.jsm"); - XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts", "resource://gre/modules/FxAccounts.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "gWebRTCUI", "resource:///modules/webrtcUI.jsm", "webrtcUI"); #ifdef MOZ_CRASHREPORTER XPCOMUtils.defineLazyModuleGetter(this, "TabCrashReporter", @@ -916,32 +913,17 @@ function _loadURIWithFlags(browser, uri, } } } // Starts a new load in the browser first switching the browser to the correct // process function LoadInOtherProcess(browser, loadOptions, historyIndex = -1) { let tab = gBrowser.getTabForBrowser(browser); - // Flush the tab state before getting it - TabState.flush(browser); - let tabState = JSON.parse(SessionStore.getTabState(tab)); - - if (historyIndex < 0) { - tabState.userTypedValue = null; - // Tell session history the new page to load - SessionStore._restoreTabAndLoad(tab, JSON.stringify(tabState), loadOptions); - } - else { - // Update the history state to point to the requested index - tabState.index = historyIndex + 1; - // SessionStore takes care of setting the browser remoteness before restoring - // history into it. - SessionStore.setTabState(tab, JSON.stringify(tabState)); - } + SessionStore.navigateAndRestore(tab, loadOptions, historyIndex); } // Called when a docshell has attempted to load a page in an incorrect process. // This function is responsible for loading the page in the correct process. function RedirectLoad({ target: browser, data }) { // We should only start the redirection if the browser window has finished // starting up. Otherwise, we should wait until the startup is done. if (gBrowserInit.delayedStartupFinished) { @@ -6598,51 +6580,29 @@ var gIdentityHandler = { IDENTITY_MODE_CHROMEUI : "chromeUI", // Part of the product's UI // Cache the most recent SSLStatus and Location seen in checkIdentity _lastStatus : null, _lastUri : null, _mode : "unknownIdentity", // smart getters - get _encryptionLabel () { - delete this._encryptionLabel; - this._encryptionLabel = {}; - this._encryptionLabel[this.IDENTITY_MODE_DOMAIN_VERIFIED] = - gNavigatorBundle.getString("identity.encrypted2"); - this._encryptionLabel[this.IDENTITY_MODE_IDENTIFIED] = - gNavigatorBundle.getString("identity.encrypted2"); - this._encryptionLabel[this.IDENTITY_MODE_UNKNOWN] = - gNavigatorBundle.getString("identity.unencrypted"); - this._encryptionLabel[this.IDENTITY_MODE_MIXED_DISPLAY_LOADED] = - gNavigatorBundle.getString("identity.broken_loaded"); - this._encryptionLabel[this.IDENTITY_MODE_MIXED_ACTIVE_LOADED] = - gNavigatorBundle.getString("identity.mixed_active_loaded2"); - this._encryptionLabel[this.IDENTITY_MODE_MIXED_DISPLAY_LOADED_ACTIVE_BLOCKED] = - gNavigatorBundle.getString("identity.broken_loaded"); - return this._encryptionLabel; - }, get _identityPopup () { delete this._identityPopup; return this._identityPopup = document.getElementById("identity-popup"); }, get _identityBox () { delete this._identityBox; return this._identityBox = document.getElementById("identity-box"); }, get _identityPopupContentBox () { delete this._identityPopupContentBox; return this._identityPopupContentBox = document.getElementById("identity-popup-content-box"); }, - get _identityPopupChromeLabel () { - delete this._identityPopupChromeLabel; - return this._identityPopupChromeLabel = - document.getElementById("identity-popup-chromeLabel"); - }, get _identityPopupContentHost () { delete this._identityPopupContentHost; return this._identityPopupContentHost = document.getElementById("identity-popup-content-host"); }, get _identityPopupContentOwner () { delete this._identityPopupContentOwner; return this._identityPopupContentOwner = @@ -6653,21 +6613,16 @@ var gIdentityHandler = { return this._identityPopupContentSupp = document.getElementById("identity-popup-content-supplemental"); }, get _identityPopupContentVerif () { delete this._identityPopupContentVerif; return this._identityPopupContentVerif = document.getElementById("identity-popup-content-verifier"); }, - get _identityPopupEncLabel () { - delete this._identityPopupEncLabel; - return this._identityPopupEncLabel = - document.getElementById("identity-popup-encryption-label"); - }, get _identityIconLabel () { delete this._identityIconLabel; return this._identityIconLabel = document.getElementById("identity-icon-label"); }, get _overrideService () { delete this._overrideService; return this._overrideService = Cc["@mozilla.org/security/certoverride;1"] .getService(Ci.nsICertOverrideService); @@ -6975,58 +6930,69 @@ var gIdentityHandler = { * * @param newMode The newly set identity mode. Should be one of the IDENTITY_MODE_* constants. */ setPopupMessages : function(newMode) { this._identityPopup.className = newMode; this._identityPopupContentBox.className = newMode; - // Set the static strings up front - this._identityPopupEncLabel.textContent = this._encryptionLabel[newMode]; - // Initialize the optional strings to empty values let supplemental = ""; let verifier = ""; let host = ""; let owner = ""; + if (newMode == this.IDENTITY_MODE_CHROMEUI) { + let brandBundle = document.getElementById("bundle_brand"); + host = brandBundle.getString("brandFullName"); + } else { + try { + host = this.getEffectiveHost(); + } catch (e) { + // Some URIs might have no hosts. + host = this._lastUri.specIgnoringRef; + } + } + switch (newMode) { case this.IDENTITY_MODE_DOMAIN_VERIFIED: - host = this.getEffectiveHost(); verifier = this._identityBox.tooltipText; break; case this.IDENTITY_MODE_IDENTIFIED: { // If it's identified, then we can populate the dialog with credentials let iData = this.getIdentityData(); - host = this.getEffectiveHost(); - owner = iData.subjectOrg; + host = owner = iData.subjectOrg; verifier = this._identityBox.tooltipText; // Build an appropriate supplemental block out of whatever location data we have if (iData.city) supplemental += iData.city + "\n"; if (iData.state && iData.country) supplemental += gNavigatorBundle.getFormattedString("identity.identified.state_and_country", [iData.state, iData.country]); else if (iData.state) // State only supplemental += iData.state; else if (iData.country) // Country only supplemental += iData.country; - break; } - case this.IDENTITY_MODE_CHROMEUI: { - let brandBundle = document.getElementById("bundle_brand"); - let brandShortName = brandBundle.getString("brandShortName"); - this._identityPopupChromeLabel.textContent = gNavigatorBundle.getFormattedString("identity.chrome", - [brandShortName]); - break; } - } - - // Push the appropriate strings out to the UI - this._identityPopupContentHost.textContent = host; + break; + } + case this.IDENTITY_MODE_MIXED_DISPLAY_LOADED: + case this.IDENTITY_MODE_MIXED_DISPLAY_LOADED_ACTIVE_BLOCKED: + supplemental = gNavigatorBundle.getString("identity.broken_loaded"); + break; + case this.IDENTITY_MODE_MIXED_ACTIVE_LOADED: + supplemental = gNavigatorBundle.getString("identity.mixed_active_loaded2"); + break; + } + + // Push the appropriate strings out to the UI. Need to use |value| for the + // host as it's a <label> that will be cropped if too long. Using + // |textContent| would simply wrap the value. + this._identityPopupContentHost.value = host; this._identityPopupContentOwner.textContent = owner; this._identityPopupContentSupp.textContent = supplemental; this._identityPopupContentVerif.textContent = verifier; }, /** * Click handler for the identity-box element in primary chrome. */
--- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -193,39 +193,16 @@ nsContextMenu.prototype = { this.onCanvas || this.onVideo || this.onAudio); let targetURI = (this.onSaveableLink || this.onPlainTextLink) ? this.linkURI : this.browser.currentURI; let canPocket = CustomizableUI.getPlacementOfWidget("pocket-button") && window.pktApi && window.pktApi.isUserLoggedIn(); canPocket = canPocket && (targetURI.schemeIs("http") || targetURI.schemeIs("https") || (targetURI.schemeIs("about") && ReaderMode.getOriginalUrl(targetURI.spec))); canPocket = canPocket && window.gBrowser && this.browser.getTabBrowser() == window.gBrowser; - if (canPocket) { - let locale = Cc["@mozilla.org/chrome/chrome-registry;1"]. - getService(Ci.nsIXULChromeRegistry). - getSelectedLocale("browser"); - if (locale != "en-US") { - if (locale == "ja-JP-mac") - locale = "ja"; - let url = "chrome://browser/content/browser-pocket-" + locale + ".properties"; - let bundle = Services.strings.createBundle(url); - let saveToPocketItem = document.getElementById("context-pocket"); - let saveLinkToPocketItem = document.getElementById("context-savelinktopocket"); - try { - saveToPocketItem.setAttribute("label", bundle.GetStringFromName("saveToPocketCmd.label")); - saveToPocketItem.setAttribute("accesskey", bundle.GetStringFromName("saveToPocketCmd.accesskey")); - saveLinkToPocketItem.setAttribute("label", bundle.GetStringFromName("saveLinkToPocketCmd.label")); - saveLinkToPocketItem.setAttribute("accesskey", bundle.GetStringFromName("saveLinkToPocketCmd.accesskey")); - } catch (err) { - // GetStringFromName throws when the bundle doesn't exist. In that - // case, the item will retain the browser-pocket.dtd en-US string that - // it has in the markup. - } - } - } this.showItem("context-pocket", canPocket && showSaveCurrentPageToPocket); let showSaveLinkToPocket = canPocket && !showSaveCurrentPageToPocket && (this.onSaveableLink || this.onPlainTextLink); this.showItem("context-savelinktopocket", showSaveLinkToPocket); }, initViewItems: function CM_initViewItems() { // View source is always OK, unless in directory listing.
--- a/browser/base/content/popup-notifications.inc +++ b/browser/base/content/popup-notifications.inc @@ -57,22 +57,32 @@ <popupnotification id="password-notification" hidden="true"> <popupnotificationcontent orient="vertical"> <textbox id="password-notification-username"/> <textbox id="password-notification-password" type="password" disabled="true"/> </popupnotificationcontent> </popupnotification> - <vbox id="login-fill-doorhanger" hidden="true"> - <description id="login-fill-testing" - value="Thanks for testing the login fill doorhanger!"/> - <textbox id="login-fill-filter"/> - <richlistbox id="login-fill-list"/> - </vbox> + <stack id="login-fill-doorhanger" hidden="true"> + <vbox id="login-fill-mainview"> + <description id="login-fill-testing" + value="Thanks for testing the login fill doorhanger!"/> + <textbox id="login-fill-filter"/> + <richlistbox id="login-fill-list"/> + </vbox> + <vbox id="login-fill-clickcapturer"/> + <vbox id="login-fill-details"> + <textbox id="login-fill-username" readonly="true"/> + <textbox id="login-fill-password" type="password" disabled="true"/> + <hbox> + <button id="login-fill-use" label="Use in form"/> + </hbox> + </vbox> + </stack> #ifdef E10S_TESTING_ONLY <popupnotification id="enable-e10s-notification" hidden="true"> <popupnotificationcontent orient="vertical"/> </popupnotification> #endif <popupnotification id="addon-progress-notification" hidden="true">
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1493,16 +1493,19 @@ <body> <![CDATA[ let isRemote = aBrowser.getAttribute("remote") == "true"; if (isRemote == aShouldBeRemote) return false; let wasActive = document.activeElement == aBrowser; + // Unmap the old outerWindowID. + this._outerWindowIDBrowserMap.delete(aBrowser.outerWindowID); + // Unhook our progress listener. let tab = this.getTabForBrowser(aBrowser); let index = tab._tPos; let filter = this.mTabFilters[index]; aBrowser.webProgress.removeProgressListener(filter); // Make sure the browser is destroyed so it unregisters from observer notifications aBrowser.destroy(); @@ -1524,16 +1527,19 @@ if (aShouldBeRemote) { // Switching the browser to be remote will connect to a new child // process so the browser can no longer be considered to be // crashed. tab.removeAttribute("crashed"); } else { aBrowser.messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: tab.pinned }) + + // Register the new outerWindowID. + this._outerWindowIDBrowserMap.set(aBrowser.outerWindowID, aBrowser); } if (wasActive) aBrowser.focus(); let evt = document.createEvent("Events"); evt.initEvent("TabRemotenessChange", true, false); tab.dispatchEvent(evt); @@ -1789,23 +1795,16 @@ usingPreloadedContent = !!b; } if (!b) { // No preloaded browser found, create one. b = this._createBrowser({remote, uriIsAboutBlank}); } - // A remote browser doesn't initially have the outerWindowID - // set. Once a remote browser initializes, it sends the Browser:Init - // message, and we map the browser at that point. - if (!remote) { - this._outerWindowIDBrowserMap.set(b.outerWindowID, b); - } - let notificationbox = this.getNotificationBox(b); var position = this.tabs.length - 1; var uniqueId = this._generateUniquePanelID(); notificationbox.id = uniqueId; t.linkedPanel = uniqueId; t.linkedBrowser = b; this._tabForBrowser.set(b, t); t._tPos = position; @@ -1885,16 +1884,29 @@ Cu.reportError(ex); } } // We start our browsers out as inactive, and then maintain // activeness in the tab switcher. b.docShellIsActive = false; + // When addTab() is called with an URL that is not "about:blank" we + // set the "nodefaultsrc" attribute that prevents a frameLoader + // from being created as soon as the linked <browser> is inserted + // into the DOM. We thus have to register the new outerWindowID + // for non-remote browsers after we have called browser.loadURI(). + // + // Note: Only do this of we still have a docShell. The TabOpen + // event was dispatched above and a gBrowser.removeTab() call from + // one of its listeners could cause us to fail here. + if (!remote && b.docShell) { + this._outerWindowIDBrowserMap.set(b.outerWindowID, b); + } + // Check if we're opening a tab related to the current tab and // move it to after the current tab. // aReferrerURI is null or undefined if the tab is opened from // an external application or bookmark, i.e. somewhere other // than the current tab. if ((aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) && Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) { let newTabPos = (this._lastRelatedTab || @@ -2498,19 +2510,39 @@ let tabListener = this.mTabListeners[index]; let ourBrowser = this.getBrowserForTab(aOurTab); ourBrowser.webProgress.removeProgressListener(filter); filter.removeProgressListener(tabListener); // Make sure to unregister any open URIs. this._swapRegisteredOpenURIs(ourBrowser, aOtherBrowser); + // Unmap old outerWindowIDs. + this._outerWindowIDBrowserMap.delete(ourBrowser.outerWindowID); + let remoteBrowser = aOtherBrowser.ownerDocument.defaultView.gBrowser; + if (remoteBrowser) { + remoteBrowser._outerWindowIDBrowserMap.delete(aOtherBrowser.outerWindowID); + } + // Swap the docshells ourBrowser.swapDocShells(aOtherBrowser); + if (ourBrowser.isRemoteBrowser) { + // Switch outerWindowIDs for remote browsers. + let ourOuterWindowID = ourBrowser._outerWindowID; + ourBrowser._outerWindowID = aOtherBrowser._outerWindowID; + aOtherBrowser._outerWindowID = ourOuterWindowID; + } + + // Register new outerWindowIDs. + this._outerWindowIDBrowserMap.set(ourBrowser.outerWindowID, ourBrowser); + if (remoteBrowser) { + remoteBrowser._outerWindowIDBrowserMap.set(aOtherBrowser.outerWindowID, aOtherBrowser); + } + // Swap permanentKey properties. let ourPermanentKey = ourBrowser.permanentKey; ourBrowser.permanentKey = aOtherBrowser.permanentKey; aOtherBrowser.permanentKey = ourPermanentKey; // Restore the progress listener this.mTabListeners[index] = tabListener = this.mTabProgressListener(aOurTab, ourBrowser, false);
--- a/browser/base/content/test/general/browser_devices_get_user_media.js +++ b/browser/base/content/test/general/browser_devices_get_user_media.js @@ -237,24 +237,26 @@ let gTests = [ expectObserverCalled("getUserMedia:request"); is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID, "webRTC-shareDevices-notification-icon", "anchored to device icon"); checkDeviceSelectors(true, true); is(PopupNotifications.panel.firstChild.getAttribute("popupid"), "webRTC-shareDevices", "panel using devices icon"); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "CameraAndMicrophone", "expected camera and microphone to be shared"); + yield indicator; yield checkSharingUI({audio: true, video: true}); yield closeStream(); } }, { desc: "getUserMedia audio only", run: function checkAudioOnly() { @@ -265,23 +267,25 @@ let gTests = [ expectObserverCalled("getUserMedia:request"); is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID, "webRTC-shareMicrophone-notification-icon", "anchored to mic icon"); checkDeviceSelectors(true); is(PopupNotifications.panel.firstChild.getAttribute("popupid"), "webRTC-shareMicrophone", "panel using microphone icon"); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "Microphone", "expected microphone to be shared"); + yield indicator; yield checkSharingUI({audio: true}); yield closeStream(); } }, { desc: "getUserMedia video only", run: function checkVideoOnly() { @@ -292,23 +296,25 @@ let gTests = [ expectObserverCalled("getUserMedia:request"); is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID, "webRTC-shareDevices-notification-icon", "anchored to device icon"); checkDeviceSelectors(false, true); is(PopupNotifications.panel.firstChild.getAttribute("popupid"), "webRTC-shareDevices", "panel using devices icon"); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "Camera", "expected camera to be shared"); + yield indicator; yield checkSharingUI({video: true}); yield closeStream(); } }, { desc: "getUserMedia audio+video, user disables video", run: function checkDisableVideo() { @@ -317,28 +323,30 @@ let gTests = [ content.wrappedJSObject.requestDevice(true, true); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(true, true); // disable the camera enableDevice("Camera", false); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); // reset the menuitem to have no impact on the following tests. enableDevice("Camera", true); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "Microphone", "expected microphone to be shared"); + yield indicator; yield checkSharingUI({audio: true}); yield closeStream(); } }, { desc: "getUserMedia audio+video, user disables audio", run: function checkDisableAudio() { @@ -347,28 +355,30 @@ let gTests = [ content.wrappedJSObject.requestDevice(true, true); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(true, true); // disable the microphone enableDevice("Microphone", false); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); // reset the menuitem to have no impact on the following tests. enableDevice("Microphone", true); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "Camera", "expected microphone to be shared"); + yield indicator; yield checkSharingUI({video: true}); yield closeStream(); } }, { desc: "getUserMedia audio+video, user disables both audio and video", run: function checkDisableAudioVideo() { @@ -422,24 +432,26 @@ let gTests = [ run: function checkStopSharing() { yield promisePopupNotificationShown("webRTC-shareDevices", () => { info("requesting devices"); content.wrappedJSObject.requestDevice(true, true); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(true, true); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "CameraAndMicrophone", "expected camera and microphone to be shared"); + yield indicator; yield checkSharingUI({video: true, audio: true}); yield promiseNotificationShown(PopupNotifications.getNotification("webRTC-sharingDevices")); activateSecondaryAction(kActionDeny); yield promiseObserverCalled("recording-device-events"); expectObserverCalled("getUserMedia:revoke"); @@ -464,24 +476,26 @@ let gTests = [ run: function checkReloading() { yield promisePopupNotificationShown("webRTC-shareDevices", () => { info("requesting devices"); content.wrappedJSObject.requestDevice(true, true); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(true, true); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "CameraAndMicrophone", "expected camera and microphone to be shared"); + yield indicator; yield checkSharingUI({video: true, audio: true}); yield promiseNotificationShown(PopupNotifications.getNotification("webRTC-sharingDevices")); info("reloading the web page"); yield promiseObserverCalled("recording-device-events", () => { content.location.reload(); }); @@ -725,23 +739,25 @@ let gTests = [ function stopAndCheckPerm(aRequestAudio, aRequestVideo) { let Perms = Services.perms; let uri = content.document.documentURIObject; // Initially set both permissions to 'allow'. Perms.add(uri, "microphone", Perms.ALLOW_ACTION); Perms.add(uri, "camera", Perms.ALLOW_ACTION); + let indicator = promiseIndicatorWindow(); // Start sharing what's been requested. yield promiseMessage("ok", () => { content.wrappedJSObject.requestDevice(aRequestAudio, aRequestVideo); }); expectObserverCalled("getUserMedia:request"); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); + yield indicator; yield checkSharingUI({video: aRequestVideo, audio: aRequestAudio}); yield promiseNotificationShown(PopupNotifications.getNotification("webRTC-sharingDevices")); let expectedIcon = "webRTC-sharingDevices"; if (aRequestAudio && !aRequestVideo) expectedIcon = "webRTC-sharingMicrophone"; is(PopupNotifications.getNotification("webRTC-sharingDevices").anchorID, expectedIcon + "-notification-icon", "anchored to correct icon"); @@ -796,23 +812,25 @@ let gTests = [ run: function checkShowSharingDoorhanger() { yield promisePopupNotificationShown("webRTC-shareDevices", () => { info("requesting devices"); content.wrappedJSObject.requestDevice(false, true); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(false, true); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "Camera", "expected camera to be shared"); + yield indicator; yield checkSharingUI({video: true}); yield promisePopupNotificationShown("webRTC-sharingDevices", () => { if ("nsISystemStatusBar" in Ci) { let activeStreams = gWebRTCUI.getActiveStreams(true, false, false); gWebRTCUI.showSharingDoorhanger(activeStreams[0], "Devices"); } else {
--- a/browser/base/content/test/general/browser_devices_get_user_media_in_frame.js +++ b/browser/base/content/test/general/browser_devices_get_user_media_in_frame.js @@ -236,48 +236,52 @@ let gTests = [ expectObserverCalled("getUserMedia:request"); is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID, "webRTC-shareDevices-notification-icon", "anchored to device icon"); checkDeviceSelectors(true, true); is(PopupNotifications.panel.firstChild.getAttribute("popupid"), "webRTC-shareDevices", "panel using devices icon"); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "CameraAndMicrophone", "expected camera and microphone to be shared"); + yield indicator; yield checkSharingUI({audio: true, video: true}); yield closeStream(global); } }, { desc: "getUserMedia audio+video: stop sharing", run: function checkStopSharing() { let global = getFrameGlobal("frame1"); yield promisePopupNotificationShown("webRTC-shareDevices", () => { info("requesting devices"); global.requestDevice(true, true); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(true, true); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "CameraAndMicrophone", "expected camera and microphone to be shared"); + yield indicator; yield checkSharingUI({video: true, audio: true}); yield promiseNotificationShown(PopupNotifications.getNotification("webRTC-sharingDevices")); activateSecondaryAction(kActionDeny); yield promiseObserverCalled("recording-device-events"); expectObserverCalled("getUserMedia:revoke"); @@ -303,24 +307,26 @@ let gTests = [ let global = getFrameGlobal("frame1"); yield promisePopupNotificationShown("webRTC-shareDevices", () => { info("requesting devices"); global.requestDevice(true, true); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(true, true); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "CameraAndMicrophone", "expected camera and microphone to be shared"); + yield indicator; yield checkSharingUI({video: true, audio: true}); info("reloading the frame"); yield promiseObserverCalled("recording-device-events", () => { global.location.reload(); }); yield promiseNoPopupNotification("webRTC-sharingDevices"); if (gObservedTopics["recording-device-events"] == 1) { @@ -365,23 +371,25 @@ let gTests = [ yield promisePopupNotificationShown("webRTC-shareDevices", () => { info("requesting microphone in the first frame"); g1.requestDevice(true, false); }); expectObserverCalled("getUserMedia:request"); checkDeviceSelectors(true, false); + let indicator = promiseIndicatorWindow(); yield promiseMessage("ok", () => { PopupNotifications.panel.firstChild.button.click(); }); expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); is(getMediaCaptureState(), "Microphone", "microphone to be shared"); + yield indicator; yield checkSharingUI({video: false, audio: true}); expectNoObserverCalled(); yield promisePopupNotificationShown("webRTC-shareDevices", () => { info("requesting both devices in the second frame"); g2.requestDevice(true, true); }); expectObserverCalled("getUserMedia:request");
--- a/browser/base/content/test/general/browser_e10s_chrome_process.js +++ b/browser/base/content/test/general/browser_e10s_chrome_process.js @@ -117,17 +117,17 @@ let TESTS = [ ], ]; // The different ways to transition from one page to another let TRANSITIONS = [ // Loads the new page by calling browser.loadURI directly function* loadURI(browser, uri) { info("Calling browser.loadURI"); - browser.loadURI(uri); + yield BrowserTestUtils.loadURI(browser, uri); return true; }, // Loads the new page by finding a link with the right href in the document and // clicking it function* clickLink(browser, uri) { info("Clicking link");
--- a/browser/base/content/test/general/browser_e10s_switchbrowser.js +++ b/browser/base/content/test/general/browser_e10s_switchbrowser.js @@ -192,28 +192,28 @@ add_task(function* test_synchronous() { let {permanentKey} = gBrowser.selectedBrowser; yield waitForLoad("http://example.org/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); info("2"); // Load another page info("Loading about:robots"); - gBrowser.selectedBrowser.loadURI("about:robots"); + yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "about:robots"); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield waitForDocLoadComplete(); is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); info("3"); // Load the remote page again info("Loading http://example.org/" + DUMMY_PATH); - gBrowser.loadURI("http://example.org/" + DUMMY_PATH); + yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "http://example.org/" + DUMMY_PATH); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); yield waitForDocLoadComplete(); is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct"); is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same"); info("4");
--- a/browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js +++ b/browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js @@ -21,17 +21,17 @@ function frame_script() { /** * Takes some browser in some window, and forces that browser * to become non-remote, and then navigates it to a page that * we're not supposed to be displaying remotely. Returns a * Promise that resolves when the browser is no longer remote. */ function prepareNonRemoteBrowser(aWindow, browser) { browser.loadURI(NON_REMOTE_PAGE); - return waitForDocLoadComplete(browser); + return BrowserTestUtils.browserLoaded(browser); } registerCleanupFunction(() => { Services.prefs.clearUserPref(OPEN_LOCATION_PREF); }); /** * Test that if we open a new tab from a link in a non-remote
--- a/browser/base/content/test/general/head.js +++ b/browser/base/content/test/general/head.js @@ -628,31 +628,43 @@ function waitForNewTabEvent(aTabBrowser) * Waits for a window with the given URL to exist. * * @param url * The url of the window. * @return {Promise} resolved when the window exists. * @resolves to the window */ function promiseWindow(url) { - info("waiting for a " + url + " window"); + info("expecting a " + url + " window"); return new Promise(resolve => { Services.obs.addObserver(function obs(win) { win.QueryInterface(Ci.nsIDOMWindow); - if (win.location.href !== url) { - info("ignoring a window with this url: " + win.location.href); - return; - } + win.addEventListener("load", function loadHandler() { + win.removeEventListener("load", loadHandler); - Services.obs.removeObserver(obs, "domwindowopened"); - resolve(win); + if (win.location.href !== url) { + info("ignoring a window with this url: " + win.location.href); + return; + } + + Services.obs.removeObserver(obs, "domwindowopened"); + resolve(win); + }); }, "domwindowopened", false); }); } +function promiseIndicatorWindow() { + // We don't show the indicator window on Mac. + if ("nsISystemStatusBar" in Ci) + return Promise.resolve(); + + return promiseWindow("chrome://browser/content/webrtcIndicator.xul"); +} + function assertWebRTCIndicatorStatus(expected) { let ui = Cu.import("resource:///modules/webrtcUI.jsm", {}).webrtcUI; let expectedState = expected ? "visible" : "hidden"; let msg = "WebRTC indicator " + expectedState; if (!expected && ui.showGlobalIndicator) { // It seems the global indicator is not always removed synchronously // in some cases. info("waiting for the global indicator to be hidden"); @@ -689,19 +701,16 @@ function assertWebRTCIndicatorStatus(exp if (e.target == win.document) { win.removeEventListener("unload", arguments.callee); resolve(); } }, false); }); } } - if (expected && - !Services.wm.getMostRecentWindow("Browser:WebRTCGlobalIndicator")) - yield promiseWindow("chrome://browser/content/webrtcIndicator.xul"); let indicator = Services.wm.getEnumerator("Browser:WebRTCGlobalIndicator"); let hasWindow = indicator.hasMoreElements(); is(hasWindow, !!expected, "popup " + msg); if (hasWindow) { let document = indicator.getNext().document; let docElt = document.documentElement; if (document.readyState != "complete") {
--- a/browser/base/content/web-panels.xul +++ b/browser/base/content/web-panels.xul @@ -7,18 +7,16 @@ <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?> <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?> <!DOCTYPE page [ <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd"> %browserDTD; -<!ENTITY % browserPocketDTD SYSTEM "chrome://browser/content/browser-pocket.dtd"> -%browserPocketDTD; <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd"> %textcontextDTD; ]> <page id="webpanels-window" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="load()" onunload="unload()">
--- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -70,22 +70,16 @@ browser.jar: content/browser/aboutSocialError.xhtml (content/aboutSocialError.xhtml) content/browser/aboutProviderDirectory.xhtml (content/aboutProviderDirectory.xhtml) content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css) content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js) content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml) * content/browser/browser.css (content/browser.css) * content/browser/browser.js (content/browser.js) * content/browser/browser.xul (content/browser.xul) - content/browser/browser-pocket-en-US.properties (content/browser-pocket-en-US.properties) - content/browser/browser-pocket.dtd (content/browser-pocket.dtd) - content/browser/browser-pocket-de.properties (content/browser-pocket-de.properties) - content/browser/browser-pocket-es-ES.properties (content/browser-pocket-es-ES.properties) - content/browser/browser-pocket-ja.properties (content/browser-pocket-ja.properties) - content/browser/browser-pocket-ru.properties (content/browser-pocket-ru.properties) * content/browser/browser-tabPreviews.xml (content/browser-tabPreviews.xml) * content/browser/chatWindow.xul (content/chatWindow.xul) content/browser/tab-content.js (content/tab-content.js) content/browser/content.js (content/content.js) content/browser/social-content.js (content/social-content.js) content/browser/defaultthemes/1.footer.jpg (content/defaultthemes/1.footer.jpg) content/browser/defaultthemes/1.header.jpg (content/defaultthemes/1.header.jpg) content/browser/defaultthemes/1.icon.jpg (content/defaultthemes/1.icon.jpg)
--- a/browser/components/controlcenter/content/panel.inc.xul +++ b/browser/components/controlcenter/content/panel.inc.xul @@ -8,47 +8,32 @@ noautofocus="true" onpopupshown="if (event.target == this) gIdentityHandler.onPopupShown(event);" orient="vertical" level="top"> <hbox id="identity-popup-container" align="top"> <image id="identity-popup-icon"/> <vbox id="identity-popup-content-box"> - <label id="identity-popup-brandName" - class="identity-popup-label" - value="&brandFullName;"/> - <label id="identity-popup-chromeLabel" - class="identity-popup-label"/> - <label id="identity-popup-connectedToLabel" + <label id="identity-popup-content-host" + class="identity-popup-description" + crop="end"/> + <label id="identity-popup-connection-secure" class="identity-popup-label" - value="&identity.connectedTo;"/> - <label id="identity-popup-connectedToLabel2" + value="&identity.connectionSecure;"/> + <label id="identity-popup-connection-not-secure" class="identity-popup-label" - value="&identity.unverifiedsite2;"/> - <description id="identity-popup-content-host" - class="identity-popup-description"/> - <label id="identity-popup-runByLabel" - class="identity-popup-label" - value="&identity.runBy;"/> + value="&identity.connectionNotSecure;"/> <description id="identity-popup-content-owner" class="identity-popup-description"/> <description id="identity-popup-content-supplemental" class="identity-popup-description"/> <description id="identity-popup-content-verifier" class="identity-popup-description"/> - <hbox id="identity-popup-encryption" flex="1"> - <vbox> - <image id="identity-popup-encryption-icon"/> - </vbox> - <description id="identity-popup-encryption-label" flex="1" - class="identity-popup-description"/> - </hbox> <vbox id="identity-popup-permissions"> - <separator class="thin"/> <label class="identity-popup-label header" value="&identity.permissions;"/> <vbox id="identity-popup-permission-list" class="indent"/> </vbox> </vbox> </hbox> <!-- Footer button to open security page info --> <hbox id="identity-popup-button-container" align="center">
--- a/browser/components/customizableui/CustomizableWidgets.jsm +++ b/browser/components/customizableui/CustomizableWidgets.jsm @@ -1060,57 +1060,36 @@ if (Services.prefs.getBoolPref("privacy. let forgetButton = aEvent.target.querySelector("#PanelUI-panic-view-button"); forgetButton.removeEventListener("command", this); }, }); } if (Services.prefs.getBoolPref("browser.pocket.enabled")) { let isEnabledForLocale = true; - let browserLocale; if (Services.prefs.getBoolPref("browser.pocket.useLocaleList")) { let chromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"] .getService(Ci.nsIXULChromeRegistry); - browserLocale = chromeRegistry.getSelectedLocale("browser"); + let browserLocale = chromeRegistry.getSelectedLocale("browser"); let enabledLocales = []; try { enabledLocales = Services.prefs.getCharPref("browser.pocket.enabledLocales").split(' '); } catch (ex) { Cu.reportError(ex); } isEnabledForLocale = enabledLocales.indexOf(browserLocale) != -1; } if (isEnabledForLocale) { - if (browserLocale == "ja-JP-mac") - browserLocale = "ja"; - let url = "chrome://browser/content/browser-pocket-" + browserLocale + ".properties"; - let strings = Services.strings.createBundle(url); - let label; - let tooltiptext; - try { - label = strings.GetStringFromName("pocket-button.label"); - tooltiptext = strings.GetStringFromName("pocket-button.tooltiptext"); - } catch (err) { - // GetStringFromName throws when the bundle doesn't exist. In that case, - // fall back to the en-US browser-pocket.properties. - url = "chrome://browser/content/browser-pocket-en-US.properties"; - strings = Services.strings.createBundle(url); - label = strings.GetStringFromName("pocket-button.label"); - tooltiptext = strings.GetStringFromName("pocket-button.tooltiptext"); - } - let pocketButton = { id: "pocket-button", defaultArea: CustomizableUI.AREA_NAVBAR, introducedInVersion: "pref", type: "view", viewId: "PanelUI-pocketView", - label: label, - tooltiptext: tooltiptext, // Use forwarding functions here to avoid loading Pocket.jsm on startup: onViewShowing: function() { return Pocket.onPanelViewShowing.apply(this, arguments); }, onViewHiding: function() { return Pocket.onPanelViewHiding.apply(this, arguments); },
--- a/browser/components/customizableui/test/browser_934951_zoom_in_toolbar.js +++ b/browser/components/customizableui/test/browser_934951_zoom_in_toolbar.js @@ -5,17 +5,19 @@ "use strict"; const kTimeoutInMS = 20000; // Bug 934951 - Zoom controls percentage label doesn't update when it's in the toolbar and you navigate. add_task(function() { CustomizableUI.addWidgetToArea("zoom-controls", CustomizableUI.AREA_NAVBAR); let tab1 = gBrowser.addTab("about:mozilla"); - let tab2 = gBrowser.addTab("about:newtab"); + yield BrowserTestUtils.browserLoaded(tab1.linkedBrowser); + let tab2 = gBrowser.addTab("about:robots"); + yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser); gBrowser.selectedTab = tab1; let zoomResetButton = document.getElementById("zoom-reset-button"); registerCleanupFunction(() => { info("Cleaning up."); CustomizableUI.reset(); gBrowser.removeTab(tab2); gBrowser.removeTab(tab1); @@ -25,17 +27,17 @@ add_task(function() { let zoomChangePromise = promiseObserverNotification("browser-fullZoom:zoomChange"); FullZoom.enlarge(); yield zoomChangePromise; is(parseInt(zoomResetButton.label, 10), 110, "Zoom is changed to 110% for about:mozilla"); let tabSelectPromise = promiseTabSelect(); gBrowser.selectedTab = tab2; yield tabSelectPromise; - is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:newtab"); + is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:robots"); gBrowser.selectedTab = tab1; let zoomResetPromise = promiseObserverNotification("browser-fullZoom:zoomReset"); FullZoom.reset(); yield zoomResetPromise; is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:mozilla"); // Test zoom label updates while navigating pages in the same tab. @@ -47,16 +49,17 @@ add_task(function() { }); yield promiseTabLoadEvent(tab1, "about:home"); yield attributeChangePromise; is(parseInt(zoomResetButton.label, 10), 100, "Default zoom is 100% for about:home"); yield promiseTabHistoryNavigation(-1, function() { return parseInt(zoomResetButton.label, 10) == 110; }); is(parseInt(zoomResetButton.label, 10), 110, "Zoom is still 110% for about:mozilla"); + FullZoom.reset(); }); function promiseObserverNotification(aObserver) { let deferred = Promise.defer(); function notificationCallback(e) { Services.obs.removeObserver(notificationCallback, aObserver, false); clearTimeout(timeoutId); deferred.resolve();
--- a/browser/components/loop/content/css/contacts.css +++ b/browser/components/loop/content/css/contacts.css @@ -129,17 +129,17 @@ border-radius: 50%; background-image: url("../shared/img/icons-16x16.svg#google"); background-position: center; background-size: 16px 16px; background-repeat: no-repeat; background-color: #fff; } -body[dir="rtl"] .contact > .details > .username > i.icon-google { +html[dir="rtl"] .contact > .details > .username > i.icon-google { left: 1rem; right: auto; } .contact > .details > .email { color: #999; font-size: 11px; line-height: 16px; @@ -188,17 +188,17 @@ body[dir="rtl"] .contact > .details > .u .contact > .dropdown-menu { z-index: 2; top: 10px; bottom: auto; right: 3em; left: auto; } -body[dir="rtl"] .contact > .dropdown-menu { +html[dir="rtl"] .contact > .dropdown-menu { right: auto; left: 3em; } .contact > .dropdown-menu-up { bottom: 10px; top: auto; } @@ -206,17 +206,17 @@ body[dir="rtl"] .contact > .dropdown-men .contact > .dropdown-menu > .dropdown-menu-item > .icon { width: 20px; height: 10px; background-position: center left; background-size: 10px 10px; margin-top: 3px; } -body[dir="rtl"] .contact > .dropdown-menu > .dropdown-menu-item > .icon { +html[dir="rtl"] .contact > .dropdown-menu > .dropdown-menu-item > .icon { background-position: center right; } .contact > .dropdown-menu > .dropdown-menu-item > .icon-audio-call { background-image: url("../shared/img/icons-16x16.svg#audio"); } .contact > .dropdown-menu > .dropdown-menu-item > .icon-video-call { @@ -254,17 +254,17 @@ body[dir="rtl"] .contact > .dropdown-men .contacts-gravatar-promo > p { margin-top: 2px; margin-bottom: 8px; margin-right: 4px; word-wrap: break-word; } -body[dir=rtl] .contacts-gravatar-promo > p { +html[dir="rtl"] .contacts-gravatar-promo > p { margin-right: 0; margin-left: 4px; } .contacts-gravatar-promo > p > a { color: #0295df; text-decoration: none; } @@ -274,12 +274,12 @@ body[dir=rtl] .contacts-gravatar-promo > } .contacts-gravatar-promo > .button-close { position: absolute; top: 8px; right: 8px; } -body[dir=rtl] .contacts-gravatar-promo > .button-close { +html[dir="rtl"] .contacts-gravatar-promo > .button-close { right: auto; left: 8px; }
--- a/browser/components/loop/content/css/panel.css +++ b/browser/components/loop/content/css/panel.css @@ -260,17 +260,17 @@ body { .new-room-view > .context > .context-content > .context-preview { float: left; width: 16px; max-height: 16px; -moz-margin-end: .8em; flex: 0 1 auto; } -body[dir=rtl] .new-room-view > .context > .context-content > .context-preview { +html[dir="rtl"] .new-room-view > .context > .context-content > .context-preview { float: left; } .new-room-view > .context > .context-content > .context-preview[src=""] { display: none; } .new-room-view > .context > .context-content > .context-description { @@ -562,17 +562,17 @@ body[dir=rtl] .new-room-view > .context position: absolute; pointer-events: none; z-index: 1; top: 4px; left: auto; right: 4px; } -body[dir=rtl] .generate-url-spinner { +html[dir="rtl"] .generate-url-spinner { left: 4px; right: auto; } #fte-button, .generate-url .button { background-color: #0096dd; border-color: #0096dd; @@ -748,17 +748,17 @@ body[dir=rtl] .generate-url-spinner { let's anchor it from the bottom-right, while resetting the top & left values set by .dropdown-menu */ top: auto; left: auto; bottom: -8px; right: 14px; } -body[dir="rtl"] .settings-menu .dropdown-menu { +html[dir="rtl"] .settings-menu .dropdown-menu { /* This is specified separately rather than using -moz-margin-start etc, as we need to override .dropdown-menu's values which can't use the gecko specific extensions. */ left: 14px; right: auto; } .settings-menu .icon {
--- a/browser/components/loop/content/js/conversation.js +++ b/browser/components/loop/content/js/conversation.js @@ -158,17 +158,18 @@ loop.conversation = (function(mozL10n) { dispatcher.dispatch(new sharedActions.WindowUnload()); }); React.render(React.createElement(AppControllerView, { roomStore: roomStore, dispatcher: dispatcher, mozLoop: navigator.mozLoop}), document.querySelector("#main")); - document.body.setAttribute("dir", mozL10n.getDirection()); + document.documentElement.setAttribute("lang", mozL10n.getLanguage()); + document.documentElement.setAttribute("dir", mozL10n.getDirection()); document.body.setAttribute("platform", loop.shared.utils.getPlatform()); dispatcher.dispatch(new sharedActions.GetWindowData({ windowId: windowId })); } return {
--- a/browser/components/loop/content/js/conversation.jsx +++ b/browser/components/loop/content/js/conversation.jsx @@ -158,17 +158,18 @@ loop.conversation = (function(mozL10n) { dispatcher.dispatch(new sharedActions.WindowUnload()); }); React.render(<AppControllerView roomStore={roomStore} dispatcher={dispatcher} mozLoop={navigator.mozLoop} />, document.querySelector("#main")); - document.body.setAttribute("dir", mozL10n.getDirection()); + document.documentElement.setAttribute("lang", mozL10n.getLanguage()); + document.documentElement.setAttribute("dir", mozL10n.getDirection()); document.body.setAttribute("platform", loop.shared.utils.getPlatform()); dispatcher.dispatch(new sharedActions.GetWindowData({ windowId: windowId })); } return {
--- a/browser/components/loop/content/js/conversationViews.js +++ b/browser/components/loop/content/js/conversationViews.js @@ -560,42 +560,54 @@ loop.conversationViews = (function(mozL1 ) ) ); } }); var OngoingConversationView = React.createClass({displayName: "OngoingConversationView", mixins: [ + loop.store.StoreMixin("conversationStore"), sharedMixins.MediaSetupMixin ], propTypes: { dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, + // local video: React.PropTypes.object, - audio: React.PropTypes.object + // local + audio: React.PropTypes.object, + remoteVideoEnabled: React.PropTypes.bool, + // This is used from the props rather than the state to make it easier for + // the ui-showcase. + mediaConnected: React.PropTypes.bool, + // The poster URLs are for UI-showcase testing and development. + localPosterUrl: React.PropTypes.string, + remotePosterUrl: React.PropTypes.string }, getDefaultProps: function() { return { video: {enabled: true, visible: true}, audio: {enabled: true, visible: true} }; }, + getInitialState: function() { + return this.getStoreState(); + }, + componentDidMount: function() { // The SDK needs to know about the configuration and the elements to use // for display. So the best way seems to pass the information here - ideally // the sdk wouldn't need to know this, but we can't change that. this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ publisherConfig: this.getDefaultPublisherConfig({ publishVideo: this.props.video.enabled - }), - getLocalElementFunc: this._getElement.bind(this, ".local"), - getRemoteElementFunc: this._getElement.bind(this, ".remote") + }) })); }, /** * Hangs up the call. */ hangup: function() { this.props.dispatcher.dispatch( @@ -611,33 +623,56 @@ loop.conversationViews = (function(mozL1 publishStream: function(type, enabled) { this.props.dispatcher.dispatch( new sharedActions.SetMute({ type: type, enabled: enabled })); }, + shouldRenderRemoteVideo: function() { + if (this.props.mediaConnected) { + // If remote video is not enabled, we're muted, so we'll show an avatar + // instead. + return this.props.remoteVideoEnabled; + } + + // We're not yet connected, but we don't want to show the avatar, and in + // the common case, we'll just transition to the video. + return true; + }, + render: function() { var localStreamClasses = React.addons.classSet({ local: true, "local-stream": true, "local-stream-audio": !this.props.video.enabled }); return ( React.createElement("div", {className: "video-layout-wrapper"}, React.createElement("div", {className: "conversation"}, React.createElement("div", {className: "media nested"}, React.createElement("div", {className: "video_wrapper remote_wrapper"}, - React.createElement("div", {className: "video_inner remote focus-stream"}) + React.createElement("div", {className: "video_inner remote focus-stream"}, + React.createElement(sharedViews.MediaView, {displayAvatar: !this.shouldRenderRemoteVideo(), + posterUrl: this.props.remotePosterUrl, + mediaType: "remote", + srcVideoObject: this.state.remoteSrcVideoObject}) + ) ), - React.createElement("div", {className: localStreamClasses}) + React.createElement("div", {className: localStreamClasses}, + React.createElement(sharedViews.MediaView, {displayAvatar: !this.props.video.enabled, + posterUrl: this.props.localPosterUrl, + mediaType: "local", + srcVideoObject: this.state.localSrcVideoObject}) + ) ), React.createElement(loop.shared.views.ConversationToolbar, { + dispatcher: this.props.dispatcher, video: this.props.video, audio: this.props.audio, publishStream: this.publishStream, hangup: this.hangup}) ) ) ); } @@ -737,17 +772,20 @@ loop.conversationViews = (function(mozL1 contact: this.state.contact, outgoing: this.state.outgoing} )); } case CALL_STATES.ONGOING: { return (React.createElement(OngoingConversationView, { dispatcher: this.props.dispatcher, video: {enabled: !this.state.videoMuted}, - audio: {enabled: !this.state.audioMuted}} + audio: {enabled: !this.state.audioMuted}, + remoteVideoEnabled: this.state.remoteVideoEnabled, + mediaConnected: this.state.mediaConnected, + remoteSrcVideoObject: this.state.remoteSrcVideoObject} ) ); } case CALL_STATES.FINISHED: { this.play("terminated"); return this._renderFeedbackView(); } case CALL_STATES.INIT: {
--- a/browser/components/loop/content/js/conversationViews.jsx +++ b/browser/components/loop/content/js/conversationViews.jsx @@ -560,42 +560,54 @@ loop.conversationViews = (function(mozL1 </div> </div> ); } }); var OngoingConversationView = React.createClass({ mixins: [ + loop.store.StoreMixin("conversationStore"), sharedMixins.MediaSetupMixin ], propTypes: { dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, + // local video: React.PropTypes.object, - audio: React.PropTypes.object + // local + audio: React.PropTypes.object, + remoteVideoEnabled: React.PropTypes.bool, + // This is used from the props rather than the state to make it easier for + // the ui-showcase. + mediaConnected: React.PropTypes.bool, + // The poster URLs are for UI-showcase testing and development. + localPosterUrl: React.PropTypes.string, + remotePosterUrl: React.PropTypes.string }, getDefaultProps: function() { return { video: {enabled: true, visible: true}, audio: {enabled: true, visible: true} }; }, + getInitialState: function() { + return this.getStoreState(); + }, + componentDidMount: function() { // The SDK needs to know about the configuration and the elements to use // for display. So the best way seems to pass the information here - ideally // the sdk wouldn't need to know this, but we can't change that. this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ publisherConfig: this.getDefaultPublisherConfig({ publishVideo: this.props.video.enabled - }), - getLocalElementFunc: this._getElement.bind(this, ".local"), - getRemoteElementFunc: this._getElement.bind(this, ".remote") + }) })); }, /** * Hangs up the call. */ hangup: function() { this.props.dispatcher.dispatch( @@ -611,33 +623,56 @@ loop.conversationViews = (function(mozL1 publishStream: function(type, enabled) { this.props.dispatcher.dispatch( new sharedActions.SetMute({ type: type, enabled: enabled })); }, + shouldRenderRemoteVideo: function() { + if (this.props.mediaConnected) { + // If remote video is not enabled, we're muted, so we'll show an avatar + // instead. + return this.props.remoteVideoEnabled; + } + + // We're not yet connected, but we don't want to show the avatar, and in + // the common case, we'll just transition to the video. + return true; + }, + render: function() { var localStreamClasses = React.addons.classSet({ local: true, "local-stream": true, "local-stream-audio": !this.props.video.enabled }); return ( <div className="video-layout-wrapper"> <div className="conversation"> <div className="media nested"> <div className="video_wrapper remote_wrapper"> - <div className="video_inner remote focus-stream"></div> + <div className="video_inner remote focus-stream"> + <sharedViews.MediaView displayAvatar={!this.shouldRenderRemoteVideo()} + posterUrl={this.props.remotePosterUrl} + mediaType="remote" + srcVideoObject={this.state.remoteSrcVideoObject} /> + </div> </div> - <div className={localStreamClasses}></div> + <div className={localStreamClasses}> + <sharedViews.MediaView displayAvatar={!this.props.video.enabled} + posterUrl={this.props.localPosterUrl} + mediaType="local" + srcVideoObject={this.state.localSrcVideoObject} /> + </div> </div> <loop.shared.views.ConversationToolbar + dispatcher={this.props.dispatcher} video={this.props.video} audio={this.props.audio} publishStream={this.publishStream} hangup={this.hangup} /> </div> </div> ); } @@ -738,16 +773,19 @@ loop.conversationViews = (function(mozL1 outgoing={this.state.outgoing} />); } case CALL_STATES.ONGOING: { return (<OngoingConversationView dispatcher={this.props.dispatcher} video={{enabled: !this.state.videoMuted}} audio={{enabled: !this.state.audioMuted}} + remoteVideoEnabled={this.state.remoteVideoEnabled} + mediaConnected={this.state.mediaConnected} + remoteSrcVideoObject={this.state.remoteSrcVideoObject} /> ); } case CALL_STATES.FINISHED: { this.play("terminated"); return this._renderFeedbackView(); } case CALL_STATES.INIT: {
--- a/browser/components/loop/content/js/panel.js +++ b/browser/components/loop/content/js/panel.js @@ -997,17 +997,18 @@ loop.panel = (function(_, mozL10n) { }); React.render(React.createElement(PanelView, { notifications: notifications, roomStore: roomStore, mozLoop: navigator.mozLoop, dispatcher: dispatcher}), document.querySelector("#main")); - document.body.setAttribute("dir", mozL10n.getDirection()); + document.documentElement.setAttribute("lang", mozL10n.getLanguage()); + document.documentElement.setAttribute("dir", mozL10n.getDirection()); document.body.setAttribute("platform", loop.shared.utils.getPlatform()); // Notify the window that we've finished initalization and initial layout var evtObject = document.createEvent("Event"); evtObject.initEvent("loopPanelInitialized", true, false); window.dispatchEvent(evtObject); }
--- a/browser/components/loop/content/js/panel.jsx +++ b/browser/components/loop/content/js/panel.jsx @@ -997,17 +997,18 @@ loop.panel = (function(_, mozL10n) { }); React.render(<PanelView notifications={notifications} roomStore={roomStore} mozLoop={navigator.mozLoop} dispatcher={dispatcher} />, document.querySelector("#main")); - document.body.setAttribute("dir", mozL10n.getDirection()); + document.documentElement.setAttribute("lang", mozL10n.getLanguage()); + document.documentElement.setAttribute("dir", mozL10n.getDirection()); document.body.setAttribute("platform", loop.shared.utils.getPlatform()); // Notify the window that we've finished initalization and initial layout var evtObject = document.createEvent("Event"); evtObject.initEvent("loopPanelInitialized", true, false); window.dispatchEvent(evtObject); }
--- a/browser/components/loop/content/js/roomStore.js +++ b/browser/components/loop/content/js/roomStore.js @@ -508,17 +508,21 @@ loop.store = loop.store || {}; } // TODO: there currently is no clear UX defined on what to do when all // context data was cleared, e.g. when diff.removed contains all the // context properties. Until then, we can't deal with context removal here. // When no properties have been set on the roomData object, there's nothing // to save. if (!Object.getOwnPropertyNames(roomData).length) { - this.dispatchAction(new sharedActions.UpdateRoomContextDone()); + // Ensure async actions so that we get separate setStoreState events + // that React components won't miss. + setTimeout(function() { + this.dispatchAction(new sharedActions.UpdateRoomContextDone()); + }.bind(this), 0); return; } this.setStoreState({error: null}); this._mozLoop.rooms.update(actionData.roomToken, roomData, function(err, data) { var action = err ? new sharedActions.UpdateRoomContextError({ error: err }) :
--- a/browser/components/loop/content/js/roomViews.js +++ b/browser/components/loop/content/js/roomViews.js @@ -333,24 +333,31 @@ loop.roomViews = (function(mozL10n) { newState.newRoomDescription = url.description; } if (!this.state.newRoomThumbnail && url.thumbnail) { newState.newRoomThumbnail = url.thumbnail; } } } + // Make sure we do not show the edit-mode when we just successfully saved + // context. + if (this.props.savingContext && nextProps.savingContext !== this.props.savingContext && + !nextProps.error && this.state.editMode) { + newState.editMode = false; + } + if (Object.getOwnPropertyNames(newState).length) { this.setState(newState); } }, getDefaultProps: function() { return { editMode: false }; - }, + }, getInitialState: function() { var url = this._getURL(); return { // `availableContext` prop only used in tests. availableContext: this.props.availableContext, editMode: this.props.editMode, show: this.props.show, @@ -523,17 +530,17 @@ loop.roomViews = (function(mozL10n) { React.createElement("textarea", {rows: "3", type: "text", className: "room-context-comments", onKeyDown: this.handleTextareaKeyDown, placeholder: mozL10n.get("context_edit_comments_placeholder"), valueLink: this.linkState("newRoomDescription")}) ), React.createElement("button", {className: "btn btn-info", disabled: this.props.savingContext, onClick: this.handleFormSubmit}, - mozL10n.get("context_save_label") + mozL10n.get("context_save_label2") ), React.createElement("button", {className: "room-context-btn-close", onClick: this.handleCloseClick, title: mozL10n.get("cancel_button")}) ) ); } @@ -574,32 +581,32 @@ loop.roomViews = (function(mozL10n) { sharedMixins.DocumentTitleMixin, sharedMixins.MediaSetupMixin, sharedMixins.RoomsAudioMixin, sharedMixins.WindowCloseMixin ], propTypes: { dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - mozLoop: React.PropTypes.object.isRequired + mozLoop: React.PropTypes.object.isRequired, + // The poster URLs are for UI-showcase testing and development. + localPosterUrl: React.PropTypes.string, + remotePosterUrl: React.PropTypes.string }, componentWillUpdate: function(nextProps, nextState) { // The SDK needs to know about the configuration and the elements to use // for display. So the best way seems to pass the information here - ideally // the sdk wouldn't need to know this, but we can't change that. if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT && nextState.roomState === ROOM_STATES.MEDIA_WAIT) { this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ publisherConfig: this.getDefaultPublisherConfig({ publishVideo: !this.state.videoMuted - }), - getLocalElementFunc: this._getElement.bind(this, ".local"), - getScreenShareElementFunc: this._getElement.bind(this, ".screen"), - getRemoteElementFunc: this._getElement.bind(this, ".remote") + }) })); } }, /** * User clicked on the "Leave" button. */ leaveRoom: function() { @@ -630,16 +637,50 @@ loop.roomViews = (function(mozL10n) { _shouldRenderContextView: function() { return !!( this.props.mozLoop.getLoopPref("contextInConversations.enabled") && (this.state.roomContextUrls || this.state.roomDescription) ); }, + /** + * Works out if remote video should be rended or not, depending on the + * room state and other flags. + * + * @return {Boolean} True if remote video should be rended. + */ + shouldRenderRemoteVideo: function() { + switch(this.state.roomState) { + case ROOM_STATES.HAS_PARTICIPANTS: + if (this.state.remoteVideoEnabled) { + return true; + } + + if (this.state.mediaConnected) { + // since the remoteVideo hasn't yet been enabled, if the + // media is connected, then we should be displaying an avatar. + return false; + } + + return true; + + case ROOM_STATES.SESSION_CONNECTED: + case ROOM_STATES.JOINED: + // this case is so that we don't show an avatar while waiting for + // the other party to connect + return true; + + default: + console.warn("StandaloneRoomView.shouldRenderRemoteVideo:" + + " unexpected roomState: ", this.state.roomState); + return true; + } + }, + render: function() { if (this.state.roomName) { this.setTitle(this.state.roomName); } var localStreamClasses = React.addons.classSet({ local: true, "local-stream": true, @@ -669,36 +710,46 @@ loop.roomViews = (function(mozL10n) { } case ROOM_STATES.ENDED: { return ( React.createElement(sharedViews.FeedbackView, { onAfterFeedbackReceived: this.closeWindow}) ); } default: { + return ( React.createElement("div", {className: "room-conversation-wrapper"}, React.createElement(sharedViews.TextChatView, {dispatcher: this.props.dispatcher}), React.createElement(DesktopRoomInvitationView, { dispatcher: this.props.dispatcher, error: this.state.error, mozLoop: this.props.mozLoop, roomData: roomData, savingContext: this.state.savingContext, show: shouldRenderInvitationOverlay, showContext: shouldRenderContextView, socialShareProviders: this.state.socialShareProviders}), React.createElement("div", {className: "video-layout-wrapper"}, React.createElement("div", {className: "conversation room-conversation"}, React.createElement("div", {className: "media nested"}, React.createElement("div", {className: "video_wrapper remote_wrapper"}, - React.createElement("div", {className: "video_inner remote focus-stream"}) + React.createElement("div", {className: "video_inner remote focus-stream"}, + React.createElement(sharedViews.MediaView, {displayAvatar: !this.shouldRenderRemoteVideo(), + posterUrl: this.props.remotePosterUrl, + mediaType: "remote", + srcVideoObject: this.state.remoteSrcVideoObject}) + ) ), - React.createElement("div", {className: localStreamClasses}), - React.createElement("div", {className: "screen hide"}) + React.createElement("div", {className: localStreamClasses}, + React.createElement(sharedViews.MediaView, {displayAvatar: this.state.videoMuted, + posterUrl: this.props.localPosterUrl, + mediaType: "local", + srcVideoObject: this.state.localSrcVideoObject}) + ) ), React.createElement(sharedViews.ConversationToolbar, { dispatcher: this.props.dispatcher, video: {enabled: !this.state.videoMuted, visible: true}, audio: {enabled: !this.state.audioMuted, visible: true}, publishStream: this.publishStream, hangup: this.leaveRoom, screenShare: screenShareData})
--- a/browser/components/loop/content/js/roomViews.jsx +++ b/browser/components/loop/content/js/roomViews.jsx @@ -333,24 +333,31 @@ loop.roomViews = (function(mozL10n) { newState.newRoomDescription = url.description; } if (!this.state.newRoomThumbnail && url.thumbnail) { newState.newRoomThumbnail = url.thumbnail; } } } + // Make sure we do not show the edit-mode when we just successfully saved + // context. + if (this.props.savingContext && nextProps.savingContext !== this.props.savingContext && + !nextProps.error && this.state.editMode) { + newState.editMode = false; + } + if (Object.getOwnPropertyNames(newState).length) { this.setState(newState); } }, getDefaultProps: function() { return { editMode: false }; - }, + }, getInitialState: function() { var url = this._getURL(); return { // `availableContext` prop only used in tests. availableContext: this.props.availableContext, editMode: this.props.editMode, show: this.props.show, @@ -523,17 +530,17 @@ loop.roomViews = (function(mozL10n) { <textarea rows="3" type="text" className="room-context-comments" onKeyDown={this.handleTextareaKeyDown} placeholder={mozL10n.get("context_edit_comments_placeholder")} valueLink={this.linkState("newRoomDescription")} /> </form> <button className="btn btn-info" disabled={this.props.savingContext} onClick={this.handleFormSubmit}> - {mozL10n.get("context_save_label")} + {mozL10n.get("context_save_label2")} </button> <button className="room-context-btn-close" onClick={this.handleCloseClick} title={mozL10n.get("cancel_button")}/> </div> ); } @@ -574,32 +581,32 @@ loop.roomViews = (function(mozL10n) { sharedMixins.DocumentTitleMixin, sharedMixins.MediaSetupMixin, sharedMixins.RoomsAudioMixin, sharedMixins.WindowCloseMixin ], propTypes: { dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - mozLoop: React.PropTypes.object.isRequired + mozLoop: React.PropTypes.object.isRequired, + // The poster URLs are for UI-showcase testing and development. + localPosterUrl: React.PropTypes.string, + remotePosterUrl: React.PropTypes.string }, componentWillUpdate: function(nextProps, nextState) { // The SDK needs to know about the configuration and the elements to use // for display. So the best way seems to pass the information here - ideally // the sdk wouldn't need to know this, but we can't change that. if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT && nextState.roomState === ROOM_STATES.MEDIA_WAIT) { this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ publisherConfig: this.getDefaultPublisherConfig({ publishVideo: !this.state.videoMuted - }), - getLocalElementFunc: this._getElement.bind(this, ".local"), - getScreenShareElementFunc: this._getElement.bind(this, ".screen"), - getRemoteElementFunc: this._getElement.bind(this, ".remote") + }) })); } }, /** * User clicked on the "Leave" button. */ leaveRoom: function() { @@ -630,16 +637,50 @@ loop.roomViews = (function(mozL10n) { _shouldRenderContextView: function() { return !!( this.props.mozLoop.getLoopPref("contextInConversations.enabled") && (this.state.roomContextUrls || this.state.roomDescription) ); }, + /** + * Works out if remote video should be rended or not, depending on the + * room state and other flags. + * + * @return {Boolean} True if remote video should be rended. + */ + shouldRenderRemoteVideo: function() { + switch(this.state.roomState) { + case ROOM_STATES.HAS_PARTICIPANTS: + if (this.state.remoteVideoEnabled) { + return true; + } + + if (this.state.mediaConnected) { + // since the remoteVideo hasn't yet been enabled, if the + // media is connected, then we should be displaying an avatar. + return false; + } + + return true; + + case ROOM_STATES.SESSION_CONNECTED: + case ROOM_STATES.JOINED: + // this case is so that we don't show an avatar while waiting for + // the other party to connect + return true; + + default: + console.warn("StandaloneRoomView.shouldRenderRemoteVideo:" + + " unexpected roomState: ", this.state.roomState); + return true; + } + }, + render: function() { if (this.state.roomName) { this.setTitle(this.state.roomName); } var localStreamClasses = React.addons.classSet({ local: true, "local-stream": true, @@ -669,36 +710,46 @@ loop.roomViews = (function(mozL10n) { } case ROOM_STATES.ENDED: { return ( <sharedViews.FeedbackView onAfterFeedbackReceived={this.closeWindow} /> ); } default: { + return ( <div className="room-conversation-wrapper"> <sharedViews.TextChatView dispatcher={this.props.dispatcher} /> <DesktopRoomInvitationView dispatcher={this.props.dispatcher} error={this.state.error} mozLoop={this.props.mozLoop} roomData={roomData} savingContext={this.state.savingContext} show={shouldRenderInvitationOverlay} showContext={shouldRenderContextView} socialShareProviders={this.state.socialShareProviders} /> <div className="video-layout-wrapper"> <div className="conversation room-conversation"> <div className="media nested"> <div className="video_wrapper remote_wrapper"> - <div className="video_inner remote focus-stream"></div> + <div className="video_inner remote focus-stream"> + <sharedViews.MediaView displayAvatar={!this.shouldRenderRemoteVideo()} + posterUrl={this.props.remotePosterUrl} + mediaType="remote" + srcVideoObject={this.state.remoteSrcVideoObject} /> + </div> </div> - <div className={localStreamClasses}></div> - <div className="screen hide"></div> + <div className={localStreamClasses}> + <sharedViews.MediaView displayAvatar={this.state.videoMuted} + posterUrl={this.props.localPosterUrl} + mediaType="local" + srcVideoObject={this.state.localSrcVideoObject} /> + </div> </div> <sharedViews.ConversationToolbar dispatcher={this.props.dispatcher} video={{enabled: !this.state.videoMuted, visible: true}} audio={{enabled: !this.state.audioMuted, visible: true}} publishStream={this.publishStream} hangup={this.leaveRoom} screenShare={screenShareData} />
--- a/browser/components/loop/content/libs/l10n.js +++ b/browser/components/loop/content/libs/l10n.js @@ -33,18 +33,19 @@ return text.replace(/\{\{\s*(\w+)\s*\}\}/g, function(all, name) { return name in args ? args[name] : '{{' + name + '}}'; }); } // translate a string function translateString(key, args, fallback) { - if (args && args.num) { - var num = args && args.num; + var num; + if (args && ("num" in args)) { + num = args.num; } var data = getL10nData(key, num); if (!data && fallback) data = {textContent: fallback}; if (!data) return '{{' + key + '}}'; return substArguments(data.textContent, args); }
--- a/browser/components/loop/content/shared/css/common.css +++ b/browser/components/loop/content/shared/css/common.css @@ -421,17 +421,17 @@ p { left: 0; background-color: #fdfdfd; box-shadow: 0 1px 3px rgba(0,0,0,.3); list-style: none; padding: 5px; border-radius: 2px; } -body[dir=rtl] .dropdown-menu { +html[dir="rtl"] .dropdown-menu { left: auto; right: 0; } .dropdown-menu-item { text-align: start; margin: .3em 0; padding: .2em .5em; @@ -476,17 +476,17 @@ body[dir=rtl] .dropdown-menu { border-radius: 3px; cursor: pointer; background-color: transparent; background-position: center center; background-repeat: no-repeat; background-size: 1em 1em; } -body[dir="rtl"] .checkbox { +html[dir="rtl"] .checkbox { float: right; } .checkbox.checked { background-image: url("../img/check.svg#check"); } .checkbox.checked:hover,
--- a/browser/components/loop/content/shared/css/conversation.css +++ b/browser/components/loop/content/shared/css/conversation.css @@ -249,16 +249,22 @@ .fx-embedded .remote_wrapper { position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; } +.fx-embedded .no-video { + background: black none repeat scroll 0% 0%; + height: 100%; + width: 100%; +} + .standalone .local-stream, .standalone .remote-inset-stream { /* required to have it superimposed to the control toolbar */ z-index: 1001; } .standalone .room-conversation .local-stream, .standalone .room-conversation .remote-inset-stream { @@ -507,21 +513,16 @@ position: absolute; right: 3px; bottom: 5px; /* next two lines are workaround for lack of object-fit; see bug 1020445 */ max-width: 140px; width: 30%; height: 28%; max-height: 105px; - box-shadow: 0px 2px 4px rgba(0,0,0,.5); -} - -.fx-embedded .room-conversation .local-stream { - box-shadow: none; } .fx-embedded .local-stream.room-preview { top: 0px; left: 0px; right: 0px; bottom: 0px; height: 100%; @@ -536,82 +537,41 @@ width: 100%; top: 0; bottom: 0; left: 0; right: 0; } /* - * XXX this approach is fragile because it makes assumptions - * about the generated OT markup, any change will break it - */ - -/* * For any audio-only streams, we want to display our own background */ -.OT_audio-only .OT_widget-container .OT_video-poster { +.avatar { background-image: url("../img/audio-call-avatar.svg"); background-repeat: no-repeat; background-color: #4BA6E7; background-size: contain; background-position: center; -} -/* - * Audio-only. For local streams, cancel out the SDK's opacity of 0.25. - * For remote streams we leave them shaded, as otherwise its too bright. - */ -.local-stream-audio .OT_publisher .OT_video-poster { - opacity: 1 -} - -/* - * In audio-only mode, don't display the video element, doing so interferes - * with the background opacity of the video-poster element. - */ -.OT_audio-only .OT_widget-container .OT_video-element { - display: none; + /* + * Expand to fill the available space, since there is no video any + * intrinsic width. XXX should really change to an <img> for clarity + */ + height: 100%; + width: 100%; } -/* - * Ensure that the publisher (i.e. local) video is never cropped, so that it's - * not possible for someone to be presented with a picture that displays - * (for example) a person from the neck up, even though the camera is capturing - * and transmitting a picture of that person from the waist up. - * - * The !importants are necessary to override the SDK attempts to avoid - * letterboxing entirely. - * - * If we could easily use test video streams with the SDK (eg if initPublisher - * supported something like a "testMediaToStreamURI" parameter that it would - * use to source the stream rather than the output of gUM, it wouldn't be too - * hard to generate a video with a 1 pixel border at the edges that one could - * at least visually see wasn't being cropped. - * - * Another less ugly possibility would be to work with Ted Mielczarek to use - * the fake camera drivers he has for Linux. - */ -.room-conversation .OT_publisher .OT_widget-container { - height: 100% !important; - width: 100% !important; - top: 0 !important; - left: 0 !important; - background-color: transparent; /* avoid visually obvious letterboxing */ +.local .avatar { + position: absolute; + z-index: 1; } -.room-conversation .OT_publisher .OT_widget-container video { - background-color: transparent; /* avoid visually obvious letterboxing */ -} - -.fx-embedded .room-conversation .room-preview .OT_publisher .OT_widget-container, -.fx-embedded .room-conversation .room-preview .OT_publisher .OT_widget-container video { - /* Desktop conversation window room preview local stream actually wants - a black background */ - background-color: #000; +.remote .avatar { + /* make visually distinct from local avatar */ + opacity: 0.25; } .fx-embedded .media.nested { min-height: 200px; } .fx-embedded-call-identifier { display: inline; @@ -707,17 +667,18 @@ html, .fx-embedded, #main, width: 100%; } .fx-embedded .text-chat-box { width: 100%; margin: auto; } -@media screen and (min-width:640px) { +/* We use 641px rather than 640, as min-width and max-width are inclusive */ +@media screen and (min-width:641px) { .standalone .conversation-toolbar { position: absolute; bottom: 0; left: 0; right: 0; } .fx-embedded .local-stream { @@ -761,21 +722,16 @@ html, .fx-embedded, #main, .standalone .conversation { height: 100%; } .standalone .media { height: 90%; } - .standalone .OT_subscriber { - height: 100%; - width: auto; - } - .standalone .media.nested { min-height: 500px; } .standalone .remote-inset-stream { display: none; } @@ -793,17 +749,17 @@ html, .fx-embedded, #main, flex-direction: column; align-items: center; justify-content: center; flex: 1 1 0%; } .standalone .video_wrapper.remote_wrapper { /* Because of OT markup we need to set a high flex value - * Flex rule assures remote and local streams stack on top of eachother + * Flex rule assures remote and local streams stack on top of each other * Computed width is not 100% unless the `width` rule */ flex: 2; width: 100%; position: relative; } } @media screen and (max-width:420px) { @@ -918,17 +874,17 @@ html, .fx-embedded, #main, cursor: pointer; } .room-invitation-addcontext:hover, .room-invitation-addcontext:hover:active { text-decoration: underline; } -body[dir="rtl"] .room-invitation-addcontext { +html[dir="rtl"] .room-invitation-addcontext { padding-left: 0; padding-right: 1.5em; background-position: right top; } .share-service-dropdown { color: #000; text-align: start; @@ -1147,23 +1103,23 @@ body[platform="win"] .share-service-drop background-image: url("../img/icons-10x10.svg#edit-active"); } .room-context-btn-close:hover, .room-context-btn-close:hover:active { background-image: url("../img/icons-10x10.svg#close-active"); } -body[dir=rtl] .room-context-btn-close, -body[dir=rtl] .room-context-btn-edit { +html[dir="rtl"] .room-context-btn-close, +html[dir="rtl"] .room-context-btn-edit { right: auto; left: 8px; } -body[dir=rtl] .room-context-btn-edit { +html[dir="rtl"] .room-context-btn-edit { left: 20px; } /* Standalone rooms */ .standalone .room-conversation-wrapper { position: relative; height: 100%; @@ -1273,17 +1229,17 @@ body[dir=rtl] .room-context-btn-edit { } .standalone .room-conversation .media { background: #000; } .standalone .room-conversation .video_wrapper.remote_wrapper { background-color: #4e4e4e; - width: 75%; + width: calc(75% - 10px); /* Take the left margin into account. */ } .standalone .room-conversation .conversation-toolbar { background: #000; border: none; } .standalone .room-conversation .conversation-toolbar .btn-hangup-entry { @@ -1396,19 +1352,52 @@ body[dir=rtl] .room-context-btn-edit { /* Avoid the privacy problem where a user can size the window so small that * part of the self view is not shown. If the self view isn't completely * displayable... */ @media screen and (max-height:160px) { /* disable the self view */ - .standalone .OT_publisher { + .standalone .local-video { display: none; } /* and enable a message telling the user how to get it back */ .standalone .self-view-hidden-message { display: inline; position: relative; top: 90px; } } + +.remote-video { + /* Since there is grey stuff behind us, avoid obvious letterboxing, only do + * this on remote video as local video has transparent background. + */ + background-color: black; +} + +.standalone .screen.focus-stream { + /* Since there is grey stuff behind us, avoid obvious letterboxing */ + background-color: black; +} + +.local-video { + width: 100%; + height: 100%; + /* Transform is to make the local video act like a mirror, as is the + convention in video conferencing systems. */ + transform: scale(-1, 1); + transform-origin: 50% 50% 0; +} + +.remote-video { + width: 100%; + height: 100%; + display: block; + position: absolute; +} + +.screen-share-video { + width: 100%; + height: 100%; +}
--- a/browser/components/loop/content/shared/js/actions.js +++ b/browser/components/loop/content/shared/js/actions.js @@ -188,24 +188,17 @@ loop.shared.actions = (function() { }), /** * Used by the ongoing views to notify stores about the elements * required for the sdk. */ SetupStreamElements: Action.define("setupStreamElements", { // The configuration for the publisher/subscribe options - publisherConfig: Object, - // The local stream element - getLocalElementFunc: Function, - // The screen share element; optional until all conversation - // types support it. - // getScreenShareElementFunc: Function, - // The remote stream element - getRemoteElementFunc: Function + publisherConfig: Object }), /** * Used for notifying that local media has been obtained. */ GotMediaPermission: Action.define("gotMediaPermission", { }), @@ -221,16 +214,52 @@ loop.shared.actions = (function() { */ VideoDimensionsChanged: Action.define("videoDimensionsChanged", { isLocal: Boolean, videoType: String, dimensions: Object }), /** + * Video has been enabled from the remote sender. + * + * XXX somewhat tangled up with remote video muting semantics; see bug + * 1171969 + * + * @note if/when we want to untangle this, we'll may want to include the + * reason provided by the SDK and documented hereI: + * https://tokbox.com/opentok/libraries/client/js/reference/VideoEnabledChangedEvent.html + */ + RemoteVideoEnabled: Action.define("remoteVideoEnabled", { + /* The SDK video object that the views will be copying the remote + stream from. */ + srcVideoObject: Object + }), + + /** + * Video has been disabled by the remote sender. + * + * @see RemoteVideoEnabled + */ + RemoteVideoDisabled: Action.define("remoteVideoDisabled", { + }), + + /** + * Video from the local camera has been enabled. + * + * XXX we should implement a LocalVideoDisabled action to cleanly prevent + * leakage; see bug 1171978 for details + */ + LocalVideoEnabled: Action.define("localVideoEnabled", { + /* The SDK video object that the views will be copying the remote + stream from. */ + srcVideoObject: Object + }), + + /** * Used to mute or unmute a stream */ SetMute: Action.define("setMute", { // The part of the stream to enable, e.g. "audio" or "video" type: String, // Whether or not to enable the stream. enabled: Boolean }), @@ -245,28 +274,32 @@ loop.shared.actions = (function() { /** * Used to end a screen share. */ EndScreenShare: Action.define("endScreenShare", { }), /** - * Used to notifiy that screen sharing is active or not. + * Used to notify that screen sharing is active or not. */ ScreenSharingState: Action.define("screenSharingState", { // One of loop.shared.utils.SCREEN_SHARE_STATES. state: String }), /** * Used to notify that a shared screen is being received (or not). + * + * XXX this is going to need to be split into two actions so when + * can display a spinner when the screen share is pending (bug 1171933) */ ReceivingScreenShare: Action.define("receivingScreenShare", { receiving: Boolean + // srcVideoObject: Object (only present if receiving is true) }), /** * Creates a new room. * XXX: should move to some roomActions module - refs bug 1079284 */ CreateRoom: Action.define("createRoom", { // The localized template to use to name the new room
--- a/browser/components/loop/content/shared/js/activeRoomStore.js +++ b/browser/components/loop/content/shared/js/activeRoomStore.js @@ -72,34 +72,40 @@ loop.store.ActiveRoomStore = (function() * due to user choice, failure or other reason. It is a subset of * getInitialStoreState as some items (e.g. roomState, failureReason, * context information) can persist across room exit & re-entry. * * @type {Array} */ _statesToResetOnLeave: [ "audioMuted", + "localSrcVideoObject", "localVideoDimensions", + "mediaConnected", "receivingScreenShare", + "remoteSrcVideoObject", "remoteVideoDimensions", + "remoteVideoEnabled", "screenSharingState", + "screenShareVideoObject", "videoMuted" ], /** * Returns initial state data for this active room. * * When adding states, consider if _statesToResetOnLeave needs updating * as well. */ getInitialStoreState: function() { return { roomState: ROOM_STATES.INIT, audioMuted: false, videoMuted: false, + remoteVideoEnabled: false, failureReason: undefined, // Tracks if the room has been used during this // session. 'Used' means at least one call has been placed // with it. Entering and leaving the room without seeing // anyone is not considered as 'used' used: false, localVideoDimensions: {}, remoteVideoDimensions: {}, @@ -110,17 +116,20 @@ loop.store.ActiveRoomStore = (function() // The roomCryptoKey to decode the context data if necessary. roomCryptoKey: null, // The description for a room as stored in the context data. roomDescription: null, // Room information failed to be obtained for a reason. See ROOM_INFO_FAILURES. roomInfoFailure: null, // The name of the room. roomName: null, - socialShareProviders: null + // Social API state. + socialShareProviders: null, + // True if media has been connected both-ways. + mediaConnected: false }; }, /** * Handles a room failure. * * @param {sharedActions.RoomFailure} actionData */ @@ -164,21 +173,25 @@ loop.store.ActiveRoomStore = (function() "setMute", "screenSharingState", "receivingScreenShare", "remotePeerDisconnected", "remotePeerConnected", "windowUnload", "leaveRoom", "feedbackComplete", + "localVideoEnabled", + "remoteVideoEnabled", + "remoteVideoDisabled", "videoDimensionsChanged", "startScreenShare", "endScreenShare", "updateSocialShareInfo", - "connectionStatus" + "connectionStatus", + "mediaConnected" ]); }, /** * Execute setupWindowData event action from the dispatcher. This gets * the room data from the mozLoop api, and dispatches an UpdateRoomInfo event. * It also dispatches JoinRoom as this action is only applicable to the desktop * client, and needs to auto-join. @@ -546,42 +559,85 @@ loop.store.ActiveRoomStore = (function() */ setMute: function(actionData) { var muteState = {}; muteState[actionData.type + "Muted"] = !actionData.enabled; this.setStoreState(muteState); }, /** + * Records the local video object for the room. + * + * @param {sharedActions.LocalVideoEnabled} actionData + */ + localVideoEnabled: function(actionData) { + this.setStoreState({localSrcVideoObject: actionData.srcVideoObject}); + }, + + /** + * Records the remote video object for the room. + * + * @param {sharedActions.RemoteVideoEnabled} actionData + */ + remoteVideoEnabled: function(actionData) { + this.setStoreState({ + remoteVideoEnabled: true, + remoteSrcVideoObject: actionData.srcVideoObject + }); + }, + + /** + * Records when remote video is disabled (e.g. due to mute). + */ + remoteVideoDisabled: function() { + this.setStoreState({remoteVideoEnabled: false}); + }, + + /** + * Records when the remote media has been connected. + */ + mediaConnected: function() { + this.setStoreState({mediaConnected: true}); + }, + + /** * Used to note the current screensharing state. */ screenSharingState: function(actionData) { this.setStoreState({screenSharingState: actionData.state}); this._mozLoop.setScreenShareState( this.getStoreState().windowId, actionData.state === SCREEN_SHARE_STATES.ACTIVE); }, /** * Used to note the current state of receiving screenshare data. + * + * XXX this is going to need to be split into two actions so when + * can display a spinner when the screen share is pending (bug 1171933) */ receivingScreenShare: function(actionData) { if (!actionData.receiving && this.getStoreState().remoteVideoDimensions.screen) { // Remove the remote video dimensions for type screen as we're not // getting the share anymore. var newDimensions = _.extend(this.getStoreState().remoteVideoDimensions); delete newDimensions.screen; this.setStoreState({ receivingScreenShare: actionData.receiving, - remoteVideoDimensions: newDimensions + remoteVideoDimensions: newDimensions, + screenShareVideoObject: null }); } else { - this.setStoreState({receivingScreenShare: actionData.receiving}); + this.setStoreState({ + receivingScreenShare: actionData.receiving, + screenShareVideoObject: actionData.srcVideoObject ? + actionData.srcVideoObject : null + }); } }, /** * Handles switching browser (aka tab) sharing to a new window. Should * only be used for browser sharing. * * @param {Number} windowId The new windowId to start sharing. @@ -671,17 +727,20 @@ loop.store.ActiveRoomStore = (function() }, /** * Handles a remote peer disconnecting from the session. As we currently only * support 2 participants, we declare the room as SESSION_CONNECTED as soon as * one participantleaves. */ remotePeerDisconnected: function() { - this.setStoreState({roomState: ROOM_STATES.SESSION_CONNECTED}); + this.setStoreState({ + roomState: ROOM_STATES.SESSION_CONNECTED, + remoteSrcVideoObject: null + }); }, /** * Handles an SDK status update, forwarding it to the server. * * @param {sharedActions.ConnectionStatus} actionData */ connectionStatus: function(actionData) {
--- a/browser/components/loop/content/shared/js/conversationStore.js +++ b/browser/components/loop/content/shared/js/conversationStore.js @@ -88,30 +88,33 @@ loop.store = loop.store || {}; // A link for emailing once obtained from the server emailLink: undefined, // Call Connection information // The call id from the loop-server callId: undefined, // The caller id of the contacting side callerId: undefined, + // True if media has been connected both-ways. + mediaConnected: false, // The connection progress url to connect the websocket progressURL: undefined, // The websocket token that allows connection to the progress url websocketToken: undefined, // SDK API key apiKey: undefined, // SDK session ID sessionId: undefined, // SDK session token sessionToken: undefined, - // If the audio is muted + // If the local audio is muted audioMuted: false, - // If the video is muted - videoMuted: false + // If the local video is muted + videoMuted: false, + remoteVideoEnabled: false }; }, /** * Handles initialisation of the store. * * @param {Object} options Options object. */ @@ -227,16 +230,19 @@ loop.store = loop.store || {}; "connectCall", "hangupCall", "remotePeerDisconnected", "cancelCall", "retryCall", "mediaConnected", "setMute", "fetchRoomEmailLink", + "localVideoEnabled", + "remoteVideoDisabled", + "remoteVideoEnabled", "windowUnload" ]); this.setStoreState({ apiKey: actionData.apiKey, callerId: actionData.callerId, callId: actionData.callId, callState: CALL_STATES.GATHER, @@ -403,16 +409,17 @@ loop.store = loop.store || {}; } }, /** * Notifies that all media is now connected */ mediaConnected: function() { this._websocket.mediaUp(); + this.setStoreState({mediaConnected: true}); }, /** * Records the mute state for the stream. * * @param {sharedActions.setMute} actionData The mute state for the stream type. */ setMute: function(actionData) { @@ -436,16 +443,54 @@ loop.store = loop.store || {}; this.trigger("error:emailLink"); return; } this.setStoreState({"emailLink": createdRoomData.roomUrl}); }.bind(this)); }, /** + * Handles when the remote stream has been enabled and is supplied. + * + * @param {sharedActions.RemoteVideoEnabled} actionData + */ + remoteVideoEnabled: function(actionData) { + this.setStoreState({ + remoteVideoEnabled: true, + remoteSrcVideoObject: actionData.srcVideoObject + }); + }, + + /** + * Handles when the remote stream has been disabled, e.g. due to video mute. + * + * @param {sharedActions.RemoteVideoDisabled} actionData + */ + remoteVideoDisabled: function(actionData) { + this.setStoreState({ + remoteVideoEnabled: false, + remoteSrcVideoObject: undefined}); + }, + + /** + * Handles when the local stream is supplied. + * + * XXX should write a localVideoDisabled action in otSdkDriver.js to + * positively ensure proper cleanup (handled by window teardown currently) + * (see bug 1171978) + * + * @param {sharedActions.LocalVideoEnabled} actionData + */ + localVideoEnabled: function(actionData) { + this.setStoreState({ + localSrcVideoObject: actionData.srcVideoObject + }); + }, + + /** * Called when the window is unloaded, either by code, or by the user * explicitly closing it. Expected to do any necessary housekeeping, such * as shutting down the call cleanly and adding any relevant telemetry data. */ windowUnload: function() { if (!this.getStoreState("outgoing") && this.getStoreState("callState") === CALL_STATES.ALERTING && this._websocket) {
--- a/browser/components/loop/content/shared/js/otSdkDriver.js +++ b/browser/components/loop/content/shared/js/otSdkDriver.js @@ -99,36 +99,38 @@ loop.OTSdkDriver = (function() { /** * Handles the setupStreamElements action. Saves the required data and * kicks off the initialising of the publisher. * * @param {sharedActions.SetupStreamElements} actionData The data associated * with the action. See action.js. */ setupStreamElements: function(actionData) { - this.getLocalElement = actionData.getLocalElementFunc; - this.getScreenShareElementFunc = actionData.getScreenShareElementFunc; - this.getRemoteElement = actionData.getRemoteElementFunc; this.publisherConfig = actionData.publisherConfig; this.sdk.on("exception", this._onOTException.bind(this)); // At this state we init the publisher, even though we might be waiting for // the initial connect of the session. This saves time when setting up // the media. this._publishLocalStreams(); }, /** * Internal function to publish a local stream. * XXX This can be simplified when bug 1138851 is actioned. */ _publishLocalStreams: function() { - this.publisher = this.sdk.initPublisher(this.getLocalElement(), + // We expect the local video to be muted automatically by the SDK. Hence + // we don't mute it manually here. + this._mockPublisherEl = document.createElement("div"); + + this.publisher = this.sdk.initPublisher(this._mockPublisherEl, _.extend(this._getDataChannelSettings, this._getCopyPublisherConfig)); + this.publisher.on("streamCreated", this._onLocalStreamCreated.bind(this)); this.publisher.on("streamDestroyed", this._onLocalStreamDestroyed.bind(this)); this.publisher.on("accessAllowed", this._onPublishComplete.bind(this)); this.publisher.on("accessDenied", this._onPublishDenied.bind(this)); this.publisher.on("accessDialogOpened", this._onAccessDialogOpened.bind(this)); }, @@ -177,17 +179,19 @@ loop.OTSdkDriver = (function() { // For browser sharing, we store the window Id so that we can avoid unnecessary // re-triggers. if (options.videoSource === "browser") { this._windowId = options.constraints.browserWindow; } var config = _.extend(this._getCopyPublisherConfig, options); - this.screenshare = this.sdk.initPublisher(this.getScreenShareElementFunc(), + this._mockScreenSharePreviewEl = document.createElement("div"); + + this.screenshare = this.sdk.initPublisher(this._mockScreenSharePreviewEl, config); this.screenshare.on("accessAllowed", this._onScreenShareGranted.bind(this)); this.screenshare.on("accessDenied", this._onScreenShareDenied.bind(this)); this.screenshare.on("streamCreated", this._onScreenShareStreamCreated.bind(this)); this._noteSharingState(options.videoSource, true); }, @@ -204,29 +208,30 @@ loop.OTSdkDriver = (function() { this._windowId = windowId; this.screenshare._.switchAcquiredWindow(windowId); }, /** * Ends an active screenshare session. Return `true` when an active screen- * sharing session was ended or `false` when no session is active. * - * @type {Boolean} + * @returns {Boolean} */ endScreenShare: function() { if (!this.screenshare) { return false; } this._notifyMetricsEvent("Publisher.streamDestroyed"); this.session.unpublish(this.screenshare); this.screenshare.off("accessAllowed accessDenied streamCreated"); this.screenshare.destroy(); delete this.screenshare; + delete this._mockScreenSharePreviewEl; this._noteSharingState(this._windowId ? "browser" : "window", false); delete this._windowId; return true; }, /** * Connects a session for the SDK, listening to the required events. * @@ -284,16 +289,17 @@ loop.OTSdkDriver = (function() { this._noteConnectionLengthIfNeeded(this._getTwoWayMediaStartTime(), performance.now()); // Also, tidy these variables ready for next time. delete this._sessionConnected; delete this._publisherReady; delete this._publishedLocalStream; delete this._subscribedRemoteStream; + delete this._mockPublisherEl; this.connections = {}; this._setTwoWayMediaStartTime(this.CONNECTION_START_TIME_UNINITIALIZED); }, /** * Oust all users from an ongoing session. This is typically done when a room * owner deletes the room. * @@ -494,29 +500,33 @@ loop.OTSdkDriver = (function() { * Handles when a remote screen share is created, subscribing to * the stream, and notifying the stores that a share is being * received. * * @param {Stream} stream The SDK Stream: * https://tokbox.com/opentok/libraries/client/js/reference/Stream.html */ _handleRemoteScreenShareCreated: function(stream) { - if (!this.getScreenShareElementFunc) { - return; - } + // Let the stores know first so they can update the display. + // XXX We do want to do this - we want them to start re-arranging the + // display so that we can a) indicate connecting, b) be ready for + // when we get the stream. However, we're currently limited by the fact + // the view calculations require the remote (aka screen share) element to + // be present and laid out. Hence, we need to drop this for the time being, + // and let the client know via _onScreenShareSubscribeCompleted. + // Bug 1171933 is going to look at fixing this. + // this.dispatcher.dispatch(new sharedActions.ReceivingScreenShare({ + // receiving: true + // })); - // Let the stores know first so they can update the display. - this.dispatcher.dispatch(new sharedActions.ReceivingScreenShare({ - receiving: true - })); - - var remoteElement = this.getScreenShareElementFunc(); - - this.session.subscribe(stream, - remoteElement, this._getCopyPublisherConfig); + // There's no audio for screen shares so we don't need to worry about mute. + this._mockScreenShareEl = document.createElement("div"); + this.session.subscribe(stream, this._mockScreenShareEl, + this._getCopyPublisherConfig, + this._onScreenShareSubscribeCompleted.bind(this)); }, /** * Handles the event when the remote stream is created. * * @param {StreamEvent} event The event details: * https://tokbox.com/opentok/libraries/client/js/reference/StreamEvent.html */ @@ -531,44 +541,110 @@ loop.OTSdkDriver = (function() { })); } if (event.stream.videoType === "screen") { this._handleRemoteScreenShareCreated(event.stream); return; } - var remoteElement = this.getRemoteElement(); + // Setting up the subscribe might want to be before the VideoDimensionsChange + // dispatch. If so, we might also want to consider moving the dispatch to + // _onSubscribeCompleted. However, this seems to work fine at the moment, + // so we haven't felt the need to move it. + + // XXX This mock element currently handles playing audio for the session. + // We might want to consider making the react tree responsible for playing + // the audio, so that the incoming audio could be disable/tracked easly from + // the UI (bug 1171896). + this._mockSubscribeEl = document.createElement("div"); this.subscriber = this.session.subscribe(event.stream, - remoteElement, this._getCopyPublisherConfig, - this._onRemoteSessionSubscribed.bind(this, event.stream.connection)); + this._mockSubscribeEl, this._getCopyPublisherConfig, + this._onSubscribeCompleted.bind(this)); + }, + + /** + * This method is passed as the "completionHandler" parameter to the SDK's + * Session.subscribe. + * + * @param err {(null|Error)} - null on success, an Error object otherwise + * @param sdkSubscriberObject {OT.Subscriber} - undocumented; returned on success + * @param subscriberVideo {HTMLVideoElement} - used for unit testing + */ + _onSubscribeCompleted: function(err, sdkSubscriberObject, subscriberVideo) { + // XXX test for and handle errors better (bug 1172140) + if (err) { + console.log("subscribe error:", err); + return; + } + + var sdkSubscriberVideo = subscriberVideo ? subscriberVideo : + this._mockSubscribeEl.querySelector("video"); + if (!sdkSubscriberVideo) { + console.error("sdkSubscriberVideo unexpectedly falsy!"); + } + + sdkSubscriberObject.on("videoEnabled", this._onVideoEnabled.bind(this)); + sdkSubscriberObject.on("videoDisabled", this._onVideoDisabled.bind(this)); + + // XXX for some reason, the SDK deliberately suppresses sending the + // videoEnabled event after subscribe, in spite of docs claiming + // otherwise, so we do it ourselves. + if (sdkSubscriberObject.stream.hasVideo) { + this.dispatcher.dispatch(new sharedActions.RemoteVideoEnabled({ + srcVideoObject: sdkSubscriberVideo})); + } this._subscribedRemoteStream = true; if (this._checkAllStreamsConnected()) { this._setTwoWayMediaStartTime(performance.now()); this.dispatcher.dispatch(new sharedActions.MediaConnected()); } + + this._setupDataChannelIfNeeded(sdkSubscriberObject.stream.connection); + }, + + /** + * This method is passed as the "completionHandler" parameter to the SDK's + * Session.subscribe. + * + * @param err {(null|Error)} - null on success, an Error object otherwise + * @param sdkSubscriberObject {OT.Subscriber} - undocumented; returned on success + * @param subscriberVideo {HTMLVideoElement} - used for unit testing + */ + _onScreenShareSubscribeCompleted: function(err, sdkSubscriberObject, subscriberVideo) { + // XXX test for and handle errors better + if (err) { + console.log("subscribe error:", err); + return; + } + + var sdkSubscriberVideo = subscriberVideo ? subscriberVideo : + this._mockScreenShareEl.querySelector("video"); + + // XXX no idea why this is necessary in addition to the dispatch in + // _handleRemoteScreenShareCreated. Maybe these should be separate + // actions. But even so, this shouldn't be necessary.... + this.dispatcher.dispatch(new sharedActions.ReceivingScreenShare({ + receiving: true, srcVideoObject: sdkSubscriberVideo + })); + }, /** * Once a remote stream has been subscribed to, this triggers the data * channel set-up routines. A data channel cannot be requested before this * time as the peer connection is not set up. * - * @param {OT.Connection} connection The OT connection class object. - * @param {OT.Error} err Indicates if there's been an error in - * completing the subscribe. + * @param {OT.Connection} connection The OT connection class object.paul + * sched + * */ - _onRemoteSessionSubscribed: function(connection, err) { - if (err) { - console.error(err); - return; - } - + _setupDataChannelIfNeeded: function(connection) { if (this._useDataChannels) { this.session.signal({ type: "readyForDataChannel", to: connection }, function(signalError) { if (signalError) { console.error(signalError); } @@ -665,16 +741,22 @@ loop.OTSdkDriver = (function() { * * @param {StreamEvent} event The event details: * https://tokbox.com/opentok/libraries/client/js/reference/StreamEvent.html */ _onLocalStreamCreated: function(event) { this._notifyMetricsEvent("Publisher.streamCreated"); if (event.stream[STREAM_PROPERTIES.HAS_VIDEO]) { + + var sdkLocalVideo = this._mockPublisherEl.querySelector("video"); + + this.dispatcher.dispatch(new sharedActions.LocalVideoEnabled( + {srcVideoObject: sdkLocalVideo})); + this.dispatcher.dispatch(new sharedActions.VideoDimensionsChanged({ isLocal: true, videoType: event.stream.videoType, dimensions: event.stream[STREAM_PROPERTIES.VIDEO_DIMENSIONS] })); } }, @@ -734,31 +816,35 @@ loop.OTSdkDriver = (function() { * * @param {StreamEvent} event The event details: * https://tokbox.com/opentok/libraries/client/js/reference/StreamEvent.html */ _onRemoteStreamDestroyed: function(event) { this._notifyMetricsEvent("Session.streamDestroyed"); if (event.stream.videoType !== "screen") { + delete this._mockSubscribeEl; return; } // All we need to do is notify the store we're no longer receiving, // the sdk should do the rest. this.dispatcher.dispatch(new sharedActions.ReceivingScreenShare({ receiving: false })); + + delete this._mockScreenShareEl; }, /** * Handles the event when the remote stream is destroyed. */ _onLocalStreamDestroyed: function() { this._notifyMetricsEvent("Publisher.streamDestroyed"); + delete this._mockPublisherEl; }, /** * Called from the sdk when the media access dialog is opened. * Prevents the default action, to prevent the SDK's "allow access" * dialog from being shown. * * @param {OT.Event} event @@ -788,27 +874,30 @@ loop.OTSdkDriver = (function() { */ _onPublishDenied: function(event) { // This prevents the SDK's "access denied" dialog showing. event.preventDefault(); this.dispatcher.dispatch(new sharedActions.ConnectionFailure({ reason: FAILURE_DETAILS.MEDIA_DENIED })); + + delete this._mockPublisherEl; }, _onOTException: function(event) { if (event.code === OT.ExceptionCodes.UNABLE_TO_PUBLISH && event.message === "GetUserMedia") { // We free up the publisher here in case the store wants to try // grabbing the media again. if (this.publisher) { this.publisher.off("accessAllowed accessDenied accessDialogOpened streamCreated"); this.publisher.destroy(); delete this.publisher; + delete this._mockPublisherEl; } this.dispatcher.dispatch(new sharedActions.ConnectionFailure({ reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA })); } }, /** @@ -820,16 +909,52 @@ loop.OTSdkDriver = (function() { isLocal: event.stream.connection.id == this.session.connection.id, videoType: event.stream.videoType, dimensions: event.stream[STREAM_PROPERTIES.VIDEO_DIMENSIONS] })); } }, /** + * Handle the (remote) VideoEnabled event from the subscriber object + * by dispatching an action with the (hidden) video element from + * which to copy the stream when attaching it to visible video element + * that the views control directly. + * + * @param event {OT.VideoEnabledChangedEvent} from the SDK + * + * @see https://tokbox.com/opentok/libraries/client/js/reference/VideoEnabledChangedEvent.html + * @private + */ + _onVideoEnabled: function(event) { + var sdkSubscriberVideo = this._mockSubscribeEl.querySelector("video"); + if (!sdkSubscriberVideo) { + console.error("sdkSubscriberVideo unexpectedly falsy!"); + } + + this.dispatcher.dispatch( + new sharedActions.RemoteVideoEnabled( + {srcVideoObject: sdkSubscriberVideo})); + }, + + /** + * Handle the SDK disabling of remote video by dispatching the + * appropriate event. + * + * @param event {OT.VideoEnabledChangedEvent) from the SDK + * + * @see https://tokbox.com/opentok/libraries/client/js/reference/VideoEnabledChangedEvent.html + * @private + */ + _onVideoDisabled: function(event) { + this.dispatcher.dispatch( + new sharedActions.RemoteVideoDisabled()); + }, + + /** * Publishes the local stream if the session is connected * and the publisher is ready. */ _maybePublishLocalStream: function() { if (this._sessionConnected && this._publisherReady) { // We are clear to publish the stream to the session. this.session.publish(this.publisher); @@ -863,16 +988,17 @@ loop.OTSdkDriver = (function() { /** * Called when a screenshare is denied. Notifies the other stores. */ _onScreenShareDenied: function() { this.dispatcher.dispatch(new sharedActions.ScreenSharingState({ state: SCREEN_SHARE_STATES.INACTIVE })); + delete this._mockScreenSharePreviewEl; }, /** * Called when a screenshare stream is published. */ _onScreenShareStreamCreated: function() { this._notifyMetricsEvent("Publisher.streamCreated"); },
--- a/browser/components/loop/content/shared/js/views.js +++ b/browser/components/loop/content/shared/js/views.js @@ -673,19 +673,138 @@ loop.shared.views = (function(_, l10n) { this.props.label ? React.createElement("label", null, this.props.label) : null ) ); } }); + /** + * Renders an avatar element for display when video is muted. + */ + var AvatarView = React.createClass({displayName: "AvatarView", + mixins: [React.addons.PureRenderMixin], + + render: function() { + return React.createElement("div", {className: "avatar"}); + } + }); + + /** + * Renders a media element for display. This also handles displaying an avatar + * instead of the video, and attaching a video stream to the video element. + */ + var MediaView = React.createClass({displayName: "MediaView", + // srcVideoObject should be ok for a shallow comparison, so we are safe + // to use the pure render mixin here. + mixins: [React.addons.PureRenderMixin], + + PropTypes: { + displayAvatar: React.PropTypes.bool.isRequired, + posterUrl: React.PropTypes.string, + // Expecting "local" or "remote". + mediaType: React.PropTypes.string.isRequired, + srcVideoObject: React.PropTypes.object + }, + + componentDidMount: function() { + if (!this.props.displayAvatar) { + this.attachVideo(this.props.srcVideoObject); + } + }, + + componentDidUpdate: function() { + if (!this.props.displayAvatar) { + this.attachVideo(this.props.srcVideoObject); + } + }, + + /** + * Attaches a video stream from a donor video element to this component's + * video element if the component is displaying one. + * + * @param {Object} srcVideoObject The src video object to clone the stream + * from. + * + * XXX need to have a corresponding detachVideo or change this to syncVideo + * to protect from leaks (bug 1171978) + */ + attachVideo: function(srcVideoObject) { + if (!srcVideoObject) { + // Not got anything to display. + return; + } + + var videoElement = this.getDOMNode(); + + if (videoElement.tagName.toLowerCase() !== "video") { + // Must be displaying the avatar view, so don't try and attach video. + return; + } + + // Set the src of our video element + var attrName = ""; + if ("srcObject" in videoElement) { + // srcObject is according to the standard. + attrName = "srcObject"; + } else if ("mozSrcObject" in videoElement) { + // mozSrcObject is for Firefox + attrName = "mozSrcObject"; + } else if ("src" in videoElement) { + // src is for Chrome. + attrName = "src"; + } else { + console.error("Error attaching stream to element - no supported attribute found"); + return; + } + + // If the object hasn't changed it, then don't reattach it. + if (videoElement[attrName] !== srcVideoObject[attrName]) { + videoElement[attrName] = srcVideoObject[attrName]; + } + videoElement.play(); + }, + + render: function() { + if (this.props.displayAvatar) { + return React.createElement(AvatarView, null); + } + + if (!this.props.srcVideoObject && !this.props.posterUrl) { + return React.createElement("div", {className: "no-video"}); + } + + var optionalPoster = {}; + if (this.props.posterUrl) { + optionalPoster.poster = this.props.posterUrl; + } + + // For now, always mute media. For local media, we should be muted anyway, + // as we don't want to hear ourselves speaking. + // + // For remote media, we would ideally have this live video element in + // control of the audio, but due to the current method of not rendering + // the element at all when video is muted we have to rely on the hidden + // dom element in the sdk driver to play the audio. + // We might want to consider changing this if we add UI controls relating + // to the remote audio at some stage in the future. + return ( + React.createElement("video", React.__spread({}, optionalPoster, + {className: this.props.mediaType + "-video", + muted: true})) + ); + } + }); + return { + AvatarView: AvatarView, Button: Button, ButtonGroup: ButtonGroup, Checkbox: Checkbox, ConversationView: ConversationView, ConversationToolbar: ConversationToolbar, MediaControlButton: MediaControlButton, + MediaView: MediaView, ScreenShareControlButton: ScreenShareControlButton, NotificationListView: NotificationListView }; })(_, navigator.mozL10n || document.mozL10n);
--- a/browser/components/loop/content/shared/js/views.jsx +++ b/browser/components/loop/content/shared/js/views.jsx @@ -673,19 +673,138 @@ loop.shared.views = (function(_, l10n) { {this.props.label ? <label>{this.props.label}</label> : null} </div> ); } }); + /** + * Renders an avatar element for display when video is muted. + */ + var AvatarView = React.createClass({ + mixins: [React.addons.PureRenderMixin], + + render: function() { + return <div className="avatar"/>; + } + }); + + /** + * Renders a media element for display. This also handles displaying an avatar + * instead of the video, and attaching a video stream to the video element. + */ + var MediaView = React.createClass({ + // srcVideoObject should be ok for a shallow comparison, so we are safe + // to use the pure render mixin here. + mixins: [React.addons.PureRenderMixin], + + PropTypes: { + displayAvatar: React.PropTypes.bool.isRequired, + posterUrl: React.PropTypes.string, + // Expecting "local" or "remote". + mediaType: React.PropTypes.string.isRequired, + srcVideoObject: React.PropTypes.object + }, + + componentDidMount: function() { + if (!this.props.displayAvatar) { + this.attachVideo(this.props.srcVideoObject); + } + }, + + componentDidUpdate: function() { + if (!this.props.displayAvatar) { + this.attachVideo(this.props.srcVideoObject); + } + }, + + /** + * Attaches a video stream from a donor video element to this component's + * video element if the component is displaying one. + * + * @param {Object} srcVideoObject The src video object to clone the stream + * from. + * + * XXX need to have a corresponding detachVideo or change this to syncVideo + * to protect from leaks (bug 1171978) + */ + attachVideo: function(srcVideoObject) { + if (!srcVideoObject) { + // Not got anything to display. + return; + } + + var videoElement = this.getDOMNode(); + + if (videoElement.tagName.toLowerCase() !== "video") { + // Must be displaying the avatar view, so don't try and attach video. + return; + } + + // Set the src of our video element + var attrName = ""; + if ("srcObject" in videoElement) { + // srcObject is according to the standard. + attrName = "srcObject"; + } else if ("mozSrcObject" in videoElement) { + // mozSrcObject is for Firefox + attrName = "mozSrcObject"; + } else if ("src" in videoElement) { + // src is for Chrome. + attrName = "src"; + } else { + console.error("Error attaching stream to element - no supported attribute found"); + return; + } + + // If the object hasn't changed it, then don't reattach it. + if (videoElement[attrName] !== srcVideoObject[attrName]) { + videoElement[attrName] = srcVideoObject[attrName]; + } + videoElement.play(); + }, + + render: function() { + if (this.props.displayAvatar) { + return <AvatarView />; + } + + if (!this.props.srcVideoObject && !this.props.posterUrl) { + return <div className="no-video"/>; + } + + var optionalPoster = {}; + if (this.props.posterUrl) { + optionalPoster.poster = this.props.posterUrl; + } + + // For now, always mute media. For local media, we should be muted anyway, + // as we don't want to hear ourselves speaking. + // + // For remote media, we would ideally have this live video element in + // control of the audio, but due to the current method of not rendering + // the element at all when video is muted we have to rely on the hidden + // dom element in the sdk driver to play the audio. + // We might want to consider changing this if we add UI controls relating + // to the remote audio at some stage in the future. + return ( + <video {...optionalPoster} + className={this.props.mediaType + "-video"} + muted /> + ); + } + }); + return { + AvatarView: AvatarView, Button: Button, ButtonGroup: ButtonGroup, Checkbox: Checkbox, ConversationView: ConversationView, ConversationToolbar: ConversationToolbar, MediaControlButton: MediaControlButton, + MediaView: MediaView, ScreenShareControlButton: ScreenShareControlButton, NotificationListView: NotificationListView }; })(_, navigator.mozL10n || document.mozL10n);
--- a/browser/components/loop/modules/MozLoopService.jsm +++ b/browser/components/loop/modules/MozLoopService.jsm @@ -117,17 +117,17 @@ XPCOMUtils.defineLazyServiceGetter(this, XPCOMUtils.defineLazyServiceGetter(this, "gWM", "@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator"); // Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref. XPCOMUtils.defineLazyGetter(this, "log", () => { let ConsoleAPI = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).ConsoleAPI; let consoleOptions = { - maxLogLevel: Services.prefs.getCharPref(PREF_LOG_LEVEL).toLowerCase(), + maxLogLevelPref: PREF_LOG_LEVEL, prefix: "Loop" }; return new ConsoleAPI(consoleOptions); }); function setJSONPref(aName, aValue) { let value = !!aValue ? JSON.stringify(aValue) : ""; Services.prefs.setCharPref(aName, value);
--- a/browser/components/loop/standalone/content/js/standaloneMozLoop.js +++ b/browser/components/loop/standalone/content/js/standaloneMozLoop.js @@ -126,17 +126,16 @@ loop.StandaloneMozLoop = (function(mozL1 data: JSON.stringify(roomData), beforeSend: function(xhr) { if (sessionToken) { xhr.setRequestHeader("Authorization", "Basic " + btoa(sessionToken)); } }, async: async, success: function(responseData) { - console.log("done"); try { callback(null, validate(responseData, expectedProps)); } catch (err) { console.error("Error requesting call info", err.message); callback(err); } }.bind(this), error: failureHandler.bind(this, callback)
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js @@ -332,17 +332,21 @@ loop.standaloneRoomViews = (function(moz ], propTypes: { activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) ]).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - isFirefox: React.PropTypes.bool.isRequired + isFirefox: React.PropTypes.bool.isRequired, + // The poster URLs are for UI-showcase testing and development + localPosterUrl: React.PropTypes.string, + remotePosterUrl: React.PropTypes.string, + screenSharePosterUrl: React.PropTypes.string }, getInitialState: function() { var storeState = this.props.activeRoomStore.getStoreState(); return _.extend({}, storeState, { // Used by the UI showcase. roomState: this.props.roomState || storeState.roomState }); @@ -380,20 +384,17 @@ loop.standaloneRoomViews = (function(moz * * @param {Object} nextProps (Unused) * @param {Object} nextState Next state object. */ componentWillUpdate: function(nextProps, nextState) { if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT && nextState.roomState === ROOM_STATES.MEDIA_WAIT) { this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ - publisherConfig: this.getDefaultPublisherConfig({publishVideo: true}), - getLocalElementFunc: this._getElement.bind(this, ".local"), - getRemoteElementFunc: this._getElement.bind(this, ".remote"), - getScreenShareElementFunc: this._getElement.bind(this, ".screen") + publisherConfig: this.getDefaultPublisherConfig({publishVideo: true}) })); } if (this.state.roomState !== ROOM_STATES.JOINED && nextState.roomState === ROOM_STATES.JOINED) { // This forces the video size to update - creating the publisher // first, and then connecting to the session doesn't seem to set the // initial size correctly. @@ -406,31 +407,59 @@ loop.standaloneRoomViews = (function(moz this.resetDimensionsCache(); } // When screen sharing stops. if (this.state.receivingScreenShare && !nextState.receivingScreenShare) { // Remove the custom screenshare styles on the remote camera. var node = this._getElement(".remote"); node.removeAttribute("style"); + } - // Force the video sizes to update. + if (this.state.receivingScreenShare != nextState.receivingScreenShare || + this.state.remoteVideoEnabled != nextState.remoteVideoEnabled) { this.updateVideoContainer(); } }, joinRoom: function() { this.props.dispatcher.dispatch(new sharedActions.JoinRoom()); }, leaveRoom: function() { this.props.dispatcher.dispatch(new sharedActions.LeaveRoom()); }, /** + * Wrapper for window.matchMedia so that we use an appropriate version + * for the ui-showcase, which puts views inside of their own iframes. + * + * Currently, we use an icky hack, and the showcase conspires with + * react-frame-component to set iframe.contentWindow.matchMedia onto + * activeRoomStore. Once React context matures a bit (somewhere between + * 0.14 and 1.0, apparently): + * + * https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based + * + * we should be able to use those to clean this up. + * + * @param queryString + * @returns {MediaQueryList|null} + * @private + */ + _matchMedia: function(queryString) { + if ("matchMedia" in this.state) { + return this.state.matchMedia(queryString); + } else if ("matchMedia" in window) { + return window.matchMedia(queryString); + } + return null; + }, + + /** * Toggles streaming status for a given stream type. * * @param {String} type Stream type ("audio" or "video"). * @param {Boolean} enabled Enabled stream flag. */ publishStream: function(type, enabled) { this.props.dispatcher.dispatch(new sharedActions.SetMute({ type: type, @@ -453,30 +482,47 @@ loop.standaloneRoomViews = (function(moz var LOCAL_STREAM_OVERLAP = 0.25; // The minimum size of video height/width allowed by the sdk css. var SDK_MIN_SIZE = 48; var node = this._getElement(".local"); var targetWidth; node.style.right = "auto"; - if (window.matchMedia && window.matchMedia("screen and (max-width:640px)").matches) { + if (this._matchMedia("screen and (max-width:640px)").matches) { // For reduced screen widths, we just go for a fixed size and no overlap. targetWidth = 180; node.style.width = (targetWidth * ratio.width) + "px"; node.style.height = (targetWidth * ratio.height) + "px"; node.style.left = "auto"; } else { // The local camera view should be a quarter of the size of the remote stream // and positioned to overlap with the remote stream at a quarter of its width. // Now position the local camera view correctly with respect to the remote // video stream or the screen share stream. - var remoteVideoDimensions = this.getRemoteVideoDimensions( - this.state.receivingScreenShare ? "screen" : "camera"); + var remoteVideoDimensions; + var isScreenShare = this.state.receivingScreenShare; + var videoDisplayed = isScreenShare ? + this.state.screenShareVideoObject || this.props.screenSharePosterUrl : + this.state.remoteSrcVideoObject || this.props.remotePosterUrl; + + if ((isScreenShare || this.shouldRenderRemoteVideo()) && videoDisplayed) { + remoteVideoDimensions = this.getRemoteVideoDimensions( + isScreenShare ? "screen" : "camera"); + } else { + var remoteElement = this.getDOMNode().querySelector(".remote.focus-stream"); + if (!remoteElement) { + return; + } + remoteVideoDimensions = { + streamWidth: remoteElement.offsetWidth, + offsetX: remoteElement.offsetLeft + }; + } targetWidth = remoteVideoDimensions.streamWidth * LOCAL_STREAM_SIZE; var realWidth = targetWidth * ratio.width; var realHeight = targetWidth * ratio.height; // If we've hit the min size limits, then limit at the minimum. if (realWidth < SDK_MIN_SIZE) { @@ -510,17 +556,17 @@ loop.standaloneRoomViews = (function(moz */ updateRemoteCameraPosition: function(ratio) { // Nothing to do for screenshare if (!this.state.receivingScreenShare) { return; } // XXX For the time being, if we're a narrow screen, aka mobile, we don't display // the remote media (bug 1133534). - if (window.matchMedia && window.matchMedia("screen and (max-width:640px)").matches) { + if (this._matchMedia("screen and (max-width:640px)").matches) { return; } // 10px separation between the two streams. var LOCAL_REMOTE_SEPARATION = 10; var node = this._getElement(".remote"); var localNode = this._getElement(".local"); @@ -552,19 +598,61 @@ loop.standaloneRoomViews = (function(moz * @return {Boolean} */ _roomIsActive: function() { return this.state.roomState === ROOM_STATES.JOINED || this.state.roomState === ROOM_STATES.SESSION_CONNECTED || this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS; }, + /** + * Works out if remote video should be rended or not, depending on the + * room state and other flags. + * + * @return {Boolean} True if remote video should be rended. + */ + shouldRenderRemoteVideo: function() { + switch(this.state.roomState) { + case ROOM_STATES.HAS_PARTICIPANTS: + if (this.state.remoteVideoEnabled) { + return true; + } + + if (this.state.mediaConnected) { + // since the remoteVideo hasn't yet been enabled, if the + // media is connected, then we should be displaying an avatar. + return false; + } + + return true; + + case ROOM_STATES.READY: + case ROOM_STATES.INIT: + case ROOM_STATES.JOINING: + case ROOM_STATES.SESSION_CONNECTED: + case ROOM_STATES.JOINED: + case ROOM_STATES.MEDIA_WAIT: + // this case is so that we don't show an avatar while waiting for + // the other party to connect + return true; + + case ROOM_STATES.CLOSING: + // the other person has shown up, so we don't want to show an avatar + return true; + + default: + console.warn("StandaloneRoomView.shouldRenderRemoteVideo:" + + " unexpected roomState: ", this.state.roomState); + return true; + + } + }, + render: function() { var localStreamClasses = React.addons.classSet({ - hide: !this._roomIsActive(), local: true, "local-stream": true, "local-stream-audio": this.state.videoMuted }); var remoteStreamClasses = React.addons.classSet({ "video_inner": true, "remote": true, @@ -597,20 +685,35 @@ loop.standaloneRoomViews = (function(moz roomContextUrls: this.state.roomContextUrls, roomName: this.state.roomName, roomInfoFailure: this.state.roomInfoFailure}), React.createElement("div", {className: "media nested"}, React.createElement("span", {className: "self-view-hidden-message"}, mozL10n.get("self_view_hidden_message") ), React.createElement("div", {className: "video_wrapper remote_wrapper"}, - React.createElement("div", {className: remoteStreamClasses}), - React.createElement("div", {className: screenShareStreamClasses}) + React.createElement("div", {className: remoteStreamClasses}, + React.createElement(sharedViews.MediaView, {displayAvatar: !this.shouldRenderRemoteVideo(), + posterUrl: this.props.remotePosterUrl, + mediaType: "remote", + srcVideoObject: this.state.remoteSrcVideoObject}) + ), + React.createElement("div", {className: screenShareStreamClasses}, + React.createElement(sharedViews.MediaView, {displayAvatar: false, + posterUrl: this.props.screenSharePosterUrl, + mediaType: "screen-share", + srcVideoObject: this.state.screenShareVideoObject}) + ) ), - React.createElement("div", {className: localStreamClasses}) + React.createElement("div", {className: localStreamClasses}, + React.createElement(sharedViews.MediaView, {displayAvatar: this.state.videoMuted, + posterUrl: this.props.localPosterUrl, + mediaType: "local", + srcVideoObject: this.state.localSrcVideoObject}) + ) ), React.createElement(sharedViews.ConversationToolbar, { dispatcher: this.props.dispatcher, video: {enabled: !this.state.videoMuted, visible: this._roomIsActive()}, audio: {enabled: !this.state.audioMuted, visible: this._roomIsActive()}, publishStream: this.publishStream,
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx @@ -332,17 +332,21 @@ loop.standaloneRoomViews = (function(moz ], propTypes: { activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) ]).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - isFirefox: React.PropTypes.bool.isRequired + isFirefox: React.PropTypes.bool.isRequired, + // The poster URLs are for UI-showcase testing and development + localPosterUrl: React.PropTypes.string, + remotePosterUrl: React.PropTypes.string, + screenSharePosterUrl: React.PropTypes.string }, getInitialState: function() { var storeState = this.props.activeRoomStore.getStoreState(); return _.extend({}, storeState, { // Used by the UI showcase. roomState: this.props.roomState || storeState.roomState }); @@ -380,20 +384,17 @@ loop.standaloneRoomViews = (function(moz * * @param {Object} nextProps (Unused) * @param {Object} nextState Next state object. */ componentWillUpdate: function(nextProps, nextState) { if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT && nextState.roomState === ROOM_STATES.MEDIA_WAIT) { this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({ - publisherConfig: this.getDefaultPublisherConfig({publishVideo: true}), - getLocalElementFunc: this._getElement.bind(this, ".local"), - getRemoteElementFunc: this._getElement.bind(this, ".remote"), - getScreenShareElementFunc: this._getElement.bind(this, ".screen") + publisherConfig: this.getDefaultPublisherConfig({publishVideo: true}) })); } if (this.state.roomState !== ROOM_STATES.JOINED && nextState.roomState === ROOM_STATES.JOINED) { // This forces the video size to update - creating the publisher // first, and then connecting to the session doesn't seem to set the // initial size correctly. @@ -406,31 +407,59 @@ loop.standaloneRoomViews = (function(moz this.resetDimensionsCache(); } // When screen sharing stops. if (this.state.receivingScreenShare && !nextState.receivingScreenShare) { // Remove the custom screenshare styles on the remote camera. var node = this._getElement(".remote"); node.removeAttribute("style"); + } - // Force the video sizes to update. + if (this.state.receivingScreenShare != nextState.receivingScreenShare || + this.state.remoteVideoEnabled != nextState.remoteVideoEnabled) { this.updateVideoContainer(); } }, joinRoom: function() { this.props.dispatcher.dispatch(new sharedActions.JoinRoom()); }, leaveRoom: function() { this.props.dispatcher.dispatch(new sharedActions.LeaveRoom()); }, /** + * Wrapper for window.matchMedia so that we use an appropriate version + * for the ui-showcase, which puts views inside of their own iframes. + * + * Currently, we use an icky hack, and the showcase conspires with + * react-frame-component to set iframe.contentWindow.matchMedia onto + * activeRoomStore. Once React context matures a bit (somewhere between + * 0.14 and 1.0, apparently): + * + * https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based + * + * we should be able to use those to clean this up. + * + * @param queryString + * @returns {MediaQueryList|null} + * @private + */ + _matchMedia: function(queryString) { + if ("matchMedia" in this.state) { + return this.state.matchMedia(queryString); + } else if ("matchMedia" in window) { + return window.matchMedia(queryString); + } + return null; + }, + + /** * Toggles streaming status for a given stream type. * * @param {String} type Stream type ("audio" or "video"). * @param {Boolean} enabled Enabled stream flag. */ publishStream: function(type, enabled) { this.props.dispatcher.dispatch(new sharedActions.SetMute({ type: type, @@ -453,30 +482,47 @@ loop.standaloneRoomViews = (function(moz var LOCAL_STREAM_OVERLAP = 0.25; // The minimum size of video height/width allowed by the sdk css. var SDK_MIN_SIZE = 48; var node = this._getElement(".local"); var targetWidth; node.style.right = "auto"; - if (window.matchMedia && window.matchMedia("screen and (max-width:640px)").matches) { + if (this._matchMedia("screen and (max-width:640px)").matches) { // For reduced screen widths, we just go for a fixed size and no overlap. targetWidth = 180; node.style.width = (targetWidth * ratio.width) + "px"; node.style.height = (targetWidth * ratio.height) + "px"; node.style.left = "auto"; } else { // The local camera view should be a quarter of the size of the remote stream // and positioned to overlap with the remote stream at a quarter of its width. // Now position the local camera view correctly with respect to the remote // video stream or the screen share stream. - var remoteVideoDimensions = this.getRemoteVideoDimensions( - this.state.receivingScreenShare ? "screen" : "camera"); + var remoteVideoDimensions; + var isScreenShare = this.state.receivingScreenShare; + var videoDisplayed = isScreenShare ? + this.state.screenShareVideoObject || this.props.screenSharePosterUrl : + this.state.remoteSrcVideoObject || this.props.remotePosterUrl; + + if ((isScreenShare || this.shouldRenderRemoteVideo()) && videoDisplayed) { + remoteVideoDimensions = this.getRemoteVideoDimensions( + isScreenShare ? "screen" : "camera"); + } else { + var remoteElement = this.getDOMNode().querySelector(".remote.focus-stream"); + if (!remoteElement) { + return; + } + remoteVideoDimensions = { + streamWidth: remoteElement.offsetWidth, + offsetX: remoteElement.offsetLeft + }; + } targetWidth = remoteVideoDimensions.streamWidth * LOCAL_STREAM_SIZE; var realWidth = targetWidth * ratio.width; var realHeight = targetWidth * ratio.height; // If we've hit the min size limits, then limit at the minimum. if (realWidth < SDK_MIN_SIZE) { @@ -510,17 +556,17 @@ loop.standaloneRoomViews = (function(moz */ updateRemoteCameraPosition: function(ratio) { // Nothing to do for screenshare if (!this.state.receivingScreenShare) { return; } // XXX For the time being, if we're a narrow screen, aka mobile, we don't display // the remote media (bug 1133534). - if (window.matchMedia && window.matchMedia("screen and (max-width:640px)").matches) { + if (this._matchMedia("screen and (max-width:640px)").matches) { return; } // 10px separation between the two streams. var LOCAL_REMOTE_SEPARATION = 10; var node = this._getElement(".remote"); var localNode = this._getElement(".local"); @@ -552,19 +598,61 @@ loop.standaloneRoomViews = (function(moz * @return {Boolean} */ _roomIsActive: function() { return this.state.roomState === ROOM_STATES.JOINED || this.state.roomState === ROOM_STATES.SESSION_CONNECTED || this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS; }, + /** + * Works out if remote video should be rended or not, depending on the + * room state and other flags. + * + * @return {Boolean} True if remote video should be rended. + */ + shouldRenderRemoteVideo: function() { + switch(this.state.roomState) { + case ROOM_STATES.HAS_PARTICIPANTS: + if (this.state.remoteVideoEnabled) { + return true; + } + + if (this.state.mediaConnected) { + // since the remoteVideo hasn't yet been enabled, if the + // media is connected, then we should be displaying an avatar. + return false; + } + + return true; + + case ROOM_STATES.READY: + case ROOM_STATES.INIT: + case ROOM_STATES.JOINING: + case ROOM_STATES.SESSION_CONNECTED: + case ROOM_STATES.JOINED: + case ROOM_STATES.MEDIA_WAIT: + // this case is so that we don't show an avatar while waiting for + // the other party to connect + return true; + + case ROOM_STATES.CLOSING: + // the other person has shown up, so we don't want to show an avatar + return true; + + default: + console.warn("StandaloneRoomView.shouldRenderRemoteVideo:" + + " unexpected roomState: ", this.state.roomState); + return true; + + } + }, + render: function() { var localStreamClasses = React.addons.classSet({ - hide: !this._roomIsActive(), local: true, "local-stream": true, "local-stream-audio": this.state.videoMuted }); var remoteStreamClasses = React.addons.classSet({ "video_inner": true, "remote": true, @@ -597,20 +685,35 @@ loop.standaloneRoomViews = (function(moz roomContextUrls={this.state.roomContextUrls} roomName={this.state.roomName} roomInfoFailure={this.state.roomInfoFailure} /> <div className="media nested"> <span className="self-view-hidden-message"> {mozL10n.get("self_view_hidden_message")} </span> <div className="video_wrapper remote_wrapper"> - <div className={remoteStreamClasses}></div> - <div className={screenShareStreamClasses}></div> + <div className={remoteStreamClasses}> + <sharedViews.MediaView displayAvatar={!this.shouldRenderRemoteVideo()} + posterUrl={this.props.remotePosterUrl} + mediaType="remote" + srcVideoObject={this.state.remoteSrcVideoObject} /> + </div> + <div className={screenShareStreamClasses}> + <sharedViews.MediaView displayAvatar={false} + posterUrl={this.props.screenSharePosterUrl} + mediaType="screen-share" + srcVideoObject={this.state.screenShareVideoObject} /> + </div> </div> - <div className={localStreamClasses}></div> + <div className={localStreamClasses}> + <sharedViews.MediaView displayAvatar={this.state.videoMuted} + posterUrl={this.props.localPosterUrl} + mediaType="local" + srcVideoObject={this.state.localSrcVideoObject} /> + </div> </div> <sharedViews.ConversationToolbar dispatcher={this.props.dispatcher} video={{enabled: !this.state.videoMuted, visible: this._roomIsActive()}} audio={{enabled: !this.state.audioMuted, visible: this._roomIsActive()}} publishStream={this.publishStream}
--- a/browser/components/loop/test/desktop-local/conversationViews_test.js +++ b/browser/components/loop/test/desktop-local/conversationViews_test.js @@ -3,18 +3,18 @@ describe("loop.conversationViews", function () { "use strict"; var expect = chai.expect; var TestUtils = React.addons.TestUtils; var sharedActions = loop.shared.actions; var sharedUtils = loop.shared.utils; - var sharedView = loop.shared.views; - var sandbox, view, dispatcher, contact, fakeAudioXHR; + var sharedViews = loop.shared.views; + var sandbox, view, dispatcher, contact, fakeAudioXHR, conversationStore; var fakeMozLoop, fakeWindow; var CALL_STATES = loop.store.CALL_STATES; var CALL_TYPES = loop.shared.utils.CALL_TYPES; var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS; var REST_ERRNOS = loop.shared.utils.REST_ERRNOS; var WEBSOCKET_REASONS = loop.shared.utils.WEBSOCKET_REASONS; @@ -99,16 +99,29 @@ describe("loop.conversationViews", funct navigator: { mozLoop: fakeMozLoop }, close: sinon.stub(), document: {}, addEventListener: function() {}, removeEventListener: function() {} }; loop.shared.mixins.setRootObject(fakeWindow); + var feedbackStore = new loop.store.FeedbackStore(dispatcher, { + feedbackClient: {} + }); + conversationStore = new loop.store.ConversationStore(dispatcher, { + client: {}, + mozLoop: fakeMozLoop, + sdkDriver: {} + }); + + loop.store.StoreMixin.register({ + conversationStore: conversationStore, + feedbackStore: feedbackStore + }); }); afterEach(function() { loop.shared.mixins.setRootObject(window); view = undefined; delete navigator.mozLoop; sandbox.restore(); }); @@ -250,39 +263,30 @@ describe("loop.conversationViews", funct sinon.assert.calledOnce(dispatcher.dispatch); sinon.assert.calledWithMatch(dispatcher.dispatch, sinon.match.hasOwn("name", "cancelCall")); }); }); describe("CallFailedView", function() { - var store, fakeAudio; + var fakeAudio; var contact = {email: [{value: "test@test.tld"}]}; function mountTestComponent(options) { options = options || {}; return TestUtils.renderIntoDocument( React.createElement(loop.conversationViews.CallFailedView, { dispatcher: dispatcher, contact: options.contact })); } beforeEach(function() { - store = new loop.store.ConversationStore(dispatcher, { - client: {}, - mozLoop: navigator.mozLoop, - sdkDriver: {} - }); - loop.store.StoreMixin.register({ - conversationStore: store - }); - fakeAudio = { play: sinon.spy(), pause: sinon.spy(), removeAttribute: sinon.spy() }; sandbox.stub(window, "Audio").returns(fakeAudio); }); @@ -352,170 +356,214 @@ describe("loop.conversationViews", funct React.addons.TestUtils.Simulate.click(emailLinkBtn); expect(view.getDOMNode().querySelector(".btn-email").disabled).eql(true); }); it("should compose an email once the email link is received", function() { var composeCallUrlEmail = sandbox.stub(sharedUtils, "composeCallUrlEmail"); view = mountTestComponent({contact: contact}); - store.setStoreState({emailLink: "http://fake.invalid/"}); + conversationStore.setStoreState({emailLink: "http://fake.invalid/"}); sinon.assert.calledOnce(composeCallUrlEmail); sinon.assert.calledWithExactly(composeCallUrlEmail, "http://fake.invalid/", "test@test.tld"); }); it("should close the conversation window once the email link is received", function() { view = mountTestComponent({contact: contact}); - store.setStoreState({emailLink: "http://fake.invalid/"}); + conversationStore.setStoreState({emailLink: "http://fake.invalid/"}); sinon.assert.calledOnce(fakeWindow.close); }); it("should display an error message in case email link retrieval failed", function() { view = mountTestComponent({contact: contact}); - store.trigger("error:emailLink"); + conversationStore.trigger("error:emailLink"); expect(view.getDOMNode().querySelector(".error")).not.eql(null); }); it("should allow retrying to get a call url if it failed previously", function() { view = mountTestComponent({contact: contact}); - store.trigger("error:emailLink"); + conversationStore.trigger("error:emailLink"); expect(view.getDOMNode().querySelector(".btn-email").disabled).eql(false); }); it("should play a failure sound, once", function() { view = mountTestComponent({contact: contact}); sinon.assert.calledOnce(navigator.mozLoop.getAudioBlob); sinon.assert.calledWithExactly(navigator.mozLoop.getAudioBlob, "failure", sinon.match.func); sinon.assert.calledOnce(fakeAudio.play); expect(fakeAudio.loop).to.equal(false); }); it("should show 'something went wrong' when the reason is WEBSOCKET_REASONS.MEDIA_FAIL", function () { - store.setStoreState({callStateReason: WEBSOCKET_REASONS.MEDIA_FAIL}); + conversationStore.setStoreState({callStateReason: WEBSOCKET_REASONS.MEDIA_FAIL}); view = mountTestComponent({contact: contact}); sinon.assert.calledWith(document.mozL10n.get, "generic_failure_title"); }); it("should show 'contact unavailable' when the reason is WEBSOCKET_REASONS.REJECT", function () { - store.setStoreState({callStateReason: WEBSOCKET_REASONS.REJECT}); + conversationStore.setStoreState({callStateReason: WEBSOCKET_REASONS.REJECT}); view = mountTestComponent({contact: contact}); sinon.assert.calledWithExactly(document.mozL10n.get, "contact_unavailable_title", {contactName: loop.conversationViews._getContactDisplayName(contact)}); }); it("should show 'contact unavailable' when the reason is WEBSOCKET_REASONS.BUSY", function () { - store.setStoreState({callStateReason: WEBSOCKET_REASONS.BUSY}); + conversationStore.setStoreState({callStateReason: WEBSOCKET_REASONS.BUSY}); view = mountTestComponent({contact: contact}); sinon.assert.calledWithExactly(document.mozL10n.get, "contact_unavailable_title", {contactName: loop.conversationViews._getContactDisplayName(contact)}); }); it("should show 'something went wrong' when the reason is 'setup'", function () { - store.setStoreState({callStateReason: "setup"}); + conversationStore.setStoreState({callStateReason: "setup"}); view = mountTestComponent({contact: contact}); sinon.assert.calledWithExactly(document.mozL10n.get, "generic_failure_title"); }); it("should show 'contact unavailable' when the reason is REST_ERRNOS.USER_UNAVAILABLE", function () { - store.setStoreState({callStateReason: REST_ERRNOS.USER_UNAVAILABLE}); + conversationStore.setStoreState({callStateReason: REST_ERRNOS.USER_UNAVAILABLE}); view = mountTestComponent({contact: contact}); sinon.assert.calledWithExactly(document.mozL10n.get, "contact_unavailable_title", {contactName: loop.conversationViews._getContactDisplayName(contact)}); }); it("should show 'no media' when the reason is FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA", function () { - store.setStoreState({callStateReason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA}); + conversationStore.setStoreState({callStateReason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA}); view = mountTestComponent({contact: contact}); sinon.assert.calledWithExactly(document.mozL10n.get, "no_media_failure_message"); }); it("should display a generic contact unavailable msg when the reason is" + " WEBSOCKET_REASONS.BUSY and no display name is available", function() { - store.setStoreState({callStateReason: WEBSOCKET_REASONS.BUSY}); + conversationStore.setStoreState({callStateReason: WEBSOCKET_REASONS.BUSY}); var phoneOnlyContact = { tel: [{"pref": true, type: "work", value: ""}] }; view = mountTestComponent({contact: phoneOnlyContact}); sinon.assert.calledWith(document.mozL10n.get, "generic_contact_unavailable_title"); }); }); describe("OngoingConversationView", function() { - function mountTestComponent(props) { + function mountTestComponent(extraProps) { + var props = _.extend({ + dispatcher: dispatcher + }, extraProps); return TestUtils.renderIntoDocument( React.createElement(loop.conversationViews.OngoingConversationView, props)); } it("should dispatch a setupStreamElements action when the view is created", function() { - view = mountTestComponent({ - dispatcher: dispatcher - }); + view = mountTestComponent(); sinon.assert.calledOnce(dispatcher.dispatch); sinon.assert.calledWithMatch(dispatcher.dispatch, sinon.match.hasOwn("name", "setupStreamElements")); }); + it("should display an avatar for remote video when the stream is not enabled", function() { + view = mountTestComponent({ + mediaConnected: true, + remoteVideoEnabled: false + }); + + TestUtils.findRenderedComponentWithType(view, sharedViews.AvatarView); + }); + + it("should display the remote video when the stream is enabled", function() { + conversationStore.setStoreState({ + remoteSrcVideoObject: { fake: 1 } + }); + + view = mountTestComponent({ + mediaConnected: true, + remoteVideoEnabled: true + }); + + expect(view.getDOMNode().querySelector(".remote video")).not.eql(null); + }); + + it("should display an avatar for local video when the stream is not enabled", function() { + view = mountTestComponent({ + video: { + enabled: false + } + }); + + TestUtils.findRenderedComponentWithType(view, sharedViews.AvatarView); + }); + + it("should display the local video when the stream is enabled", function() { + conversationStore.setStoreState({ + localSrcVideoObject: { fake: 1 } + }); + + view = mountTestComponent({ + video: { + enabled: true + } + }); + + expect(view.getDOMNode().querySelector(".local video")).not.eql(null); + }); + it("should dispatch a hangupCall action when the hangup button is pressed", function() { - view = mountTestComponent({ - dispatcher: dispatcher - }); + view = mountTestComponent(); var hangupBtn = view.getDOMNode().querySelector(".btn-hangup"); React.addons.TestUtils.Simulate.click(hangupBtn); sinon.assert.calledWithMatch(dispatcher.dispatch, sinon.match.hasOwn("name", "hangupCall")); }); it("should dispatch a setMute action when the audio mute button is pressed", function() { view = mountTestComponent({ - dispatcher: dispatcher, audio: {enabled: false} }); var muteBtn = view.getDOMNode().querySelector(".btn-mute-audio"); React.addons.TestUtils.Simulate.click(muteBtn); sinon.assert.calledWithMatch(dispatcher.dispatch, @@ -524,17 +572,16 @@ describe("loop.conversationViews", funct sinon.match.hasOwn("enabled", true)); sinon.assert.calledWithMatch(dispatcher.dispatch, sinon.match.hasOwn("type", "audio")); }); it("should dispatch a setMute action when the video mute button is pressed", function() { view = mountTestComponent({ - dispatcher: dispatcher, video: {enabled: true} }); var muteBtn = view.getDOMNode().querySelector(".btn-mute-video"); React.addons.TestUtils.Simulate.click(muteBtn); sinon.assert.calledWithMatch(dispatcher.dispatch, @@ -542,191 +589,180 @@ describe("loop.conversationViews", funct sinon.assert.calledWithMatch(dispatcher.dispatch, sinon.match.hasOwn("enabled", false)); sinon.assert.calledWithMatch(dispatcher.dispatch, sinon.match.hasOwn("type", "video")); }); it("should set the mute button as mute off", function() { view = mountTestComponent({ - dispatcher: dispatcher, video: {enabled: true} }); var muteBtn = view.getDOMNode().querySelector(".btn-mute-video"); expect(muteBtn.classList.contains("muted")).eql(false); }); it("should set the mute button as mute on", function() { view = mountTestComponent({ - dispatcher: dispatcher, audio: {enabled: false} }); var muteBtn = view.getDOMNode().querySelector(".btn-mute-audio"); expect(muteBtn.classList.contains("muted")).eql(true); }); }); describe("CallControllerView", function() { - var store, feedbackStore; + var feedbackStore; function mountTestComponent() { return TestUtils.renderIntoDocument( React.createElement(loop.conversationViews.CallControllerView, { dispatcher: dispatcher, mozLoop: fakeMozLoop })); } beforeEach(function() { - store = new loop.store.ConversationStore(dispatcher, { - client: {}, - mozLoop: fakeMozLoop, - sdkDriver: {} - }); - loop.store.StoreMixin.register({ - conversationStore: store - }); - feedbackStore = new loop.store.FeedbackStore(dispatcher, { feedbackClient: {} }); }); it("should set the document title to the callerId", function() { - store.setStoreState({ + conversationStore.setStoreState({ contact: contact }); mountTestComponent(); expect(fakeWindow.document.title).eql("mrsmith"); }); it("should fallback to the contact email if the contact name is not defined", function() { delete contact.name; - store.setStoreState({ + conversationStore.setStoreState({ contact: contact }); mountTestComponent({contact: contact}); expect(fakeWindow.document.title).eql("fakeEmail"); }); it("should fallback to the caller id if no contact is defined", function() { - store.setStoreState({ + conversationStore.setStoreState({ callerId: "fakeId" }); mountTestComponent({contact: contact}); expect(fakeWindow.document.title).eql("fakeId"); }); it("should render the CallFailedView when the call state is 'terminated'", function() { - store.setStoreState({ + conversationStore.setStoreState({ callState: CALL_STATES.TERMINATED, contact: contact }); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.conversationViews.CallFailedView); }); it("should render the PendingConversationView for outgoing calls when the call state is 'gather'", function() { - store.setStoreState({ + conversationStore.setStoreState({ callState: CALL_STATES.GATHER, contact: contact, outgoing: true }); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.conversationViews.PendingConversationView); }); it("should render the AcceptCallView for incoming calls when the call state is 'alerting'", function() { - store.setStoreState({ + conversationStore.setStoreState({ callState: CALL_STATES.ALERTING, outgoing: false }); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.conversationViews.AcceptCallView); }); it("should render the OngoingConversationView when the call state is 'ongoing'", function() { - store.setStoreState({callState: CALL_STATES.ONGOING}); + conversationStore.setStoreState({callState: CALL_STATES.ONGOING}); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.conversationViews.OngoingConversationView); }); it("should render the FeedbackView when the call state is 'finished'", function() { - store.setStoreState({callState: CALL_STATES.FINISHED}); + conversationStore.setStoreState({callState: CALL_STATES.FINISHED}); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.shared.views.FeedbackView); }); it("should set the document title to conversation_has_ended when displaying the feedback view", function() { - store.setStoreState({callState: CALL_STATES.FINISHED}); + conversationStore.setStoreState({callState: CALL_STATES.FINISHED}); mountTestComponent(); expect(fakeWindow.document.title).eql("conversation_has_ended"); }); it("should play the terminated sound when the call state is 'finished'", function() { var fakeAudio = { play: sinon.spy(), pause: sinon.spy(), removeAttribute: sinon.spy() }; sandbox.stub(window, "Audio").returns(fakeAudio); - store.setStoreState({callState: CALL_STATES.FINISHED}); + conversationStore.setStoreState({callState: CALL_STATES.FINISHED}); view = mountTestComponent(); sinon.assert.calledOnce(fakeAudio.play); }); it("should update the rendered views when the state is changed.", function() { - store.setStoreState({ + conversationStore.setStoreState({ callState: CALL_STATES.GATHER, contact: contact, outgoing: true }); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.conversationViews.PendingConversationView); - store.setStoreState({callState: CALL_STATES.TERMINATED}); + conversationStore.setStoreState({callState: CALL_STATES.TERMINATED}); TestUtils.findRenderedComponentWithType(view, loop.conversationViews.CallFailedView); }); }); describe("AcceptCallView", function() { var view;
--- a/browser/components/loop/test/desktop-local/l10n_test.js +++ b/browser/components/loop/test/desktop-local/l10n_test.js @@ -29,9 +29,13 @@ describe("document.mozL10n", function() it("should get a simple string", function() { expect(document.mozL10n.get("test")).eql("test"); }); it("should get a plural form", function() { expect(document.mozL10n.get("plural", {num: 10})).eql("10 plural forms"); }); + + it("should correctly get a plural form for num = 0", function() { + expect(document.mozL10n.get("plural", {num: 0})).eql("0 plural form"); + }); });
--- a/browser/components/loop/test/desktop-local/roomStore_test.js +++ b/browser/components/loop/test/desktop-local/roomStore_test.js @@ -598,33 +598,38 @@ describe("loop.store.RoomStore", functio dispatcher.dispatch(new sharedActions.OpenRoom({roomToken: "42abc"})); sinon.assert.calledOnce(fakeMozLoop.rooms.open); sinon.assert.calledWithExactly(fakeMozLoop.rooms.open, "42abc"); }); }); describe("#updateRoomContext", function() { - var store, fakeMozLoop; + var store, fakeMozLoop, clock; beforeEach(function() { + clock = sinon.useFakeTimers(); fakeMozLoop = { rooms: { get: sinon.stub().callsArgWith(1, null, { roomToken: "42abc", decryptedContext: { roomName: "sillier name" } }), update: null } }; store = new loop.store.RoomStore(dispatcher, {mozLoop: fakeMozLoop}); }); + afterEach(function() { + clock.restore(); + }); + it("should rename the room via mozLoop", function() { fakeMozLoop.rooms.update = sinon.spy(); dispatcher.dispatch(new sharedActions.UpdateRoomContext({ roomToken: "42abc", newRoomName: "silly name" })); sinon.assert.calledOnce(fakeMozLoop.rooms.get); @@ -669,16 +674,17 @@ describe("loop.store.RoomStore", functio it("should ensure only submitting a non-empty room name", function() { fakeMozLoop.rooms.update = sinon.spy(); dispatcher.dispatch(new sharedActions.UpdateRoomContext({ roomToken: "42abc", newRoomName: " \t \t " })); + clock.tick(1); sinon.assert.notCalled(fakeMozLoop.rooms.update); expect(store.getStoreState().savingContext).to.eql(false); }); it("should save updated context information", function() { fakeMozLoop.rooms.update = sinon.spy(); @@ -726,14 +732,15 @@ describe("loop.store.RoomStore", functio dispatcher.dispatch(new sharedActions.UpdateRoomContext({ roomToken: "42abc", // Room name doesn't need to change. newRoomName: "sillier name", newRoomDescription: "", newRoomThumbnail: "", newRoomURL: "" })); + clock.tick(1); sinon.assert.notCalled(fakeMozLoop.rooms.update); expect(store.getStoreState().savingContext).to.eql(false); }); }); });
--- a/browser/components/loop/test/desktop-local/roomViews_test.js +++ b/browser/components/loop/test/desktop-local/roomViews_test.js @@ -3,16 +3,17 @@ describe("loop.roomViews", function () { "use strict"; var expect = chai.expect; var TestUtils = React.addons.TestUtils; var sharedActions = loop.shared.actions; var sharedUtils = loop.shared.utils; + var sharedViews = loop.shared.views; var ROOM_STATES = loop.store.ROOM_STATES; var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES; var sandbox, dispatcher, roomStore, activeRoomStore, fakeWindow, fakeMozLoop, fakeContextURL; var favicon = "data:image/x-icon;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; beforeEach(function() { @@ -62,16 +63,23 @@ describe("loop.roomViews", function () { activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: {}, sdkDriver: {} }); roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: fakeMozLoop, activeRoomStore: activeRoomStore }); + var textChatStore = new loop.store.TextChatStore(dispatcher, { + sdkDriver: {} + }); + + loop.store.StoreMixin.register({ + textChatStore: textChatStore + }); fakeContextURL = { description: "An invalid page", location: "http://invalid.com", thumbnail: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" }; }); @@ -417,26 +425,16 @@ describe("loop.roomViews", function () { sinon.assert.calledOnce(fakeWindow.close); }); describe("#componentWillUpdate", function() { function expectActionDispatched(view) { sinon.assert.calledOnce(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, sinon.match.instanceOf(sharedActions.SetupStreamElements)); - sinon.assert.calledWithExactly(dispatcher.dispatch, - sinon.match(function(value) { - return value.getLocalElementFunc() === - view.getDOMNode().querySelector(".local"); - })); - sinon.assert.calledWithExactly(dispatcher.dispatch, - sinon.match(function(value) { - return value.getRemoteElementFunc() === - view.getDOMNode().querySelector(".remote"); - })); } it("should dispatch a `SetupStreamElements` action when the MEDIA_WAIT state " + "is entered", function() { activeRoomStore.setStoreState({roomState: ROOM_STATES.READY}); var view = mountTestComponent(); activeRoomStore.setStoreState({roomState: ROOM_STATES.MEDIA_WAIT}); @@ -511,16 +509,64 @@ describe("loop.roomViews", function () { used: true }); view = mountTestComponent(); TestUtils.findRenderedComponentWithType(view, loop.shared.views.FeedbackView); }); + + it("should display an avatar for remote video when the room has participants but video is not enabled", + function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + mediaConnected: true, + remoteVideoEnabled: false + }); + + view = mountTestComponent(); + + TestUtils.findRenderedComponentWithType(view, sharedViews.AvatarView); + }); + + it("should display the remote video when there are participants and video is enabled", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + mediaConnected: true, + remoteVideoEnabled: true, + remoteSrcVideoObject: { fake: 1 } + }); + + view = mountTestComponent(); + + expect(view.getDOMNode().querySelector(".remote video")).not.eql(null); + }); + + it("should display an avatar for local video when the stream is muted", function() { + activeRoomStore.setStoreState({ + videoMuted: true + }); + + view = mountTestComponent(); + + TestUtils.findRenderedComponentWithType(view, sharedViews.AvatarView); + }); + + it("should display the local video when the stream is enabled", function() { + activeRoomStore.setStoreState({ + localSrcVideoObject: { fake: 1 }, + videoMuted: false + }); + + view = mountTestComponent(); + + expect(view.getDOMNode().querySelector(".local video")).not.eql(null); + }); + }); describe("Mute", function() { it("should render local media as audio-only if video is muted", function() { activeRoomStore.setStoreState({ roomState: ROOM_STATES.SESSION_CONNECTED, videoMuted: true @@ -636,16 +682,17 @@ describe("loop.roomViews", function () { afterEach(function() { view = null; }); function mountTestComponent(props) { props = _.extend({ dispatcher: dispatcher, mozLoop: fakeMozLoop, + savingContext: false, show: true, roomData: { roomToken: "fakeToken" } }, props); return TestUtils.renderIntoDocument( React.createElement(loop.roomViews.DesktopRoomContextView, props)); } @@ -721,17 +768,17 @@ describe("loop.roomViews", function () { roomContextUrls: [fakeContextURL] } }); var checkbox = view.getDOMNode().querySelector(".checkbox"); expect(checkbox.classList.contains("disabled")).to.eql(true); }); - it("should render the editMode view when the edit button is clicked", function(next) { + it("should render the editMode view when the edit button is clicked", function(done) { var roomName = "Hello, is it me you're looking for?"; view = mountTestComponent({ roomData: { roomToken: "fakeToken", roomName: roomName, roomContextUrls: [fakeContextURL] } }); @@ -744,21 +791,21 @@ describe("loop.roomViews", function () { expect(view.state.availableContext.previewImage).to.eql(favicon); var node = view.getDOMNode(); expect(node.querySelector(".checkbox-wrapper").classList.contains("disabled")).to.eql(true); expect(node.querySelector(".room-context-name").value).to.eql(roomName); expect(node.querySelector(".room-context-url").value).to.eql(fakeContextURL.location); expect(node.querySelector(".room-context-comments").value).to.eql(fakeContextURL.description); - next(); + done(); }); }); - it("should hide the checkbox when no context data is stored or available", function(next) { + it("should hide the checkbox when no context data is stored or available", function(done) { view = mountTestComponent({ roomData: { roomToken: "fakeToken", roomName: "Hello, is it me you're looking for?" } }); // Switch to editMode via setting the prop, since we can control that @@ -766,17 +813,17 @@ describe("loop.roomViews", function () { view.setProps({ editMode: true }, function() { // First check if availableContext is set correctly. expect(view.state.availableContext).to.not.eql(null); expect(view.state.availableContext.previewImage).to.eql(favicon); var node = view.getDOMNode(); expect(node.querySelector(".checkbox-wrapper").classList.contains("hide")).to.eql(true); - next(); + done(); }); }); }); describe("Update Room", function() { var roomNameBox; beforeEach(function() { @@ -826,16 +873,31 @@ describe("loop.roomViews", function () { new sharedActions.UpdateRoomContext({ roomToken: "fakeToken", newRoomName: "reallyFake", newRoomDescription: fakeContextURL.description, newRoomURL: fakeContextURL.location, newRoomThumbnail: fakeContextURL.thumbnail })); }); + + it("should close the edit form when context was saved successfully", function(done) { + view.setProps({ savingContext: true }, function() { + var node = view.getDOMNode(); + // The button should show up as disabled. + expect(node.querySelector(".btn-info").hasAttribute("disabled")).to.eql(true); + + // Now simulate a successful save. + view.setProps({ savingContext: false }, function() { + // The editMode flag should be updated. + expect(view.state.editMode).to.eql(false); + done(); + }); + }); + }); }); describe("#handleCheckboxChange", function() { var node, checkbox; beforeEach(function() { view = mountTestComponent({ availableContext: {
--- a/browser/components/loop/test/functional/test_1_browser_call.py +++ b/browser/components/loop/test/functional/test_1_browser_call.py @@ -97,17 +97,17 @@ class Test1BrowserCall(MarionetteTestCas def local_check_room_self_video(self): self.switch_to_chatbox() # expect a video container on desktop side media_container = self.wait_for_element_displayed(By.CLASS_NAME, "media") self.assertEqual(media_container.tag_name, "div", "expect a video container") - self.check_video(".local .OT_publisher .OT_widget-container"); + self.check_video(".local-video") def local_get_and_verify_room_url(self): self.switch_to_chatbox() button = self.wait_for_element_displayed(By.CLASS_NAME, "btn-copy") button.click() # click the element @@ -122,43 +122,40 @@ class Test1BrowserCall(MarionetteTestCas self.switch_to_standalone() self.marionette.navigate(url) # Join the room join_button = self.wait_for_element_displayed(By.CLASS_NAME, "btn-join") join_button.click() - # Assumes the standlone or the conversation window is selected first. + # Assumes the standalone or the conversation window is selected first. def check_video(self, selector): - video_wrapper = self.wait_for_element_displayed(By.CSS_SELECTOR, + video = self.wait_for_element_displayed(By.CSS_SELECTOR, selector, 20) - video = self.wait_for_subelement_displayed(video_wrapper, - By.TAG_NAME, "video") - self.wait_for_element_attribute_to_be_false(video, "paused") self.assertEqual(video.get_attribute("ended"), "false") def standalone_check_remote_video(self): self.switch_to_standalone() - self.check_video(".remote .OT_subscriber .OT_widget-container") + self.check_video(".remote-video") def local_check_remote_video(self): self.switch_to_chatbox() - self.check_video(".remote .OT_subscriber .OT_widget-container") + self.check_video(".remote-video") def local_enable_screenshare(self): self.switch_to_chatbox() button = self.marionette.find_element(By.CLASS_NAME, "btn-screen-share") button.click() def standalone_check_remote_screenshare(self): self.switch_to_standalone() - self.check_video(".media .screen .OT_subscriber .OT_widget-container") + self.check_video(".screen-share-video") def remote_leave_room_and_verify_feedback(self): self.switch_to_standalone() button = self.marionette.find_element(By.CLASS_NAME, "btn-hangup") button.click() # check that the feedback form is displayed
--- a/browser/components/loop/test/shared/activeRoomStore_test.js +++ b/browser/components/loop/test/shared/activeRoomStore_test.js @@ -966,16 +966,71 @@ describe("loop.store.ActiveRoomStore", f type: "video", enabled: false })); expect(store.getStoreState().videoMuted).eql(true); }); }); + describe("#localVideoEnabled", function() { + it("should add a localSrcVideoObject to the store", function() { + var fakeVideoElement = {name: "fakeVideoElement"}; + expect(store.getStoreState()).to.not.have.property("localSrcVideoObject"); + + store.localVideoEnabled({srcVideoObject: fakeVideoElement}); + + expect(store.getStoreState()).to.have.property("localSrcVideoObject", + fakeVideoElement); + }); + }); + + describe("#remoteVideoEnabled", function() { + var fakeVideoElement; + + beforeEach(function() { + fakeVideoElement = {name: "fakeVideoElement"}; + }); + + it("should add a remoteSrcVideoObject to the store", function() { + expect(store.getStoreState()).to.not.have.property("remoteSrcVideoObject"); + + store.remoteVideoEnabled({srcVideoObject: fakeVideoElement}); + + expect(store.getStoreState()).to.have.property("remoteSrcVideoObject", + fakeVideoElement); + }); + + it("should set remoteVideoEnabled", function() { + store.remoteVideoEnabled({srcVideoObject: fakeVideoElement}); + + expect(store.getStoreState().remoteVideoEnabled).eql(true); + }); + }); + + describe("#remoteVideoDisabled", function() { + it("should set remoteVideoEnabled to false", function() { + store.setStoreState({ + remoteVideoEnabled: true + }); + + store.remoteVideoDisabled(); + + expect(store.getStoreState().remoteVideoEnabled).eql(false); + }); + }); + + describe("#mediaConnected", function() { + it("should set mediaConnected to true", function() { + store.mediaConnected(); + + expect(store.getStoreState().mediaConnected).eql(true); + }); + }); + describe("#screenSharingState", function() { beforeEach(function() { store.setStoreState({windowId: "1234"}); }); it("should save the state", function() { store.screenSharingState(new sharedActions.ScreenSharingState({ state: SCREEN_SHARE_STATES.ACTIVE @@ -1007,16 +1062,44 @@ describe("loop.store.ActiveRoomStore", f it("should save the state", function() { store.receivingScreenShare(new sharedActions.ReceivingScreenShare({ receiving: true })); expect(store.getStoreState().receivingScreenShare).eql(true); }); + it("should add a screenShareVideoObject to the store when sharing is active", function() { + var fakeVideoElement = {name: "fakeVideoElement"}; + expect(store.getStoreState()).to.not.have.property("screenShareVideoObject"); + + store.receivingScreenShare(new sharedActions.ReceivingScreenShare({ + receiving: true, + srcVideoObject: fakeVideoElement + })); + + expect(store.getStoreState()).to.have.property("screenShareVideoObject", + fakeVideoElement); + }); + + it("should clear the screenShareVideoObject from the store when sharing is inactive", function() { + store.setStoreState({ + screenShareVideoObject: { + name: "fakeVideoElement" + } + }); + + store.receivingScreenShare(new sharedActions.ReceivingScreenShare({ + receiving: false, + srcVideoObject: null + })); + + expect(store.getStoreState().screenShareVideoObject).eql(null); + }); + it("should delete the screen remote video dimensions if screen sharing is not active", function() { store.setStoreState({ remoteVideoDimensions: { screen: {fake: 10}, camera: {fake: 20} } }); @@ -1157,16 +1240,26 @@ describe("loop.store.ActiveRoomStore", f }); describe("#remotePeerDisconnected", function() { it("should set the state to `SESSION_CONNECTED`", function() { store.remotePeerDisconnected(); expect(store.getStoreState().roomState).eql(ROOM_STATES.SESSION_CONNECTED); }); + + it("should clear the remoteSrcVideoObject", function() { + store.setStoreState({ + remoteSrcVideoObject: { name: "fakeVideoElement" } + }); + + store.remotePeerDisconnected(); + + expect(store.getStoreState().remoteSrcVideoObject).eql(null); + }); }); describe("#connectionStatus", function() { it("should call rooms.sendConnectionStatus on mozLoop", function() { store.setStoreState({ roomToken: "fakeToken", sessionToken: "9876543210" });
--- a/browser/components/loop/test/shared/conversationStore_test.js +++ b/browser/components/loop/test/shared/conversationStore_test.js @@ -8,17 +8,17 @@ describe("loop.store.ConversationStore", var CALL_STATES = loop.store.CALL_STATES; var WS_STATES = loop.store.WS_STATES; var CALL_TYPES = loop.shared.utils.CALL_TYPES; var WEBSOCKET_REASONS = loop.shared.utils.WEBSOCKET_REASONS; var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS; var sharedActions = loop.shared.actions; var sharedUtils = loop.shared.utils; var sandbox, dispatcher, client, store, fakeSessionData, sdkDriver; - var contact, fakeMozLoop; + var contact, fakeMozLoop, fakeVideoElement; var connectPromise, resolveConnectPromise, rejectConnectPromise; var wsCancelSpy, wsCloseSpy, wsDeclineSpy, wsMediaUpSpy, fakeWebsocket; function checkFailures(done, f) { try { f(); done(); } catch (err) { @@ -84,16 +84,18 @@ describe("loop.store.ConversationStore", callId: "142536", sessionId: "321456", sessionToken: "341256", websocketToken: "543216", windowId: "28", progressURL: "fakeURL" }; + fakeVideoElement = { id: "fakeVideoElement" }; + var dummySocket = { close: sinon.spy(), send: sinon.spy() }; connectPromise = new Promise(function(resolve, reject) { resolveConnectPromise = resolve; rejectConnectPromise = reject; @@ -922,16 +924,72 @@ describe("loop.store.ConversationStore", describe("#mediaConnected", function() { it("should send mediaUp via the websocket", function() { store._websocket = fakeWebsocket; store.mediaConnected(new sharedActions.MediaConnected()); sinon.assert.calledOnce(wsMediaUpSpy); }); + + it("should set store.mediaConnected to true", function () { + store._websocket = fakeWebsocket; + + store.mediaConnected(new sharedActions.MediaConnected()); + + expect(store.getStoreState("mediaConnected")).eql(true); + }); + }); + + describe("#localVideoEnabled", function() { + it("should set store.localSrcVideoObject from the action data", function () { + store.localVideoEnabled( + new sharedActions.LocalVideoEnabled({srcVideoObject: fakeVideoElement})); + + expect(store.getStoreState("localSrcVideoObject")).eql(fakeVideoElement); + }); + }); + + describe("#remoteVideoEnabled", function() { + it("should set store.remoteSrcVideoObject from the actionData", function () { + store.setStoreState({remoteSrcVideoObject: undefined}); + + store.remoteVideoEnabled( + new sharedActions.RemoteVideoEnabled({srcVideoObject: fakeVideoElement})); + + expect(store.getStoreState("remoteSrcVideoObject")).eql(fakeVideoElement); + }); + + it("should set store.remoteVideoEnabled to true", function () { + store.setStoreState({remoteVideoEnabled: false}); + + store.remoteVideoEnabled( + new sharedActions.RemoteVideoEnabled({srcVideoObject: fakeVideoElement})); + + expect(store.getStoreState("remoteVideoEnabled")).to.be.true; + }); + }); + + describe("#remoteVideoDisabled", function() { + it("should set store.remoteVideoEnabled to false", function () { + store.setStoreState({remoteVideoEnabled: true}); + + store.remoteVideoDisabled(new sharedActions.RemoteVideoDisabled({})); + + expect(store.getStoreState("remoteVideoEnabled")).to.be.false; + }); + + it("should set store.remoteSrcVideoObject to undefined", function () { + store.setStoreState({remoteSrcVideoObject: fakeVideoElement}); + + store.remoteVideoDisabled(new sharedActions.RemoteVideoDisabled({})); + + expect(store.getStoreState("remoteSrcVideoObject")).to.be.undefined; + }); + }); describe("#setMute", function() { it("should save the mute state for the audio stream", function() { store.setStoreState({"audioMuted": false}); dispatcher.dispatch(new sharedActions.SetMute({ type: "audio",
--- a/browser/components/loop/test/shared/mixins_test.js +++ b/browser/components/loop/test/shared/mixins_test.js @@ -363,98 +363,16 @@ describe("loop.shared.mixins", function( expect(result.streamHeight).eql(360); expect(result.offsetX).eql(0); // The remote element width (640) minus the stream width (360) split in 2. expect(result.offsetY).eql(140); }); }); describe("Events", function() { - describe("resize", function() { - it("should update the width on the local stream element", function() { - localElement = { - offsetWidth: 100, - offsetHeight: 100, - style: { width: "0%" } - }; - - rootObject.events.resize(); - sandbox.clock.tick(10); - - expect(localElement.style.width).eql("100%"); - }); - - it("should update the height on the remote stream element", function() { - remoteElement = { - offsetWidth: 100, - offsetHeight: 100, - style: { height: "0%" } - }; - - rootObject.events.resize(); - sandbox.clock.tick(10); - - expect(remoteElement.style.height).eql("100%"); - }); - - it("should update the height on the screen share stream element", function() { - screenShareElement = { - offsetWidth: 100, - offsetHeight: 100, - style: { height: "0%" } - }; - - rootObject.events.resize(); - sandbox.clock.tick(10); - - expect(screenShareElement.style.height).eql("100%"); - }); - }); - - describe("orientationchange", function() { - it("should update the width on the local stream element", function() { - localElement = { - offsetWidth: 100, - offsetHeight: 100, - style: { width: "0%" } - }; - - rootObject.events.orientationchange(); - sandbox.clock.tick(10); - - expect(localElement.style.width).eql("100%"); - }); - - it("should update the height on the remote stream element", function() { - remoteElement = { - offsetWidth: 100, - offsetHeight: 100, - style: { height: "0%" } - }; - - rootObject.events.orientationchange(); - sandbox.clock.tick(10); - - expect(remoteElement.style.height).eql("100%"); - }); - - it("should update the height on the screen share stream element", function() { - screenShareElement = { - offsetWidth: 100, - offsetHeight: 100, - style: { height: "0%" } - }; - - rootObject.events.orientationchange(); - sandbox.clock.tick(10); - - expect(screenShareElement.style.height).eql("100%"); - }); - }); - describe("Video stream dimensions", function() { var localVideoDimensions = { camera: { width: 640, height: 480 } };
--- a/browser/components/loop/test/shared/otSdkDriver_test.js +++ b/browser/components/loop/test/shared/otSdkDriver_test.js @@ -8,25 +8,21 @@ describe("loop.OTSdkDriver", function () var sharedActions = loop.shared.actions; var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS; var STREAM_PROPERTIES = loop.shared.utils.STREAM_PROPERTIES; var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES; var CHAT_CONTENT_TYPES = loop.store.CHAT_CONTENT_TYPES; var sandbox; var dispatcher, driver, mozLoop, publisher, sdk, session, sessionData, subscriber; - var fakeLocalElement, fakeRemoteElement, fakeScreenElement; var publisherConfig, fakeEvent; beforeEach(function() { sandbox = sinon.sandbox.create(); - fakeLocalElement = { fake: 1 }; - fakeRemoteElement = { fake: 2 }; - fakeScreenElement = { fake: 3 }; fakeEvent = { preventDefault: sinon.stub() }; publisherConfig = { fake: "config" }; sessionData = { apiKey: "1234567890", @@ -115,39 +111,37 @@ describe("loop.OTSdkDriver", function () new loop.OTSdkDriver({dispatcher: dispatcher}); }).to.Throw(/sdk/); }); }); describe("#setupStreamElements", function() { it("should call initPublisher", function() { driver.setupStreamElements(new sharedActions.SetupStreamElements({ - getLocalElementFunc: function() { return fakeLocalElement; }, - getRemoteElementFunc: function() { return fakeRemoteElement; }, publisherConfig: publisherConfig })); var expectedConfig = _.extend({ channels: { text: {} } }, publisherConfig); sinon.assert.calledOnce(sdk.initPublisher); - sinon.assert.calledWith(sdk.initPublisher, fakeLocalElement, expectedConfig); + sinon.assert.calledWith(sdk.initPublisher, + sinon.match.instanceOf(HTMLDivElement), + expectedConfig); }); }); describe("#retryPublishWithoutVideo", function() { beforeEach(function() { sdk.initPublisher.returns(publisher); driver.setupStreamElements(new sharedActions.SetupStreamElements({ - getLocalElementFunc: function() { return fakeLocalElement; }, - getRemoteElementFunc: function() { return fakeRemoteElement; }, publisherConfig: publisherConfig })); }); it("should make MediaStreamTrack.getSources return without a video source", function(done) { driver.retryPublishWithoutVideo(); window.MediaStreamTrack.getSources(function(sources) { @@ -164,27 +158,27 @@ describe("loop.OTSdkDriver", function () var expectedConfig = _.extend({ channels: { text: {} } }, publisherConfig); sinon.assert.calledTwice(sdk.initPublisher); - sinon.assert.calledWith(sdk.initPublisher, fakeLocalElement, expectedConfig); + sinon.assert.calledWith(sdk.initPublisher, + sinon.match.instanceOf(HTMLDivElement), + expectedConfig); }); }); describe("#setMute", function() { beforeEach(function() { sdk.initPublisher.returns(publisher); driver.setupStreamElements(new sharedActions.SetupStreamElements({ - getLocalElementFunc: function() { return fakeLocalElement; }, - getRemoteElementFunc: function() { return fakeRemoteElement; }, publisherConfig: publisherConfig })); }); it("should publishAudio with the correct enabled value", function() { driver.setMute(new sharedActions.SetMute({ type: "audio", enabled: false @@ -201,44 +195,35 @@ describe("loop.OTSdkDriver", function () })); sinon.assert.calledOnce(publisher.publishVideo); sinon.assert.calledWithExactly(publisher.publishVideo, true); }); }); describe("#startScreenShare", function() { - var fakeElement; - beforeEach(function() { sandbox.stub(driver, "_noteSharingState"); - - fakeElement = { - className: "fakeVideo" - }; - - driver.getScreenShareElementFunc = function() { - return fakeElement; - }; }); it("should initialize a publisher", function() { // We're testing with `videoSource` set to 'browser', not 'window', as it // has multiple options. var options = { videoSource: "browser", constraints: { browserWindow: 42, scrollWithPage: true } }; driver.startScreenShare(options); sinon.assert.calledOnce(sdk.initPublisher); - sinon.assert.calledWithMatch(sdk.initPublisher, fakeElement, options); + sinon.assert.calledWithMatch(sdk.initPublisher, + sinon.match.instanceOf(HTMLDivElement), options); }); it("should log a telemetry action", function() { var options = { videoSource: "browser", constraints: { browserWindow: 42, scrollWithPage: true @@ -254,20 +239,16 @@ describe("loop.OTSdkDriver", function () beforeEach(function() { var options = { videoSource: "browser", constraints: { browserWindow: 42, scrollWithPage: true } }; - driver.getScreenShareElementFunc = function() { - return fakeScreenElement; - }; - driver.startScreenShare(options); }); it("should switch to the acquired window", function() { driver.switchAcquiredWindow(72); sinon.assert.calledOnce(publisher._.switchAcquiredWindow); sinon.assert.calledWithExactly(publisher._.switchAcquiredWindow, 72); @@ -277,18 +258,16 @@ describe("loop.OTSdkDriver", function () driver.switchAcquiredWindow(42); sinon.assert.notCalled(publisher._.switchAcquiredWindow); }); }); describe("#endScreenShare", function() { beforeEach(function() { - driver.getScreenShareElementFunc = function() {}; - sandbox.stub(driver, "_noteSharingState"); }); it("should unpublish the share", function() { driver.startScreenShare({ videoSource: "window" }); driver.session = session; @@ -633,24 +612,44 @@ describe("loop.OTSdkDriver", function () sinon.assert.calledOnce(driver._publisherChannel.send); sinon.assert.calledWithExactly(driver._publisherChannel.send, JSON.stringify(message)); }); }); }); - describe("Events (general media)", function() { + describe("Events: general media", function() { + var fakeConnection, fakeStream, fakeSubscriberObject, + fakeSdkContainerWithVideo, videoElement; + beforeEach(function() { + fakeConnection = "fakeConnection"; + fakeStream = { + hasVideo: true, + videoType: "camera", + videoDimensions: {width: 1, height: 2} + }; + + fakeSubscriberObject = _.extend({ + session: { connection: fakeConnection }, + stream: fakeStream + }, Backbone.Events); + + fakeSdkContainerWithVideo = { + querySelector: sinon.stub().returns(videoElement) + }; + + // use a real video element so that these tests correctly reflect + // test behavior when run in firefox or chrome + videoElement = document.createElement("video"); + driver.connectSession(sessionData); driver.setupStreamElements(new sharedActions.SetupStreamElements({ - getLocalElementFunc: function() {return fakeLocalElement; }, - getScreenShareElementFunc: function() {return fakeScreenElement; }, - getRemoteElementFunc: function() {return fakeRemoteElement; }, publisherConfig: publisherConfig })); }); describe("connectionDestroyed", function() { it("should dispatch a remotePeerDisconnected action if the client" + "disconnected", function() { session.trigger("connectionDestroyed", { @@ -755,19 +754,23 @@ describe("loop.OTSdkDriver", function () sinon.assert.calledWith(driver._noteConnectionLengthIfNeeded, startTime, endTime); }); }); describe("streamCreated (publisher/local)", function() { - var fakeStream; + var fakeStream, fakeMockVideo; beforeEach(function() { + driver._mockPublisherEl = document.createElement("div"); + fakeMockVideo = document.createElement("video"); + + driver._mockPublisherEl.appendChild(fakeMockVideo); fakeStream = { hasVideo: true, videoType: "camera", videoDimensions: {width: 1, height: 2} }; }); it("should dispatch a VideoDimensionsChanged action", function() { @@ -777,16 +780,26 @@ describe("loop.OTSdkDriver", function () sinon.assert.calledWithExactly(dispatcher.dispatch, new sharedActions.VideoDimensionsChanged({ isLocal: true, videoType: "camera", dimensions: {width: 1, height: 2} })); }); + it("should dispatch a LocalVideoEnabled action", function() { + publisher.trigger("streamCreated", { stream: fakeStream }); + + sinon.assert.called(dispatcher.dispatch); + sinon.assert.calledWithExactly(dispatcher.dispatch, + new sharedActions.LocalVideoEnabled({ + srcVideoObject: fakeMockVideo + })); + }); + it("should dispatch a ConnectionStatus action", function() { driver._metrics.recvStreams = 1; driver._metrics.connections = 2; publisher.trigger("streamCreated", {stream: fakeStream}); sinon.assert.called(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, @@ -795,26 +808,17 @@ describe("loop.OTSdkDriver", function () state: "sendrecv", connections: 2, recvStreams: 1, sendStreams: 1 })); }); }); - describe("streamCreated (session/remote)", function() { - var fakeStream; - - beforeEach(function() { - fakeStream = { - hasVideo: true, - videoType: "camera", - videoDimensions: {width: 1, height: 2} - }; - }); + describe("streamCreated: session/remote", function() { it("should dispatch a VideoDimensionsChanged action", function() { session.trigger("streamCreated", { stream: fakeStream }); sinon.assert.called(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, new sharedActions.VideoDimensionsChanged({ isLocal: false, @@ -838,79 +842,121 @@ describe("loop.OTSdkDriver", function () sendStreams: 0 })); }); it("should subscribe to a camera stream", function() { session.trigger("streamCreated", { stream: fakeStream }); sinon.assert.calledOnce(session.subscribe); - sinon.assert.calledWith(session.subscribe, - fakeStream, fakeRemoteElement, publisherConfig); + sinon.assert.calledWithExactly(session.subscribe, + fakeStream, sinon.match.instanceOf(HTMLDivElement), publisherConfig, + sinon.match.func); + }); + + it("should dispatch RemoteVideoEnabled if the stream has video" + + " after subscribe is complete", function() { + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + videoElement).returns(this.fakeSubscriberObject); + driver.session = session; + fakeStream.connection = fakeConnection; + fakeStream.hasVideo = true; + + session.trigger("streamCreated", { stream: fakeStream }); + + sinon.assert.called(dispatcher.dispatch); + sinon.assert.calledWithExactly(dispatcher.dispatch, + new sharedActions.RemoteVideoEnabled({ + srcVideoObject: videoElement + })); + }); + + it("should not dispatch RemoteVideoEnabled if the stream is audio-only", function() { + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + videoElement); + fakeStream.connection = fakeConnection; + fakeStream.hasVideo = false; + + session.trigger("streamCreated", { stream: fakeStream }); + + sinon.assert.called(dispatcher.dispatch); + sinon.assert.neverCalledWith(dispatcher.dispatch, + new sharedActions.RemoteVideoEnabled({ + srcVideoObject: videoElement + })); }); it("should trigger a readyForDataChannel signal after subscribe is complete", function() { - session.subscribe.callsArgWith(3, null); + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + document.createElement("video")); driver._useDataChannels = true; - fakeStream.connection = "fakeID"; + fakeStream.connection = fakeConnection; session.trigger("streamCreated", { stream: fakeStream }); sinon.assert.calledOnce(session.signal); sinon.assert.calledWith(session.signal, { type: "readyForDataChannel", - to: "fakeID" + to: fakeConnection }); }); it("should not trigger readyForDataChannel signal if data channels are not wanted", function() { - session.subscribe.callsArgWith(3, null); + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + document.createElement("video")); driver._useDataChannels = false; - fakeStream.connection = "fakeID"; + fakeStream.connection = fakeConnection; session.trigger("streamCreated", { stream: fakeStream }); sinon.assert.notCalled(session.signal); }); it("should subscribe to a screen sharing stream", function() { fakeStream.videoType = "screen"; session.trigger("streamCreated", { stream: fakeStream }); sinon.assert.calledOnce(session.subscribe); sinon.assert.calledWithExactly(session.subscribe, - fakeStream, fakeScreenElement, publisherConfig); + fakeStream, sinon.match.instanceOf(HTMLDivElement), publisherConfig, + sinon.match.func); }); it("should dispatch a mediaConnected action if both streams are up", function() { + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + videoElement); driver._publishedLocalStream = true; session.trigger("streamCreated", { stream: fakeStream }); // Called twice due to the VideoDimensionsChanged above. sinon.assert.called(dispatcher.dispatch); sinon.assert.calledWithMatch(dispatcher.dispatch, new sharedActions.MediaConnected({})); }); it("should store the start time when both streams are up and" + " driver._sendTwoWayMediaTelemetry is true", function() { + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + videoElement); driver._sendTwoWayMediaTelemetry = true; driver._publishedLocalStream = true; var startTime = 1; sandbox.stub(performance, "now").returns(startTime); session.trigger("streamCreated", { stream: fakeStream }); expect(driver._getTwoWayMediaStartTime()).to.eql(startTime); }); it("should not store the start time when both streams are up and" + " driver._isDesktop is false", function() { + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + videoElement); driver._isDesktop = false; driver._publishedLocalStream = true; var startTime = 73; sandbox.stub(performance, "now").returns(startTime); session.trigger("streamCreated", { stream: fakeStream }); expect(driver._getTwoWayMediaStartTime()).to.not.eql(startTime); @@ -931,30 +977,32 @@ describe("loop.OTSdkDriver", function () it("should not dispatch a ReceivingScreenShare action for camera streams", function() { session.trigger("streamCreated", {stream: fakeStream}); sinon.assert.neverCalledWithMatch(dispatcher.dispatch, new sharedActions.ReceivingScreenShare({receiving: true})); }); - it("should dispatch a ReceivingScreenShare action for screen sharing streams", - function() { + // XXX See bug 1171933 and the comment in + // OtSdkDriver#_handleRemoteScreenShareCreated + it.skip("should dispatch a ReceivingScreenShare action for screen" + + " sharing streams", function() { fakeStream.videoType = "screen"; session.trigger("streamCreated", { stream: fakeStream }); // Called twice due to the VideoDimensionsChanged above. sinon.assert.called(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, new sharedActions.ReceivingScreenShare({ receiving: true })); }); }); - describe("streamDestroyed (publisher/local)", function() { + describe("streamDestroyed: publisher/local", function() { it("should dispatch a ConnectionStatus action", function() { driver._metrics.sendStreams = 1; driver._metrics.recvStreams = 1; driver._metrics.connections = 2; publisher.trigger("streamDestroyed"); sinon.assert.calledOnce(dispatcher.dispatch); @@ -964,17 +1012,17 @@ describe("loop.OTSdkDriver", function () state: "receiving", connections: 2, recvStreams: 1, sendStreams: 0 })); }); }); - describe("streamDestroyed (session/remote)", function() { + describe("streamDestroyed: session/remote", function() { var fakeStream; beforeEach(function() { fakeStream = { videoType: "screen" }; }); @@ -1177,16 +1225,46 @@ describe("loop.OTSdkDriver", function () describe("accessDialogOpened", function() { it("should prevent the default event behavior", function() { publisher.trigger("accessDialogOpened", fakeEvent); sinon.assert.calledOnce(fakeEvent.preventDefault); }); }); + describe("videoEnabled", function() { + it("should dispatch RemoteVideoEnabled", function() { + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + videoElement).returns(this.fakeSubscriberObject); + session.trigger("streamCreated", {stream: fakeSubscriberObject.stream}); + driver._mockSubscribeEl.appendChild(videoElement); + + fakeSubscriberObject.trigger("videoEnabled"); + + sinon.assert.called(dispatcher.dispatch); + sinon.assert.calledWith(dispatcher.dispatch, + new sharedActions.RemoteVideoEnabled({srcVideoObject: videoElement})); + }); + }); + + describe("videoDisabled", function() { + it("should dispatch RemoteVideoDisabled", function() { + session.subscribe.yieldsOn(driver, null, fakeSubscriberObject, + videoElement).returns(this.fakeSubscriberObject); + session.trigger("streamCreated", {stream: fakeSubscriberObject.stream}); + + + fakeSubscriberObject.trigger("videoDisabled"); + + sinon.assert.called(dispatcher.dispatch); + sinon.assert.calledWithExactly(dispatcher.dispatch, + new sharedActions.RemoteVideoDisabled({})); + }); + }); + describe("signal:readyForDataChannel", function() { beforeEach(function() { driver.subscriber = subscriber; driver._useDataChannels = true; }); it("should not do anything if data channels are not wanted", function() { driver._useDataChannels = false; @@ -1265,25 +1343,29 @@ describe("loop.OTSdkDriver", function () new sharedActions.ConnectionFailure({ reason: FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA })); }); }); }); }); - describe("Events (screenshare)", function() { + describe("Events: screenshare:", function() { + var videoElement; + beforeEach(function() { driver.connectSession(sessionData); - driver.getScreenShareElementFunc = function() {}; - driver.startScreenShare({ videoSource: "window" }); + + // use a real video element so that these tests correctly reflect + // code behavior when run in whatever browser + videoElement = document.createElement("video"); }); describe("accessAllowed", function() { it("should publish the stream", function() { publisher.trigger("accessAllowed", fakeEvent); sinon.assert.calledOnce(session.publish); });
--- a/browser/components/loop/test/shared/views_test.js +++ b/browser/components/loop/test/shared/views_test.js @@ -809,10 +809,130 @@ describe("loop.shared.views", function() sinon.assert.calledOnce(onChange); sinon.assert.calledWithExactly(onChange, { checked: true, value: "some-value" }); }); }); }); + + describe("MediaView", function() { + var view; + + function mountTestComponent(props) { + return TestUtils.renderIntoDocument( + React.createElement(sharedViews.MediaView, props)); + } + + it("should display an avatar view", function() { + view = mountTestComponent({ + displayAvatar: true, + mediaType: "local" + }); + + TestUtils.findRenderedComponentWithType(view, + sharedViews.AvatarView); + }); + + it("should display a no-video div if no source object is supplied", function() { + view = mountTestComponent({ + displayAvatar: false, + mediaType: "local" + }); + + var element = view.getDOMNode(); + + expect(element.className).eql("no-video"); + }); + + it("should display a video element if a source object is supplied", function() { + view = mountTestComponent({ + displayAvatar: false, + mediaType: "local", + // This doesn't actually get assigned to the video element, but is enough + // for this test to check display of the video element. + srcVideoObject: { + fake: 1 + } + }); + + var element = view.getDOMNode(); + + expect(element).not.eql(null); + expect(element.className).eql("local-video"); + expect(element.muted).eql(true); + }); + + // We test this function by itself, as otherwise we'd be into creating fake + // streams etc. + describe("#attachVideo", function() { + var fakeViewElement; + + beforeEach(function() { + fakeViewElement = { + play: sinon.stub(), + tagName: "VIDEO" + }; + + view = mountTestComponent({ + displayAvatar: false, + mediaType: "local", + srcVideoObject: { + fake: 1 + } + }); + }); + + it("should not throw if no source object is specified", function() { + expect(function() { + view.attachVideo(null); + }).to.not.Throw(); + }); + + it("should not throw if the element is not a video object", function() { + sinon.stub(view, "getDOMNode").returns({ + tagName: "DIV" + }); + + expect(function() { + view.attachVideo({}); + }).to.not.Throw(); + }); + + it("should attach a video object according to the standard", function() { + fakeViewElement.srcObject = null; + + sinon.stub(view, "getDOMNode").returns(fakeViewElement); + + view.attachVideo({ + srcObject: {fake: 1} + }); + + expect(fakeViewElement.srcObject).eql({fake: 1}); + }); + + it("should attach a video object for Firefox", function() { + fakeViewElement.mozSrcObject = null; + + sinon.stub(view, "getDOMNode").returns(fakeViewElement); + + view.attachVideo({ + mozSrcObject: {fake: 2} + }); + + expect(fakeViewElement.mozSrcObject).eql({fake: 2}); + }); + + it("should attach a video object for Chrome", function() { + fakeViewElement.src = null; + + sinon.stub(view, "getDOMNode").returns(fakeViewElement); + + view.attachVideo({ + src: {fake: 2} + }); + + expect(fakeViewElement.src).eql({fake: 2}); + }); + }); + }); }); -
--- a/browser/components/loop/test/standalone/standaloneRoomViews_test.js +++ b/browser/components/loop/test/standalone/standaloneRoomViews_test.js @@ -173,34 +173,26 @@ describe("loop.standaloneRoomViews", fun }); }); describe("StandaloneRoomView", function() { function mountTestComponent() { return TestUtils.renderIntoDocument( React.createElement( loop.standaloneRoomViews.StandaloneRoomView, { - dispatcher: dispatcher, - activeRoomStore: activeRoomStore, - isFirefox: true - })); + dispatcher: dispatcher, + activeRoomStore: activeRoomStore, + isFirefox: true + })); } function expectActionDispatched(view) { sinon.assert.calledOnce(dispatch); sinon.assert.calledWithExactly(dispatch, sinon.match.instanceOf(sharedActions.SetupStreamElements)); - sinon.assert.calledWithExactly(dispatch, sinon.match(function(value) { - return value.getLocalElementFunc() === - view.getDOMNode().querySelector(".local"); - })); - sinon.assert.calledWithExactly(dispatch, sinon.match(function(value) { - return value.getRemoteElementFunc() === - view.getDOMNode().querySelector(".remote"); - })); } describe("#componentWillUpdate", function() { it("should dispatch a `SetupStreamElements` action when the MEDIA_WAIT state " + "is entered", function() { activeRoomStore.setStoreState({roomState: ROOM_STATES.READY}); var view = mountTestComponent(); @@ -293,16 +285,20 @@ describe("loop.standaloneRoomViews", fun describe("Local Stream Size Position", function() { var view, localElement; beforeEach(function() { sandbox.stub(window, "matchMedia").returns({ matches: false }); + activeRoomStore.setStoreState({ + remoteSrcVideoObject: {}, + remoteVideoEnabled: true + }); view = mountTestComponent(); localElement = view._getElement(".local"); }); it("should be a quarter of the width of the main stream", function() { sandbox.stub(view, "getRemoteVideoDimensions").returns({ streamWidth: 640, offsetX: 0 @@ -312,16 +308,44 @@ describe("loop.standaloneRoomViews", fun width: 1, height: 0.75 }); expect(localElement.style.width).eql("160px"); expect(localElement.style.height).eql("120px"); }); + it("should be a quarter of the width of the remote view element when there is no stream", function() { + activeRoomStore.setStoreState({ + remoteSrcVideoObject: null, + remoteVideoEnabled: false + }); + + sandbox.stub(view, "getDOMNode").returns({ + querySelector: function(selector) { + if (selector === ".local") { + return localElement; + } + + return { + offsetWidth: 640, + offsetLeft: 0 + }; + } + }); + + view.updateLocalCameraPosition({ + width: 1, + height: 0.75 + }); + + expect(localElement.style.width).eql("160px"); + expect(localElement.style.height).eql("120px"); + }); + it("should be a quarter of the width reduced for aspect ratio", function() { sandbox.stub(view, "getRemoteVideoDimensions").returns({ streamWidth: 640, offsetX: 0 }); view.updateLocalCameraPosition({ width: 0.75, @@ -372,16 +396,44 @@ describe("loop.standaloneRoomViews", fun width: 1, height: 0.75 }); expect(localElement.style.width).eql("160px"); expect(localElement.style.left).eql("600px"); }); + it("should position the stream to overlap the remote view element when there is no stream", function() { + activeRoomStore.setStoreState({ + remoteSrcVideoObject: null, + remoteVideoEnabled: false + }); + + sandbox.stub(view, "getDOMNode").returns({ + querySelector: function(selector) { + if (selector === ".local") { + return localElement; + } + + return { + offsetWidth: 640, + offsetLeft: 0 + }; + } + }); + + view.updateLocalCameraPosition({ + width: 1, + height: 0.75 + }); + + expect(localElement.style.width).eql("160px"); + expect(localElement.style.left).eql("600px"); + }); + it("should position the stream to overlap the main stream by a quarter when the aspect ratio is vertical", function() { sandbox.stub(view, "getRemoteVideoDimensions").returns({ streamWidth: 640, offsetX: 0 }); view.updateLocalCameraPosition({ width: 0.75, @@ -571,16 +623,111 @@ describe("loop.standaloneRoomViews", fun TestUtils.Simulate.click(getJoinButton(view)); sinon.assert.calledOnce(dispatch); sinon.assert.calledWithExactly(dispatch, new sharedActions.JoinRoom()); }); }); + describe("Participants", function() { + var videoElement; + + beforeEach(function() { + videoElement = document.createElement("video"); + }); + + it("should render local video when video_muted is false", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + localSrcVideoObject: videoElement, + videoMuted: false + }); + + expect(view.getDOMNode().querySelector(".local video")).not.eql(null); + }); + + it("should not render a local avatar when video_muted is false", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + videoMuted: false + }); + + expect(view.getDOMNode().querySelector(".local .avatar")).eql(null); + }); + + it("should render remote video when the room HAS_PARTICIPANTS and" + + " remoteVideoEnabled is true", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + remoteSrcVideoObject: videoElement, + remoteVideoEnabled: true + }); + + expect(view.getDOMNode().querySelector(".remote video")).not.eql(null); + }); + + it("should not render remote video when the room HAS_PARTICIPANTS," + + " remoteVideoEnabled is false, and mediaConnected is true", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + remoteSrcVideoObject: videoElement, + mediaConnected: true, + remoteVideoEnabled: false + }); + + expect(view.getDOMNode().querySelector(".remote video")).eql(null); + }); + + it("should render remote video when the room HAS_PARTICIPANTS," + + " and both remoteVideoEnabled and mediaConnected are false", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + remoteSrcVideoObject: videoElement, + mediaConnected: false, + remoteVideoEnabled: false + }); + + expect(view.getDOMNode().querySelector(".remote video")).not.eql(null); + }); + + it("should not render a remote avatar when the room is in MEDIA_WAIT", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.MEDIA_WAIT, + remoteSrcVideoObject: videoElement, + remoteVideoEnabled: false + }); + + expect(view.getDOMNode().querySelector(".remote .avatar")).eql(null); + }); + + it("should not render a remote avatar when the room is CLOSING and" + + " remoteVideoEnabled is false", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.CLOSING, + remoteSrcVideoObject: videoElement, + remoteVideoEnabled: false + }); + + expect(view.getDOMNode().querySelector(".remote .avatar")).eql(null); + }); + + it("should render a remote avatar when the room HAS_PARTICIPANTS, " + + "remoteVideoEnabled is false, and mediaConnected is true", function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + remoteSrcVideoObject: videoElement, + remoteVideoEnabled: false, + mediaConnected: true + }); + + expect(view.getDOMNode().querySelector(".remote .avatar")).not.eql(null); + }); + }); + describe("Leave button", function() { function getLeaveButton(view) { return view.getDOMNode().querySelector(".btn-hangup"); } it("should disable the Leave button when the room state is READY", function() { activeRoomStore.setStoreState({roomState: ROOM_STATES.READY}); @@ -671,16 +818,28 @@ describe("loop.standaloneRoomViews", fun activeRoomStore.setStoreState({ roomState: ROOM_STATES.SESSION_CONNECTED, videoMuted: true }); expect(view.getDOMNode().querySelector(".local-stream-audio")) .not.eql(null); }); + + it("should render a local avatar if the room HAS_PARTICIPANTS and" + + " .videoMuted is true", + function() { + activeRoomStore.setStoreState({ + roomState: ROOM_STATES.HAS_PARTICIPANTS, + videoMuted: true + }); + + expect(view.getDOMNode().querySelector(".local .avatar")). + not.eql(null); + }); }); describe("Marketplace hidden iframe", function() { it("should set src when the store state change", function(done) { var marketplace = view.getDOMNode().querySelector("#marketplace");
--- a/browser/components/loop/ui/index.html +++ b/browser/components/loop/ui/index.html @@ -79,11 +79,12 @@ ContactDetailsForm: React.createClass({render: function() { return React.DOM.div(); }}) }; } </script> <script src="../content/js/panel.js"></script> <script src="../content/js/conversation.js"></script> + <script src="react-frame-component.js"></script> <script src="ui-showcase.js"></script> </body> </html>
new file mode 100644 --- /dev/null +++ b/browser/components/loop/ui/react-frame-component.js @@ -0,0 +1,138 @@ +/* + * Copied from <https://github.com/ryanseddon/react-frame-component> 0.3.2, + * by Ryan Seddon, under the MIT license, since that original version requires + * a browserify-style loader. + */ + +/** + * This is an array of frames that are queued and waiting to be loaded before + * their rendering is completed. + * + * @type {Array} + */ +window.queuedFrames = []; + +/** + * Renders this.props.children inside an <iframe>. + * + * Works by creating the iframe, waiting for that to finish, and then + * rendering the children inside that. Waits for a while in the hopes that the + * contents will have been rendered, and then fires a callback indicating that. + * + * @see onContentsRendered for the gory details about this. + * + * @type {ReactComponentFactory<P>} + */ +window.Frame = React.createClass({ + propTypes: { + style: React.PropTypes.object, + head: React.PropTypes.node, + width: React.PropTypes.number, + height: React.PropTypes.number, + onContentsRendered: React.PropTypes.func + }, + render: function() { + return React.createElement("iframe", { + style: this.props.style, + head: this.props.head, + width: this.props.width, + height: this.props.height + }); + }, + componentDidMount: function() { + this.renderFrameContents(); + }, + renderFrameContents: function() { + var doc = this.getDOMNode().contentDocument; + if (doc && doc.readyState === "complete") { + // Remove this from the queue. + window.queuedFrames.splice(window.queuedFrames.indexOf(this), 1); + + var iframeHead = doc.querySelector("head"); + var parentHeadChildren = document.querySelector("head").children; + + [].forEach.call(parentHeadChildren, function(parentHeadNode) { + iframeHead.appendChild(parentHeadNode.cloneNode(true)); + }); + + var contents = React.createElement("div", + undefined, + this.props.head, + this.props.children + ); + + React.render(contents, doc.body, this.fireOnContentsRendered.bind(this)); + + // Set the RTL mode. We assume for now that rtl is the only query parameter. + // + // See also "ShowCase" in ui-showcase.jsx + if (document.location.search === "?rtl=1") { + doc.documentElement.setAttribute("lang", "ar"); + doc.documentElement.setAttribute("dir", "rtl"); + } + } else { + // Queue it, only if it isn't already. We do need to set the timeout + // regardless, as this function can get re-entered several times. + if (window.queuedFrames.indexOf(this) === -1) { + window.queuedFrames.push(this); + } + setTimeout(this.renderFrameContents.bind(this), 0); + } + }, + /** + * Fires the onContentsRendered callback passed in via this.props, + * with the first argument set to the window global used by the iframe. + * This is useful in extracting things specific to that iframe (such as + * the matchMedia function) for use by code running in that iframe. Once + * React gets a more complete "context" feature: + * + * https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based + * + * we should be able to avoid reaching into the DOM like this. + * + * XXX wait a little while. After React has rendered this iframe (eg the + * virtual DOM cache gets flushed to the browser), there's still more stuff + * that needs to happen before layout completes. If onContentsRendered fires + * before that happens, the wrong sizes (eg remote stream vertical height + * of 0) are used to compute the position in the MediaSetupStream, resulting + * in everything looking wonky. One high likelihood candidate for the delay + * here involves loading/decode poster images, but even using link + * rel=prefetch on those isn't enough to workaround this problem, so there + * may be more. + * + * There doesn't appear to be a good cross-browser way to handle this + * at the moment without gross violation of encapsulation (see + * http://stackoverflow.com/questions/27241186/how-to-determine-when-document-has-loaded-after-loading-external-csshttp://stackoverflow.com/questions/27241186/how-to-determine-when-document-has-loaded-after-loading-external-css + * for discussion of a related problem. + * + * For now, just wait for multiple seconds. Yuck. + */ + fireOnContentsRendered: function() { + if (!this.props.onContentsRendered) { + return; + } + + var contentWindow; + try { + contentWindow = this.getDOMNode().contentWindow; + if (!contentWindow) { + throw new Error("no content window returned"); + } + + } catch (ex) { + console.error("exception getting content window", ex); + } + + // Using bind to construct a "partial function", where |this| is unchanged, + // but the first parameter is guaranteed to be set. Details at + // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Example.3A_Partial_Functions + setTimeout(this.props.onContentsRendered.bind(undefined, contentWindow), + 3000); + }, + componentDidUpdate: function() { + this.renderFrameContents(); + }, + componentWillUnmount: function() { + React.unmountComponentAtNode(React.findDOMNode(this).contentDocument.body); + } +});
index 468a842acdf6d74904bf239a4e49ff47869239ad..becee6b59f96d6a91a49f8cf23051c0fe9bbde6f GIT binary patch literal 411982 zc${RnWmFtY&@MQ*Gmv1xo!}PS-6cqHcXzje1a}x*gS)%C!yv)k-QD;7?!CKv&TgI4 zr@N}3eyXc~bXA2bD@vgu<0AtA05lnCaTNdn8Uz49Z6U({XW^Jx+xu^Va#4{I1yoHD z9{;BxIZA7}001ao|7Sn}(lhb?187;PX}W4E$n%;w*fANIIvATVdD=Mw{zv#ddH-A5 znYkK~dfM6AyYPAnkpC|P?|<w6F*B2s{x68DjR3i(f-<R?gR>ba2h$HG7IHykQc_ZW zXH#=t6>-V`bNoL|fZWp6)sdH(*~7zw$%CEA!P$bDm4}CinT3s+jg9d?1fz?Wy{nNY zqrD5o|0emrdBn|JOq{J8U9BAKN&iPTGInrt6(A@7KbZe5|J#wPmHGec$=>Dvg!Ny5 z%>T2)%*w>V{Qq$O5B>jGd6k^4%>MKIKm3BM{LKG9+y8wR=Ks%S{&%Fz|0h&IWPaxV z=h+02<@;!~003ctjJSxJC)8P|MG9qWLeXKVdN_{81geJ&6J-1Iljf~YiGOc<+u6PP z=t8B`j522!^&sXdY-Hl(<if{CvjiEzkOdF5Z+-Iz;wJCw)!c6Gs<jYIY%Hci8&b<2 z9kW%vCbE@GR&(RLscVA)T?>cR3tN1lY&pc5`fEg~Z!4Wxj(+QY`CZ=RuEe5))u5;k zP33beN?z=n61-?y>r9jq52^z&w&{A|<Eq7l+xDFBYL%#|$s^?aJka3bkdxs)GM!9Z z=(U(qTdly^Zr|LspnR2ie@G=Cl?ek?wivrlB6U0{XFEbjFz;`}(+oPw>N%NzY?IM0 zk>4t_vy_TCp%;VBsHanw@4ZYGodi5BFQsIc6(zMp(L$pvx>oP>_*kA)IOQNC`xjZ+ zmxGD|SuLsZhMV$>{4Pe-eU5c)yv4%Jk_F5{LLnWU)hKQvrxs&*I4+|ndDZTY^Q1b` zDG2(X>bsJMkR{z@OG=$Y8)RCe_%FxN`lGYSdShcuXm+ABUUhHsvF^5mCyd0zA)%qK zC6hQ@5YETxiwmZP(CxP!U+(TU{0l<ksLtKrokkX?PTYJ#1RDWQEScF^=oS_^A@#8& zA(6n#P>+Dm)2rRhkJYQ~ex-iw{_BrzO#fA;RXY)$$H(S=DmI}k{kYGyj3gf~pO$th z;A+B+M@x!_mFeX^{%r{hzj(CmW##tKktg@w<K*b})q|(QlJT1X>EqjtGq+GTzP<fr zNdGR3sV$I8qq+ZllE}IFd1iBst7*5lx7X3rljZDnb(19KiRj`S-KX8>Z>V4A;Jcf* z6VKaXcL4s!&4(>F&k_;(V{>Td`JiJ>w^Y~f?WZSG&-asgM_11gPt5^`&<4Ae>um4! zx#Xtf>(TP<*w5o`)PT3e&mSFLx12Yh*Gd7zA6JI~L|tC5la4h~#3$}P9ySov*8vZ! zNN=XHPj11j)XaPu?<NA9G~Vcx<ZKwqR)tKwpk!UD<y3xbi-EmQJZ6f{(Fvnq>ZqjT zdN%lgD6uaI4)WS)uwu>v<L&9M`{1HSId(Ons7a9_1#SC<_QD_4DTT!9lE?ox+a<=) z$;^I#==hO@%DX6170Q1tIE@C!my7!VVG;C0$j4o+q7?p#1MTaJ?h+PRqk7ARkD9>| z7NZoeCFf-mrNoJKrJjXnipGen$}R;vp$(<+dpeciV+p;3B!lJ;_{j$5&IN^!`n|g{ zW~35tut9i|5s_ZD?Bz3>#w*r4mH$|szq{JA>QsTeli1bGRm4L~C>|THdi&u@>f~OG zSwS^yMPDSIhO?j?-XQWpSk(0|(@pQ9B)UP|YbLVL%5xZ}`xr}=Br!z-iR#fw&mc4D ze0DutHnHDPhe`j2062JhqnW-g&3#)D{>c8!v=jpkmZPYF)MAiY7M#Vg2wl0epR_7s zZ@g6_35`~x@c{(|Be_W2_<a5$<>G#)GfPrkUhNv*EO)Z%+Xg!tK6YT%WMabmE&2z~ z63JB@s#7eWHQ@Ap_q_%{y1u>%l?SWH)$c~y12yf!W_x}C%iYo4{>{F+I)omuct5}I z=;A`;b@I0pV_E<N-R!Xo%xI~PXa2Df)P%6a%gvAMNcp70;%)|cgKrASa{tX;u?y@{ z=8?qiK)Km~Q6vdj^$|89h+4gapyxtz0z{sbFuns;gJ|0GIr1KV3%Tv&Y`OSYFbkKy z*usc<0Div$26y{Ax92|;N7@?&JQL4KuGZgcP?kD+H<vp}9@3>(r#Ug+1lDwNd{z*z ze4JP_v$7=xfL6Z+0DDs#UDzawF^bbJ7A>8fA_SS%7x^hBF$Rs5GHuENJQVtkHc6-} z^(hNjgItlKOc5V@|Cqna?M=58nhGiKAgbSdaZ)hF>Y_eRA?GRaFJeDbrSp&3OSorO z*UG3gP5!(IQF7}1_~u{MWTOsB_43v_<vuj=CW6RWnP_2KS_>VFQx2RhoK7`#8ATB9 z$%;-}&-<x?P2#?$?a1WZn2ur5WR0kFglkKctK2ClaRsk1a?dPMacDOnZD$u!+TT=K z397NBELyKl%oQ+V>d1)_kVvzH7JR{2W^>TTjx&=;Tg%jPkAs3q%l<Oi3oM5+7a|UN zc}}SX4tRbqnnvWhXqf%+q81qslE0yA)-6}{mZKf4ooU`Ubyo9H)Aq3lCX{Pp2<Twy z8~dkrwT^KOSK5U-bWq|RrYkEw`ZFf2{X{K|oc=aeW-Rh8dZCys?;<i@$Wk}Y_FX1f zf{xBBdeT|q5Oxs^Ee9zK%gwczr=}HH{PByyF^wH|fXc=6MO?zWj3q&|a+Z9SdVQWu z*Z@&3nql4YT~cJ05<V;n6fcjilwLIh&iVssPw1pn8%hA*{HyVl1^V)CAXIHhh5+`z zcXZZ&O%|>UY<@&4tAe6m1a!zTT5CclH8&T#UBL>waOoNtzW2{QehlXTe&hgt14R5q z`E?GMKonbuAQS!y`zJndV}0oUxinF8C`yHmh6Wd)aCqDP@A_RJ>xVQCh?CJ>8`@6o z4Im<|130sX(p#Wl4Cd<>Oct<dlgfUFS0RZnHS=9$t1VbpZT4|(CUTGec8~j=Zqprb zc1}#lDhTKS)#&XY3`>!Au5X{i**S&m-|o0SAujp2G~jahb-=$tU0sw$;!G@p+U&-< zy9+A@?T+x7dGN2`>G#gxcdw4;jvfEZUjfE<V=w*jH$L7S`n%swyU_wZ=DH1+`H>A7 z4fPDMU4NMX%L`s4o4tBV>(0}=*3<3`Bkm02khp^Lr(|^7IGtFT(kW-T*0s{+UrVf1 z3!DEG0mDzYMs?7cX<1^$hXfBZw^4Q~(Yl5ERI*+k)Qc!ywI=NxdtoxYh8qZFR8Xr5 zq#0-!j|nouV25=hcJP<k51ztG7QHb-h-J_3m>#Ij3Mr)4WtshKHr7-Kd>qmf7WcN> z228qsS$?gp^=A}VLeu!WuhAw$RyUvI`iW{g`X#cSRjuJo8iF7<Rz+ZJd{sRrqg*Y5 zq_kNkWle8j?SyL~GYJmo4c;rs+*fKXYU5~PvSMOS^hQHfqEh%vMP_m=_m4_l)_l|k zCdRTx-6tC6r%cfk3(StR0}S^Gd&H<PD%q+dtbdU3ZU+T8p?8#|5CNqY;u7|1n?hmE zu}b}tImh<icqkT?h=j!(V+pq^O{^cKOP<-5U@y7S+W7We|HJV?<ip_)YvEvVQyCac zv@Ds;I!%KgBcJ55r%m$R|IM3tDfBq*r?I3qiZqGUs9MDVM`^4a!8$+L9(c_wuTFY5 zAd2}9Ui1BF3YB`7R=G}E*-}YQn=pNV-fW~LWY6KGG-9E&4N_(wM9XL$)Wt5mNo#nR zPCJj%vstV}qK%!J4GYc;c;U{3c~MMzcz@d63{~y(kk{D&04{6st&`dja@S$NEcr8r z(DEx(Lkz+w>AyHWJ==#P+@0K_1J9sL@JW@Yhr0DX)HXN2Ze35quOV$UWp+t?Hhe(+ zq8;Dx#B)#WTK|UbVe9jOhuRZbs4`A|(*#wO+&bu2*SO^sh+65xyKnb*6Fpg|(ob<! zFfX9tEAC~z9$<;9S}6q1t;2_($p2;AyM^?VsErwr6vTTLz)Jq052H(aY7}qCyMo_S z#-Y|JG~?dI?hZsx^A;pl+~^{TG3X=~d`tP{s3=uL+cZ*e^Iow!(^<KK#qbti;{|in z+$jl5QI&X|7L+WydYS7k;l-FPEjS&hn#z`1sEl$+Aa&ZT?A?~jrQW*9*!<2J@BTF+ z^rxjt{UD;JKVUemYK4J3{++7v@B;0djc4Z~DScU$iKA(35F3vrBXQKb+0<gOI=5We zQUpmvmGUA+vfIc@rIC)9_S7<~8gv)RVBJqjCbVZ#SToxkefZIODW4Rf+lL!!t3hfB zq`_4e4>$?Ool&rtZdrrd-Tj_d>(AlB_Ab*Thi{3er6KjvH~5~$rj}4)jW}dEOgA^X z-ON*jtyDSu3espto;8h_gj}O)-_xR|V<&Hl8E$DQRBz1A*#$?`CoX%K-|ZN)a$)+V z|4|@TzMt`W)eUW&by@z6!>|*P9S!sC)xnY*b<~gMT7)Z{$W!eQhf|IGqser_>NGaf zDriEXLAEbvU$+y?K16TmZ6G;zR_~DspQ6Y5KrXu(*FIrC@jBeaQoh?P9_3%644p{d zs>)^Nn_O<I-oxOMz(qOb`5K6kA4DJ<nVHM{!@Q^E;F65Nrn%zSN9gUTf3xN+3ylPd zq4-I=c}lbX5eKwm&ELCG=~a`wzPXNuTcD?xMH4nKYu0UbUViWo`OuFc7juM=_yPu0 zvxd2efU37?0OU$(mKQ;p!pj0si=1RRx5Tqn@SNha>1tSL-wo`$fks~Qe{VyjwQEk` z0C+3YAFmjoJ&n{0idOlVbx#l51a%bUcKX+imv}aidJ4N*tCHP(!L*iq!#B;b>erK} zyMR30tIzZG;_WZvo7fRu#@3!0wC8*$zMbR$H5S{Bp)+&5*1aA1S@~IUW<Ds2jTg_v z-T-BNzdmnouU_w-eof}*hm2-nnFZWgYDMhV*AHL-Uf1)(>h=}L%4Gqrt%_~v*T&Hw zw<an5N}Zt~EL^M3$h-J3eOJvUOGwf-r|i(51OaoJLSTkI|9)(m0p7@mAK5L$sJtoC z>5dKR8eszE*)I0p?NZ0Ob!|r}Mjc5&AX_-TH_lI^)hF%L^7dvjI&x=^SxbbpOEKiz z?BHw^HV)#(lSuVVL40usD<d=&(_5)vq1ek;3z~X}Ob-0vlGKcBZ+ztdJ7qB{y#}(q zg7QF7@u0fM({sR{7K!wHal^hmm7Q&Pc>J_(WZ{6c!REKbf2_m2DvkPb1X@EqsqINg z*NvmSKcTOU@LzqfD6(?0W~f5=rL|J1J7+s-w;l9HqM;J^!d`PD?Bhq#nT1@fW%N9~ zt#l5An)4;gr>tl77y8X3i^^H7cm}*WYp<zR+I}YJbJZJ9rUAW75-I!rMn`GfoL#gB zuU{+7Sp+vgetBN5Nn9pgSu@&AfPnaavo@LHMfy$Kf*a$U{D}smV>(VQTBEA}?mA^3 z56d`-7zODF|6D*1CtT>wLeR}iA?DRxJ+T2G;z|{yC+G95cdC+EYd5cb{6=7ZJITlE zRm|}^iT@KBr^s5uM@qnFK!}E|yXX64bFKd+{^=H)YG>7FJ7q<qa?S3K@<Cp|Qa8qh z1<VEL2hjYKGdgh^9ULXnh@xW5Ot=Dte1`r8Tc?~pV<5B&QAjrcjB?@j>8sK7HrC#0 zLPUOgVsFq*zG(ya0-&#h+B%B$F<oQ+;>ufC?l$#SYb7f*b`?8H)XuU(#pw(SfIZS* zL(`FZ?YAj1Z*Gnax!lY~{d`v1L>KaF3p?J*D%o_`#Lr6Zf=0Avb(PhgE~N|l<`zvw zsEs^I@#JeNHbErpeJ$)WV-MZy(DiQ44KGftva#^6aTSinsiA4+09ba|?3kLQmM?cW zXBDXWu){mjN>=<_o?$gno-5uIrk!tkonNok3%QJP4iU;%=|)AY=v#a)Tvd&Z6G$Sw zvDj4LDN;^0?AW9J?AVhoWIO?uOB+CVA?bO;<ikBt*?ncL#qPQWVH^|f#k1oEjQ)yR zG^=ZE-vD4WnPUxB2@Zii-L|r{T9;FYtb}-!)X_@NmxX;!%?`QXC~-XUY8J!J)Bg$! z7d@$;CV(Qr4)P|YvqHOEIsLZy5fgs>x`V@TJ>#H7=tyBl+RqVERhPNAI8v#WUw`g_ zHK7hmt^wUrT*q1GUrD)wiX3&e;9}iURGdugNMQx)o86_aXaruVb|q8v92pYhrd45d z;d|xi3m|{dZAM0C<;vv0+97jbihQT@#*m-UkJNWw_$i<9<lR{JOQ6tH>FuC0)&Gx) zu0~o~dO#{^<W$%L?S^4F+gM8K_GGo*T+;gMkhWI@-W;0JO;n-HkNZKDVz@D)ZVwQW zNNQ<Sq>m$hB8P*=6D|k?DzlKG2Ha}1$PsW+;0DuAi&Os9KlIE~kMwW>jdXGGs>qj% zcTLn|;-YTB0Rf}__n=%&XfCHf1bXvgL2VaW?%ly2B1``*6icX<Eq6C{6nrZ>MotB* z0BRhcF-=`EOQnm(;!(&Y`6Yc(JnK|&@EHiTio*3ac&;Z%Z(N8QHlbFofAU+^txM$= zld$Z1HI%~!u1|Y1f@eO|4)!0xw_;xgzv(V73e9))^;&a%eKH!6h77KXTdE%(e8r9E z_#94;_8|NFzjor)v*%wuu7y;pBX3m!Iln{z9Oq7b4Oe6trcB=tnWw9mAR$7vI-b2% z+m&3Kxm+})--8vS4u3NyizY?Yd;De@BHuD2M<|UQsvoGZ(TnMl&(0?K>J#i8ZUbjW z&50@d-6|vPQ-oH%lLmVNpI;-^Gn;XgRkZ4tWQQRAmw7$oDR|4^3NW0Jw;D$)tD$y# z<=1&E{6tB(U3<%K_jL_kX+v)JnPZMJr>%dZXHW;8f_2x(!sNO>3u3;}(Y|?qYH8?s zW^Jg*7NN+*&6Qi=z@5(Kgt*VJmqx;Q=+h}lX(KB#$H9tSrR2_*4d&O=D}2LFhB!9F zA(dZ*7Z@`A%%4!lWFJd~@usC4r}j1r<ywNHgFmro1G?+ps|~Giu$g%#3l?g+3;dC_ zFG~KkpOQW#rA>eQxTRoHbL>D>al&1r!<c*6GODd;XC{d7q4vu92laE7U>EXZB(s`1 z--;^{5So^Zcc@~n)n*Cd3D;ck;7Lw<_04KY%4MU`7gMEOwpLBvp%0LyC1a#|8T^+( z)#-eU+j+>ENjsPZZc8rO7n;m!_1@U2MljU=)IFuSy0v$$7dtyJ>)gcNc8T$HI?w5m zEziwm@vYRU9lA_+3kV3enpt0e*W|<PQ9;3#Xur5bm&+!gX@b&NeR(VUnE3(@a0@R) z^(O2O8nlh1&}pjKvSW|-{yaA4ZdU*y6T_51Mb#i~z~pj2)Amx@oeGg)Yr|LbpX|?J z_k^vtfqrl)+M+m@4oAOCe*hKR@xNd|cfs0q@xz9(awuqH;3NKs%~iTOfJf)*MHKG# zaS<hg3z2_iv#2b3EjZ6Tj6M%nzuTT?{g*$jm)l<18uNffD0mb3isxqwT)b*~n5EtJ zS$R50x~UFbtlpf?UhF^L{P26an)8@pHmaf2&{Fa!X;)or<;3{;ZydL%pLNLKDcOin z<2p)VW+KkXE28^4dLxy(Uw&!ijw6mSE}DaLImEp7*rJ-Bo2$`IDi$H&>k6{fhB&II zoB6%g=y&hBSTDZdAW8mv0v_sTR4|WQ!U2mm6U9Y!HmA9LAnQiNcOX&G36mU0WR<Fq zBq-l3djUW#=aFO;@yoHuAHs&sW~L(xIbf1uqcStSOeEC~oUucWMI8?`yu3|aqgPr< zwFNZ@YCW*7OScSJj;WBxkF6b{$4z&?Bc%;nE&asVE0>h~$c$c$F=9Vzbd)6JKi~OF z!a%#|7E-&wvS+GKbpXtE9P;nBPkf;0jP_-ml*u>|Sf``#_#v)c_{v$zFQIc#eV^&f zSd0~L$%Wpb@FvjNw@)vF<hQ1o#5WUJo}?gp{bNj=<?GZ#oJCso;FU2Uf`yamPy|&! zo|rbl9M2P`;R-l=`<LfPmVx}~^WpI~2m(vy&zSpZ1-k@Ykutg6QSbz{qx5O=T+AW> zyBODDn09TPd+{>e$}li@u5Hm4v9%Tc-;eU_g^plD43M)U;A&f*A1XIjMJ|1~8nH{* zxpu)0LAXgG%^rP**Aq>+PFF<ZY=Y_%6Gs5D!-x18qSuGp|4}@?9a^7Jas>5Dl(irh z^Rwg*52x7Oj?;{<6JK>GuHhofV2$*YtS7}oJd^BbM^rekJ-YF#Rp&`It`!c$Y;ps0 zYf^za4B8SJ%yY=RK%DpWtaf{Ed!r5M&OPL^%L^N4?D0|vjYJ8em6LjiV14bH7N1*j zS3l`NqID^~x-O&~g8f%aw-|3XysZW175PecZeeR->DV@dp{8%e9T^PaNP&LR&_s&0 z<tqB~2o6?ldRYNxhvLhM%eF_s(C%^sB}?WmJ5G-Gd=V>JoG*xP4ij2*=<{dw64HpJ zx!LDCD#RCD<W1UmRrj2s>pBz4O79p|)$q$|`%0XnB@!j){7d(1P*u5&N$LjuAm205 zqd1{hQa!U3a)!s4!QG7%8DountZy9h_XXuksspSmUG(U`C5|SBcCI@%XD*^<8fgjI z4VHIf%|pyxeQekU{cUOg*d!?UsXz_I3B}O7RmkT1hP2RRzoYH@337xDWyTQ<4iZJY zkxt(d)R(<;8l)e{@C_4&eg1f1t~ydt2S4%zXlz@i>+i-GzH1Po2^L$ZPLz77LQ3gx zeicv+-#$~zm}m%}+}^vk(%U8Gd{LN`)U2{Ph!{rhZF^={qUpdai(>7Brbm*PhBzN? zL9U1B)6~397CnbOv9DHN3MESQD;Yrlv<uYf14(d%DijsZv;E(=Gi#6gi8_fNd`Det z_?tn%VwLrdn&H2vi=f!{P@SpX-CT>k0d0QazsaJHG=O+Z{FQ!Z<(_Cf?V&1%8aDD% zIsnzL7NVlKR*z1*M<6#26^P<=mz0#3Q`@tP#FKvEpVfJr#KJejo8(oJ4xD|~-}s93 znfIOfsEl^~wK%c>I=^l2K6cKuvkiXK>K)J#(Nm41;2LTu&C1o2l>WHeA<H*t;S1-h zdL-@pGb8Hoe4?1;Gy<tczz8wGk`G|S2!iG&O|^y{>E!y#J23uzg>vpDP{zdT2I_4l z1ORCdmfG1fPpiLm=^;8riuVzJ#;us_*xIs#Shy-|JqA2cAV_!bzx9|r>8hqZHW^L} zP94^ymkdy+98;t~>E5!b{Gl1BkkgK5mGNP_bGa3uy~9<!n_~Wc+hM75SgNi5()P<& z+k0Pkm_vYu(Pz#jK)tUXtR7PPRGO@H@Z*7P(8tdjnIbXchPv~I;tSYmhy7BVM2wMT zXj?|B3hEA$PnB{FD<Aeiy}s3lZ0v1S6X-^6QL=-cTB=$kO5GN;pZ$7+V@F)Y?SHiK zRHmHRfB)>G9el6BCZdz*Fhw27bfh(0rYiWy(%(mLrRte&Se3Qj`~VBQ_hqFRtNMqm zVMJ*6V)#|xHnXiD3N%Oi%8fI!_n7Km<$7|+Qz8z8MKF;+MU{8rn2b8i*_57IsYzo` zC!<t@^!7oFL%Vh#<y&2BAZ>zbzZ?<|w6U$(H|r#xJY0<Wi5y)XXS&R{Z{uqj^tJlh z%ti^?Dw0H;W*g!;;+05gqhFlmqfyl@Z9?Pi`P6s-U{m_OR4Zcx<VI(_H?w^mSz?OO z<}!_AUN#lM4w0#bX^@XuWa+A&d)5Vsaj;D&caFa=m#^m|6DZdU){nFnz$33*w{c0m zCjf13J?3gd(9^v8cZQIpAIqwO5eowfxib{bh6^N<<k*=z*IyLA(o~}uPe|&p1g&et z+99+D6<vDy2aU+MMyDvRT7VpW$ZpK-cc@f}Zs145UT`T2<gZsxL#0s8%+~n#*O!n< zl0BEsoLG{`uH7`JP-3X$h9aYQK7sCnx617#16(7!tn*9ot#RNKU{qkXFArYtG#`>| z$7yv|3-feO;DHKr0*=hK&;a%?b2x8fV!W8e`xWQsqulsQMt>J8u@oxHQN1`okU&^+ zH;KMyyCfsMOLa?LFc>eRmMgBP{);4Uz;5RI2m1=-mPTCD8Ld983N>+w5!M|+C;ubU zHOn=PT#(?9`o8KW>Iaf)HU>wLpLy<RmBqNl!N+io226Fscp0x?PIg&FUWdiYLexUm zqfVGUQ%%Zx3Tp`0SP8L?nP&3xB8``Z^N+sF?E8dtrrF)u`M;R`zbn({35hgf=1D1w zHL@<>b}~id!uBp6WRP)s#>{`|nakAiB=B~_x8B6?n;1@Y{fdfin^L%w&lzS{%4r5> ztPJb4(7+8xVTdlykpFG(_(QW?pSIsD=lnes(m(AE$(NN+R_)rOs@d5aA(E*tP!3i5 z7={5${Oiz5Z(*S5&3XRKGiPorNK?jSaKbsN`Ii~9B9_X6uW?1btOBE`pv?8)?6}^M z`FGu~%UJ5t-Hag`tN9`JTFG_>xzdayIeF%=r5`!WHhwX-hi=doZ!;vieHt=4V#EQZ zGpVLGN3v7=jYn)vZ{O>yNF;x%ZpXd675+Ba92WY#!#rJKsr2_x+d;=jJUmBoU6Sur zyQD#P`?$Io27r8CrG5r^!I?to*MJ!T2C=~G>J;Ir+YjLYR&}q@J8OXOjisNCVX_V& zB9r(b6)e#04t1rP^0Y>1ctGrDKfV7z7>N@w+$rc4b?@d+wi{=nx8Zyj@zDPC1&PB= z+b!0c@Isl%8>KE234V7F%rt(xg^&rw<l#lBYa&};<pW@a+C;wt1g0<LmEO!>Ur-FU z0SZ3e1o*3K4WN%;O`7Esg>Lu;kUjc_Py_XCcXHj_0h-!?*r$$FV(Kx3g_CD>tVMEO zyN`I@b(Q6Ov75R`PoVxi1dY`mT?8sgB)K|CiYsv`dm5C5QP-_oT!KAaUD#pXd>1o( zuKQ^)qjbUR&ij<G-g`mlKZz+YOjCW#e#3HK<%0SoG?eHT6Co9ZiGr>|NmbaWAd!7L zYQQG-*~(w<DzPQHi24yz)udbA!>+x0s5H;IHK?L9qIAlHUE5U=H~Idp;#4!)6r4xq zClR1ES9y|QC8HESsJH9s_O$oJlxEjpdO#Y|h6$muLf5npZoCK0u&zcoF33(VG%%gb za4IC*MDU?eaAMNYLFzB+Q*)9Q*u_I1|1hKFpHvsy(P`)<oXcCes<`@6&Pime;s#uo z$y7&gFYxuQ>Mc;Ii$qU$XM4#~;2&U=bHpve2S+NLy;(wJt9<oXGlIxs2GCX{nglDK ze7yX;XZBBz{X7MfoWXB>y4cnHke3WLuxQ4toMU0RVoq^+4;~>*l2!m?twq>Xy)Ka$ zu5SD-&!4zko<2eYy&~&$hD6Oqh&C0S6VIad!Z+4&abMGO?2zd^L3llsqC!Pb@#U00 zRJy@Kiy@bT{X@%EYJ5&e>?QZaHw@RQG?yR|kwmGMfxr<Ecct})Mb)m3ql3&NH})dt zhT(Oad1A0?yEZhOZxHUKJJ9Q)#++>Og4pH+R%FlRJi}s-=d^Cgm^ZByLeFJwtB0T$ zcY<|*)N_C-aPi~}e<iJnb$X|WJ_5{bH&q=8>SzjPhH}a>ynKR<{KhppiT#W1P8B%k z`?qAHvfT-303P{fqnDy*Hp09$)OUFCM{HO;lV=flY59~_5E$t$yJj&SLtw<Me{h}M z@dVU)D|zp|*uOfC+SLIhA2y7elsDt>R(ksk&4|R=`Pp%uk}ly)zvQVPc)@yUXo|t5 z^NskKMi;?P=jgW+q%tQUs^L0#ZagcPO<};=b_?=^ySrEBR%QRbj;KJ8E^rjVK~?Q} zvS=N{5Y-3Id4FzXHNLND+fL1?5Khc+4%Kf8R%7{iqhZJzk?~T6dNTdX#nuB4rCUX7 z-ZONgr83DSrT3{s(t0Uis_vx6?MErF7I7_aWZ1nG2&$(a?^7#8<_T#5d^WZ;$?l$q zYGmJWE>h?$)I3n%kXI;lt{-HcaAtU|qNI>(J)fj24O|;rCzI^Q8nQ9=NB-P0_QCL? zdtk$I9`>`i{`Z07k*doV?gm&9c;JWr)55GQxTBs-9>H7&<J>XTq6nrrG{Syoywwfq z_!;Ylq{_KWt<mwcUQaiNxzH@vt|W5{*SvB6<{Xv0I@EQ;ondh_AQ=D8sS>G+)TEYS zu|E~qT^r86#q9x7FRGP(PH7niGb2xoVRj5$==J<2ow&S5{t)a4;Cj2;1!i79a-n;E z^hg3@NVY#_tlb9x4mZp1M||T?5Ep<WapGok!xBbjF;<27E}>kCJ$5|O-acG&z%zK- z#uqrdz&RHW61e9++}g`pha*J+Py%3=T1SHzzhV^?qGOD@Rxk9^GnhNnwzP^p0j`?H zXXt>M&jKV@AkKO6=6-6lT%sN%3`7N!bQ}rdE2tW9XaCkJI!0(A<^W}j$q=p<fDgeO z#P$-?vd|SvqGXc3QthAFqKKiN0KLVVH8F8l^BFCy1dyiqdBEA`eUY;%y&!tzj8$nz z%<9r}83b8dSN@a(RE0`i)?5!{4a8~+3mC54$7?Ii`yucs-nQ9jrYVx3xL!7tuw^%_ zAnV%&^ghrUSS}X|z=dez(S`_i_2PT-`;G_B`ox07=s_-HSvG&pH4M_)=G*I@5=@>q z%HI^^qjqJif9Bkt?!OamUXrcjjN<sWHf7v4U=1mCR7=MDq4&EizO=kxC6CnR;lX|( ze4$q%7o+jOss0vTdpXUzb_b%-PGhSyrg9@DNh%SN)-I%pZ-7ZF@{G|LE_k`SOTrIE zR{O`9inq)1JZrK1U$;wXLZKysO&c)O70AEqEvRkx%6~XV*bNp`N)auC<0-kyPrIYI zz(UKCK)B6Rl>9~xBhP4Xkg%b9r3Tx5+7pxB`#ml<_;$QBhLBrk%$Z@#^U{1qkhYIm z=2Bg6xI3mvWf}$Xbgv@65_=wx>ss#e^d}qVwMJW)UE4o_0Wp2u1a?zC_=Ca*(cwCs z>^-haaK5MM&k0R)49bV97M~So&xvk%^yQy{RNfkCWiZgx0+qM;5<!0<?Ub&x<foF~ zPQ{z)VodO}-zY)>ZC)f#b8W82hwDqqTZgL~^;3}24U*3f4RoImlni7+HUS?H)p_=M zS0)r92242V1c#|2<{>66G()er<`d#8QXgYcs0T0=xzM3`37at4^X|*PHJB5A&*wi% zspnAI7Z4_Z=frrrqTcfu!Sib1$WPp2i)EzoA=GyPdU)ko@8;hUD84v=ISxO?Nc;8! zU?HqN3LugD@aKBGKg`G%N*-=tOj=RlG{8%fv)TdB4xr*Mipw&e^xls=#~)t_IyS9z zgkI+FSWzHTd>?8Kgc?z_y5zb#!WXFwZwD}}_E)EazHUPe{9Wbp$V?eQ4Zgqe6&siE zl%GTX0=IZU=kBc!up%yY6p)%G>N=?@4~}y!?qIHMXnU5BJ6qU5K!#@Nqrel|nsfH4 zIKN|e4wXmhHcDZsfI`Q;LYy$s6|VPc^+v*dgqg|nY(9xn`b*mR#I}E4S5Omk^$J`m zqF{N+J82lwT9kCxbe-)0HBPVyh&be(<<JnBJroP^kG|^elmtXa+~ka>nlzSmsnLrw z!0dw?>Ado;idUQi<z@;;C>cbPe))gR7nPvvrmDQp-uFs2s$7bH3SO4t$sw|Y(|G1D zH|}8jlNVSZH1wnL??WQ(muy-)LVf`Q0%WqW?vCecmb=5>KZsou7%Q<&o_HR=WFMNo ztsLi+@5((H^wpQ@H#xMniQJ!Wc%oy<v;k##{;MU76@=MDq#f0P^KH+GTy@}{d&qzx ztx<Hq9kut^IhdJP%X}~5B(~-UY(YnYwr@m)dnqi^WF=XALiL(pz_rwF;~(qOS_MfX z_%|w(EfQnmH{U_?KvnnqA;r!5Ic}G!Nti{=NT$>m4!KN)LzRe@Sb(H|9I8_-50qo- zaFruhJ_s}{bi{u#X!4U7K;Z*OL~szfu`zOqaLu8ervQx*lPZqypaHHDHlydjpxT;D zGNtHI*%|GdRF<JK&!Ofphw7DgRL^DaB?*VF78K_S4nLnit*fC3Aaj6fTzrlxA77-p zYkzrS=XNR@mOc7)?(wQlj7hI`%XkCptA;TRYnep(vQ`P4=RXw>xDk~AAQ38o*_Gun z|8CefsI6XlcPQ1*%op=vmTf<Xz}_<jVnYCbls5r==BxjDi*w%rnBL=M#UE^;^K*Cm zD3EPJSj_WJ)Yd#lq7Q(lIK{&j0@yjrE%LW_`wB3=fRXnnpLhfxZ}#v0hkkOihwUYQ z8os=&F(n2L+oC%)KV0OWVk}oq+_FkVc<BH3=CL(?ixM$zi>Jw7cbi(KYRn}}#<oYr z+7^nr^fOX8A1c;s(z3ZPwWGTe|4`56v8eix_8v^WuQi>Ou@$rD@gk1&7O}-1_r}jk z5rDK%$1p(Y9Ne|Z^yhhGDr_cb6OxfHm%;rmoTUht7Bn+PZV{h|s3ugsfxqX44@#<h z+y6Je#M@<w{H2dZt{h^0VDbIbR48#@Lk?Z9<;gJi1>?%;Yx(aTh}#!4WDIH2R7%Ru zI6u?{G{yuiOu`;W{qUE!XFxP=?vBb%0!jRZ%K1io7kq#@N&|I{vxUchIZ;o($8mtd z7IEl7Sq73FI}l&}=K+!(_Y>(wMDwpZVH#(xTSxxQiD+_|&nT{02&ok5Eu0)n?6<Z$ z|7XJ_m9~MGA7O%V?<vek3yns#ZKmr>-$0l7e7*rMftyPGG!+5FRL<z<7bmEHJO~<Z zv#-aAR{4U6i?~}`Vfhs|k;h<N75QGiqOOoT6%o(1DZaj#Mf5Y?LOB9Fv<r0UEd^I0 zlNhnF2%0tA0dcO<S9`8SW~)WZ$xT{{0wyt0MB}lVlyLIN+mcv9a=5>Ed!j(&6FOB2 zu3r(oFJbCZnbF?gct?om>Yz(uPMUq5xCs+JQy+c?K;Gm|33L4Vol6FtV#P87Tl>lG zSMvQ8N6WI@+Rb_2<6_@8ZimmRNagKnHIZ$tE|zL)PrZU>elCpD>MgKCV*m}#^Z52> zs%FrG%x_+nxw%#?N9ze!b%cFJ@2+cL45=nRIzu*L^0f}|RIex6^4Z@fG{gm=aDeDB z&R-GTu!X&UL?sVs0+DOft8y1guTs-$2kl$~Mj{?^m@wQ#EE#^5Qg&bAKi0HPM%d^} zcIg|eK`)~`NWwTO9WY$XFHC(b#Vy<FB@3>Ea_uSBaj}`WB}OLlkUyJ!;gZ7-Weij> zt4iKp*~R6n|HP>pOMC5>Snf9e_LGE3y*jw00$|{(EqCVg&HEz>P&@OwH><(Q+g<)` z^Lmf$9Gn1;S}ZMZ&(Qn$Z@<u2Y4j<*X$^Y*W5z@LjJaQsz_;^PP6&xOvBG&T>q~Tb zK(?Cao>kD0AnG%ffLlcBZlx?ya4Nb0TShI4+z*q2?Z$#IQKh<ARqL;C-|0_rO4+bF zfe0D_r32ZmN;$zsiR^b|TMf3h4_o^e;36DKE8;7Lr`N0P_p6^*kGlrX??iwn7*JsS zXX=-Ss7?y^XgcO%l3GqE&Nui<o7pCAr9oOn4}+u4mozqyZ0I%JL{3{5UzEqpb|W}V zhRMjfW**&Tw_rtjpQy;;zl3Lea9&~l(1iQ{C8kiVCjKh3NJ#f}W>~c+ASN>br=T^^ zG-vYL1am0y!#uj`zzO3K%%Rh6y@*MG4R>C^Be%&FKIpJHxOweouQ}2pIx*?0((3xA z@iwI%Lt8TnqI(MaT!S_&v;9c_HD^JaVO(`=%LTIsE1y8+2G>bJV8Y?l6lYE~Uw03w z$Kdva=JrxA!&PGzgZ9;l(ISoJP6OM;EfSx@ANm`_e;)715$A}O^?nT??_WE#Hw=ep zkwCi)lm$!VhlkQ}0pVYyXBJPHY)wGe5Gl<!{citBn$rzbu7Ia(<FoR$s9kPMQ~2p9 z9{>u~Ip!y!vYb8fW7YiN5rG)ylH<2t$@a~OXA;OVUAOq;8Jw<9Y6ErT!HJKt?OYO= zl;LNmgpUSfqQGu?)d^$XODoG<!gL|7mPx3A%K1cD%t7~6ph-l=VC>I}1Vp)Ew4}N5 z^eN-2to_lXC8qEvb+sq;*y1$AF3@_s#~<-J@ar5dAqd~0_9$$q(P_)}yIunV;Ggk! zo|_rpd0qpZhuBp0-ew8h!Ta=Pv3n=8{d*h9tz;Il%MeAh+{*w3VJ&HsGHb)#K5`7d z`mDJ0kO~$Y+R%44d800H;b3eeq*$;bWEP870Gi4`G+05$xfgApwupLOR%*A9<=*8z zb%6^AFWAk!>p{FFPQQ+wA-Hz@8m>S>;{Wn`b^Q+Pe=dIP$6gRxtmj#8gQ<ZEhZ21g zg%^e@$7Rm}!=zGP;PSmehe_pWZs6buIwCUlDirkYDrz#yRT;Q=vlh8;&+ZgNt~b?I z#U0Q16$Q|`pv>uNuJx&f6x#K^(^mtLPp#gckgyy8ELBLZFKmDu*`6qEGMy`vR|6QF zthyM5@1TB0Q@-7;H2-FB^KUa|K*k|y9#9Eo-o#}%h}j3Q!&Ds#EGFCz;<&s^(5L#u zG2pv?u9NF;VPB!O@PL0kH#}{F5Ky_x_aFRS#{F*G38%FRCVQGSMvjW2HR$#`!(<$; zxNNtmAEgq8;5K@1!tiF{G<`rnBb>N6#c0LX%$?iMhDY=I5DzHuK^tER`$2cJ*z$Lf zQ~_f`=K@}HjDL^3dI(8$eT^x*j)m^tJkvybpVlK{9KIIdJ?RawbRrskkmBm&dtnzD z+)7W0-+a*y*1%@yF4MK@1}S#umPA+DX*_@TOgp7tJG4y78MRhh34v~7la+n$ED&5X z`!;&ZU;YB&8LBYA(_~KR{yCTSHvitlXqYiP4i5FLK!`Hh;I;M(P(Y43MrS9Fp(Hlu zc|ZN<5F|u$T<7ohsmo}X^Ax#ZL!<^oHHaxv<Nu)q#udr&yat8<!d{3xYH%3e7--n( z+Yas3*wg;yU8C=PImDL~7det>83OMu$uHlinLGC)Yg&4zGuYvWhq!5J7f}@!D}ueG z-{Uc{sT6W7D;g=z4(B&m8(&jCKMZPLoQjBsI|dF{Q`tJ8@j?b;pGSSVG`FYL{20{Q z0ni?I8$!;hEWap$#PE_VlSmk_x-H}CaofOOW8?S!{-29(!9haBm~f&&lZ+LC!)I#( zf`X`#;0#I?gI)?y^c(beYQ*{@B6f@hCJA&=#W1uUG542)z*kL_F5zi3lJ8ic@m=FL zipwxJcOT8UCMYfK9p7w1V?WfIVS8;4s#gijSSg+uYE>x!fz{5;Am##hkF~Fn*m&B0 zDP3~sZoi+}g0{O*X1)0(^imT|k680yP}A2;JHGev7>gDDTjNF;Qe+S?Eu=F)nwd%K z65+@ht-ywU7m?U>gEfm@6YIo#Z(_lw$RDcuP*X<Fr-VaA*}Vs%*C{p9ZuD5|=e4b9 zw6fOZ>&TnZWKk}CR`Q@T-aZvB<ogvOCQ^^!)xP?gd3|*<$;Ha?Hpx}6dbB4{@CI0o za!RN5*LV5joMhjZkpB@aR>vdtLDhvbI>0o{TV#;7;2NgF8LV^u+Ge*<=70tFAS%P2 z_VE5(wKq)E{VVGI#uZcRgOYYoULfn(3C)jv-SggZAzxjJHyB<B&f;Q1^>+b-ZFJk7 zf<%ENYgIBGi_=}5%^UXVQ>ZK^gV`9qnfZ_LQPcaZ6=zsb@B95tMk7eiI5hc^sn4?) z-Yg5Bjh!%A64uuwGxVqCXXe9xJaYRG(td#3X9uJ5``2{?KO|NWQt!pdXb0yHL;{+G ze|M*UzuqO|yp3|BVb2wC;Ql>^Ht0HQh~Np@5t+*tR2c~Ddig?#gP6I;b7Wl-0?XVM zV}>(&2kBHns8r#pOqr|8zI8|Nymc|HO4F%Hd_1@-);#p^avDvq&CpFmh>K`*szx+z zkZJvp2OVm+Xf_X1W5k+Zem_BZGoEC^{&#b5cg1-$L6O{Yx|B863=&~XX5?<|bn>2Q z^sErEAswRCD|Y8UWv&SowOSP@GHKpgcUK@C&L2=~0)f}RDOz2yuAkCO*Q}!zJ6&Yi zY%iV5N+EXW4&y8c_bp6ZA@wYvkyq)-M{4L?!h5zCqb^RH8Nj^hYJ^catu}fAWQ#R{ zG4@a?G`7S%1RH+*1cI4PuIK>y=_U_Yp?yS_#y2e?h^VVFa={vu?_C6QDodmPc+8Pl zk!5A^mLtk|e(uc8BcPm^!i2Atcy!mf0TEfzDsS2c6Uep_)?mVrhI_PiVNl#Jz@Uwi zO}f78`c~v552`0-P40?240+&vf66X3?aC9)|Gb8La=wj!Ugd-~J8b?5o@tt0mLvw& z2lHF)qHwAlrr`g3X%gqv5i-_~2;TDSo;+e)4Ul%Q{gy+tetWQ3ayA}WqUe=JAvtJ~ z&gm_~(pYfxS;vGzFg$00$b5h3AO5}Vx*AZUy-%{Wiiy7F2y4x<pJ?JG4M)Np^WbTf zR@6Z@a*SdC&kxxHK96S_n0yW}8V2l_e^2^HYRb&?*jihF)%iUp6%!9RhFnN6Fbodn zW~HCob3gpfa7r$hOMiiK0IW&%*YKDo%qi+vLx!vbsh$abTw+abT3Zw&vT0zWn@>*s zmOXLB>i#-7+vdahWZ~WzD8HRub9)B~cuCpjAU#6Mp?$r&aD1wn3;}|W<W>PNnu|55 zJXEEG#o@cE#+sk7Uw^6sa;+Xg;cGU?@_#m!YL}UOj5>|QpdT{>?9MOhL*g=n(w^wx z0CziBovGG$a>Us`n;~k&L^nMb%W%gWg$zf|T3MA_YKM%5;=<(0{D!|J<P)L&VI^0W zc3=y#vk+j7?Q(E_oEd<)#@%Iq$*s^c!~q{)`;|xp;YwT)DpZT{2!9_&G_^&wJxyEz zr2zCGCmWy~etXg*@Occ8fOd`F$N(jGBg^Pm?4ddH^N=K6qu9b}O<sPRR{*UC$1|(t zA@&}un8i1Eao2H=xo2nM7JZ9mb&5~~21404mER{rIQ$TSTiU<$bcSf%7SVaV&u(3c zYO4WjoZbHwRYxR%*ngjajWINUX@Me;gVyKs^?R&u8s(y{|Lr*mAe~Q>JJvG)>lD(S zA>r_sPcUXrY>Q*Nuwj%Fviq8ZNr`d`XY#8f#k}7FUNMwCud)7~?3>)P0p;Bxiv)#* zWDYR@w4cHWwZy$)U3wX-1bJ$oakzL1D?(7jRxp<O<s~74pz~M68Dgm?4K%cgaU#L6 z%<eIz-Pr7m>P4OFFfmwCS23d?G+m8<mbSf(`UtG-uc4`u5mpUwY&G-0O?_AXUHpbk z)uvyu-R`a0J0PqavH*(H$+wW$(&!V?L5b3{<#Oh-_}q^svU0lSH1Nk_Sj?YIhrslP z>UMVQEK@Q<Kl7u6V>$paVYSu3b3IumbXKaz@j&a6`5WoeXF5WER?c~b?L(e>4Ls?R zd6;_uc2)SUFot_+Ta(<h^FZW#P)!DsJ2%k&@oK(impU$%1WI^sv2H+S#P(}=1QMOG z1~Vx+L-;^HuCn3!ZEX1#4&IGbvlIX<>A{|Yt+KV#U{C1Y_v0KoE|25dDZ}CDViTrI z{%_Wi>Ea=>XJ%XH<2WgR4k~lAZBR0d>Egr98V>{U%86I2Jk?<Gip9nQdlM@2;<7g8 zZw6=@9d8w;>%6ma`~DgeM8oI~T?PZ%i%FK7BKHj#`#U@1G=<;dWz3AOu`!p9G=2LW zyV7l#u=Xaz;f!~GlB$O=LLvYm)g-j)^x<u&mK0)T1!deA8nN6JQ}|Sd=wutts@^Fk z_^N_(M7+riF@poKzED^CFby<l0xq1YO0h<?W5pI|t+&-uxWO4{Ts~DwuDGtk++AzF zULrSQz6499SM)pnGJ7$cYBYhR@3;^}*QS*B=BaxV{<-}OcsGIsFGwR8TZaCR8x>>t zde4<jLNV`P?n_W!vd$3-Y$s{CpC+VP{h@1{uTr}vzrs9eCt96ojXQg?USCDZ?z}@r zIlo#ix#=u|{+;85ss8ILGC(7JubD#4Ln8bEhpFSaQ>udoZuiW%?F+e3AhrF_J;#gE zI<y>2o)vPm1_iFZ3?O8Q{$Di0Yp4Hhn~Z@>LsT|{>U12@H~B360FLZ}lZbVO`$zzi z2@@Q)2`(y>f%i`)W*dVQoG&0zL*ZlM`)f}_ZD`&~oAmjM23sfMwe5_{(7}stU`}ds z2Lc8IfPVoZl*+#%-t%Qac%ihlXfmtYf71g>xZd8U!lRzw19vmQzhAo>0dj+dcQg0w zAC~o`xd*G)uGs?X3Eed3Qp6E|yvX=ql`qhf=2zA@{W5^d05C@Y2%jE#x7zfS+&dvZ z0m?H8B;EBwap78bzg>y8UVzrSJ;uI)5aVW%i<72HC%80s*9dRJ(Xene1-tzc`CQ=S zg}Q`Drj+IHvqZ7)vabE~Ahf=d_B!3A?fXvL4V9ap_qY}?&>glNUxiD1?xTo0v?boB zs*~GL+|PK|FL1-pa94+E-940<VYRL<+K%Dl4jyB(1e;=lhHJ7_0s>p-TFvVnU>Dk7 z&vM~)U(~_<{TZ6=p5aUy0Oj5~q8b;(o_!!ds^Ao@TI<V}qtoFHv6cOon^+LgK?wHy znxw%nC|Sy{c;Vb){izFLnZMr>DGixJT&CD#49W9gGnXl!Nt$r!qc(EsQlDuW_vV7| z?Gogh7*ZEOn3YI!YGZh94@SWZHZQlXOcor(ep15<35%yX|F&#SIIEGeD5DA+oLJGK zWVQNrWSH-;1!9_O{fZ_`2>$(UQ|&lO@Us!k7Z1j(R+jC*NqWNutRR01bGZ@9suf&T z7Q5OAXo+>c;pZ!vy{A7w=AqqGB{wl=Jn;59?FYJT;ZS8_FN^w&a%?beds){HMhgmM z+JNHwG|l&tF;*YnNsUJhjk(8bYkV=2tK9}P+=tNQq)F1vI2eO8+44!#x~Iu#ica!W zN<B390bftj+NhN*;YwCJTXzN_U~&R<VT`zSxX67}0KysIJ5>z^q2;=>!is=Y(LftZ z+%QG5AZA#ykVsl1vj+rRa(dqcP*?>ah(zBY^&}^I7OPcuy<;CDLicTC6S4`6_Kt$x z&O%UQL@;~SjgeNjeTAXGq*B7ps9}76a86I+3JT|}l#6SAeupB3`~Hf5wReDWyNsi8 z)D+EgeuW*Xqzbd^PqWw<`4hgwK@mM9_UumJ-4)6a768@2U$y_yL!naF*$_eJkfVV2 zP|fE;LXx&HC<GWlN*6F6K7Q<6Zzj{hpt<ZaT)dAyI&!U1C{fhjS*svpi=3o~^(ct9 z@fdbNgL3$HkF(6G4qOjNx3km#tu1$ZWjFP;K;R$2Z+h?Lk305Ujjd?>+R`Dtk>q2j zEgu9SR2o8{%OCZ*>OY>`u9|r7Vx-8qQ5(zQ$>l82F=EdL3q{`W<M;LJvIp3G5S;f_ z^M>BK&e@!l52|~*WtX&Xv8=)*@BEJqXZq%-NQgN)vub@<Dpg{a`_>l68@L=7VAf8A zsO|J=x>Dc7mh-N*09TZ~{7J>Tl&UsPK2`0)2G_iq<CtW_Z0^L})BDGN(C-RX0o18u zK3whk=)F>kwmkUMTf-<-Y}-n8UkG2szdhSwQ8*5c)9V}WVz5CSrm7&BHW~~h*<}V; z??CE;V%f;$l&u-kR~oGJSxULh{x1L&K<mFe^`HwCTW-AOtcSW$b^}|M*|f;|kS-um z_B~+7FMM3G^Y_!Ij~oH>p0$8KaNsj*=&mp0Ou4;-S6G#fIWG^;wGTi#!fIv#Dgcig zI#`_s&;nq9B|s3VH|4u#j`LfHYpugl7}~)L2r(Ss1gq8#An2H%Q>0qfv^M&gGIbZY z#c?U@YP}K+a@H|6H+H3ZP&2?1*;>U|Aji&K>cslSLx9`;F>C(-St2T@RJDFxKHkKd zwmq$1G{DUb`*x{^=kWQ35`m-N2KEmL@uS}*e#_A-PBH&@dJPafM<*<u-wFiz%o@|a z=j@=Sa#SeK%o98d-oEwg9?aNV=>Pyg07*naROspF*aUv|2U%!y&m}}S?WOf^vB<-) z4>*r-AD#u^&uMS=fsmVeVbTsOA9BFJ$bgDo0@NMqq@~jhHGVtTvj7Fu>SnixwH8@n zgat6#&L*gr;LkG!wW7)^u)V(IYbrOF@dtr<zWM(9;oHkU4Byi)`&cOjftlaV4?*~o zOR%Rj$9lVerexaHeCgy`aUIe7yIdE9v>Yp*RsV&2!PW{6PePx!Q);P@HT23hD&KfU zdY5OUmC!CNNX1a;>1WSYTKS|^_9arjFN?H>Wm)*f*t(q1){&Rmt{1qLc@$Bc@%(BL z>sq>3dhd^EO>{1Oky>R<+$GD@EJL1ALX6jnnr_Laeg%M28~#H=Qy2C9mDHuQQ9C-1 z2aRb{7x(;xD{;*8HSo{g0@;I;mb_o0e+47rC2ddTrhd1peSLb(8(&`gKjei!MWofw zXSiWq_$^Wo2I;=!xTIg&L_Ekrk)?POv?@qqJ(4216#_lV$@ENV1vj>*ypgkXYGwQ4 z&6jW97ry)j8CrjCc;S0kuxJ1M@VCEm2=w2Fn@gsEnHCg`E%+SRE*k~Br*i6;QX05a z7dJ;7vUV`Q20+I%0$unQ?|SqQtf*J&AmGUj3SsR6oY{t+11N}d8uJl;r%YoC6xs>v z^AcQL4Ubp{U8Cng?ni(Tk73b%Skt`%8r>0j9+2x7L|lvLl(4`|E0`NV)K$RaH*mFz zImK#!XjOD=q?X1TK$@V<4G{A9<&HBxh3ERa*KCY<I08UX-z#=bBMR#uR#e;ryn?gX zwd@o+aof$Q;M>rHjTs(x4fyk5?Kt4tM!`8E1fsG2&_1)S){lNvhKFiv>11X+z_nB2 zVL{}RbyomjKS_5B5Vg(yUT~b-M+*sZgN7gH2MV;QpGWDiJQ7*CK6JrXUKaO)NY^ml z4}bdezXrf{sepas7e@R}vF(@RG_?-p#|vp{4Nu%3jh^FgWLh7{texyRn+(6SYd6V8 zv87bc@JyaD%NWSa71a+n28!@P-|{!)eIjXD_=fz;OfQQ)QKqF-Ne-KIW1t8d{T0#A zW?jj#QT9rLHyZNm8Ly<T0C1(1etUwit$KlF>D5J_qYFLjLshS3vx9XN&)C=NKYI)0 zE#3hrZd|Qx0R-*L__dpvm#oLJ_(`z5wMiyuECSr_MvTV;Duu(E!~l%Jn>;2*lt6?j zJ709h^5=6Teli-442G2{L7j|~HwuW?JcJ;^uU|icqmx!Hq*esoGp$~_5!LbrM;-;^ z*awV|AeivyBLDctFKhMAK7JV9{rxY)*@q9Y+f<<7#(=x)v*Ci5zA~KBz2SI~>t=1b z=D3mVE!Ms<RcN{Ar>DpyKji>Jf~K`i&}M#Nj$mmA9YQC7*UjP@3l<hFK#ROiHwpmV zEz5#Cjx}M*cJ~d<#_nBYxM4)gpJ(13vChr4fdX0r)-(YW>)`zC*(1}o9$T|d-1b%v zr+GcV`2=A1?c3J@h~9lV3+vgx{_(q5GxzD!IrY8@t5<xV`0#;gX#l93UjR-5F#(j; z!XrSaQ@|IjvGc1R0#ZJ*2B>8km$!!pKks_(-`+9S%RSZ)@&ynqtjDYc+@^j4Q#aCh zw2EIt+1)*+Em#xCKiB68_ypNb1K-?oej;T)(k8Z%YXY%PMm{&1sK>eA9tQjgs^!s| z8bFZtbvKJL1*vX~@sn~MowG}PkGzJR;@6aWd;T#thd4gs;BV4hqe#z1J9CNq1$8>N z6luINHWrgBT)`PF)3cP8YuT&(%SA2od`@ghP6?k2n9(ab=A9ErD3YRzPg>Bq6s;9y zw9nGW8@=SMXW%+v)rOPQDfC>S$=UPw`prt4bnG)s)Ckq{X-3YpCE`ZuG*A^#JiS)g zq{-3J;~|T1h(YPdJ)hweom9D#m3w$ex37`kv<0GL#?Hwbr1jyGdQ>-#Or0PHqA$T9 zy+qh3<ZIv`*#dUe)US1ec4MNwi2?}5?F)Bg;=+H|n5E+d%7Y<djZ{g+F+OM@i~w+5 z<&}?{w6Uxt){C*RB-w&wi3`^%Sf(m`43B{*<K-9g=~O<2#uO~!0Dkxaj#&K96z(No z1GzZ;G@O2TH+=fxuUND$*dQRRa4L~?VpxQ3_@tX4OR#kd0271>Hrzzvy0<;nxy6}# z0Lr_YLx2td31FioFwOx4`njn@oxK0lP+%j-bn19<M>s5h@FPnefyXZWw8K>D4uHtb z7V$+5&&G3#7=YtiKF=i7lI15!1kSl(K_KH{%ew&51fsSGMY5idsoYQIKN!AydmMH8 z>BA`ij*Sq1ROPh5X=RJ4R5I;TmY;0XYI=5=)8=lfc+Dr-4m`F7ta^$i(8ICijm}1n zlfe5}G5yxB>nCl`I7Iv0jVrsfiMo5V3!oB^?XG97l8+ph1Ce&%M;p?J5x!%+Cc*;* zYWV|OhP6=;YTxG9SeOc?Up&ZKJ=Dit-=0Gl;L)}fcykQQ0f%HS4v+)?&aP`8nF5E; zX=dx{;ocrm6XS(`iqHMokT~t?UJ(~^gShUJLvTv5^NVKqb6n;7oIKC+DzsPX*$gv= zUa69`hUKZcHW8B+z08@cS=77fDbX|b)#y~{YT8RFec{8VhUz=E+c&`4g+E&p-_ zmSZWeZ=XspKRGsCxo<ZmeWm~UE#TnxWnic4XYbQ>L8$WkuFT=#%UAXo9E9T*;bEE& zRbN6F44~&DEQe4@`|AIGS|EG74U6pURNf&G4~FRcV5l>r+6YO$b}g`$W5%p-`5%9L zyecyon#^ShQCt)o^bEyyBwBKlMleH_s9(Qcur%|nb44#1$rG`5$r1%y!eYmKg06e& zkyD~KapcDZUw?4g*O$H<0o+Y0coQ&eb3BVcO%b`t#tjcl6}o;9(B(nHPLb}wf51^P zkFVbF2i7^CkV76|0#p%ya5>c(Rz=DdhzSe@L~&c9oBb1C3<2P2MRUEH(~VB+%ICDI z)3H%C^bE@w5uXm)IZgM#XaBgn1FU#=pRhUP@t$K_SUdQ@`7j<bt-OyPJ`Uf1_f71w zweOFaGQQ^6lXG_F`kc{X_U6q=Oby=vg8ahBG1I=b=i>2fc))^pMOi1uY>EMxdd}g_ zr&G$px(4qRb<je12RJ-teWB|WcUjbT;E^*YSoapM@{1^x=VlJUs!l-ddPfhZb}Bj! z(vF5FG1^UQCvCz8oy7w{)pGrj-#R#k1aBXhD*w^rYXsQaT5@S6ig0RK;Ao?}sU|Fe z&~E8Jt$_RR?UR4^h_nCRd>cpH*cMh?8FADP?PVXt&-=p$3|G_^)vF;|q*=V(W+`kP z|2kR~H<vl5SNe<mnPM->BhxIOI?zv3h2&{2{*oju^ekmt{>V2nR^Um0l92DmikDx- zO}fl<ZPMd86y>L!zR(~y!aR3z+lQlD$&iWuVK%aLfi5_T$Uvq{>C18Dm5b0A%|Nw5 z@#q)d$l7$Rc(qsM^~rCpuK=)b#osV&$N2Lj@)P)bLV?QA@~v{h;M<0mM_58!a7`ck zYOGFQ&GVJ=&(Z>RZ|~wcYnRRv;)NuQPR*N`VBX8w(WF&>d(-#%$9I_tJlQJ0<%Won zp_5V4N@!DZ7ENjhF)x95;@~T@S0XrN^f#+qN_qNfw&uo{GiBt<R(Sv>z}U6ZzGtVy z8Jj=OK7EL<LAcIK3z$=-@y8KUm)HRVoOutr9l@zsh1~<P_OQTdDNHq8zXsr191Qzf z?*K860z7^KPl1U*tzHGCo9oZ4zM5$b!xqNwR^)H*Vez9f*8(^6K+X|IlsHZ5hLTt_ z7;R);v~a2u5EvFKK%Uk!En|Y(#|1l`;n`;+i`J|U=eZtGtERy5ko9}=US41Yg!Y#8 zdPe}e2R?fzm=gqPNm~Hulz)wt^#1A;K=d}cNq~5SjKwWhJu0J>PwUzJouEvR#B+w9 z09C%N$KwICIb2)-cBz|3yu>q!JOV&1h5|e3E)lSOxJI30TAr!+JNjWKrk0uN<yf43 zz~wd;N$dGQh6}8)9%B>hDxt*z-O#max;uE6utSCF0#@N;7r5&d1&H?X78XmNy{>bN zr2>G{n5ssn*ob1CkYL@u#F^c`U+Xp|H16lp*9!fWiBTaH>l>yI_vJrT`^xjOO0JX$ zVL9h&S@9eyb?it7+LB9-x@RkCjL+GN0bic{*Actmm~{+PViHDj(`k$sTk}_I)iY!p zmcA=8TIP{H3ah|Z3t-=xzggH0@yC0JF&URNgR`mAnDv$%eVAh>J2S2Vz*x@&2;@Qd zz+tE{?kUamukM#=0sEqF&+40=RwY$h#lv4qOrg=ITw+)(W$GdnG%u@qxTjZmrMQ+b zrx$-$l2`~w%DTj!aY+~v_=ChtcIiRv3qMo(++PqDKnMzQ8a6C{Y}7bA{W$!@l<#|X z{a&17)e;Ob{d&dD*o%u#+<O2Fc7D3>UqBL0v;Y|5Fco+Qra!F#RwaN#Y_wqEon?i! z4iNP~T?7&4*xB;<7<c13RjCz=^<?lSFby%oKERLLGC-Sa4doLA9RSYU^x>w5?ErO_ z;n{gur&w(mgCP{;nSs?y&|>R4J*|GO-Sg07*Ua7BF%665&4Z3VVzo=_9G1D)$DGy2 zr|>Qx;_E2N7IcD@&=C-ct^y}5ZGy9Vrp51>lD$07BWO-Ix<=kl>=eGCeFdYg3B0_x ziuHYhGZxu}4A1BbYb#T~@r4g`7O=Wo+5XW=Dd@7<ADJpnuuM8&QLEkpkSNGo#QA~f zM|C~h&~`s!ZQ%*|-(a2e$QMDozgTN1h-3YxBW$1P-yC=DE)EpPI!OD9b(Cjk<k{vd z!1u%JH*bd1Kd=+{yYB+@?{W~e2U6#eKGD23vCZ8sZLAobyOA#wB8x%lGP)d6V{|3Z zv96^3YJ{2MdDDMJX((OIGSk1FODU`pi&<)wUH(*TaTnK^(kG0>rvuB+oWA@foj#h2 zUE=Bz4c5=xWA{!0$!*MxUPtJJwNm@qk7DYtkMSWAQo9@(AFoZ}*ex7I^yRcJih?Hk zR}0|SdcRG;ruWAqDIU7Mb6Ss1KBRC{KNV&4BdH%Xq{OS0hc17fhgHIdSnU661EYDP zjIV*uYk}&H@+<c|UUdDHv=u_fO<LUi&3}s3T-BfQ#j_#;6J4H0TGfNxm0!MR9n2f` znH6F*AN-au|5ZsFr4_@Ae5EVNsZl{*P5quR?fdS>zjFM`dv?n*b%`EY>+YD^Jv;k= zxr#%M*|@NaC2k8OqUGtHdq?20#We9Q7N-Lam9|3!hyph-R#Zpua{$;9S7=S#1x(3v z4|u%a@%WM4u%JaLtd0Jq7m5l1dC^eT4d{haTadpPUOn)MHY|$!yGK~-uyS$VJ_1l( zljhW<$EiF5Oa!gg&#!H4p+i{i(1Y#5aokBvB~!=8w}4RAKfe3%$Kf?=`}`!FyL7KO z*5w*dcYn_}da?L9X4G5joDU>{-!>aCtm`dc^+B-Ad4I=8930JO(`b>ftUj<f&kY{7 z`7M^#?FC=|h;1=P<j*5#wmo`AIq2%omy(t>ilZz*p3}*+#r7V%g&P>vI{OF+T)^ad zNKh^RX+!eR!tlEGG1o^PVHM=KK>Cv<ityUj?re6w<RR<+4$;p>k2RFEpF5<lIdW#3 z@D{-D`s$p`J)Btx$o%Hp?}qRAo%mTe^xxrAb;5zAJ0xDhD(`61-{2a{+R?q1xIxZu zPOiHBjDo8<o~>UoT1JKY_MCL+MHOdg))M;k=QLi0cC#Fe<GFjPOy%W2a#hxlQIUy0 zQCes$Yf71yy*55I&D!L3#44e$ONjBtZ+d(Mfa_ZBSD;mA=-c-3<Dol6`a<od=&GK$ z6rTN2Fv;QJy2U4`Fah#XVCsd3sUXmYI)A{2Q}RE`S^p}(+GHO8T-{2}m~T#~0*Yat zUi4@DKAT~GiY|JE`{F81(RJ_l>C$x}t1%Z}pEtRx1Y?twky<1&);%76<1Tr{)=Q~0 zX}XbzfNB0lT8jsj7kj$qmq#T^X8FNKx?{Io7ev09mnp`Y$jZ|B05>a$i*xAk^V4Wp zg8U;0S$==_kZ;mzb-G~}ugAg&x=#2q$lJHyVFhDTD73p<tY&^PjM5G{qc09i29N{* z0d(0XPQ&_Di<l~;T-TiWi#3FR3$V$sh$Hy0UJ3HB@?Ep};)dx;!J^hXf7U;aa^hZf zUEqyp6<+2J)nnGDc_y8kIsB4_-!)d2WoFB09pv7o+8&TBs5;_vZJu}M#uwY~H3vV7 zId1`hcTCCd?wkZzbQ;)m1aFY-AB(nwU;a=B>tJ5xJ}Uo_-ObjUa?Nu`Ti6Kh?ll-| z04aY@OB-$I+CBM{yALS!Kx#L9xSr2xUuCIO9LXZkM3$CEcLxhxDUn8@J(;3CIN|ei z_7}eg>g2P_hu7i(aEJ^+acp`*=X<QOv9=KKXZ!2{3=gTNmQVX^2OUX@`o%OfdZ>@b z!MywN@1$W(eDijA^Y$&@F6L8r-+ezEu}0Kk<p>t!=5y20X$dM*KEZItam!xPp1LYZ z*Yd52Bx!}`NzO<d!E2RKGWvLmq5P)6JT1r&gWgw8g1??t!Z!JhH-$}kH?fcODkqeP zd?jgQ*$~jG{hV8QN<Ec_H1CqCcih7*x~{BAb}>zPl`$`>YG~Vr=A-)62Ie=lrDt@h zD>6MbEO{lS;+0MRD*)_U<5vn-2k0+hzCNKZd+hHq(5J>NWY*<WVvMLQ9>l!TNc55F z^axLDrZl1`Sj@A@J(bqyDYd1Ur;qo1o5FMcKHi5n<?rdA%WvL3&$IfE0H@D2$>^yS zE`LeSj#$BJ?}&3L`j~Htp{PZyc=}7!7Ri^`)JHu}h07lcue{6RBetwxDJ+#t%ZVA4 zHlz3PbxGrkt1Dl=QO}V+Q4IM-j|ay*fWiZy!%{}ZEv9&Pm`)YnT(P-9P_&DM&z+;L zgA-icu@3JRuy)0cVKM-)v;t|>Lni$nU#h?&=FVK#1>W6aeT(}`#RM;w&qLWCn%eH( zi|&vGLXxIc&_B!)xcK652QYu50o?EbI@gzgQo!FHx)yMH^yF!*YXZjDO-nxYb*k2B zO~K(dK*#g_+%#dCf~A<k1^ApZJuA3#iq*RK?cCcNzM8=iFy<8~#Rd&5i?*AcWm}v7 zQ8X)s@+{kRe*#a}6NW{UG@mN2r^`(^SPbD4)cIZFT`Y!{w*b)H0}|tF9s<D7&na_2 zpnQNocl$=0nFjwZ`5qns!GLGMof~SRWzo_068w2Y&6WTVaDBtkHy)w0%Nojk+QQ>@ zV!bB1M4hOgjh#S_KZ?=Q^@H#K_Wus={`$WUuK<9@uir5JeS*$>ZjZ5Hd(~P%2cPYl zO4evBANnuml=(9EJm*Zm$}l58U7D3HN4R9Hxf_dXy+3ALpZqL!(&I}d^+inptx08E zP0spOJUP7<$?+Jj2vf!+S9<v)U*;R5vwRh`##MUKrZzCXl3vLzQ=eW*DW|SU-R%qM z8Kw8}%2s}#uW0|F{Hox(MyRxBD%`Ufjvp60Kc7to=0YfNg|^I7$>mQy1to+70(tP) zFp23SAL>4I<4N0cbam^3V__4`&{WzK8d-nQfbz$($H0;bOXWSQ&l3!h^hA1J@4nFG z7U@zp$O`_JrdQP}_MSFMtHhD894Hyf)b+7-yyHWREP{mkD|P~5r9jJF(KZ$`T9R8L z-pJOgBHP3g_3ubM=L^FMn<S{eKdn4kk30n0b#R|Pas&*Y{`$l*Fzy822H@@R<qs`t zr>+IlA_Tb6q9u3}IG%IliMv$Y(BQf=zcu^7y1Rvd4!|O~IADs=^YXNCC6IA-nHGY8 zfT0U0g3o#gCb3MqZjXC&2ebobia!Lwl#~e2fDMR5x`0I*mN3f!a0y6v05={x<H6N& ze_IZ~OkD*kHf(+t4Xc-^62$1#v!w{&0^A{6uq7zH0U-P3kbC0h*2<-;V__bdCS|ur zfF7r1qm{|?xW%+F8#DF*)dSx+R-Tqt>+PY>L_;3|Wc(qz@Y}*z^f>!Z>z{h4uldxO zN~BK#YT)>DI^E-Mb^vm(+?1jPPYWbIDzUUhAil#6XxBSZH_G?3cz5)@dbz_pHijUp zEPh%HZQ(cq2aD$x4gcr{66$%#mtZbG{xtmi|NVc)Iz!8H+<g1?4VKhb(Ci%AKm-{7 zZH@J=HRJlko;ou2vefZ;_cE?*&$zY>j;YZ}>!LxQ$AdU8t(YddeLuNMm(tTGj?MHb z&$7%eFYRUttCAaKHKEI#!BO_e+bCnaHBIXyJ(IfRh-Gq8`)lTI+%Q#n@vJR!NgLx+ zu4=(ZVytJ4i<)&<j!A2+(&QyqN1q5(r11uAwh6@ieR9S7{Qv(7(;D+eXanP^cBp>n z{Rnf>??v?O{gljk+6Kdv(z5^`;_*JoLIr^y=U_gbmEoE<^?4CmVM`B<i7V=mBc(Co z&9X*<bxk*g*6|fr@0%ldD=>*@DHGv2nG@$!!gF~h&dniZtdqSihkaiBec9`1>+(zM z^A%6^WySSJom!cF+7uqS8i_~ESiqE)A+G#)Jk%pC=nkf22;~w$%ImL*g@xxBE*^o6 zIC&OXtP}O6p{^X|6BW?;5_ekl;{1Gg|I-h{yTASS;p+4q#x%}@+keIH0Kj)UTzvQm zkU+f!QveLXjh}wI<lMkxrXi0GIZ6dkp~Y?i{gEk1QIWvx5zCv?lXqC?+^s55s6(4w zdmBI#@Uy$au3`A^_z6hdd|`dv93fc5Tn2EGUl2uGXmR5gXXdf1cZUUVcho5kDMkme zjQlWJS?4y<OWkvmglh-gaN)5m9(t@r&S_3@qVfe-0!P=&)s(T|#=Z|d2(xlT4Z}+3 zdPmDrr<k&B<qOaRci?PvV;YzG3ycq$zK&1Wk$;;!TI4KKk@j_*8yGUvvKT<twxD8G z$@1Kh>>A5`fhK8ASzqzH0krL)_bwZ5f)4Nl3&N*x0if-jYa8Q?K?RcEfnodj9bmr; zZQI7$&AlTwfxI0auFr>m|3CgW{y;b#PT4$k$-2h><$wM!VeQ>w8ryMi+blm1Df5e+ zBf(bDf8M=}YrUL=5|-6m6>YR5S916(^gfeX&o!#_Iekg$hDhdFmD$+6xtm*Vv58*k zoBUCBCo6b65mDt9_jzW}YmyR<nP;MegzhqC4zB83iwwPIWjF4SKh>*B>%?yCq~e)! z7bX3u5y4(&(fEVS2g(#Jwn;=OI8nYVls8eY%yRkbq?Zo8p6mFQXrINrlyf;Umt(vX zTIL*M#nSr`?g%Num)1IAGJd98%7V<bawnNS@GFbqbuM4omAI;BPwB(sXdZ<sBX6F9 z0rQ8c`IBqXE3#Mdl{m_Ld7wmW%(0GPsY2^>md;D5C5yyfM5$lNOL=CI%{(bF(t9Su zU14L=7+6kE)-J=W{N-pp>Qb1wrko{-G=lx(vA8A`rd%oCl%!Q?;$7CDkC|i6r-es2 zC7{vr7whMEiC?p(@1AL2KK{#whD$)7yGa2$Ow78*PgEi(djw<&7`6mc+&6dZfW5kW z9L}Bc1(4i16^pKqk66`FKp^ENgPkolZ2)f4<pI=!MJ-@j4g;u>_yF%MKM$AI3KnGo z5~D8Md|ECAT&!>lpt<mP7&fE`+PqI<GZ!>BUkF@e7X$h|T@P7~L#5Hf>0GC%wek!8 z;`_vauuCkO3#L>L(8+WAtgFCFU2HS0jam>X9tYT=4j$>^KYa^y_8{(EEN<Ia0tI_p zG^Sqy32=%o9%pkzJr4nWPN64|^XQcX$T8g;APq1T?Veyaz;LvSbxU2Wi&j|kXbHT# z<4Ysgx5GKsxl20Ie!4ll8@^$^qk#ODGq0TK-A0aWA6Ck+HUgkI0_KjXW9zsLShpUF zMgEcC_l{i;_;B^#m=ZsV^AJDrjo`~a{wc<iAXKYlJg1|>XmkB?`PWUwUf}ncWuM14 zi*S@Y#cjH76VIF;YuFr2xVXwtLW0^|B6Ey@Ml5ONOEz=G%kSxxUWN2L@>RU~otHV= z6K1r2m`7LnGPafi%k(6R$jBVBI}ybv$#BG5dU!Pe^liV2!x=7_a?DJGk*(OP6*5z+ zMMn%i;xWW}dS#gVoi0riI5L#i5>lz$=M^kj6))DJ&wU>Ux@xR>+_Y60Ie?P4N?Ok; zb#lq;HD#9MUdF`zi-e+x_43<2^JFn*pY%;u<BnZHw||(13t<qKidu>^M!k~Sks?_9 zm5yI>op185SK|3236h-tbermv=_NaPy(Wc+D1i)@B;qx?Tef_;ReAaH>dT&_z92Lf z(}ceu%S%{Rq)8YXrBbW#j0cNst$^aH@+!TWL&oBjXQUJE>88b@&IVT8RLZDc@yvx3 z-5x4spjB{`)GIRPAyD#KdOmt3Rzk--3hQVsSV?Pgb+X!neKq@9O392wB2HlnssvcK zfHf_Ef+9cd=C02}z|a+zxLY<=xQ5I#;sgj<iv&Rez5p=@)DmUq+yERu0(Jy10tYus z2)4EgNI=&D_Q+JI)<dV1Z^^gKjqTSa;^-KB$NvLUp*MgfH=;aX!4iDM_#!Rt4?EL* zOigYrI0Tuw&Mm;E;LGQQwx>q{mmnAY1iTMS4ZAzmsZlpIP;}HsFsH>WrY<S(3Lt#N zw~!b2hr{7FZzApCfK4ChYkPToj+vu>;+X^hLm$Cntby~{5gJfe%Z4ALWlY05o%@LS zEsuH;VEJh~K4IrhTEc=vf3}6~7hsAuiL?4FleSMVs^8uu`utp{xrdwtk62Fu=T{tW zqh5Qg4Rq5=?6y9+3*dWAzi{#nx-czH+gM&4z71NpyhlKz^$}oZnS4tbVEn-6=iDWI z#Ex*kz_KmacRVnL1jmjGGB7go7e{Q2qtdZLBpPodJ`s@l%iO%ElGxJ?ucH?&HJIAl z3YZo$#z3cM16))73YA~H^Z1-z>E)Z=hr4*Rx$&%7aV5E8rmwnIvq|#E-U4I1<t1Ki zHs#Gw#Ya6WZ|PTll~(cci(YD0e&SuQQiC|*TeK=B<@ucGT*ZndlkCf)l;34)!R&FK z8LLUv<WovDPEo30wVTo`ETP>hU)E#FmmKqW<(s&(0;_zRD>lja$A_wIdi^8JMG)q@ z#%He2;OJa>-WDy;6g7y^U@m{NdiPPo@u!05&H^-bXytJIN=`FLjz8!X+{DeslqpM2 zw%$cC5PH7`oMUtx_hwQJ2qD98D|9Zim;a9ltB>^=ow^1gYc}bdTwdpSrg)~>uKhh5 zk}`V~6Ybu`B?eCvHcN;c(`7S2oOmh}j{{^{AEi!u$}ume;-SQHdSvv{|CA63qof)O zO3#OkGJC2iI`WlLNqE_nMlCHPLx@+4T(hRNM(dZ>BR5A}F!p0Z2sfKkfQH>&dymB^ z;=JH<rz)R>12k$u6l`!8p|;jRrb^}IPTdoraa-+i^9p|Q{>5?#&GO^;5YDx8M{<0l zmYdCfUU>frN(lQUjrb!8o>*6AJCJwbR5ED?02a@@i-U@h71PWE8$rmw%P}!|f91|s z^;O3Qrb3;fe&7tid&*RILC*o!zSuy4C3Fk$8XHN_MR0gR+AaKoK!H(xB5eeH09L`I zR?Jw_2TxdxC@*>30gX;t9K%8;0Oi1G+B__P0RVGThSRw*J=@B*?RJop8`iA7Z9p56 z?lZzJja}HtR<9k}-FCQ+>0~X7Jkwm_!cYA@<ax(0p)f@Z4vcmTizbp>`Z8<_xM_RJ zbn{HM5B<P%*9|e(d`)BvD=~N!z?xIm*4^i@?HFHmu_M*2dFq=Ef(oy78xz)Ye+ki& zRBi5xo|-JjCf-?Uu%)zo4o;j?DDzD53T>iS`rL=V%i^=G#&~j?ST#$=j=c%1r%=i6 zo)JBBAD&nVRYK(}U#3bkNVtziaz|*1{U0;3=z=RN*2N<@UaV!j?k%R>Z`OVMVpHXh z=E(b`T4oYDirYk5qGLQ?cB8-+sCfAk_f+vIZKBCH(JQ>1zE0NDv?=xX5?XBoo<}G@ zqI@Deei&N>*e&Qtv6cFK%XKxSF)b&A(3A@g4`sI0@o?l}$pe??80B)KG{NDu@LbGO zakG?u`ntL=d?A)<A-XYU*_qFpRsP8QPjXpliuUB2=vCXSqxG25tVI71O5SSgsA5!l zCZl`0MzSq4HeBQyFRQJVvX*s_y(^>T4xS}ObPYDkGokX7pQUB?i59v!P6=dfQ)qB- zDSs5#%3tfLfEf@`&o%j$)LfG>%8=eN1(-rmff%h{hph4QU}dND+!Wvj3ZPts{fycb zn?V+Ur^i_HhxLw)9D+ctc&@AS>l7ZUd<cjH2LKA)1VS3&*rke+?sRoJ*4f&i1JIlr z6)>oq*0QV%VU+e$a*u$!Sc_|le*v}u5*8`NbFUt1HKT07p)zi1CxMb+>p;-h@_59I zQ?*X>x^D1+^ZMAQffZ8FD)7R3Ch!6*ZS!0aKnVcv$?vrGK0AP8ZQ?!82mc{k)wTW! zo&;V2)X>?o0}xSFdtSX3AT9NEjbDI3^4s=;?)c0b&!331(^{JSqwIb2@YWFkMq4Y< zvT5k}ksgOsTP7gVHgxLUJ~{|Mi2gL)Bb62Wozo8P{&p^F8vv+<)ch0`0Nq~DYNwU> z5%9N##nk)(5VtrM2N3zd#u<!?0CjZZ%)>)I$+t^CSmy-t>ZB$*Iy00qT!BiH_PiU% zFsz@K^J&@2T_>+EFZ6#x%*gAYMVjqrTZWqw8)5DhL-|wsiik>zaw>vPTwZ#s5i^#N ziP{oJuec?Q;W03>Ew@igPfywTuejG_ucTIn9Lrq!Jd)g`w&Y3kiGK=>VndwZFY{O3 z<F2zOlF^Lq-I1+T`BP%`SKqWPXXFd6R=7Lxe--y@$^BK7{f&iI+tf3~4j1L;omQ#( zt(WZh=v91sl?Pf5iB9n(!^hK2@aIF2U;G72Hp?RA7jcLR&D72xkMj7-+h=+|=tAv| zH{xb!x+v%O=<@z-6&d@;nn=@?pE0l5W<|#jLd9FO-PH5^_I0{yv5Z%&CE^v|MCn7x zUp&(zDS4z<TIpN4^U+g}<`_xwmxh|<&-zS#KXF<mrH;B17^_+0e~wQlgmsyLT_@lB zl6S+y6;q<_<h<c0sN3EFfbjE7KX>lli1Xah3OJ0HJRryQY@ocjQNjx36rz?mwAZ5O zS3LH$&WSasfQKCWom)_4Xm9-lX9>`Vp^M|B#)?za(tJS#kM}4}x>KlbFcD<zP{1~2 z*=9gH$^?wD8(Dzny{(1I1EL44gPgI#J<VBu<Z&t(>=TWvbxe!jHr6lew+o<o<bXoc z1z7?>0iMUSgq~*Om*5XNz)|oP0MPujg+FD*GlWV-QRE6>7wLjdK(~Mo;2h;rhG5q9 zd_ISiAL|sU6L1*)=?KRW_0swmeIYMxD(H*@vEf_5CqQ>INP=3X<H>$Yg)Xq>#^xK^ z&@)fTMkRgrwS%<bv%MXWTL0pVR3C<b;y6o?G{=oye+3FW=c_RntP8wloJ60Q6P|Du zT46~<H@hbjBU_WYS;RjyMeVBIQ!rIpSNW=M^KGk{TcV62rsq&Aja)sa_Y9<wzZcr` zC4HnsV2t&dQu<PoI^;hYmy(tUsYIsB-&zO-D^FItakMtj3ral<iA6lwEMaVFgYxH? zb<|R35-L|PPi<umT`w#tURU{~D%UGk^BT{Rzq;S91*&6g|NQZgk{CTxsV#1Y(ZAKj z!BVVE<#7nci^7*l{?+QU&RuVv#FpdBJ@xga5-%kpG0;VW%~jnV+Y3#y`b0(4i{P)J zm*xE0F7F#!-AZ>ZUyTx$>BcfG=~KSqoBF76w6-aFHC$I%1Y3Rw$lQ&jlCg=Q7|S2K zXzZX|`=ky{55}1^tv8X&a1$RKL`vgQ&3I64ykbsDq`c&kGLX^+mtO23C9}Zjf+@XE z?Bsm^;r;OO{ku5gWp9r)X`JnM@0Tz*2k`0^UHJltU-~%o>kohyt!7sMC;Mf8|1bcA zmN{>{L%`!9e=7TP(}RCC2M7eL2&M#Q@t{VBXlayEKYs!r<+#?+ACaVkR0JNLF_`Pj z8ju9I$bZL_rj|B0L2Pq2pkT<hy8*;parm)k@oizHath}VAQ;D_kfv4Af38J*WDVdp zK+Z#%1%7d43+=A;E7s-#dYzgTMB1)`LIIj*Bx?N>09pq(mUy<F)9ZpbWeJXT3yxwj z?q~K6u$~<NHa*AC^^2aBXj!HQ0JL1>TaNl^0o0*wwu$_<DdlN-i!|EEV`;R)UQtH0 zDLUM<mhuuS?(4%d`jaqi5-O>id2KKFY-7QoZ6}~}y{46Y1OV=Csk{9L0EFX=wUU2l z$N2Yu`q$xK{>@E8o+s&s8FxejS=*Ra?$fRt+-n%0%WaEHuDFv{cXCmSZyqoD=leC1 zmDov*x|a@0HLdh4Upmf)8q<O@i%rRn)pAp)C{2{nb%_((7z(X6@@8qF-k75_m}RQy z%=ewAGAYBnjR7x0<v01#il?6W<!6r8#^xi~Vma0rXXcF_p}?>VB2OO6&tYf@>s_RG z$ra2pawO$bXMO&!)L*#;><E8?qL^8W7ixCTa?#RS_q9P`v^sR;HH`;Vg1>y|Dm$ir zN2V_iSgtrv@aNfFcj)bN)#te{;~Jd#0;GJ>eK;=wf<B6Uf$FNJ<tO#`c(p~=)k1pj zjQ2m&il_YIueiRl^@}D?S6&3`)nHmWA1HQ4#~BGzJY}ZTW%>E&kzMX7M+orZ3p{#r z%3XX?%uznUN%cwy;+I@nxl}S<?7XCJuo9hfw%>>MKMkiJKd}4tf)_aTXDP%2KybtQ zJ^|PE_8}<9Y1TZtMerot@DN}h&H-xim8;cHi`J_{cDRDJPOzGJ%!%vVw3HpNW-NF7 z3J}P{&tp+yGYK-|AxxcZ&$uy2%hpW2<A@ihami;RX;IU~cZTu3$4tqW06N0!<`cj9 zd#8`(&^q2yhuG8sU{O|B6RBTJ_X-r@eSB<IMgWlj(CKFDksCE~?VDgRrq2a&05w6J zc_VB*z+C=usmcp)`~q%*L_nGr)G&?)Zvw`64ncI|jn=(r4<8s&KO2Y|S{CU}zlQaX z0unT{{!$wCi8BhJyH@iXrhhN7+THT-ynb}2H-L?{vb}7_{At-lyycKD0AaKz;l?8v zbSPh8{rmARx5H2W@;?qA_ygh(XMc*%;0cIpePZYt+FMFF!`W|HdeL9*_YzifWm(fT zT5l|ImH+2ZO8>dPPL@2SacZ@`-j%jaMo%kQJ?**hbF$Z`=Y7`8Uc*<Una^m9jE?)L zujA9Oevu3riDt}nQ>Sv1HnmsetPIWP{w2S%eTSMqVR;H3<6SuxSiPbu;YxIirlb~W z-d6y)+#bJq%ub76baX3zr6*U_ikG|O>SRZZzj)HtU(`ub+%M%U&Y!P;AGY@>!qS`g zFuQ*(`!b4~B2)o{^7Qq%3SY4QAA4`st4ofh=f$4qGvrXJt`^)42?Au;7rOEf@Nf2o zpeq3~V8|A1saxG$-CdPcS(%lU!#R1TJ&%5$cdf->#P{vtoE!@}+&hBgnz%RwxjvG? z(D0)HM3Gbo4>&$D{~R4fP7a*sr5WgRMmR4|i}g5|BOcv*MFlf0_})Rwpb3nJ|L#%@ zJhYjnWR4uv*$6jP#Z3hSN7utWG)#`9Xj&&FT6JzrtOLG#u=K^hlu^Xe@0n)*j^Df< z-e~Y<Fn3#&QNb@~3@Sd!rgdL^I&Duz;id+49nB(x?DWmC-U3}8_I*Ukjh2x0A_z;z zYUS)9<ltf6Y~7df$B`tvI)s?xRQ#fej2@OtIlm5Fc*(?Xr!spa*|?hhqUqa!Nh6IV z$ua<02BwI-42t1|Jn7BZcNllJw`C1(if3E6GZ~|2G6K&u19y&*tJy4n4Mi_JAjfHn z&inUlcy&v;it{!td+IRucJvl3=N@kJ6%6GQ7(TOg%zQDMN4FBPFe2k8B~64`N*u75 z=?g=R^ojEV$ttserU@Cu{lHiN?I~KYgqR0|lY!4aCNY>J^IpQgkb!x*b>V$_`}=#t zlha4Tu~w2_YX<Oyvf_mpX7`k?OgxoEv{w60NEzXw@ul{x=KzXToe9W3!`H{34=<ko z+u_->XTwJyzZeemg^>OI16GwK6E;d0ebJi&7-NJU=FAkV_cAP_T?Pw5fgv1v-YtI2 zOVHoPQ+QG#Jf;@uRJ{CUG*gX2;<WGRDYCf7{;5aa8m{!G1krm<VaxLoG);=L5wYrb zoOOdzs=^WCPJ}$=AMG61d`AEf&^^kDy~p~ON?oZyqBxSqK0fH-O%WLwd-*^WU8XN! zm9*1Q{JjB4N&SSb>N|WIfI~|)a_6H)<jSK?U9WB-BfUCNe*JUl-%V>oezy>sRk9d= z%>12cj5|~0{9GHbIb4=wE^;vQ$@~1GSI^0E(gw?C>PR^`jSm)}-0is){?EkKb3Ll- ziW#F06|DRjnvw;Dv9~C&BQAc`u?@qjm5wBX(QPckv*8GVtdMuR6!3+`PiIi^ckl_m zBIPfkE7V*1baiybTo`K{g>roKW_bDX+u_+)UugOF8@=pttbtn%&NF?yy~+<GnRT9} zju%6i5#+cJzQ4Q5(y#Pb<wuMREsl_3&)>ETz(>2=!;^!(;qg8PM8})195v!SZD|1V zonQ7GA`joQO?sYVKOAXGIB9F<3&ROx(U*)IW*dc(p+vo^#P#q>jbT&zoy)NCQltPe z+o?11E_Jrxg<fzGo-^*4#e~K)X5@iBK+hb;6ownis=Ta$VHZZ;mX~>VWYF@m%+9XP zG)%*fSwLpoSRTfx^h}y%N;_unq@bIq^rHpPK7bi+n^$4_AB;kN0A@$zvPCcW;j|E- zxTqT&i{itPm-u!vLL={6GX5xEbj4^r&>p}8eF|<*N4gvyuMEd3TW0o<=eL)Ye`ZYC zuX!0_tuuPZz^j16Do?ec%h!Y2&zHmJpZ;E-3fxs5VwU*eVBbFiD3^FK1Y<SwVu2y% zJKQM|$@>lx-i|d=8dH3ml%b89AN^&i7tJ!<2)m!^eu|RT47382Pg`3eW(lY`M&IpJ z?0utG*!_=$hUk(Xa1ui{_c>n(4(yl+&jhu>kE_mQQS;0=A-8QPpszdhRVVo2@+qsR z{E*zse{TSG#q(1JU9YY?Zgnl!$m70HuE_DGcvilIm4t*W7xa!$x?}z5*5MQ~{uDXY zI`FB!b;|ctFVD0TqfXdOnf*T6f3=|v=oo)M*JU(Dcg`TCeLGT+S-?M6mwm&c`c+9_ z>WM32;ao5IFdJO;s7R56UaUVLMKLA|1WeR?bv}#SBS%R|d9)eQu3s0{P1KI}T!b^V zi7L^31v#>y6M+HcFX|1|LtJr^q+RNV&ivruC4mzicfyw(zWGK5;PYoX2>M)0l3I?` zEFLdKu&<3}!cz{3)}e9Cz=6Y<SkrRu3VX~Xoa02+BzHwVhQp=?`dt})Pao~;6JZB3 zpfHfwr^b&g88~X^%z&}Kj5((b!D4S<;9^!!Wn!I`6O6qy1TpA17Z9V=Ve+H6Us#ZV zh$D?l8Df{3*}B$pC%W;YiZk+<{bZ&y_Nq~T)Q)tQJ{Vyvr*h^YZ|kDx_U`Vmr%#;i z>++E;HugAgPlln&fwzZkG>X^z{m7p#t4`~3Ktl`VW9@XO9MWjJV(%h2(P7L<Z5x3m zZ8wyR8pT5n%kdan=842q4w){;@aUzNb=B3n_Cs>q3@@c%w6ko#t-9M*J?R@KDqHnT z7_B#YK}LojbnJ`VSl3c92S}@iuGJ=~CxJyv>QR17G_LKf4~J?)pZxRR+t8$~9BNki zU;Ofy!_%ivW&H0b-IzJ`%P!1jHWzt{95tW<1@B=a74;R)3QdV-u_*IJi6Nn|#War> z9A9PYlJ8*=u1CJOv#J&erFUs=c_suhLYFX2K=)CG@ibw%HF7KMEg85k?MXtC;r`J; z@|}NzSGo&6<xph;9lR~>h^0{tQ5Rv<>4^#2d=3nSnK=9jpO&+whdfAI2r6QMZ&Vq0 zZvb`$^^*mweyG^K<`xuc)#v)G1_?AUy1Q{i$9boy1=$Y+kPb&*VE7%YzkMSs@bE;R z)jHI9S~_0i{N&JwsG<>{U0T<y%GS1)mzZT>hCzqI?riG=@nn^OL-Ke@h2=5Ak&lPz z@@GMHPloE@gpB&C_}zJfl0i7DyAcClE@PArMWhsI5fA6tXLnG-7lToeUQktd>eGQu zSVRm(B&84$2)OJDQ1N&5m9C7a3%&rN!J2d3&QFi@W8_dU_SVU`(%Zir;>=8#%qX4n zOIy`!j|{x6-TmPj!%)Vc&y<rI%-(TKiJGdvIs15bOJAJW9UebA7#=@<Y~zoaKR>P* z^D;QtH+a3yUNt=w;-yV{zZ_|bFiMAFPyq;E2B2rT(jfHSLE*xvV`dU#1%r@fZeH-< z3PaIx8-Ey(DKE>_FQv#ZVfNDopmgOW4wk9I0AyKnUrW9*3y2}LA;ZcqddRqmnJpPZ zt~NcR*{4v4u0Gx9dnf=Kgcw|UmH{ziS2LgBgz|-I;29+ArI?Tg4g45?QC2}4t<$YU zWx1|$(P`M8z2p$<IIod?pXbB=kv{3B8QOhaM=G-mE%Wn6vXWD|@l%!a{lvS8VXd-M z8HO$_Gdmlm;kLTIuXgl$IQiXg^%BjYz8TEn;p*hnj+Dh=c+5V{J=dR^NMykQgc!G! zAW#py&n3*`A*RwRp?Ak=k;_~!+u^)XUK6J}!ErB1eb~r9(;Lm5{FXn>Mi_k2j=L}= zK>_F%WfeFg{Pn&GO&j!4fJ#&kOO<6a0xNM4;_>qaFXV;0#kV03PiPQK2<hB=1F$QM zpDM_+L}j)LZGm^x$ij4se>a?Wlw`JE9rc$QLbdcO|44ejRR8+&_-uHkP4`EyUJmC+ zuRRD~^Vuv0APq9R2akvSgC`n1pA7oMI_GD2^8ri2ybz+f7tI1j!z8U~6BXcR?EFCT zfX$We;tf}s%b(cp7#go0)2^T^*ohh2hsz@<kWEL0W613317?)5flHbRp#<nZ^g&o4 z{g$uUGXW7rS{l`@EQU|vBm$UNkz=TEhS9*m1u%I_FSATi88Nqq$aj@1{*?xLE?!o6 z^yq`(Ld$}e7cVqWbN-!-rZfbcHI4chaGTo8#~Zd7EbJeo4Pu-e>x&ZyYu7R;_zc;m zmVLK}N9>c+>=|#lZZHES1B=NYmf>SYNn!P-46GOmHlh@8`@rDPtRAxcqYY!mMjOYv zsI0I;bnzK829`A$k{F2SrK~xlVF<=j@P&*VzU6zai&;m{JRpa(F`{%a+lRr&vM+|O zea!~)V{B(fZ$5AD`2`S+KxVRRAd1dE%BVM`Y{S*{OT|U~rAAH*DkbJ{)RcHUoiDA6 zPvrx5>F7LZMo<6FBgUT%bJEs+LlZ0SDiFnG7(%Cmns3O1^2qYEXGnGMHAel}srnb~ z$J|rB?C+jw30N=3=v%?-G5}BXmN0J$v&_#-AWPrc2&!_;SwN*@^HBB3Y%Z%5tGYHc z6TE%!SHqru9IVIyq)$83_JVW0L9R`Ks(+T%`@!0^6h+YP4}noK%UzZ8hz(l$-`)ju zE~nyCzhXWAvapI-E}vnAOPBI#l*npv3y%E8J@Ct9zb!2KR}!1bUnU1yx3f8tw#f5g zf7H9mBXde3jWb!?j0<XCH_|{IUoM4+RNCP~lW^pkN3{nm(}^;ysA2%r7R#wMMi6D} zkV&5+QsflaxIWTqrsW7MDL0qo?+w6KB0uLqHX7I9q#8%1`^M&~hAsyCzG;jMZx=!u zpPo8X;85-Ox%T`$dvi8?_3h#C{F|?bZ@>D}aHP%mXWD#!rdhyC9jwKe&qw3;pL{Sp zdh+4$;fKG_GTMj32l^z{-u~9`bWh*-+|sbCjaEC-byIqOAG*F>&b|+7w61#Ta}W>g z6c_k<L}SSn9iqMnrHMvx;zkO<V><2&T9iOgy05W>j62M2Dv8+WA~uB~vl6H<K7(Ls zt9W))*n8@s_%~bm?!2agMKHP~9|3oSq7$Zk<MPZ?E}43%P=*i7u)xua&YwMi7!-7# z-VZ2ig*4ee$GL$w`UDs=J?A=aZvC+g3K>g}_jiUTTKavY*}pv<8N<FXmLM?z)||1@ zL1|#jcs7f0q)8UqY#;hbzNejRgv5*<vw(<-yo3?h+J^<8B?e&_fXobH{GICs5cUw( zK;t~-Oq$Q_!}!Axl)+*Hk6Ey-UCoZM-%rQ2$e3a|+k5^*=K+%Rq>Qw8b>cHKp<CGe z)z~Og1}N7#ZGj9_lz8XF<5mJMMy?DxHUU#Ep8Zoj;n#r2Te%@Y^d#XJ^(QIFpzJPn zwxMPM&vs5^sA&dJFN8eO3m~ew;e;ZlZbixqIUEnPsnrM^+f)4cJ7`4U{h&&0og;B{ zQE%+=<LDsXW{wwGw2zS4Qk9usl+ltiKQx+-T~=KPiJ5?xMx@{p+N%3G3)G8lR@O~k z!OLId3`nMy!tpA7mo+it3K|+4CegGR=wd(eZE5^?@X}`?McOG!QyiJs1)3S4SbA`j z38E+$$^;+7E?}g=pMBDE96WRpSHvRYp3+GSC(>&3mIEwN1mZaYMt*u6gi}Xy_qq25 z;C&_ZBjH_H_f*&dI$LP9593=y3&lM~y<;9qF6<a{`XJSCB>#mv&o9->e*V>0!|y-& z?eP4MpAT<ze%7gG0I#&X#xmTMexb88MaRCSx9D~sJszI?;+Mmt4?Y?``iox;Pe1x- z_~kEtF?_6jHP_nD#Ebw9T%WLyJ%L?jyC6hAsT&`vDxJ`dA+8?mP*CxS;z?f>0*+sE z`4sc8m&6(4B)`4L7#K5sdr06as_H^U$stVm1QlgVq>%<D)D_Sj6rDW;aYg!Y78AJ% z*_F+}=$?FiE{m(B9o!L3#hOtv617lt!np)0D6^3)lb&loATxi=)M#WETn7hh&YC@7 zWMfThn-|Rf$ncZ-Bs@#R>I!vm@}>+9J~g(tqc?t;S<<rNE`}eoe=-6#H9KSjlj%Qo z{4ybAFR3IjE^T}Xo^=qqXD+2z7=M~`k`ZD~`D-#zZ3sy*7qRs65-AjFY>Wpra8S1O zV#K!Ov1}cC|AN*9gB<I@fyy#ecxgf9U?We4-<B?BxY#@A<6nfwSY*}^M_TC3U)8fm zBn&jc3vXquu-U{2Idv~SuJJ(;J8|fcO*v?`lRY1D7GWOtJq4Z1O)#hBc7q7YNd~q6 zEI`x0%4c0hFNbrptn0mt%-HdEwv6*#?JYUiiUdo<d@2tEkd(;ZhV;ACmrt&)looZz zj{{-(F;Fw6{5Y`ssvC|E+T4FK?0xX@@ZrDs)$og7{%Uxn8Nh7}Yn4a1$j4$Bi1H&x zy-i$3o%g~etkDK*V=D<Gn9vw2!hq=RfNsSo0)m0>bP}+osk}qO-E9t`hM7puNk~A3 z+lcB0T8uxco7fNLqOh#beQBWI+h{VD$y9PLgK(9Jedn3yE-sf7%_-@EHrhJvo${fq zxI4WR9x%9QPl<=vbn@L86%|vka8Hfp5em2ha)}uu9kOr%ir9I|((wQQKmbWZK~#GK zFpBCYyHgqc)grfO!~k3kaZVD;OOnPz>nmhe#n0&<5=S?TGkqy(c%#VI`i#OChiAhl zUp^l``OQBLzy7cP_wej@|1_Nc@e{p4_goE7#@yNQaH)M*S4Yo=E3KNW>}b$^^3kyW z*Z=FV_ZNRT{KdcepNC)k<zEkfb@Z=?*Qb9uoPG4+@X_w(@ZpyB2dcrdd&m2aNc?By z{9H;O)auK0R1;`oM_}flI0{jIpbHzZDJ}&x4{Vo`;RP$q?GkRsv;>;Of{@zu8ucAR z)}cBq(cd>9j5=33=|5COk-MF%%wzTqLx!bKW@xnMZB0KycwR8hco9M~UYnab-i5D6 zXtwB59Ww?aIbc@kLQ9aFn;eg_;&0_1XxW#UCHBiP`?sYTpbhP5_3<b&DC$f)8xS(O zJd36Lqdt0-5fvpTsAvB$He~<`@0UMTWe`G}1{Prt7?M(Xlg(oq;^3e$PSJRYgaM|8 z5~U_tt2*eKPpPfRSYft`89;RBkZWLmE0`r>;V_Q8kFnZrtI{-Pl{aKE7=;ZW0%uA$ zbmLY$)ISjuf|E0>f-xwXyurzr@LXosP4yPWVw7iWB~b4oV|85zUt@@0>5bqWE&U#- zex6|P>4)j5_V{s(&!J{>Io5?FR2uS;C!d*HjCVOqPRft00mBf+IQLnF+8VI6qnY2Q z9}Q2ma`EW#Q?-G8{|Jbsaj8gsG^H&vZ<Ueqdt4VTH2xiK5$!?}2maKR$T^PI0nW0l zcj;e#wkhaDRC#NDCKKgI%dWpb*a$Ris?Sdqqhy@d@1j62fUwIY1!mp*xg+c!ZV*J- z@zc#^=jRp6Fv=BfYQi-q+6V-UyPq56<@1B5M<G!0@Ihsl(Tpweig1SN%jUfSI4hi= zB1%1t4;>nGHP;0fbt|MLn9oL_IyD9j^@na>ZfuLpw?Z1d0yJH9qk~RI7{1nC=ucmr z48Q-wr^7$}`X7cbe*2HZ^MCl8;rLIV=^(CehwIZfqEd&g**|T-(%vSPpv0uL<C`}} z!^t22I9wcQsqOG|c>URD!|69)4X^&{uZNR=^>2o=fB8QRHy=D69?=J@v({0){>ARD zI<r~173v3b3u(*%73CqetEV$H%12u<@KuuKLsa3C)YWzawEzrDT}kgLEA6IR<LuK6 z4!ZB+E#KrtDr^r&cF7NtxVx`PSx^uUrx>Fz19^d(4<xQ>DgrnDMtpk!T3w{TQXNJO zZ)qNA&*}N;xt4Wh6v)`SWKh>E6u5Kk2V6Nim0Efu6ys0)9QDGRu4~ejuU+u@HQp@c zh?E_DC4`IFKOb<cSs@H2zxAp&a>)fVY#3WO4+su9;!x$5vT&JTkY?JR9AkD%0WTZF zp_xdRWtJyp6n0<K0)_0Ng-T&&A-uOvto#78K`K3&)w0eQO)8uC#2RqvtMvSG2ZEaG zTZQ1psc`Vy1u^ktD!=Nj;?g6WE2ssLgCS-C9SQmHfJOsC7IOS-;gd)C<PAex`MFVk zu2m;C0JXpKTrX;z>FmWfIu2%&Sw>#mP`&fUu3wzdtRXLiP)-=z>(YTbS2ra;!juX1 zv!<orO)Zu0?i~yteE6~7{@qZU@HeBydqerr2AtQHVd>Y0tv1T%C9k=lbC!H7gd!<| znhqC!e{V#^HuFPn3YJIv!Py|eCr+6L(C}!tl(QM+t4;D(bfRs>pUP-y+i4a_=^p8l z%xw<J`>Af@z6CD*r1&DT;N>q;+zOfGD9a?ulk&=P(ld=?tA=wG5ACQ+rxT^?;xb1* zcL1Pig+dsZh^#X{!D=1k6HsYqVM}j_z%><;<-GwI<?@r=sThnkHyI+WhN{Ydp&m76 zf@lj3-2xDaL}s4{1O^4|ff8Hwvq5nGJyHpsjuknSj4w5q{z1myKm6fO!*Blk-wuEC zpZ>$}`Zxc5So!DwqPIcRi9Xr4dht+12fw1X<yJJC;tlZHlz;x)f7SuLT0$QFvu6~) z{NMk#;p6}1-|76WBke8J(u_85f4rwRGWFGkeTmqWsx;78oQe{-U;B5bn3ZG{cPDNE z-*8no0yHAQ0N?6@r;$(S?qqC~!OMN54_L?sK4M@SW6%XH@Nkan#<&}l3;~53c@t!> z`ckma5|4m958w={g4bYPcyrHgmDmitEQ%P?s+k=OFbqKUXz`N6`o?P?PJXIoU*4GI zEm8KoZEEJvZ|o{927F{Nxcj9IDbCC@OTZlb%&gy@mVPlZI3i_3ve#uCc!o%ZfO6*a zZ4AgT@nESzpp_cWvIl|ClY;OJzByyC2qRg~DodhL#(yqEMN?A9r97kKkGzW#gGJ?F zJcT4aj6bgU;zk&LHc*+}0*3)5-7#QYc1nemxVT3(DP$179z<V+4HOlQl*@r5ocI<7 zM5Lo7PPyQl4nBg;Nk$a5BFxe8M_ENLwxW6lI_NWg<QwA-6w8x*=lS)U!{LSY6>B2b zFLi8aCiqNC{g)ifP5CKZ3}DwD<tP5yzXlGy*zdQy7Y9J^s}1a`?lE|faj9~IjxxS+ z8HUOWck+0v1J`AKMz@@^=;!{(Tzr&^UHTDMIV$cyq48Z0!1D5s2zVS<n+$3wrEM5} zZab6{&kitM#^O<D_{|yEVz&hzMs*waEpT)sFLPJ$^5^(Io{Ek7DaVuzG$lKVtCeA! z`J>H3Qz|5V)lGrHTfT0V-HgCS5k(3=I(IIfnbK~GgRC$e%R=zI0k}{kKOTT8uFF<n zHL8U7RobCC1&abHS>5~!(Jx;*HV4%?-em-qgc8a#On1wEKi>3xsmM1v^X1d$uZK^5 z|NG&e{_bywKmOC-564>ez4_|%FwSJDvCj$@4**RwE;<G6vQdYjU+w;={l&1RW#Mhv zsV852I()50{b={G24nH-#gWTj{mWtH!;glmO+_^tZ%ZG)EiBn|{JC|=xpjh0vqHD~ zT?v^eORF*P-1V-H&daFiqE6^Qqx6CIeA7s)p<<`d9G>t1nJ2hFFp7v!Cuh!ki?A>y zrgAD7@>AgoEYMdvB97%B)K*<Pj$iqOFgi`Mq+q-fG1cOMF)`C0a$&sj&0Lo7d{D2J zfEmnAkM*6{qgPt?;~TO&9{4%PSnp8yC=ix<*~`U}E*g3{SOWRZF2>?+Zu+lp39oSm zUG4#7e<3X!hYsWh6D0;y4V^rE(xJ-1VaO6-gOg_lBSc0bC)3s7fGjUpO0d&F4tR_m zIU8;=Kp2cg5DsHRmtR^C&PJc(F<S|)$wY2{AtW+E%4(J=v<yG#7zvGZj$0kwlH39F z79jNH$+au6%dK#MYIkUwA%UKvb031Q6clElTwT}MetN0bhrLKV%lZ47{d>d<A?(}K ztnIOugKyNY(4TR%529%&p)lu?O0zZnAP_Gv)9^wF<;L>zqepsCO|qz$%Zqd4{S0Ke zMV`q+%ap>nsPhVkA2ihB!(7QM-&r?nKvJH?jWVnKI32ec;rP#Rv`zFYO$cYZ6D$nC zhzD(kl`=mzuC+zNCb`OhJ{=>N>{Fy-cbj@x{zj@%`w@0m$VR#d(C=LxrMH|r%5{z{ z+VV-4Cfdr8^7KVZ6P3yoKU5?Rhg|ABmOf8gpu_l685X(x_+bKb>4lKx4w=iS#uPFg z^zKBwHvqfB_%VZ20vCNc?Zs`wKmef$-lS4z4JfF%LzR5Y0BWh@MxTVb*4uV0r}FkL zj;?R+Dh+%tt&nLi6esFy=1<|Tj?RWZyf_^G@zc+S-~6}#GW^Yd{6B`X&psJezWD91 z$x_wsFBzKJ1Hd4Kn(d;&spIhAqZyi&T@A30r7;<Q@p5?m>;F9bK^E$p!<Rar?O3YQ zl-Gw-y?uGEV><Tqg2=9{zD>!&5M+j?x^VK6StGdADV64K3s=z<VNVBaA)WwxeYgbN z;zOF`T_A`X{1)EZ!D9(bWsLACuT6?6C}Y-dBIGt19lP2Jl?^4V?x6d4!aI&u25?0O z1$L5fPrf`%y1GaYV=4@)$Q#GO@FK|R@hiP8daUK!-B_}dF+e+{>0vDHYG%(fIZA=I zLs5Z4kZbuDJhOl7om-Q&;n_dV%=0W@7=WZ$13{IRXS{hk*Rz3wVhrLWpMir}6VJdU zfW3sPdInfJ@^eF}IB!tm1jh)Ai2N9QZPcZ4#@;qBP3O`i@|m^b3R&<gEP8qAGSJ7N z5w@19J-VAgQ2b)1x*8whj1(<-gP`Dz7&s343d?V@S|DK&XMl9!P?VkpM1*GRKr2ry z^D|q==i&DCg^)eH9ekw2=~c4+Qp)AJUg{7n#!9_SjloA5@-j&5rIcACS<I69r5Vix z->5Cw0Hh8jfcE3Irey8VtL3rs1EvoL>GWRsF25$Ic=>ZK@g-{+K~ullWB8O=w9oVv z$IwHF;l`(-m&RbUL&50FE3qsW?HX0v$dN=UQhp|(VW-N=HJ|3=JI6?*itrtT-Oav; zC40Cq{30BHD5F+Vt!$H~bTr(h-Z4iODz*HrV|>9T#2HCd6pK(xqCw_dA+2PV57m1E za9&nFaJ;W9`Z5M1w+#mbC<62Vhi}&&#RjYgAEH*N2&>KJS6Tvg73(4OGduoDFg-W9 zn17J*r|_xR*-ZUX$Gp7MKB~{Zd8R#ozaM_{_kTBh@$0`GPJj0gGTi>CnLjaWd8PEL z2cRAh`;r&!KCrb62#-77YkpDcK<O_((`TBr@m}BK<TG5?Cpt<-Z`@sJCh$T7@Fn}P zbUqhfWYDAyT@Zb~^Gp`#fAJR_MX><vDHFR$w1lq{)X{grk)V?3kX_Jpl#j_0(eTAP zN(;h9&?9EyCA_z>Wq&jga2xG}Xd$x5wFn8OvGtV@QQk(JByQsjycL&U;TVvK$qbVm z4p2VU=igqucs9Iw{lYUkyL%rDd-|R$Z@$vbub2*(+tc@eIoO#aLXJ;(YnZbEbsUk} z+OC#*eLfyXq+smvQVFw*dDT%b)?MjhY&E5%2w5VpH~K!WjX~lXTrpz&+^F%|D1%b} zelZr98ijdV<<LV&U*+GkEegXIafOwxe^}vT_*GmZ3C~9ue_=$5+I+eb$}4Nc>7j@) z*)WUVFvG>vJA~M^fMW26XTD4`QUig5zQXv$Am1Zk;h+uY*%5-7cgs))SM|eEuebP+ zXpC}}Znre^x6PhSo!_{rdZjPpMHddC$FM;JdjU_iH&hF{5~}i1xlwi$0|$!p_V9^5 z3&$bTEE{7CyR0eSsyhTpcb8zRuc_{1Yz&S0B}3r~i^M9Lg0<q3?nYPfi6D}V_C{nh z^h9g?6b2<U<5F)Jei*;zRT`u52aGseDsknVZ5E_iN8n%wq82~!gI}fLa<Qtq!Fji< z?A%TD17XpX45hnQmo_~o2H14j8%0=BK2^ejn5I#rq*X4din_op4L=uMxlXp$By}%u z6hJ6ataJ-k^zRM8Dv=+-rxL0nc%1oB=?AD8e~Il0`!M`GkS6PBt-CrYBlzXUETDEb z>j`Dhqt|nV>w(4KYEB}ohXDGPy3hDKk^y!k)@N^yhp%3}8h-cb?}mT=Z~xEm>;LoL z4;MP?Z|mFV5~BTnd+Jd6g~)|YlF=?DhANCD<s!(Vp+6e4uGKB=)%vSFtp%SBNB{5t zHT+R;4j(=L!*KTU%i;3h{yX*5|7N&+@^rY;+jo~*KHk;<y`?EYe`+i9!a#>?=PSdc zi7tx{%FZn(x`j9S?&Il`Ae{8e*bM9GJJl9~52agRd>CMveh=g9GAV}J<zxn^``d|@ zCrM+1FCFZ}0ulxe1J#B0XdN9L=`(O&4#%&bX?b^3`}lMSxsD;iP~re(+WV%AJZ5-! zxq}0hkF-A(`Fz`VTSnh5FMsI5pzzzXnz`oiXO13;w`P@Qr%xCMXv6b>k)Z(*gMt%Z zc)-hv1U*n3L&622=M8IZMYHMAisN}|gS3g6l_JedS80>JXZYCDCj-YifOlGc>J{?S zW{4BbP?W#Yr64KW-dO+&=4FY5d!jB}<uDOLgnafgk_S}rgaQIgm`9x&T_jIG)0}0? z=+#p2n)*8*38OmQQoXTX69b;lzg?(4*4J3tB^B{g?lSCFv|mt_;}TK<W__@DqP@y8 z{`jomiOz$hO_hN}+EJq1OY2Ujrrd3TqQyr7*XRmbRK_Ucd@JwPzr_O%ZNr<UjJd=E zQyVmQ`Yk_-M;ISE8HXxM8-D2n<8OtfbRAHR<7WyjjnZRg+Ud{oV!{XB#<F}M!}m!> zJ5nCYRgH|0!pL`<6Q&e);g9&>2?><hNJv@X3f6~=a9Pr-a)b<Ee^1tsQ;0~bq!;vU z{QqGMz-d9gO_AMCyC7SDg5mqpP0w7ky#jzEe3x5jp~cWQ13jp@6daGM9&Gi1H=6xm zIT#T<$~?G?KbP{)rOc_8Lf&XFe4}5-&z?OW{`BP+!{@*G_3(|}_C5OKzYeQ1)YjBl zYOSf|M^c)$gvMB;6P<lE?I6Wi<5{9F_CTu6W<@U!pMLe5;raF9aG<Xg9LPA_Q95hq zzZy1l6vL`E<F9CNUeREzjXWOoSPu5!$uBcxkvOn)y)FiIg$vmN9-;*H#%u8Ue)p|Q zdrnv=i?4(WDB>POxI;}u^>h<N7b%(!G$tV6QhdU1OLrnGBVBO{GIB1;A92g%d>2?4 zQfk*4xG&C6^}9z07HKaj`}nr?G6<hO<IFo=1i9AHAhfxCecFw)@^CSD$v{wp<lyKn zor|}v9~&5neuLICfXo8Md3wA_TgRs8fsz1S;thjPIj3>kun<bivYIA$8ZHwzDutv& zm=Ho^*nxCmRyk>a70f&)7EPtWgOlMh07IYRMOH|+PS6VE-hrfHcbt1ALP{Xzl{2V^ z_sAqdSh*Az(GFgCe8lxUPB7D;M<R%`tcnDvffaC33GKR9f5eil_j0Okwp3q!*$1Ot z*P3Sg_@*<-y3ca~L|=%}L!zN=)FE#T({_N{7}S}jXMAFiGX>SgFqq5`B&gL~4Eim4 zM?lOZ9SL`Is-?_!G!;esFUdk+nBm-J9Vf-WLDy#Q3=29Nf6^JAh9_)TOcnrlTrm8I z*A@m+P%B>3q=G_jb5h*<0accmf}sPNg@Ycqki7sey)P-wrF7p5kT#$)xYsq3%n4;~ zCgODgpd7k*<1=ycP<rKpdW;vGXEoC*5I%$np5r@|ITmFayl^YJ|6vWlg%Wv7Ko#IJ zw(3%<%8R!73b_5bN0Nj@EN_z_>x$H93ufsUqG?7e@l2qMDqiI%=f186J&_S-dBX?d z>Y+c?ObFMTL(QPPex<{mKO4UMt&V#6yZ=u|w)|n(IMXu8hBoi%tiI}0JaRQ<BJD^| zCEzHxXtEJ<Gz~wGeK8<ulm6N-Ki1Zsjp6c}FNZguemZ=kuQ2#cU>UM|V&1rVq61(x zW2p0C*7Qx#D~{k`@RUdfbw!(t!8jhv22{Xh)&u6@B)F4~1mDt4SZ+z9r|HA<r0&Aa zX<J-r-kPUQU>CfDA*6OqPk`X0-G@QdQXYvRS*FBo@R^8(Xetnf5u)|S4+;4U;#=Cc zhmlubz|ec3PM(92+1&4=K?K34>8xtd=ksox`T+121|WtX`~G<G14BY>6XVZIt@xU4 z^GtjGQmFRs*3PHP^h`+s8z(oi<~)G&&}AV9Jy8H?5QSrSA)OoHGag>Voo_Y#c&pb7 z%aWlqTg4!kt9RhxkMsiDSIVfLxs1{+^JsCvEP5_G;eB$Wkjh^8mA_s@rIF=OdA5k6 zPxY);C?PVHV3spR`WAJs3**m5yGFQG-ujVT*8%mWw3uP7*)GJ>e(-sFnj?dR)Q^dn z4dgR{>?!3%5?&OFHr^|bmZ6pPz3=8aB2h9_a(H$+Mk2bbvwWrMFnSr5@xW8BqXB3` z4~>deeQ3<^rJ-koFATge1i_c_2RzCKm>nvL2jh=V^4)0bj>iCXx-N@eZx}L5WTA3r zIrrS0%sn&>Jx{YC#z2h&)^P+!$d$fa2yJ1x<7uUb=^a`}E`d8_*+FAk0V#{X26v-1 zSOk=<r3c@_-3*aV+(nT>LgJhQsySvJS9@Os%?164@wqZBr?==(^gZ1&SkFGkSG=bo zoHB1i&&ewu^i!^?it>xrX(Z{Cqftx(%V-SK&At+_@kav$LaXCfqaS3t5H&Iyn!r5T zfaw_cp6I2PL@wC(a`<{Udim|}`nk^N`|69~<rlvj&R*z%XF5?0k~~z%vF@bf3pMM} zK$E&UGVq$}fGXJJGk_`5I&mp>t?zA~=}f^xE#tlZ;KSkg>BqzAqo>2J2J|cTaj`U^ zuQoVqBr8`c&~KCTNZ)~5Z$URh14Q+iTLPL<bkUA@SsDeqC8<u(JUDg_(Lt4@IbD=N zr-tfWyggvfvP_vJuoB_=w+tY(hpDT0U@BHVv<R=OgD*+5B-4pkhYk#`AeR9r!;Q~$ z?faY4kB9Ajy;XjAqBgBPTx#Dgxikj(f(EkA^cl4aroZ(S5WWneRYHH4dR<FhHXgK` zSTB97`RqTw8?1{LNhHg<NKWV#%2eCNz@WS}q)JgV<!K|WQEzCY;Zip#2NE}8a)yg% z1B1=EKolr7c=iPPxtR#<3`w(>93o;aexkjz%mmP1*dUe1gXILl&6vp-Xu!>7dg(QA zBT5E~DkAv~CeBO>yWCQO^-vfRKkVSE-KmW9Ly)@iK0wtQKL9w|hdrIl>SFYJ_Dr+D z$X!t$iN}msmc3ByA*C)@_C3{kRqO?%?b!IwADi&gXX>LQp|(_tBIxx`y|Zj4MU>e{ ziqWh5in!=)xL8kWUw^b++B5p=FSZFpdv5tbx5}T}Iy_<E!5_1G9n8idGJugc!kLER zRo;G~(C|*bQG18b8@+0;Hzo3Oc1vn(qHf_UAO4L}l>;S+YMT*>-%8L3=PGSN=71Cg zK6xD^DhIEdddf<uylD3mTJxtoQxq23fEOg>jQ5|(3}C4@W@1$F0ii0ScVu6hLdjf; zyd79MnNSD_+?9&22$!BUBcfp?Q88v-;DgzN3f0-=k<Q7TMB@>XR#P;yQQxve+t7%H z1pp7emN>4ojCMii=MSJC`rzhkEgi3JYu}$bz4j2eb&?zdku|XvrLQB%_n&;tf<%}O zTcX6zAm+F399Eo;eD5O-$ZNv|OD~)csO1+7Q<h_5#wE2^LRKMtv3l65JXZSQ2Q)rq zG-Bqo^}rUq%E=rB9N8Tznq}x^Fcm^`1dAVFL$yGW22~At5gR%CHc=dN*-^<|8a*N5 zO0yRxSfvuRr+8}sB>;+GuFl3xfQvZ;)IYQhTq1fOl3NJE*ow4Zfs6s0cC)QdobBuE zwjCYbyQ!sLUQoKw8^G-QW8C+fo!S=`&x~fjhx6f_O?qlX7z=Bf&0rarJ$@JxHUecx z#LQpJ{$c!ixz)yiQg?PjpZXDF-#=1FiSi1gBeV@z7K4(u0O!P|lJWvh=D4slc<?Gc zo*ibs<M|PVoy!6S$%GAOpBp-qgAmsf5w<QuT2M$E>E>}TNo%71R)TxjJd8YCPirL- zCcO1AQQm|%3FRS>*T|8hGL=Ej7ebir<p>vMZ`seuQ9ZK#w0c0x6rGIy6&ZP}?yt%i zLY(9XzD6G<qlekP;ZWZhR=?w~$awFkwg6-q*+`NFNVUAXTarhzgD(E3ujfjGOu&g@ z*WzWgK{uW0iyzCtYPN5j=?jA|%YgQwe0wZ$nv_<kf=6)&pkjsu9MBRsQdrUwik}Av zJr^}hs658T!W+u1E(e6AUASKa0iLo{m?+H6Z-GR}!vV%iv{`ymBTXW4^dZF%Fz!Hc zJzMCVv=c>4>YIKVjgbe1dU-uV!F$+)!*8p^OmL-*{~bj&$tkl$H~4o5lzMJ2=qUg% zC05&U)i(Vr<s!(35+()%yYQn?0O$r+*cm8t&z?p=EnlhWC~;5>A^Ieye#x?*L%(um z0P>y9m91l+vVSFB-j+K*e(lZdUh;xb1w63<1S3D7jLtihxRzd{3qy}Xcv)&$7c*yb z#WId`((>+xI;=r2gj~uH<!G1-b;um;Q6)f1POD_%lU81&TO~s{T<}!M6}0!sM-?ry z$`PLPReVktlsyzFP%ncmLZKdArBZZbe54UhqD$|BcP*hn=|@-Lwq}(^nH4Hci4$(V z34qiUI0S<-I{n5cAaLSE(Qt;n`z>TDr%HgOxeG1Po$JiDGi~1I=nkJ5$1@-Ufv;kC zrcHbDnAkYOFw|Z_233}L*JS{%%K+dUL0$x5ADQ<6YVdE%ziOuxcC;j=o<C}w1C+rc zpfdO;sH2!@*TntIWL7N!x^m_TsZmgg>qsnD^fnHg4kbW-pFn{de+wX?u;DxH)VnZl zOc(`4o;*G4q``Ig%u9)CjluvL!$e4u(L(A{5E&Esz>);t;RL{jL8rciPuy+l1rS~W z+0q`)EzJNP>nIpz0a?1|ZEk)@a-j2?+C&&vq%3~rl{dsiCb*0$&Lma8bI!NT`2i{e z(Fv#i@HpwFn9%8f8(DyvZ@gd_7gNHJY1zUx<4<k0Em^Cbd%0FRf{z)!H1KjZuM9tq zHi{!|<crobfc(&R7=Gnbe_{AdRf*D#wmxrj;L7#kg5i_3+i*SIJRIrHp^I^JvfhiR z?*URZv|LofqHJ9RXty}pNLh}6sxaK9lg5Pe8+=?NyjX!mIFL;T!8`Jn6!gG*x_Jy5 z{XXj10o~`OA{%vR*P`zdsPcO-?=sbw!Fqvn{5;;%e&1oGRmr)HAYXm2mt{e?k5Qm? zk^oh(_F{l&rQZcWmup}#*=S?AN=sOr6BbLZK}ixAf$rq_rL4h?Q}Z|U9nJOq!(mNt z-mYj?#e3^SR&^8d0RYntr-4xadLRXZ0KahZl|^5`(1}gfn_Q%6Lr^n;f`ixld^QX> zuJz4UX8jnXujQ-LvO}(T$P2-Y+7E&xlZPs!Q%spojSY_OcBCMLymDQz@sUU5_PC%A z!zvKdlnY;SM}HX|*n*coa*ViuVdz2C>m8VpccN={LPa0Al+h=HOkI|Z-^5XdEJ>0w z6wwj8Tw1$DUSJIpZ?VILo9JZ7+ucTf{ebbTjXwRR?E}Yp3;6i(mA*xNtY(r&qo{p* z|DJW#j2}yVs|@P;QK11518{?OsbgEb2hcM~`j)VaMlb)$kC{K(oN}PVDFvAeY)H+* z$+7@W;bK$q?5U04c)gH(XB%0PRiyFHwNOH|eaYn6iDxKFQH5^4k{662r(pK0)C1UJ zq*sYbcDT^9RXC4b8oo&|^_(WRRNgX)R$xjVx$AM_b>p(25MyzoF(~1Pflblkj^-vn z!l<Klz3^irQ2RJB{MKZI`#Zmy8MMK4skg!P<A7BLw^^7K@He9+&<4AbQIDj)N3(!h zg*er9Nna#VT=+yN$pjjcw<Vw+Jr75=#N+_Xx~!a}J18H+4dYL3A&frx7<h_bsjm#< zPM^AiMsaZ0YUhq?3LIl83_awK21$fpB|27_6d@vXwYS)+LmZys>q8dl8)ZVfgo-S^ zt#dIvfXUBd%fka09!%0{P#I8W$QS?48|5>(z;(proT$Lz!&vx5MFIm4(us}bhX`E2 zLuAAazVmipif_3DT&gTd^Y)aM5HEthBm1JjpE<<&)s1eKQnjH)1FA+uW2xdUpN0`X z8<UAfF(-2~RXgHsT?{`quE$cVylAtPrhLfg`>zzZQb)g~!&J8)e=ux6{l&2P=*h6Q zyRVMoOndY6nl6nq8|V!ROBd2tV7#NEW8u3w3xI*gY#(py#c?iqq>BtWjL#a}t~jzm zXa2401(r=2erxLBG{lGAnSLxEvjm1*rNh;<$i$a<lwFl?(zl{rMsFAtNDtQr&jK|6 zeo2kgfjNC2uW<RrIgOVtXg9?~419$`!juXa5N5_)i0(|syavx)cBC3LPnZ^r3oUNz zj~Ar|ml~G>i+UyYelOcZwE^T^>j)$Us&&l*u{;bcHt*~Aj>103mPYSvt4+$l+mu1D zy>=}FP(Oln#o2$GURq@7R~DdT#=}w_v7bd$C-HP`P!+7DqqJ6-Vxp{^-^j7KDxPf< zZ{i?AzTts%k^<v9EE(wJ^XdwQALI%}?KnXDkAxfEQ6u|XN-tz7<^&4}y#SV(^mxmh zS&FZS6i+s@w0silXq-kT6gpkbb7aPGzYWZCEe5?`;9=HRZ-q-g8+<a@X|dFIy*X_e z7}(aM`cCAlOqB-4BimFkn)tzhK^4E6qurAuYs#%fI$iGwRt`<lgec&OlP<t?^9vkG zzYISNzA)@YgD>{^#d5EWKMY3Re7DgUGMzigi=?=ddwbkRNBPQecYj}<Y(NqNMbJbj z?-m>U6ZoH1#3eM<SXuHpoqkTIs4S@wSlN#vb_1bEE!C9@M-c^^hb6b^pmP-@&y;dZ zhQ7u|ut0N~E@?A>k3L%%D<V%ojma4s<vuJlPw`<~@2R>Hpa^-ks6F-!u-7gI4FDZs zkhsEt8zqv(wn(QTgdbQ8Kn+~XerOQH_*<h>n~04#<ky;!yHu;=5Y^p-C&S+3kB6N{ z9}Jt1pXwL$OIe7ol^_$wG+q7CLQ%x+hXIbXkvA$xT6B}pqQiz~{`6%JEzRsO;L6bR z44~kiClno>-Ksw1xu(H*TW?cx(mzYZ?7#7zK@Fzp+h3%^HFrqGxx5PLLK~@_jeIDJ zWYO;=ER-SCk@q>@n93Ye@lLKm#79_!Dqeo()#aXYgmSr$(Iy8SMovYnR0mOzSc&T} zf{rd)O5{jGp?IiSF6Es<M2i0V^h#E71ubcTsY}7;MA_<M%H2pZ&|_&|KB$?cTxNaL z*w<ymtz7E|5F#}jf&u6^e>Hyl#SjUAkEK8ihYg)DzP%A|5XVa&yzCJdjm_=d`IJEW z5`Zm$zL7z<|11U&nM3GRPFy3>e9lANTE45*rclx*&)h@{xtFrh!H5DvM=J>W5({fN zlPePYID<OM8){1~QprYsax_Mv2{&Dnt#~n{Odulqp{Aq2hU4R`T?G5M!A?L>{B(xv z*4R?E+F!K$OjqeeUz6WJR$HJJ=$AsY@M;^e8iHXbgRqHh!b5K*?RKG=L$(5t_?6!R z)@+-$so<K1#ah0xZ*enU<~wCj#MV0kO1)<BWaN3Nmo^;+ATyP<?Awe#^`r5^$f$>F zyoyfs6Dg+e%ur4a=$_bY2k8YCR9&O^sGnf(p>Gv_*CKqYMBbG+iX@sf?b|MaQ8KMj zxIY!jk4lmj$DPSj06k%a`+_MLf=EE|vEIgNfTd>(@{U=^x10e)#C!LBmH^ek#qhvD z<1ZEPv@La2%~9_~0=2q_Xar`JGzPCU{+I-@!Bh;LFEi0;vlmfs_v?J;jp5+tU^vhL z%=>x^cjx239BxjobfW&}(Q#@P#Dl*YPaJO{0ojXMZCacHsKLc-o%i}liCuNb7=L^E z#L|v@W&&;82}j4xb)y4uSG5mob^UVK)vU>;mgV@GC*|WjNGRbL>J)G|{D<GW$HGr2 zoE_{=K|NiB`#Y@U`(bV_tKvCeSxCV;iDj+bhOfN9DrL}T?1(yfU9gir3x*I?jb(&p zmMA(}9WIuHNyzcMjl)S$SrY|`ISVMItL65Nx*$c`Rs6^hn*eQ)Qo~@zju%08^a9B4 z-jm_v<U*J9%cU@WSa}vl1LLLMdS@n(*=V;T$>QaYtt}aXG8{caq~|AQiK4Yx_iUr+ zkr{9Lpk5SEWYBrCL1awa$haJNFfBp|XMH-4K@xWW#glOKja~pmmO#=#QuUPNR7vL) zD}d5<SxU$7(IZI_g0ru%<yRv3MF^4N4G(P^V{|$gy(XW_NItv;XJI3h@^KpJJ8cUM zc<ShFG{)(NqKrK1k*~jStcx~>+CV}dG^bCZ?s-{+CHia4lwDq)D;3H_ts3J=KR%i9 zyU>=HbG=Q@erRUkOn`QxbJg`l0ep!=F8>o!>n&gprBS<HN(lP&S1kY5Y+o%4drzP1 zG3wHap<GILdm-^&2P;!gkhJLH)+tr<51%FpA`_<H_rfNM+d~VcWBEyfWID@fnm&1q z@|(gbC;Ff$14^$#1T3y&Sd>5oh;V6|nIdvJ8B2p%Hw`zB3o%W58VkN)dT#)>QvB%x zR5-?s2Q>vauz6WC0J^Ly(HtDk#u=TjFBwy6aJ==#Ft*IW2ab=r(TVPAR&H;5-QU#Q zef(tD`QR7B`STa*70)zIX-Q0-D1#>nsyh<rm~w>Up>WsWv>9Ak?v(+!u{!L_xZ6(y zaLcnbbjHm8iBI(84+D@TvmG|&Yqn`kzj*nm9eO&oOcJkBSMXN1K$8Fu#NvunXY7rM z4!Flfq<EVGqAwQvQ>I?PB%IO&Qz#9ACflVUa0zalGaVW{1A&f6h7n<vN>)c>P{LCM zsK*Q`+<4vjm5@v?_3Rjo2&yijA`j^iv*4g{z7;1nrjX{23ZY=0aTF1BP}6RhrP<O^ zFgyCh+uozc!<#pU!;!u(&A`5XwWS{vxg4y0QJm+-(ipRa*ZTG}$AYlT$5A4@@Uh~V z?)p)ZYLXfW%2^K;RA?%&bOz>`IT;ToWI$#aj{KN4;N}s|ONk(0l*jWQ6%8zbAmJCv z&QYF|grrBwm>r^$>9DyB3Ib7?keh<=`_c_Q9BDiK&QFwy9d3Z&;a+g3FWxj}Le@y; zkmbXZa!{xEXQW1$ZcYm!j9hpjgwkSvu$O^Z%Ga#$ioOTOemFkOr|!)h?vrF7V&r>! zfWCowqpbt65<~r{o#^23Bb|nDbo53xBwvfsKYf+b%2ZnxLWx`Msrm%#a!LrgH=2;_ zb|W<TX@BDJtRCHNmKW5tKKGsIh0zUA2CS7+JrD#Kry$VVMSG==5EJbw(v5P2-k2uW zLLo6((uyQQFpSQ1F-G4tgluQ?T?Hgx>9|x@=~`{ErPZfC=PaCjJw%i}V%#+*X?VI@ zzWjt+e8Fa=*PiPRPD;JA7?SOQ4-TVi5?heA$vl|%J>d^l0@Mk{jX&T-gj%YKB2~hD z14>xdp-}pBhmw4B0xWOH2y_toTU;fhRahH=I|^_B^TFQMaPaiWu>a97hm${jDdn`O ze%RMQ8Je;O&@X;iH}x<|$j?xzAf0OFkC{GZ{0?-;?jv3My0&Em+5l9C>f;r}N5@Lu zW9DVh456+Y?E}0%S6Xq%F9ku8T;GqI7i=#zaIw5S!d=#5)S=R+{2BVzXmrOty7cM& z<x(lGg?_6SH487M)e(@~@?<)qASum81dO*ZC$aV9hJj?C0V<3n;;jvva3(q1g*#fM z<BrlW=wi@gpbrCZS4QB0W`A^Uqz3dWZ2{Bkp=#S|XEN?E%6Ov_V~ub7(rN3riH$*w zNDhAHZBo8_>Lo(8ciOyCk)V9eoT_ey8LZnl`{Eatls8!s%39=2tWj6Q$)o<m#o$4^ zCrbsZ5I&?0Rfq(Zn6L>Ivye^}ppt-)N~C<@yd;lK<-nz!0yTZ-ioj<WH)QCtDBps; zk0ZCmlg8;OoKZ9N`dDU<go1dLW%%CTnS7B2rKJEhfRRW0p|aOByBj|kwpIUvX-0T+ zlf9$t5oDH4RmYD6j7AxPRGix$?LhsU<ydZJ-3rIe$!8YjnYTkvg3yw@v(jTKtM<7S zpeG{i6s!;ZaXc6F#lWMVHkG1CsHEzf(>7ipfL2KGb_B?unW8P#v)55UB)N?%cnxjA zcMdE{eP>Z`%}Cl&;uY$B#8qhm=L*louAu7`A9y*CF3<_Iu<55fiwwDy5(Knk)kfo4 z7Aj=V7rbZ+hcKNA?+w5zv7gwdYG@;FM6TH`QWaMIQe8nt6LD21JC(ltF%2P2qyqdp z-V%66{@#{m?Dq9JwkID98=6&F(TgCVpXAXIYJl^BpZ?jS4n&RnI%g)tZexz)UD#ZY z@wclzR(tx2$exV9J-+L!Sw0(p5-Kvg`gQHkZ3*Hxg>_!rnnv*z8G;xLZoPhx$Yoq+ z{y}b}P$d+8COt{*yXvu+N{Dw`=u(0%8VCUfJ=KNEymTr}!7g{S1zb_mUWf%W1ZCKC zBV|VI(Vi&zk}}05kC0*LI6y@IVH9bqC5$5t%2Oi=iO}~FWAJ6>IU692tE+p>Zc|Vi z)MM61d$zO`%#0rfAfNEM)bHFI&FXE7#s--Nby%1Mf{(qi7=svn7>O(=bFLf)AnAJW z6TNxe21A#Cs~iNwuv8%Rk9ac#!6z>2ih2_%c_J?g6OFuA>4MLq2x3Kps;KdS*dT#j z&J;FOl9>c$(Krp=QdAO~TVcwaXDj18(}fDkRHPy^pKL?V&3ulC2SmAqIoiVkWE>KL z#b<CwTX0z9XuZ{@>SYHTZ=$O`aTxn7@lw?8XjI>;>ll1GD^SP%a84v=l(J;Z7cMyd zg}U+)D#{FBgW+sJmXf^(S!L@V1S&|UFR?9WscO_U8is55jCVP5R_FNQvtWp+H2HYd z=E{%6Rj+DCK2uB?jq0O4B3W9(XKm$64n}X+%A8!ZB+_z}<g%><Ai;sGd-nIx&Z;IU zz`UJXn$FvaSfr-laLbhp93-8(5$ymj7}^_TN$hfrXDasPhN!x`c$~CK8&PIUUZTbo z0<KKYpb=iYCWma|rqGmNicvx^7?*9LM7%cut0aCxznTPogmot{aedVaLF-Y=aD94K zC5f}vtAnVvKM}PgQpwRE^tCm8d1GzZ+t*&erymS24i0phs+NCqwho#870H{xr01t1 zmYL}kNn19bmVLwc+moz)F6}R5_U}L)uMI%W0y6W6Tnm!V(H*?8r}-Lf<X_X9z-Pmn z4)k5QVhLJrcY2_jm4&!}NaqLewgj@g)4Pr84tVC>6wwV+hD#bicH9s~_iYv$ihK33 zOx(eb(I8uTC+*&K@oYGwc7*1aj3et(dZ#R<?LiP<ZPOdrnMtWj1|S>PnO*VK8A#Dn z!l<<P_oa5hp9f#1#cT&{1w%*D$*SACwV@3qPJ`ivmVmFchig-_JP_92uQlPWbr3ZC zY(el_qni2iaWNPP%%F>=o}<V+`HHk0w{ln($i~QH&{foiEqP-$2^>IN<f#t}5^yor z-XhCrq(Kop$m!ye8-w|XCDc(UqVhsTgc?Cz5tvXx&^ggsXVHwKSck7*<xBA>7^gRp z-Biv%D+^=@mO7P0$004c3Rk=c;lpMXoV|HA^k{3M=PE;xc8CaEERU)k$(Y07<BK5| zmz*)m?4a;!2P@uwqZ*YV2pnGE^^y@U4J~z<2x?V&OX-#X(J<;{5!q_1l~X|KUiIT2 z<ErQzZJnXb#`9yQQ6pyt9O-~7O_L6<1*4C#UV^!N3JH62C8Ghl0K)FVcceeV;4<xj z8SXMBZ^ZCiQW0+Vz_|sQ2|8Uak``#xApIv)7?}>Z?9Bs<TzaOdaA0n`L#0GpRb*Vy z_Xgl?W%eV&TfKB?7HoM1j}_RlWH2~+e4(mqk!}e@tm^AH-Aw1A$#~PADvZF*o!wzY zUjpInIU8)EyVl_A0j@R2=rD*P!)N`;3S_BwN3(r9_BHdTqdB-RFqr|w_=}}q>B>W- zG*|*wO8TWPWAH}HzZWMq00(9P8EoB>r36NTJf6k3b7Hb9|2FOzPy$OL7`M8cE#lya z8?JCu#Y!!a-+`ir03??Mj~z)%Cx2;^*O9%YgbFqUg5FUVO@!iJ)WNS<0eYf^a3nZt zWJ^L+_y|xNkWVP`LI9q)Jou(z<fSwWJ{x`*f9%5xBd}%xF`|%E`3U1nsnFI`p1dIB ztp`dzQq^6vH_&6uaaJ3j@!}9@WU|b+cCIwhP(<jt!R($4Joa>5=&LuR$6i41|C3?h z!P8LPV9*UtCE>8~(#6IE1VsaZ4G`r)Y4dE9aZ4I*4kBh2DGWu*2%}May5U)r0wJ=} z1P?Ou**B}kBXlNUX3Lk9D5GRIqa{P!(ue>8I@bg%Ko}PpNWX&@K`EAoyA=se-AiBz z15x49sSyV&XbQ(ylFvwqQgXC2mVdnjEEs3{)wzC723c6a=&1h21|74#>St(&9QN!! z2ecR<yV4I%Ui{#2aoK^M9p<GGen7asRKL|$B;79b8PzYib!ZXrk$2j3xo80u3qRxq zZAgtQP-n0PyQC?<gefX?vRwJqZ3r4EhQQ=Y9i~Yt1`%HHBR8A^6)qpLLf_&~wZDa^ z1HUbO$NKg`C#D+(_ZE&k$3?k{R}qy~)+(5ihfnVzn9|_UFv^7rCxEdGBWBPjB7sp4 zJw>FE(o=5oc3x>RwuL}e+V2g(uCRVS!K$`iqZw=#HD$rFL5~k_G_peXQkR8kW-Q-s z>rmBw?Wba6{rbU&nu$|KNJCDejRviLP;FbV6pr!7w^jKLCog??Cb5=&H3PVd@uwx= z9nA!8F$1V{n1Qi#=gdqGCa5}CUIx(&%G#xtfOQS(ln0#+=q1FPXu8Zhl764p5cVDJ zsm@qx0LUP|9_Jj4BThPze|NrqtV=-o&`ceVf4H8e!i6iIF<#}|=Qpq;O>y=9-PoS8 z!gF1SFJ5EEC$thlzcwJ-;KRsa87^o1WO#9~H)r()3^<J_jHV_;8KgWJtZ5?{P7K(z z4fb%kjnGW8K*%4<fHWmO<Hp5u?wZ~v=f?`h0kcFl_SpN!o;_ZBm*eXnT(R#j4FzM+ zW-Pfr_ldR_6tn?_q=St=W;tVuN;D~hN>k8fMvn~G`jbiwAf#ajj)>`l)Qvpz3yxrt z1kWUrAeUo=$9oF5fLXdlROt{$u3eviWb`yCt0+gGw3ay23tniap&RjnK~on%;6-PV z0rT74veIH1ILOp{XuwsQQC<6GA2GA1Pp^6SI2Vj$i$Xp>M)>hT|3ke{PwH2g0ptx} zJ`G3PaX)AEP{e_*YywouTXunN^AXb#_HAus=?F|r>nUR+sGulAz#;{(vEh6`Gt<}6 z;%eB;x8R`U8awfXHQyBQrtFO4S%)tEvj|ep3vL-~BwC849E`|7E2OcAkTBsT?cyuH z1H{umrdyIi2DLpc)1U_$4m!tLpfE)cl4ejx-y49-O65m}RR!OjY){oyXjQs=g3&nQ zvFxbs7TsY(1^~|JlcA<PFk763b?|6dJ31X!&o#i&=+#+X=l3vU^EEtLP7{i6t1`QX zffqA>@zRH1{LnzVnFB69`>;5-4d-9fmK|~R+)ir+13?CZ*7Cx~u+T$QgQl4ua9b#k z?%{m^dy-HOIZ!kvVC5D&=fX_;Ab3KfxW|JIZPXs2q%pw=HO)e1g1TA&G~dlB?JnIY zYxK!WUf3`}=lT#mzGq`pXC9Dqnb#ZYWd!mmE{wk`j@_^kh(W0O6`g$-l2Vh{+H-ZC zv%)vm7=CIKIxKuu7wTccMK#7u@|M2$yTAWv*wS$@9D`IZb0GUnvxEF#P_vQ~x7sj^ z$WBMb0<+Qa;uP&q_1IOIjZyLpt9Z+R2%4%J{Q3*Ju{AVKODOv<3fToGc+$v2N-Reb z0u#8%Ec6y*x)|+8!_}0*6th4AG?>{!M`V&k%8xfhO_TVR0P#%AsJd0z6wZ|}O0Y1Z z;ImGxg-LXCq9kqt5eZg70=<0TxRPg{0KsH~o8?;A1dg1jURml@dssiyOdiIZ>R;WL zj5!&6Zil>B7JETyA3iu)fNQOOtgP)=hjV=e<mBjZI6gknmuAj}?QQjidQr&PwT`W3 z(8Nkj>$dd7CpBF7zNgLscW#890Yx8wuqu^F{(}=)<hy>HMm%vY>)^GDLZ+rBupZV) zp~OZ06m<Y_P$i@JLPn$!no|OevXfmj_xqX3{e*8rQElmMczW6>7D3{9aZw;M%N3o+ zvdEIH;%bP>8GOZ1f%5xAgA7QOX=`5=P_!f<{;a1^1XxSB2<@lJ4gKB#oD|Pb6RE1I zYKso6bSbRjZYLF&-vx`BUN8pZ^s`|UX``D3z?b;g2E#r+8E%?IVJ2`}heHonFEtZ) z;(?RTTya)b9Gd`lXpJq0;kV76KW6@Pw%V>{`?$7w`Gc81`51qEc8l}ZnBlRSadTs~ zL<~TdY8af=L9fVQsJ&yd7WB`cJr+Y|b(XVtk4C>isg#?C$5O5GE6VZ<UVTuMQt;7L z_7bM`UJ~$osvbTKyZ##Os4Lth0qBUC@<S6cU?{4w+X36;DBv(Ymj+ha-IXrRQRA)4 zYtGyAkt<>FVfb;h#ufXnwET)Oh#}Z!2W{BL%nSn$OTWzevHuF+OS*ca*Kg{s)AnfN zq8BaN)+`N197}%a1>cI=Ff<JEmzwRVy<?WIc3kqIA-B+7NiG*NL$Rdl+)^-+VI^qe z&pHSkm<YIJiatT+gDCk6Jfo%9UGk7+01v~}zTgJ?W`re>DfUKIs>%vXmSKAV0BHwU z<v~u>;;cU{Pk9$fi4A5E8!$pGVBvNbzBEd|5?LsRRLruWU2*{`ec;bzsR!4Yj64qc zzH~jS-jrwF=;r01OPwTerS^ECGXXgUh@-I(z{@{dTH59FaNY|DRPASdH4cFGxsYl@ zloc<A(6)Q$H>j(yK{Rv=bmWm{2XK&Vn7UZXPpt99>P7)1u4u6)43Owt)!eKX!Y2Y# zYNu+lS9um2&qE_F8vGI`KY|75iGE(;@1h~4Q2Z2$i_?KDYvE~5&{UBXeP0S$n&KC> z35`I}2aP3#ya-0P7v^vxo8Se4djanaz<Z16$0499X%}u>M9Mkb16s=|3i$z}GvJER zxCTfKd}@{B(9p3h36he=at(a4^W?8<Aay6H8I>!|0N$+fHn0XGS$d(X($UNb&7a24 z-apU$$++9ey?#4>>z5h9SemOPHwIoCfH?zLPY)fp2X}S6dJ{yQc$_~NiYYye3k}R( zj+PP_tmukElX9)pS|G43>c^_6d(MI_^NS8C3d<{b<@a1r12;}L{NC_0+zesF5FBAf zh@sNV_%fQ5JyMJz<n=NuJeS(&6eya$L}^_U2OXChOZXA?S2wg|hC#;H6EN^DHT#0G z$G*F(i&Gu2dtzhoQsL_~0@)L&5!TtIjm2BJabyQex(whO8?j_uMj0nXS}Q4Ves(&X zo@k~<-vd59IhK6A<RLkm{E%Q)N9~k$bt%2rcglu-_5>oEJz)Hpxzbyq-bd)YU;M~W z`@#^^;O}a%0W%g5hC#R}n~Fs(#}mo(=uV$Pg5Ew{BXt$6pI;|5wg=0XjFO2W?I;hB zHfH2YZq<+_D-w1NQUiw`v464jz;cI|^u*w2nK*KFaZ7#d8wR|0(DZSIi@)GDT%aLc zJbVH;5w$S!f(Hsn$V<3oAy^l>=>kJNQMVX*7w2kk)H7QKRR1fy1f;yFCT!@c!UgB; z031N$zh909iZ6X23d4|>L-=gv&hGB;M2F!&(Ti|<yE|@2ZM%w9$=XldJFU@J4jttd z@|JLWV+(?`84|DoKwtX~S|V&!1b%TS#RZ|t!pO!|-15!Y;*(glAqv5+{6;<vI8T|z zvZRu_Q1?ii%Kn~Xr9+iytCv}MJSbTU<4MV9P4TF+$l)X{g97d!T24T`fFKm3`-NG; zB_lXHWFcS|vhY!L9a6&kSS4pkLiD)z24GjdKUI(lvC$=;=gOV5YbmQL!x1YOzAiJM zd31siPa_HU(UaH!06+jqL_t(TNv(|w{C!4X>7XCdjKf-jQU@vd+v-5~_YQ{hBMsVG z65$sz1E$R`;r%cu3G6tQbiM4Wj`ctX`T5uvX8*J#%*!7bhs^-=5^&4_y3dlt$Q7NK z@*tiSo#(c;p<_L?98If_gHW{uOx|>@Y8DV)^TVt#xor;Et!_ejD^(!ov{~LlRuY-~ zBz<7UCsBG9IS=>oNOP1;91V(Q;%8*8VK1Ynzl*LCDEg8y_oJOkAGH(0Hk4E!mufr= z!pyQ<X;$Te{ZlNxou4SI>+EQ_I6WTDPvtv)VuP@jggv9DoO*Un#+lFe)3Gj_%tCMP z`bdtgEgj>bG^qb|U7op<9|qv@aB_S&oXG&h09etCp=SYk!9#;SKWyq{0opI=(3U-; zt;~A{sq`l=GW?L^wkBheuiubir&)zig_boRLj#>~)R@b%3Tj@E8E>;KDZ|ECqqT&H z=~*sZ)gyj?5i6SDL=)O;XcVm|AR#pJ<YizOEEt#q?mG$wHOP=kENC5CycL<{^=J@@ z#B2Cs=xGU~M~|y;`AAdUslG7YW8a>>-XWvUIaj@72y&4f%G&*x48l!J!mMNVs$&1r zUUWRPkBZsXq2iBpApY*oj<&*RCR*(!2K*|^&~?;guKTh$)JiD5ks_oBW7G(*5SVg= zRfjerdblMA|LuZGNchEG{#YT)=}J4)4V9;KKl@k}{KJ&*sVJgJu{x3vo=p+Av8c)c zw4AA$uoeiU?jwX}Q*i(am_5S~S8(*>`38pr-n*g$Hpjg;0Q-{qk;AU!tP~qxs_~jl zp{fc$s+HB}mJv|XG(rU+VMay+B7>GUz)KP&cRAQ-xEOy|ig>9*1K*lD$1Qbwdm4OK zwV&o(OS?5Y!;r!+W;!8$8FOv=&0iUO>MU9I#Tews7YxAI`<F{@GAh>uV*vKPt5n_k zqbx_vXwY8W*w(cp8os|Nm~`{F%Si4pGc@tw)mSBPI0yQiGfYg~VktZE2~jTrgk|Vf zvdV9`33o)?DI~o3d$L}}0z8p;y)MY?VJ2Ht-{N|{lAmHL`Y=D4@R(`f#|rhKrsnom zvwj$W%=*<P`m>WG8ED7D>G7-K{N&AWsxK^DU<B&A%-O*B5(7_yYDMjW^Y}P}ZCgJ+ zc6RrN%e_Z30{0?K5=_UyPJ1U!mh#R|PZegrA5J=|VK9sBSwyv)^NTR(E@U9^&1roC z*tGmm^8QwM1jC?UMv!ylxY&DGE`GTy@2y}92SEINO(7q&u4<#UG-PJPOdbR!d8}hU zwZ%~B$Ott>#+{mO(DGc`kc3AU;UpX7_W+aWRu#xkM2T-CEfBgJ;fxRmnVD)C6RdbD z!=ke5^4DlU6#ay#2O@J?K2F#2)dn!EQxCq4OMAQE({20!QU7(N&WyV7OrQ)q`Wskz zkw`68|FnT9H;W`WU2Ibzu&Ey(+d2hdOFuxEEspIfS+2#9+32(A>{u^Ci<rO*1BwLg zXn$QF)w7wT2Z&8PX17nQAQrZ8n`5Waf}EBca*`dUiCg3XVy(%HGbBLE(?r@t()S;k z={AW@BG%K8(s!mzR|}I;ok*zybs6c_$!aL$D4&8Tp-u=bsf${RWHE=a5X{Syv;;HC zA}eGO55B!O03Tdb-#;N$#zhx~(G`;f1h~Sh#z5+BU)9J=BO>6wS4)FY5_#*AP4}IF z1w~zE>2AnC2Vd?N)nqk@Zm5IYl>ztU;PJ4onU&L%SL%=X$_Jfh%=$6&SF?Y-{maW9 z%o_5h?~aT-E<Odv>>me1Z^&QQ6$T&!6@ywj@>LC69WDl-X8_mOc<n9!Dlqb>M^t)3 zP5}VQ60lw&tsoIg(neSDOxYeBlZUlOW*9!)+z;s6-S3l8_@z=oO5yZIlE}mu{~klu zM>jrKNSSjnYsUU42HZM|<xI=59Kw8h!ff2haD4P?I6Hnl9KU&P<L~tF+u=g(31je5 zh9P?bSqf$r#uck3!P$Haz&i&|hh6PKJ$wA2zVrK7>BzX;mVu`RfZ@kdF?x}<_Z{*p zMmk{t0p|w-%YYpI%M7K_rL*{3XHSF9CxltT3-V(lLNqiqgxN))2EE2#=tc!yVI><w zMlK99;$Zb0(Uwy<8sJ7h=*C7(Jg|6#EKiYmj_`vf$t>SOn^eV6r3eBkn1Cu58-Y$D z^tZ8BMi@M;EQBX)TI3<9BH&7J!783U;JN@c`o!BqP9Y#B4kF>gc^{s9zvauUGyC~4 z0A=7`szc+)EM?-^Uisb|sD8-#Qa|RILH&4T_RnR9bR8>1oe=koAhUvLKvD#wPAC)Y zOo5rRqBB@UyBc>HlDKeWE4(5Mu#*vi+H(BCFa4I#!swKJYhosWWhi8Y5=j~Wr{SRV zT*jBwOT84a6!-lCZ_{iEyg-!u68BcQ>@rBbAhA6v3WqF+j7eW!x>19mi8zwFI?RaM z9emYZIvJ3RX(ZwS-g^V^0fqEKkx<zhsyv7?p~0ZzNY^l<0gcVXx+K0DNi?`>I-(HX zXOQuhrDjL2a{m*1p!ECKjSD%&PZ&Ko7FVA})c{LG%V!!;*L7qE2H<181-x?na#%ao zjGP8wOfla0<<~PafBx*7!We*l16W31eeR7<!ELCc-4Kk6V;NQjTakd8wXpVelUxsG z%m8W+;3|6nF$VRky^KK5K1m0P!sDv^HXCC(@i>U2xe}jfKaz8*We<PRH$fSATX^Fa zBfNe27jBu%g3aj-Ph`t`%AL!D_d!mC)%+0M^BFFn&sY;q<EjT&&otZkV+KyMej0$! zWc;xVdvy3l#^3AV&C6%Q$?NCC@yoA<vqKq!`c7}m{>k`bAD~_i@eH60Nen<bJHE!T zt{(uW?CCo^)bg<g_s60Wo_&QLtfd1ph3Lxpf9Si-k}=<Tl@MMC@RkZa1O618TKVeA zg$H{Kfg12hP^N(RqZ4QL4}+4KB-%vK2}eS9K#4R!Kn>C@f1LzYT9KCI2YK?0!o-W_ zjoPw+GzSVX0N`@~0D-#V*(N1B^GIjNI;wb31Q8w%`h}1qBI`{V2<`_f87;8zL|`TX z9MYXw^9*jc#1V(IcO{~SS=IzFm0QV)B*aNu=@P3RaY6vx)O#6%v{{Q444x>qC>v;* z*^8M#V&HXjkowPKZFxD;Tfm$LXeKd6d%_Re=zucZdxcNfG%77Z`SgW_psrrdEZoak z)&@uNo-#xiu97wdHvmaq?FCxEMN7OKq)8s2z5^<vq*=z_k$lHsr}$K(E>@a~HiQ1r z(4|}yjiAG|;7DW;&sl2&DY&$ueFd%{A%z(22vLFWg%&L^Q-+_>1}&7Zp>N0wa4*jU zjcSaIq4x&hSQbB8h$^b9X58p^ZH3V)e5E=?NVJDbLNuUJR&XRg8|pQHvH4v)<%TO6 zT^@jFnd;c94V8HG!1$Bhr&$yQw2^vM{Q5wWmVbAKr}`w^+WGOYd2u{w+D4yelM$%# z%*VJ$nCv-qpd1|&%fMR-Zz@gC_+c38+SFxw!M&8CPB(gD@}>)=@CmS-g~7*5Ae#MK z)m|=trNOg>;_F-$OO*%g7SquXZ1{vPqnWXM@6ld|W$Cvf_zo$P26EoTStrUbmBX{F zjAQhHi#>le^C!bkZ3W}+Ond&A{bSHPIeH_*@A>dXhTp4aUkoSTemNXJ|7^IB0eErr zLW482e)(p%3`l0IS&~yAng#7tKLSo)KOT;?{Cn=bgU3pnmrGdURmUfV!r0S*t;Wky zF8*|vel)lfmLcaOXp|4mg=1-%fu1+WA@GYKRaoR(fBX>hY^L(V=j1&52Y(i5i?@ds zQ6&TkSx7F#fS0k_j4DfmE`?S+qsb*a1d92Y1=<)I<(PJWLKT%w2ys4*X{;dXLL$bV z;!aCMwgC94C=4(gg3yD@i*Pvy6OY$i9}!V2qejpLI(a~eR$A7pNF~$oihE-SEkSS@ z`?Mo|O)D+*ryg0pr#}gq3Myb#DoKf?O|VUXy7jR@>szAXEI@wL@FEjGBtj>OXQI-m z%AKJ~4h`%CxV1<|VykTy#t1pM13kZYaR*0AGcLI`3fK9lm!nJQNx0=*<ZkPYF8NzL z0;sYaGb4PbXykc;bs0EeW&D*+rQb9!okR%Cn*tPtH)0{h?T^w>v>Apb8hJX2_Xa~3 z381jEv05CQN+jA1vI`m-5PKW<-T-`?(h_YI`JC;(YHoN1Xe4bQCC-D51!iDKZuFT@ zRIeg52wze0ZYU=1ITWT7WI)wy2g^)g^{sRDmXaja>Ue;Y{Dp4X?xfimb)dRd#JjF^ z`~rv$g1*x78wTNq49jaR>#fKbT-RrZZ1~AvBdmdf@2c_*-wj`y@ngvs!%qV*#vlHw zd<Gm3I`Ttv-IZR1QINq}Mk_|3i~#$<e3AFy3;M1|guxk}@}R~QZNz?}JIeHm%#~Bz zAkh?Ak<2v)UNmDM`RBwBjF-&bhm~|_b_5tCJ?p17=H*x!Nf>}J^LIL&F!RT(->Ywj zmoog`eEZe#=IhUf^H<M?vzLDwu20|SOz$@_<EN!I+CDNpaAN?Hh%?RLt(az^uk@os z!?c>T&VrP~2=vmO3H9bVGk&x!w-1w8$9N+-2JuU^YYaq=lW_umOV|lT`py?dEibav zo6Ed)%&d|g4qxb2r9)XLith5u1-58-y2z2u)zL2oc#E+@2@B11uMWQ+TIdNwz?V?? z{1*`fDSvj@w<b``X;ms=1h-i~#PrXgnHy*DmafK;AMz`Cx;#_wBoPDwaD3tf3<O~M z2+Z!5pL9iDzWI{ga=GP28IWJ<9bfgs%rI?}{zDyyC{vKUDza#6+0K-9d^#{^h}FMg z2(GQ^JLr4+!{f(Khevu5WL>Kuyrq7n!^77oFQu81$NaWzS<xtl1|v`$;3G`d3mT+N z<0bq-G2W+~z$4|6q7S*9Leq#cK*0d_UAGbopu*r7I2PP8*aFc4pwe2#UASPH#(F{1 ze28utsbPJ4?j=On&D24(2_efwMPbY^jU{rzsMIJbP<|%uXD7oGnb1j$+l0j>Bc3i+ zy$p_|QdJ>be-IU-3BNb+-T=I}h=PFPE!T$&hJPQNiiHN>-6(MdxB_v9lwwSNcVc2{ zjR|~nL?o11z^j<)APGA@rzPX8nhJ32PJSeN!?XjM{nMbgp@y}s!SZJ3V7PgtWit`- zD#oSua%oLY-x1W86;`x~TFYu&s~XICdu~Hd)Vc;Hj6Hr?+xU|#!gQW~@xzTaRN~HK zQ$}(0)Y97qpsZGmKssD5_<W7L4hifcaK<8c^(an?X2$koM?3YVNr%cKjQBl@gPyaM zfH`~~FS@y3GRvRf1*E;j?4M@g)J87L`18!)Sr~tZuZP!K@_qUI%i+aWpALs#|8Y3} z>XYGGd;YFZ)OKi>;$=W`OH{`e&xU@eXwb$*^FRxw$4eU*FU6vLdD?^Owy#-2_Wogj z;IHed@^ZcFp^80%u{Y5(lv>7%FMePcM7ys|{mz%#z71OTkI9f|%ZJSVw8jZ%x=`A> zSNY<16pHA<f=)R_uei%M4B82Ga7#$xp{O!yvMVvGf&6&Ji5kVNr^&RO6r-KUF`WD? zDY$U3u=#bf+PcASc^M||P77vmLK?5QonUqoV8Y5Pnm#UijEty!A(93$4sz4w{1B#O zA|K?%WEg+OBZrKJJn&)Y@naZ+nUZI1WHbPEu9Tr{QDM*MmR@{2knwk*Z=rKE408P= z#rp@9J_*`6WrZ3b;mf_Cs+y<mlLu(Y6R!M-HIQhg#!BI*=>|72u9>VBZGjT9+!vXv zq_Ae=)?bDE?!Lu8K#Z%{bfrf!bpl$cG*|?tyy9#4dBP(-A^74_%gL}gMnpt=F(IO* z(V|U>gjAfU6nC^LTQL2`lT(|aNvCuEXgCnN0VQ)0Jiz~17=Wn#W4m`rv++1U@i&Oo zpT-1o4UJ^r>moqC5nt{K2}N{F5LcTpPcoMg$WYOo*~G`DdJVV?lsA{!xUcb*8NvGH z4w)M>4Gj76cr%g1ml;$ywFm2FOEkMNQ^P{?)z<!SeRin+l379wKYg!P*P0GnUA;cD zF}RLVC}m}9dXFIT*eh5avGuh6<HHmKdkoypi5fM(wBy&jHB&e`OWM0H3G#S`-UvnJ zq>uo9f6i%qf8wT+Tpm-<T`_bimhz$RbtGKzo_^$nqmLyuWmrP-iK@ZcP}1OkrFxIq zzu0ttu9rAY^)|2f`@Q~lc=heq!>ez;7+!z%*>I+%-;3AZXqs8GcbdWDG&UMPgRosG z*dmp%>blZqw(<1EaCY^2INH=#KE$)GmqgZlFf{u^<4xcT?IrZGvJ6b8p>(w1s|FlP z!PlNKq77+Ff?f(?<_IGYW0ALl&(xUM!^#<gEFXHnM^{~T_7#?2?KRX-e4iH^Bg`~K zySLH^Nm7C)?|90P3EhiW{0>SFGM;V>6`+HlpA#Z&;YqX5<U#q3{z5>aCJ+h4&?ddT z%5w>@K!oWc?5pGh$0a->8JA~S4Y(MGokYtyEg}K}FC12hB8VdtUyY$I$uG1~=Ppmd zZ2a*9R5N+2dVz_T(0GxFGfd&HEHN|czEMA9f$?M2KQLqv#>^l+;M}1U&{QtHIaR|K zLJ1USffiXKwF$f_(4`r<7<E8$mUYx^-ASoxTfrs^c(?^nCO(k>Ojl@-7^OEFvnB1} zekSv92A5uvPnZ>{cnhK%wBc8{C6;AHjv$NXRYDjelMh_VY`&$ANkTAkPT?)RrGeza ztE$b)Fs2d&nQ-@yrWJ+TQ_4sYOOxq<Ke+)os@rMxJq3H&SzfJTdfY>jYxEA3G?)Ax z>_ykOquw&=PDk8sY(z>N`0U`KH4=|xjLN77phN_kyM&|{yo%7-GvmUNh&x8nXofDj zz7R&z{2FG4j!$o`Yhb<MpwtZvG8ui$49eH*8^fiJWw|-iAbfKnqmP+E3_pD)?n>Y6 zmA@t<5ZD@c{dBQ`Cb{Zcr9-CbhlB?uA1uXfh=$T46x?MZ?qGC>tZ`fRAe}T9^74wD zPm0ikS!7Rl0#Qm4dAmF1gCo8B93*{GJ<kN*3F_em?)iW%r2+0TORm(f)V$4y3&*`m zrTjoB=8QO|w5cZ<QCw<EEQiJHpN?IT(S`BH`Fn?NUJkEcd?VxUPs5w9J|9lL{&cv~ zMtb%b@WX<0`BrFy46yz=i(J}b_~emz@BD=ew_PpoooS!p>t`Z5*Jr+V{iZNWy51iu zDST;UMf%a^Voz86n4xWxuJ;4djy0h3@`w!v!Rrh;I>d9~*a{&<Tm(^u(QX|Uy>%oX zy{=`gIxo<K5kjL0qe9#kz%BCV;l?n5@UzlAJ8Ick7V?VBG?pod{l*r7(#f(^u1Vur zOwzSpsgp!x3YkDlMaqPe1lOG@Q)bJLf1sfUwA=_gGWsE=i=#sU<yROs!pYuI1km^* zkgtE2lNd1Y*7YO6FPV{F{{T?mqcFyy)l$E~;qy$R@Uj|h!KWmkFS6l-R*wGC+Z-rM z;dlc$+6%v+nL(Vp(rbhl4H#U-BPKD$GD8G?am_eQJ7Xw;OZ`#W7)rtih=IpssSaK| zpAM-C646&2pnGJ`(Iq7{dw`c5D#TttX&3rYxc(0fp+;|-e$Zq*;Xr$r(o;s#3J81P zra8#u5(iO}kYY35!_8E5_!Z8ek}x?*8KoNv_$*TSv|Ay<2uxzb1UBaOYJd}`A%5n1 zKv6+*8+^t-iNe#%m>_@n2ub&9lj6IoQ+ygbqQD=d{<Hv^E|NhQy9T4D8Wo0C7(J01 z17^9#TREzRWJF*a4Q#?kTOguKontJivIkF{B1TjShYvlxkH(#)^iZ5f%XXjixZYH! zr(evg3SaTorDk7NF#crZt>_!QD_0D>G5}=+u3jF8L5LwJyi7)2@t`_Q%SK15DG$Sf zXg<6~7;OzP<j}1y*{2HYk}&ePaD`~|O04tgZa}nEY(_rthR$5v?BBsxcyuBy{Lw|7 z_*XJ{?4`}<MxF?n8X5wfBVWNvViSpts);uLRDcbTq@+bOY|;{sD-4=z%_wtuiB!wK z7+jwH(|La0_ovyv*X;S@rH>b14;MQ2WrfY9IcOr*WuiftnHo}zB}nQ%v!{SN>(a&w zsQvn3(afBdfzNJ^^kT>dUZ&g9OG=wMFnpc8eWKmae!v}lx#mDe$DHVGWR{f~z$0Dd zL+uznV)<7rN{_*wC0|XF+eaCH1xI{w3`lN2a9IVviwOM<t6P*|gDTOWPCU;v`JOh6 zVh&maHwSmtaq;l%681BUJmUTK2w?o{hATctDdf<2T>4EqP^86(;*k<#2tkQQ7QBuo z+<Ju3l!&AU55vqgSwf~B6N)*HX+mGLvo1t!sHt5^UcA^7`;F_RGixqh&)j0ni3J0g za-*!6*>jte&kxFqd(sw##0xz$z_bmAfuV!bhbGm*hsWhcAYGESa)1v<*11()EjPqk zc2FfCA}%)b7gG`8m*5dbGxM2(sly`0j4gF{yQ17$Js~su1;HyVf+3THp!p%(TyVtc zKg&5}ux|dRuOSfeXk)51#RFU`PWW*Zykrt@u8DEYw><ktRU-<0`Z_HQEy@X?QV1?d zeKKPi1~lqH38-GoMtwwJ%$u16r%i*aL`yG~6VfJCnK;80p3VS9+QqJfdhQNc+@@Se zHTa8sLOY87p+j@6?u);bK0GWBcA}jpE?y+KXoLgJLQwz#=&H&C-dr>t8iF;T(%mQ^ zFeL987s!Kv_t3@56db?8tOrIE>2krz*vbzJr>#zr-?&_B+IPjCuXQbtc?N+FQ61<F zGGze9rKP<qy>+Q;xa7zd;jXkScLfbbpo~M$_%Q3E^hnJ4lk7~J9Mzxmr+lrFw=51D ze==N~@rV9(nTDH$$>DK1JN5|?r}K9(;;rmPSRX1<%gac?if$e+IDVg2XcO4}P0-M+ zsh;eqZy}Loi~wDNptEc4{5~a^Qb_St+ikMlZCMi3%^4p=Q7@`@{xASF`^Vd{aps>4 zK+XPf-ruo~b~${dw|->+9)0_#;Zkq=4i_<)tYCoI2vpq0AFZqELn&lkM6wZQ2F+=! zt)M=gu74nj_WD%m>WG;Wy=ZcxH-vX~bxe`|*k`(>!=m^04~Bzd{Sa9{8P4@9hA%(( z2aYqSRGg5dx;@gyJxJhdW=Ksd-eT91Av1~bwGh$s|Npc1u1$6vN1A5V{e}WSkP<0% zuXVSr&Brm@{r~@DW^L8ey%Hsn0s$22e%t4HJv>jIg91pZTP@lcvMNs8JUl!iJR&?j zE-B+#76nQ97<&Bcs;w-@pkWihPs*4;k?<cP1}y`KXrCev!31|oZ!!`3OaHC(2~24D zfi}*N0x7p15!ObcB4fm0efWe<6JSE)z!@Zj1=q;Hx)}Mz7F#oZ+lH+@;uFcn)9~8T z5D@JJtV#3eAaCf~V&JlU)b1T%6axK}n>#%n$s)wjUJ>L>MO^;0sV{kRhj=xEG$+}S zhCCx6MEI+;B?wyHdZeI9lfrJ!5&c04=TdwCJQu2x65n_mSL!zPvI+qT&%nBH&f$R{ z@yldSxd9X0j9Uoob`(R8GtyOkRY$-Jn?V1m&nCk1FMlKS7?8@U{%gMsVfJJHVpn?# zRzhFdxxbXLVP4(^piosV7Khphx(<nLJ*BeZNPRUwb)AK;L@*v{@#(sYZBT;C(J<8v zw!?_Wu5=?naLN?`gM6^1p$aepg52?GkQ>0&k7(8fz=3}S(k?+i_H<lR@-eu-U-&PL zvZkl)v>W4!Z#EAOLNf6jX}wv;gFSFojW@fPPPczfkOGicTO2t>%d(r3Sgv1Dh;m@8 zXhFm$vxVVI#Q%d!B#$hGMF8ZK@9ww?VOI?h2?UCOr;vwXzu+VO<i~O22!D4>`fNJf z;vmWvOLhv2)j<&^{Y!__t_~T07@Lwf2ulhBbc9v~S2dT>UXqPvpb&nEWXy*W1yv*( zkFJz0p$ePk>QgWspP<E0W0-9m?OuR=5GG9FZ}{>R4VALv8*-JVpd4sBm1SAMn_k~4 zWC?3*)3}av5izF~#|p}{{ZyVA_JHoZBBtZ>G_0pA5ddk+JG8zxTnlu?e$b0^gg>r( zd5_lb0(0}0J%3yPouxP@S+Ywz!Fl!dm<qEDp?i>Hp7KNShJ*7Mydf}?Geeg7yU*_y zq4Vnf4_r6%<#f#zF>3yHF(=PoPFH*j_Wa@!Y%mF0K*h}}wfPbTLE=t7z^?`<`^X5F zR<(Za5!^?ss5`==5t>2cs>Tfxd)1c^YNbX;A?Jh;T95urvIEyFIV3qhg(kqM9ka!! zyX-+m=ph2TG&aFp{U(qr_;^!Vkyi#Gd6C%)I<3$}o#89pAZ|_Ckt&}-XzX@Z%$!Yw zj^H^w{zV$$lGP%t(-<+w*_IAFUi7^;9UbiF=7K%Ohh4(GpH#kcvbT-0B%Cl4)jsEY z#<cJO@x0fRpa_2}I9jjrMke%8-+6(p3SAYs$(?B&Brg0qLw1Kr5@h`3XDzV_+iYNv z&UBWMU@aZ6`saLS2jN7Jc32CrC4!~fd>8&W<(<O0z%1YgkKn>AFbtT@kl}~0hF`H? z@oMH333u-7kv?sXKjDrmWqjGIPd?Vx4=)S%<bMvg3F{-Qwsq+<8Y))8s?UW#7(ZI8 zT>Jvh2q;|rlU|f!EE<9{KdUfvtTBDn6B{n0S6<+h4@@)YYJfG{^uUD9f;CAOWeK`2 z0E+elydp57tdIW=xCZ!9_y+vj+P@Go)(W|-Dd}^7vVN=iWfVMU7uFsVVUkvRIAj`~ z@%l^JxWjxfCX-k8T_K=3i6KAnX1v~<=G4Z?$WLOCjJIMYMTExS@I)?4X>PVx$n&#U zNyAUF!Y&#>hO799kb9wcC{OV%Uwgot&Zx_OBHH*imNz@oh#QU04jZ-=0=F5_omXRs zTMB<wYV!hNWnND4@JQ{bnfOG$uEr18_!(szKCxDpT)?bGAmUcf%55p@S%q~-l{*9y zG;4xJeKeg4^G~Jiwy#pH@(K2lpmB7L!WQI!Z^WH^;csW95x_xIGXy{nfUw8&9s%(7 z77ZH$pkIi&Jo}zI`@W0j?-7A)drY9xAWjEI`7at6$|m23cdT99T`p~@t^I~8A<!-n z4PdtC9Yj;t-xI#|OCl`w9q`#M?~Ob{_&j83_=dau{Gx|iKzU5TEZ>2J9tVAi=#%MQ zPqZVS!TixCA^iFI!dgC-MhM`U>9j@(TWKN^U12h*@dZ4m9T217a+Nq5&VDc;4AL3N z#DZ72R;U;bG1Mb{?ONIcqQR1G;R)XSB#S{&aHYOxJ};Oeko0;bRwFw7OIu=^ppYYg zPuseM(e9@a=wHSy!siMaX_Aj)l$VC@<$L3Ye6BKAQ6U8OYKJefm6i3RKu6Vb7o=_L ze&@U(z$2DFdtBMpA`dG3?J(wPA_x+nSILwY=q`5`0ee}(Meuq!Kn)jJVF|eA7HR>U zxGKr2@)q@DJm3v6SJ%jFSfd%cMuN0{(w?i)L->NiH6v^I85;q*SI|PN`wUq<%ap57 zT^-Y*!@tP8%O*YYXpK!n&>Le_6bRx<x{d>$KL4n|r{)ji_o8pvqH>E{6D@C(F!R1# zVV#h(nGe2>(C5n|Jmhu~d8rPR)g<M7D|n-`M6)||8z7g}UkR?DPngijY~V0urzTuy zMb{V+k7;~}lt%E>m{q`Lxz;6tToVAr_xbs+t$}Vsb9Hj`R9Z|1HUb2IfAiRmgJEps z;Uy?8{4%Mntbqw($lRgV!k>Hziq6wi%f~neBbQDbIF<Dj!0-@`jd?^UBoIb&@&to< zV@GSLVCbaJ_f;Jv8DS+eFcE4;#wFjP#mS!&{V;aUOv;i@9t`L^yw!VhZ)eXArdbJr zRYfwnrO1yCp3Rc2VucDxfqVK#80(^+!fdL}V}-v%8urKSk-G`gZk=M_O!!7vdq1Fj z;Oh99n2qoeKe(fzXM5xv?AGP%4}H~^Y0qc?@go41CeTlAApqX+xi`KNbH#qY>$iW- z9=$ETrJ6hWXfN}HoiGSn@|7&5UpICJDdKQ~w{q7m0Z`j3XRzUoyuHhdZkkXV$!Fwl zxp-RRw}&4O;Rh${<i!97&*U4x>_xo;XN1tf&ngIHw<@y)DGbzitPkP4eLiJqT7^Lm znG}H`a;9^x#HB-o0*6jA@G;Eb6ptDqE?^x<pG_STUp>3P3%)}PBdv85T*IEZ)mS5V zW*P_?LCLyet>|{G+X*L5f!~C&t?v!INoANYtLOwj^%Gnp&sd}jN^SEKM*_;dhBT1? zv~32ueF~40v4=Dc4-co~!-MJcaE~t-ZBOUk^=KnouDNWcwf?OeCU6*Xi|er-6e2PC z(#;m1poAZaH?4pEs0+u~<r6CW>0q<bornRsbZ-VFZq>dcdd&(te!7~LksqK==0F&+ z89Ca#g5{&Ca{cQhj}QP-eo+Z4LLHb`geMch%attqg;tzCZI>@8+W8}PBOdk|v|-R^ zo5-V@(5GE~;|x#j#*NGUpbB~jes>Cf@W(X=zOFDghVinP?I6jk%Rl-R{1Qs!8~=vT z=lHM(-?&v|mwC%;gwT)x3vY$Tf($x~<_}w&@DV3u!F7vhkNi`UmXH2OaFUo{1ckVf zpEztgVX)?B)328N^YaU+0f*SMBMmZZI?~`YG;x|d#P>ijYs!eI_yJ|3I?E!EY4R2e z7a+b3j16BX`?vFumR_cl*VMYG73>K!eJvaqJ`?~Gz`<<{sJvTjZE0A3=B~gHjnJ5l z$=V8kq^l)9-5Mu*mtB~+=}bE;=gb12%hzzL0$_v)%V<R`9@8zKEQc=w>_(=jWOl=i z1S2G<=eR|kK9OR9e#7}8?y7b1Epc`-;n%}g#jEfdIPBP+W`V1Nf`xE<y3Y*zq&Mwh zOf+lS1vdXS8e=;DKxII6U#Q>TMfkcoXG!)QSG91@AKDXnE&?8HEZ?;N7`DVynwhd| zlBIR#Dj=u93$-l6b_ADgd}C)a7e0I?qmJd^d%yqcmplAq7x}qI(NB3f8TsNMEsXBT zL)vWn+8-3LE4*hNICvkaNg8|q^1bQ^fDGu+AavD{bv&v`!o}}=(_yK2`E3+ROLuJh zM;tQ>W1An%#n_q%5)rx!W}q-18N|L<sAj;zZRPkF-*pSTWsu0E841O;_H;ncEJOxW zoP{somOGE|xKsEM))g_sEI<c%3KekEF5*+JLOF+z=#^zc5_Nh7IVWM3?T-)wpB?Q_ zCujoST)0oU8pan0(@2t&b60AikQWsq)rl~H6R$963)YK=f&p6wWMD#DFv24h>qAkO z#mFa~_2{I20_usNQRK?e_`<Y~uV~o}o3SOL#=&5~U-e<BmXCl|l-#IGzR_EL!>Wl3 zSGiZ|#kG#F;!O9`o&mXu*u=?v*m!ClB#;+HI%y*2Z;I0?TM!KIBjBlI@WOD%iU@!= zcWh(fb^(OJ8w5eW7w$adlfFa+^%!N(Oc=jeDPXK{>%jqbUJ%$eHM2YwkgXuW<j)}7 zGWoAJj<Q$&0Y@JG2QWzW__E>{gpGHu9?2cx?GQ^Pmwr5XsvVnu*EE0)^4b3T)PQdb zwqtB3l)2Ffq@~mKWSl`>vB~I=tJbbq2Py|JCO^NqtG9-(k@yKq9*G%QJGV#=T?p-o z-&JJ}%><IbBBTHs5F2Jwf*tl2%Pbn-h_>h)cFafi4BA=L?3C?<UBaJ2VBWm>p6d=5 zu_^?53xB>JOd(cUqawB#TLzc%<<qsa9wt=9*p02bRXSZ|R$)m!OJW=0OVmHx-3`_W z@oxroRBR*LG#&bV))V&pS#cl#ZEOXxz!9|kjL}6aK>^gIq2V2f)CRg=3ZZX8>!;># zhjw+ZW`sN^X4=L(A#I~>zp_^X;BwQnr3<%{ab61Gxd?y^+`E`N_H4OVD_Uu_&=Ep! z&;XVuPz|+r_*H(qIIvwoK@Mvc20;Vu<RU+lVU~mt5ETLxAdZiZro$sn7ayPrLMTvE z<QF#t4(H&{W91}VnyX#b>#M=6GmYuA`Hj`#(2<1rv2|x^Ezn8=`YaF0>xB2jmpy4A zCjdkgZ{tWlZR=CWja`{nd;$h&ENKuJGvI@x(KTq|^8+llboJBtV|O?(f@|{V=*$O< zIObp+?KjZyHaZq)^(X-DGHx6{JK+l+FQ(`3FQ@O%;7MNw)b?OnBlE~uB<@~)5V1U1 z0wCiN!hu4<4SPxb#G%5Uq*!}-1)y9#=19_~o>jbU+C-be7|Ux}mf=fmhF7iuPx=pG zmwD(GW$}}qg~3??an#S87`&pkY<3Fkq%6V#lF#igjMZ)d$~!->$t%!>&is;mctzne zXH(u0GG{P{t{fkxC?tjtW9DNlimltW8gq-b<5XS(?DPtN^mAVp?`Yc_zAt`#b<1r5 zH`B${O>6~0c_sB{-KXJ)Z3XG4fV-{|92`u?j1$L<8Rnb3QsAmPosM<d)Kt-pRk+J8 zfzH5imVv<4Q~e#c73!E{8_c{?G-Xw;6D;h?bC65=*31ebEmHMa09;hqFTttYcRv^| zT(dz`SVLY}hPP+fvB2TmY9>K>2YAg-eZ(Oj(%&QWDg52yaVaj7W(ERa7z_f0Uqzqp zEyA{Vi`wFw!dv)Vtqb2K9x4zBA2B)bf}m)>$y;{V5*(<}x4G71hr!&dJxYV4@K@!r z1JvMKrJDQ0TH%Z%@24K3O8Bctp@bIPPO*9nSmKx=S0MiZ*GxBP=RUv8qDfhju$G?y zAB!Au8HsD?Nz%sI_K2@yj?5wEDXfMCJcxv$eR0z&=uG%S@Y>z>o6QWe3S5j=9yoHj zHwTYKyP3xJv-~w7mtd%0Q%_NlF%^0u0Oq9ue0O}K72L9uT3)r)%+^fuTuRM}WCcJc z@7n%=AP6t+pb6jgAW<*tIgK+ph}S0*J`;j;?H}&5m+&b23HRhfHR*B&w59wE#5w(& ze8nTtMY!!K#+rN!_Xr@=2WAJhHLhWP!v>1*fqkeF0V|H;*7;f}fZUIpsQi#VTQf%H z&{e5O>Lb!ovDI%XSOm#WZ&!R3!+`lucb-+_kD!sCxpjKo{LfF^BOnzx+*)%S4&z#= zHoE~f<B7uv>u>oC+Dy;5vBP+Az^5xu5dfdPdyi)34Py`59yB|*H@=wAc8nv{3XVJS z7MzrdfS2G~GcUn_15Q_$`M!0ww%G0&peuDx;!-2I>vd~rKcg^M)iM=cJYZXnG7!AR zH=TU8pQsdrR_NobJSuPz-C)5M{u=3wC>o%JHV!rLQ0#%Aga-jJdFjHY&a5``o9Q-S zQ64iR<cX(4H|+u1!Hbmj!eh3J{J=i<l@LQh#tBUXtJ%#sU^~MLB?P*C1>v5(!#6hw zftOd)1^b5IU+^7s1i@>xf)N4-?^{3FKdjA&Cwcn_eMh_~`b8wGWe>hm*z+Y)Hi_UT zJj##xkv!?-vEHP!{0e{i^PiuU@CR@jqq(-)s9Fe~WO7{zf#N1?&@Ewxn0&KojQK18 zQZc`j$9^LtY1gBpjUjf>6@%EYVS+_qHMg*K3lYx94E*F%_~;`z?imPNOuK>Su6Sd* zU~;_2WS<oi>LVTLkx8~bzV0Mz=c>t8_tI?Zw?nqD=o_SCuEqfvzk4!Nj;O8V)d~Sn z?cedV&3%Kp<Tt{f%noa(OrvZm-cK*%Co4cSl>I*m+b6PmDu<Ezlc}D9Ujo(;I8#2O z>hOY<H)NIY1h&q43V#L&0>U?mCq)KTp^}jF!fF`g@~7a((i?)`{_Y{)<UOK2)$Y0n zkO4*kkan%pn6}@bvUxWCYSX;nj(8^=b9AneglLBI(jYzrK=>s40-4JF2KAPj$nYbY zNa*SB_hzyX55mEo!XL&L2@il6rxx0b<YOlXuMjyx>vyC8$RQG!6tj$Dktuia9-w+9 zP@;PfhnJI|Je_(Q^)0A=ZBv?Gd2rA#^noVTY6K>|x9frctIG&2>o8xjFesIlP~0Xo z68O-YB=wVQg(J>n02E1vji=MJKe^$VLE6!_2_zi9$jmf21|oT7F82rnHbDbLmd%v% zNn79k*2XMp&=bBhA0rA!U{-+Opncf~xX;SLv(x9(^V4_J$?*ZFg14r(m-TJuJ+`EX zyvC72SM*pf)?1ZlhcU=D^K|*;IeT0Y66Bd&O;r>O8dn5Jn!dJiN~zY<j~UPHAV|SJ zl_E4gjpc*Tra^p)Dn-M}P69I-8HJ2NOX`496u&hLfGH+Fwp9%H<ado#wg5G!dO;e= zD*6+@5|RuC%!0U1H7cO{Q4wEo$uB(;e@!Z7^NOgxwgf@vAYK3z0GX#UR`A03h<V^3 z+dbd5zr8$9Tc4lvJ@adpg?VAPS3wc-N}<v(kaCMJiN{_%59xmHbl<~@)J5-eE`>!2 zW4`F-k;Ie*2bJt!MiatxrE`>{;^HP;KEcSJ&AYX{OncY|)v(NCb0-qvqGqMRC`lRi zX93U}`lUQDfo&63nHzi%*NryQ+K{$nn{p0TnnPugh6wJ)(H<kmBP>&4gufC1AL$5p zyd7On_gtrOkE*-}ZM7_!IGsF)@ojsX<r6#FwptkXVd+*l?7;&8fu2QL1cec%0BDEF zW_wO?ZtWuYVYUz~+{f6AZ%3#a8n#T|<rro7Db}LMKLRfDpAP+LWb1^EF|Cr!Bklr2 zPkM6!i<Z?OC~V;jh3n{NL@VkY-g#C5N#EY3ZPxQZl{60OzR4=EFwkM#<GH<!h8D9& zTOFV+yFqBWqrD&eG7OyLmtY(aJ&fV!0DUWNZd4dr)`3mCG9?5UuSqJ>dalU9R5VV; z?$y~v7_1ZFl~;NZ;o0W{4=Ri~SnetyI6_+i$%vjpocIlML-alxpaYk7c=1sCyv+&G zenJstkpJ_DW6&2(qP!e@WmjDHM(RFs&<xzHbsA-fhTKB(3=0x%uS##2`6ncNVJ{uU zpfaKzu^f_Cz$+ViYh($zCd*Uho_!T*nfei5mo*wjBT`vaXTU}ymM|-V=(KO+u*@c@ zGIU*suL@1t$aZq_ig50B4@?f9jl9ft^;DhA{(&cjHCqIH+wG9k;74czPmU1gIn3jh ze1(H8cvT+oCBk~j#2j+L%Ve*n&nUk#<8rV9;5qkAUZEXwIXGjK<+g3AaA}p$Gs>xZ zCMyw7|0G+<YR3T6`(b)RHG}sCY*|9v!t1FDkKrSYV+=GlT%ZT5rrB)+6Y=0`!m15N z+NJg{Lsn&7FrqhYeu~;4d-A8Ko1;>fmA-#NinzuTE=sZyXqsVc3kAL6SNcZywuC?N zl^|R%TTw<3uO2vK6fcik+-fj!pzRSsaAGUT78>J6zFy>(;yd`lit$ietwzaB@+)Di zDqL{@?fT{rjo|?XL69-zo+XN%ZE(PkGE^uYKSlkZy<+lP{lf6kDA1QWp!_*BMt;?k z9K(o#SJ#C=;6@&)GRdAXh=fQH3S&cKe-;2!Q@@O#ZX2mty4z!8$^gdAPqkw@U3GIH zY-lGLgfg`xPMYv#+I+B1qYN7P!AF~}FtNRAx+Kln%_DElSJMyg-c9e`yqO-keD{Gj z;oi3w?H_rl4cu}NSK#xraO?-$@gTtXBwT$e&bKc&ZWWxctvyup;=YWXy)6b_Iv2vk zgf?j_hRda0f<xGV+o6okgzW&FT3V|Nf_~(&j7uZ<jDiT`d@79JbQ*mfljy(Vr*SN8 z(KKGeeTKhg1^gA>P_^9HzJi~9Isjh|0>v#egb6-)j4g<s8p>bc{yGp99YScfxA@jG zlj-jE0RtZU<@i4D@zLq@z@^MLOtg2845GC4Htq<33|?6p!LD2s{}hCZUqdrl*sN_N zH1iJmS?(1~QKJB;Qdz;RJ~>#lCB2D#@Pt<o{=CAdg{n;C@q@sDlspt9582ama`Frf zV0~sz&0(}0!Nm{Y)`<NO<V9?3!tkmtP~fbM=JdbxLCVRXuHa|iammQOX@N=@p>Cj4 zO{w%zMVV}RdEBs=<XB~Va8iPVT!QRWW;*xUsxs|I@^Gi#q-hQ}!k8a>toO=K9w=;< z6HGx$U(Do4RAqu6XL3zd&^`*hg(u_2c<B?bNvwwlXIb2~$&RP45y1Bl0_(&-eVy<w zf2vwuSe0f`2+Jf6m++rW&$tZyix<zQm(Ne8KfQg=c;o11-IfWit_F)_F^ng_Lo|uc zj}E363_B-|ifD@b>dixhQ}_tDAA7_lT-zUow;~qpA^h@bf7^wT-vo5~REpG$nc7B? z!~`0K1jfgYW%}S4LDG;UQf-(|!x+Rw;!C_Q8+qZNT?<KpE`K|@q<s2WWH4u1^){!I z$VL=`iCH7O>5xYopM6@tHpwZNRjjf7`#bfnQ0yY8?QZee(#h}HU-5agtI3Oj&;i5i z))=b|TxaG75WK|xLBWn}K$5}d>gsU1K6EMhfYZQyM_eA3ue}Y!K95ldv~G)U?Ia@b z#f-m@U19c-5@g9^{5jgm|BA6{xr2zT#VP9akCc@>2(CQh;D>mf{D^0M%paVe1;DvR z{{9Xbtsd=i%O>@VIIUG+M~+sm#+QjQ*fHR_xjnKIkTQVFWj#lP2M0P)$|MZMbOQxI zgg>->-=Dpo-v00dpZ4NnUxc&>Z6wS9?!ev*t`LY(>o<Q3*zW-&^yPcOL;aqGWjaR* zkK{%gW`SrB_oC_J8V0m}kA90-duRatoEM9K&?u8vr>q(o^#aYGet_$G%P6-<H^Mu* z@yz%~XED5C7O5NjN9;~1n5o;3J5IZ;;ZI=}py6=hUhzufDVS>03R}ihDt}iwcl<Ie zOE-a%4s&U`$d#ZPh6raVO(Ad>ZS5X{`ab(L)w<mC3AP<h1^YJaKF{z3=@f3VG$M`& z@D6_^0QM!U7Lott)9zL7Au8i$=wR^Mmd_mkgHyZcbyy7|1U$|KL_kzfw7iAiw{zl% z%=QELID!}htjoS9C#N|8lB<YFk)@aLyfh3%vBc;&EJw2M5MrXyh9JlETLhb%Xb0Gv z=*DvSo<HI2qdpGoE|2>S+x_fOgf=S6C8ZLW5nQP+g%V*cfjF!PMQEMQ!`o`FvgD=5 zi2@^-nP?Yd=u5nqQW@eKafa!Pos^U-vzD|H+7%r*kutUr?BN*G@gH2$V|^?9S!S=> zh)@i?r?uTi5@Fc9T?ud&<B1T=1nNFKFX2AqIu}n^dH~ErJZcCtdxN_*p2Z(h>>~v{ zj3c`)<D&t5@%)sf;FD-&Ty+q#pa<+olR72Nwzl1m(HefiUeMp19#3DNa3~1j$K}F% zzI0@}2$w>eUuUm7&nlpDY3!?T!OADZdbn|hw$b0dG!+qrQHXlPkha23on(*~5Z<;y z2DYj<A@~a((=YO0ff@k}aRMd-=MM0-0Y`$hH_}yp3%tP=jI%2+;?7g{GDTQ#j_wSK zoH+@>$r~CfOqvGl2r``4qlD+h&;CVU+hcs%!|ivWk?Y|R4Kox*Xb-X-0CUCnA+OP( zcx#2}MXO>({;%s~YHQRTef)mEUhbAJJsG41Ez(wff7HL>)Is{7V}i@m%$4MjFzdr6 zfT`1|eBo2e9d!92lK$iP1!UT(%0DLztnBKOBs$_p_|^US`Q_Ar4b-No>PCyrPy0t3 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	bEtY4-n?DiK} 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