author | Ryan VanderMeulen <ryanvm@gmail.com> |
Fri, 11 Jul 2014 16:42:00 -0400 | |
changeset 193633 | b0701d069bf9f97eba257ab426fd62015f9d7094 |
parent 193632 | c79820bc58e9c82c083865c17b87c9bec9c4165e (current diff) |
parent 193627 | 84bd8d9f4256c3130c1a8ff4d26fc2215056fd7a (diff) |
child 193634 | 3cae5210bea736748dd8c1556731715be9edab74 |
child 193636 | 48c4d4a97a4becf0087da95f3f7b10408d12457f |
child 193718 | 42c54f0e2bf8af2029edb115dfa7c51416de4a9d |
push id | 27124 |
push user | kwierso@gmail.com |
push date | Sat, 12 Jul 2014 01:05:54 +0000 |
treeherder | mozilla-central@b0701d069bf9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 33.0a1 |
first release with | nightly linux32
b0701d069bf9
/
33.0a1
/
20140712030202
/
files
nightly linux64
b0701d069bf9
/
33.0a1
/
20140712030202
/
files
nightly mac
b0701d069bf9
/
33.0a1
/
20140712030202
/
files
nightly win32
b0701d069bf9
/
33.0a1
/
20140712030202
/
files
nightly win64
b0701d069bf9
/
33.0a1
/
20140712030202
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
33.0a1
/
20140712030202
/
pushlog to previous
nightly linux64
33.0a1
/
20140712030202
/
pushlog to previous
nightly mac
33.0a1
/
20140712030202
/
pushlog to previous
nightly win32
33.0a1
/
20140712030202
/
pushlog to previous
nightly win64
33.0a1
/
20140712030202
/
pushlog to previous
|
content/media/gmp/gmp-api/gmp-video-errors.h | file | annotate | diff | comparison | revisions | |
security/manager/ssl/tests/gtest/Makefile.in | file | annotate | diff | comparison | revisions |
--- a/browser/app/blocklist.xml +++ b/browser/app/blocklist.xml @@ -1,2227 +1,2313 @@ <?xml version="1.0"?> -<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1404245815000"> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1405034316000"> <emItems> <emItem blockID="i454" id="sqlmoz@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <versionRange minVersion="0" maxVersion="*" severity="3"> + <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i58" id="webmaster@buzzzzvideos.info"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> - <emItem blockID="i402" id="{99079a25-328f-4bd4-be04-00955acaa0a7}"> - <versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1"> + <emItem blockID="i652" id="garg_sms@yahoo.in"> + <versionRange minVersion="67.9" maxVersion="67.9" severity="3"> </versionRange> - <versionRange minVersion="0" maxVersion="*" severity="1"> - </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i71" id="youtube@2youtube.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i404" id="{a9bb9fa0-4122-4c75-bd9a-bc27db3f9155}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}"> <versionRange minVersion=" " severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i107" os="WINNT" id="{ABDE892B-13A8-4d1b-88E6-365A6E755758}"> <versionRange minVersion="0" maxVersion="15.0.5" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i88" id="anttoolbar@ant.com"> <versionRange minVersion="2.4.6.4" maxVersion="2.4.6.4" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i484" id="plugin@getwebcake.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> - <emItem blockID="i433" id="{c95a4e8e-816d-4655-8c79-d736da1adb6d}"> - <versionRange minVersion="0" maxVersion="*" severity="1"> + <emItem blockID="i640" id="jid0-l9BxpNUhx1UUgRfKigWzSfrZqAc@jetpack"> + <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i65" id="activity@facebook.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i527" id="/^({bfec236d-e122-4102-864f-f5f19d897f5e}|{3f842035-47f4-4f10-846b-6199b07f09b8}|{92ed4bbd-83f2-4c70-bb4e-f8d3716143fe})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i535" id="/^ext@WebexpEnhancedV1alpha[0-9]+\.net$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i105" id="{95ff02bc-ffc6-45f0-a5c8-619b8226a9de}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i626" id="{20AD702C-661E-4534-8CE9-BA4EC9AD6ECC}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}"> <versionRange minVersion="0.1" maxVersion="5.2.0.7164" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i506" id="/^ext@bettersurfplus/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i400" id="{dd6b651f-dfb9-4142-b0bd-09912ad22674}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i488" id="jid1-4P0kohSJxU1qGg@jetpack"> <versionRange minVersion="1.2.50" maxVersion="1.2.50" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i578" id="jid1-XLjasWL55iEE1Q@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i660" id="youplayer@addons.mozilla.org"> + <versionRange minVersion="79.9.8" maxVersion="208.0.1" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i529" id="/^(torntv@torntv\.com|trtv3@trtv\.com|torntv2@torntv\.com|e2fd07a6-e282-4f2e-8965-85565fcb6384@b69158e6-3c3b-476c-9d98-ae5838c5b707\.com)$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i486" id="xz123@ya456.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i392" id="{EEE6C361-6118-11DC-9C72-001320C79847}"> <versionRange minVersion="0" maxVersion="1.7.999" severity="1"> </versionRange> - <versionRange minVersion="0" maxVersion="*" severity="1"> + <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i406" id="{bf7380fa-e3b4-4db2-af3e-9d8783a45bfc}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}"> <versionRange minVersion="1.2" maxVersion="1.2"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.0a1" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i492" id="{af95cc15-3b9b-45ae-8d9b-98d08eda3111}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}"> <versionRange minVersion="0.1" maxVersion="1.3.328.4" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.7a1pre" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i64" id="royal@facebook.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i72" os="WINNT" id="{4ED1F68A-5463-4931-9384-8FFF5ED91D92}"> <versionRange minVersion="3.4.1" maxVersion="3.4.1.194" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}"> <versionRange minVersion="2.5.0" maxVersion="2.5.0" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}"> <versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i491" id="{515b2424-5911-40bd-8a2c-bdb20286d8f5}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i498" id="hoverst@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i127" id="plugin@youtubeplayer.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i430" id="1chtw@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i78" id="socialnetworktools@mozilla.doslash.org"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i238" id="/^pink@.*\.info$/"> <versionRange minVersion="0" maxVersion="*" severity="3"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="18.0" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i516" id="/^({3f3cddf8-f74d-430c-bd19-d2c9147aed3d}|{515b2424-5911-40bd-8a2c-bdb20286d8f5}|{17464f93-137e-4646-a0c6-0dc13faf0113}|{d1b5aad5-d1ae-4b20-88b1-feeaeb4c1ebc}|{aad50c91-b136-49d9-8b30-0e8d3ead63d0})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i630" id="webbooster@iminent.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> <pref>browser.startup.homepage</pref> <pref>browser.search.defaultenginename</pref> </prefs> </emItem> <emItem blockID="i174" id="info@thebflix.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i478" id="{7e8a1050-cf67-4575-92df-dcc60e7d952d}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i582" id="discoverypro@discoverypro.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i172" id="info@bflix.info"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i596" id="{b99c8534-7800-48fa-bd71-519a46cdc7e1}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i140" id="mozillahmpg@mozilla.org"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i500" id="{2aab351c-ad56-444c-b935-38bffe18ad26}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i494" id="/^({e9df9360-97f8-4690-afe6-996c80790da4}|{687578b9-7132-4a7a-80e4-30ee31099e03}|{46a3135d-3683-48cf-b94c-82655cbc0e8a}|{49c795c2-604a-4d18-aeb1-b3eba27e5ea2}|{7473b6bd-4691-4744-a82b-7854eb3d70b6}|{96f454ea-9d38-474f-b504-56193e00c1a5})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i467" id="plugin@analytic-s.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i47" id="youtube@youtube2.com"> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i360" id="ytd@mybrowserbar.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i5" id="support@daemon-tools.cc"> <versionRange minVersion=" " maxVersion="1.0.0.5"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i436" id="/(\{7aeae561-714b-45f6-ace3-4a8aed6e227b\})|(\{01e86e69-a2f8-48a0-b068-83869bdba3d0\})|(\{77f5fe49-12e3-4cf5-abb4-d993a0164d9e\})/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i97" id="support3_en@adobe122.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i342" id="lbmsrvfvxcblvpane@lpaezhjez.org"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i481" id="{B40794A0-7477-4335-95C5-8CB9BBC5C4A5}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <versionRange minVersion="0" maxVersion="*" severity="3"> + <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <versionRange minVersion="0" maxVersion="*" severity="3"> + <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i11" id="yslow@yahoo-inc.com"> <versionRange minVersion="2.0.5" maxVersion="2.0.5"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.5.7" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i624" id="/^({b95faac1-a3d7-4d69-8943-ddd5a487d966}|{ecce0073-a837-45a2-95b9-600420505f7e}|{2713b394-286f-4d7c-89ea-4174eeab9f5a}|{da7a20cf-bef4-4342-ad78-0240fdf87055})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i472" id="linksicle@linksicle.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i66" id="youtubeer@youtuber.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i438" id="{02edb56b-9b33-435b-b7df-b2843273a694}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i450" id="{dff137ae-1ffd-11e3-8277-b8ac6f996f26}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i521" id="/^({66b103a7-d772-4fcd-ace4-16f79a9056e0}|{6926c7f7-6006-42d1-b046-eba1b3010315}|{72cabc40-64b2-46ed-8648-26d831761150}|{73ee2cf2-7b76-4c49-b659-c3d8cf30825d}|{ca6446a5-73d5-4c35-8aa1-c71dc1024a18}|{5373a31d-9410-45e2-b299-4f61428f0be4})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i499" id="{babb9931-ad56-444c-b935-38bffe18ad26}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i356" id="{341f4dac-1966-47ff-aacf-0ce175f1498a}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i101" id="{3a12052a-66ef-49db-8c39-e5b0bd5c83fa}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i111" os="WINNT" id="{C3949AC2-4B17-43ee-B4F1-D26B9D42404D}"> <versionRange minVersion="0" maxVersion="15.0.5" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i136" id="Adobe@flash.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i543" id="{badea1ae-72ed-4f6a-8c37-4db9a4ac7bc9}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i447" id="{B18B1E5C-4D81-11E1-9C00-AFEB4824019B}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i519" id="703db0db-5fe9-44b6-9f53-c6a91a0ad5bd@7314bc82-969e-4d2a-921b-e5edd0b02cf1.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i537" id="rally_toolbar_ff@bulletmedia.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i526" id="/^({83a8ce1b-683c-4784-b86d-9eb601b59f38}|{ef1feedd-d8da-4930-96f1-0a1a598375c6}|{79ff1aae-701f-4ca5-aea3-74b3eac6f01b}|{8a184644-a171-4b05-bc9a-28d75ffc9505}|{bc09c55d-0375-4dcc-836e-0e3c8addfbda}|{cef81415-2059-4dd5-9829-1aef3cf27f4f})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i532" id="249911bc-d1bd-4d66-8c17-df533609e6d8@c76f3de9-939e-4922-b73c-5d7a3139375d.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i258" id="helperbar@helperbar.com"> <versionRange minVersion="0" maxVersion="1.0" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i98" id="youtubeeing@youtuberie.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i515" id="/^({bf9194c2-b86d-4ebc-9b53-1c08b6ff779e}|{61a83e16-7198-49c6-8874-3e4e8faeb4f3}|{f0af464e-5167-45cf-9cf0-66b396d1918c}|{5d9968c3-101c-4944-ba71-72d77393322d}|{01e86e69-a2f8-48a0-b068-83869bdba3d0})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i549" id="/^firefox@(albrechto|swiftbrowse|springsmart|storimbo|squirrelweb|betterbrowse|lizardlink|rolimno|browsebeyond|clingclang|weblayers|kasimos|higher-aurum|xaven|bomlabio)\.(com?|net|org|info|biz)$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i168" id="flashX@adobe.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}"> <versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}"> <versionRange minVersion="0.1" maxVersion="14.4.0" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i449" id="gystqfr@ylgga.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i502" id="{df6bb2ec-333b-4267-8c4f-3f27dc8c6e07}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <versionRange minVersion="0" maxVersion="*" severity="3"> + <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i142" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}"> <versionRange minVersion="2.0.3" maxVersion="2.0.3"> </versionRange> - <versionRange minVersion="4.2" maxVersion="4.2" severity="3"> + <versionRange minVersion="4.2" maxVersion="4.2" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i306" id="{ADFA33FD-16F5-4355-8504-DF4D664CFE10}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> - <emItem blockID="i632" id="jid1-4vUehhSALFNqCw@jetpack"> + <emItem blockID="i634" id="jid1-4vUehhSALFNqCw@jetpack"> <versionRange minVersion="100.7" maxVersion="100.7" severity="3"> </versionRange> - <prefs> + <versionRange minVersion="99.7" maxVersion="99.7" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i63" id="youtube@youtuber.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i398" id="{377e5d4d-77e5-476a-8716-7e70a9272da0}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i18" id="msntoolbar@msn.com"> <versionRange minVersion=" " maxVersion="6.*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i358" id="lfind@nijadsoft.net"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i628" id="ffxtlbr@iminent.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> <pref>browser.startup.homepage</pref> <pref>browser.search.defaultenginename</pref> </prefs> </emItem> <emItem blockID="i228" id="crossriderapp5060@crossrider.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i465" id="trtv3@trtv.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i554" id="lightningnewtab@gmail.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i550" id="colmer@yopmail.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i618" id="toolbar@ask.com"> <versionRange minVersion="3.15.5" maxVersion="3.15.5.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.8" maxVersion="3.15.8.*" severity="1"> + <versionRange minVersion="3.15.8" maxVersion="3.15.8.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.10" maxVersion="3.15.11.*" severity="1"> + <versionRange minVersion="3.15.10" maxVersion="3.15.11.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.13" maxVersion="3.15.13.*" severity="1"> + <versionRange minVersion="3.15.13" maxVersion="3.15.13.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.18" maxVersion="3.15.20.*" severity="1"> + <versionRange minVersion="3.15.18" maxVersion="3.15.20.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.22" maxVersion="3.15.22.*" severity="1"> + <versionRange minVersion="3.15.22" maxVersion="3.15.22.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.24" maxVersion="3.15.24.*" severity="1"> + <versionRange minVersion="3.15.24" maxVersion="3.15.24.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.26" maxVersion="3.15.26.*" severity="1"> + <versionRange minVersion="3.15.26" maxVersion="3.15.26.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.28" maxVersion="3.15.28.*" severity="1"> + <versionRange minVersion="3.15.28" maxVersion="3.15.28.*" severity="1"> </versionRange> - <versionRange minVersion="3.15.31" maxVersion="3.15.31.*" severity="1"> + <versionRange minVersion="3.15.31" maxVersion="3.15.31.*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com"> <versionRange minVersion="1.9.0" maxVersion="1.9.0" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="9.0a1" maxVersion="9.*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i514" id="/^(67314b39-24e6-4f05-99f3-3f88c7cddd17@6c5fa560-13a3-4d42-8e90-53d9930111f9\.com|ffxtlbr@visualbee\.com|{7aeae561-714b-45f6-ace3-4a8aed6e227b}|{7093ee04-f2e4-4637-a667-0f730797b3a0}|{53c4024f-5a2e-4f2a-b33e-e8784d730938})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i348" id="{13c9f1f9-2322-4d5c-81df-6d4bf8476ba4}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i338" id="{1FD91A9C-410C-4090-BBCC-55D3450EF433}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i364" id="{FE1DEEEA-DB6D-44b8-83F0-34FC0F9D1052}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i59" id="ghostviewer@youtube2.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i222" id="dealcabby@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i51" id="admin@youtubeplayer.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i433" id="{c95a4e8e-816d-4655-8c79-d736da1adb6d}"> + <versionRange minVersion="0" maxVersion="*" severity="1"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i352" id="vpyekkifgv@vpyekkifgv.org"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i466" id="afext@anchorfree.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i650" id="jid1-qj0w91o64N7Eeg@jetpack"> + <versionRange minVersion="39.5.1" maxVersion="47.0.4" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i468" id="05dd836e-2cbd-4204-9ff3-2f8a8665967d@a8876730-fb0c-4057-a2fc-f9c09d438e81.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i522" id="/^({976cd962-e0ca-4337-aea7-d93fae63a79c}|{525ba996-1ce4-4677-91c5-9fc4ead2d245}|{91659dab-9117-42d1-a09f-13ec28037717}|{c1211069-1163-4ba8-b8b3-32fc724766be})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i642" id="{bee6eb20-01e0-ebd1-da83-080329fb9a3a}"> + <versionRange minVersion="40.10.1" maxVersion="44.10.1" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i479" id="mbrsepone@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> - <emItem blockID="i620" id="{21EAF666-26B3-4A3C-ABD0-CA2F5A326744}"> - <versionRange minVersion="0" maxVersion="*" severity="3"> + <emItem blockID="i666" id="wecarereminder@bryan"> + <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i646" id="{e1aaa9f8-4500-47f1-9a0a-b02bd60e4076}"> + <versionRange minVersion="178.7.0" maxVersion="178.7.0" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i552" id="jid0-O6MIff3eO5dIGf5Tcv8RsJDKxrs@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i256" id="/^[0-9a-f]+@[0-9a-f]+\.info/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i584" id="{52b0f3db-f988-4788-b9dc-861d016f4487}"> <versionRange minVersion="0" maxVersion="0.1.9999999" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i370" id="happylyrics@hpyproductions.net"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i440" id="{2d069a16-fca1-4e81-81ea-5d5086dcbd0c}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i396" id="/@(ft|putlocker|clickmovie|m2k|sharerepo|smarter-?)downloader\.com$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i22" id="ShopperReports@ShopperReports.com"> <versionRange minVersion="3.1.22.0" maxVersion="3.1.22.0"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i376" id="{9e09ac65-43c0-4b9d-970f-11e2e9616c55}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i44" id="sigma@labs.mozilla"> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i501" id="xivars@aol.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i482" id="brasilescapeeight@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i226" id="{462be121-2b54-4218-bf00-b9bf8135b23f}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i246" id="support@vide1flash2.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i48" id="admin@youtubespeedup.com"> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i218" id="ffxtlbr@claro.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}"> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i548" id="/^firefox@(jumpflip|webconnect|browsesmart|mybuzzsearch|outobox|greygray|lemurleap|divapton|secretsauce|batbrowse|whilokii|linkswift|qualitink|browsefox|kozaka|diamondata|glindorus|saltarsmart|bizzybolt|websparkle)\.(com?|net|org|info|biz)$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i79" id="GifBlock@facebook.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}"> <versionRange minVersion="2.2" maxVersion="2.2"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i115" id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i477" id="mbrnovone@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}"> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i446" id="{E90FA778-C2B7-41D0-9FA9-3FEC1CA54D66}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i562" id="iobitapps@mybrowserbar.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i507" id="4zffxtbr-bs@VideoDownloadConverter_4z.com"> <versionRange minVersion="0" maxVersion="5.75.3.25126" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}"> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i525" id="/^({65f9f6b7-2dae-46fc-bfaf-f88e4af1beca}|{9ed31f84-c8b3-4926-b950-dff74047ff79}|{0134af61-7a0c-4649-aeca-90d776060cb3}|{02edb56b-9b33-435b-b7df-b2843273a694}|{da51d4f6-3e7e-4ef8-b400-9198e0874606}|{b24577db-155e-4077-bb37-3fdd3c302bb5})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i485" id="/^brasilescape.*\@facebook\.com$//"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i52" id="ff-ext@youtube"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i644" id="youtubeunblocker@unblocker.yt"> + <versionRange minVersion="43.4.1" maxVersion="77.5.1" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i38" id="{B7082FAA-CB62-4872-9106-E42DD88EDE45}"> <versionRange minVersion="0.1" maxVersion="3.3.0.*"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.7a1" maxVersion="*" /> </targetApplication> </versionRange> - <versionRange minVersion="3.3.1" maxVersion="*"> + <versionRange minVersion="3.3.1" maxVersion="*"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="5.0a1" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i471" id="firefox@luckyleap.net"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i495" id="kallow@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i483" id="brasilescapefive@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i442" id="pennerdu@faceobooks.ws"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i43" id="supportaccessplugin@gmail.com"> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i588" id="quick_start@gmail.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i340" id="chiang@programmer.net"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i664" id="123456789@offeringmedia.com"> + <versionRange minVersion="0" maxVersion="*" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i54" id="applebeegifts@mozilla.doslash.org"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}"> <versionRange minVersion="1.0" maxVersion="1.0"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i504" id="aytac@abc.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i92" id="play5@vide04flash.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}"> <versionRange minVersion="0" maxVersion="1.0.8" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i474" id="{906000a4-88d9-4d52-b209-7a772970d91f}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i453" id="/^brasilescape.*\@facebook\.com$/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i658" id="low_quality_flash@pie2k.com"> + <versionRange minVersion="46.2" maxVersion="47.1" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i598" id="{29b136c9-938d-4d3d-8df8-d649d9b74d02}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i286" id="{58bd07eb-0ee0-4df0-8121-dc9b693373df}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i1" id="mozilla_cc@internetdownloadmanager.com"> <versionRange minVersion="2.1" maxVersion="3.3"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.0a1" maxVersion="*" /> </targetApplication> </versionRange> - <versionRange minVersion=" " maxVersion="6.9.8"> + <versionRange minVersion=" " maxVersion="6.9.8"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.7a1pre" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i308" id="9518042e-7ad6-4dac-b377-056e28d00c8f@f1cc0a13-4df1-4d66-938f-088db8838882.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i560" id="adsremoval@adsremoval.net"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i461" id="{8E9E3331-D360-4f87-8803-52DE43566502}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i542" id="/^({bf67a47c-ea97-4caf-a5e3-feeba5331231}|{24a0cfe1-f479-4b19-b627-a96bf1ea3a56})$/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i493" id="12x3q@3244516.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i344" id="lrcsTube@hansanddeta.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i536" id="{25D77636-38B1-1260-887C-2D4AFA92D6A4}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i426" id="addlyrics@addlyrics.net"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i448" id="{0134af61-7a0c-4649-aeca-90d776060cb3}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i83" id="flash@adobee.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i104" id="yasd@youasdr3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i530" id="{739df940-c5ee-4bab-9d7e-270894ae687a}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i524" id="/^({4e988b08-8c51-45c1-8d74-73e0c8724579}|{93ec97bf-fe43-4bca-a735-5c5d6a0a40c4}|{aed63b38-7428-4003-a052-ca6834d8bad3}|{0b5130a9-cc50-4ced-99d5-cda8cc12ae48}|{C4CFC0DE-134F-4466-B2A2-FF7C59A8BFAD})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i68" id="flashupdate@adobe.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i382" id="{6926c7f7-6006-42d1-b046-eba1b3010315}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i432" id="lugcla21@gmail.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i91" id="crossriderapp4926@crossrider.com"> <versionRange minVersion="0" maxVersion="0.81.43" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i480" id="pluggets@gmail.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <versionRange minVersion="0" maxVersion="*" severity="1"> + <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i570" id="jid1-vW9nopuIAJiRHw@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i520" id="/^({7316e43a-3ebd-4bb4-95c1-9caf6756c97f}|{0cc09160-108c-4759-bab1-5c12c216e005}|{ef03e721-f564-4333-a331-d4062cee6f2b}|{465fcfbb-47a4-4866-a5d5-d12f9a77da00}|{7557724b-30a9-42a4-98eb-77fcb0fd1be3}|{b7c7d4b0-7a84-4b73-a7ef-48ef59a52c3b})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i460" id="{845cab51-d8d2-472f-8bd9-2b44642d97c2}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i547" id="{87934c42-161d-45bc-8cef-ef18abe2a30c}"> <versionRange minVersion="0" maxVersion="3.7.9999999999" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}"> <versionRange minVersion=" " maxVersion="8.5"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i56" id="flash@adobe.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i538" id="{354dbb0a-71d5-4e9f-9c02-6c88b9d387ba}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i451" id="{e44a1809-4d10-4ab8-b343-3326b64c7cdd}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i540" id="/^(ffxtlbr@mixidj\.com|{c0c2693d-2ee8-47b4-9df7-b67a0ee31988}|{67097627-fd8e-4f6b-af4b-ecb65e50112e}|{f6f0f973-a4a3-48cf-9a7a-b7a69c30d71a}|{a3d0e35f-f1da-4ccb-ae77-e9d27777e68d}|{1122b43d-30ee-403f-9bfa-3cc99b0caddd})$/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i216" id="fdm_ffext@freedownloadmanager.org"> <versionRange minVersion="1.0" maxVersion="1.3.1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.0a1" maxVersion="*" /> </targetApplication> </versionRange> - <versionRange minVersion="1.5.7.5" maxVersion="1.5.7.5" severity="1"> + <versionRange minVersion="1.5.7.5" maxVersion="1.5.7.5" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i566" id="{77BEC163-D389-42c1-91A4-C758846296A5}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i533" id="extension@Fast_Free_Converter.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i362" id="addon@defaulttab.com"> <versionRange minVersion="0" maxVersion="1.4.4" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i12" id="masterfiler@gmail.com"> <versionRange severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i576" id="newmoz@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i444" id="fplayer@adobe.flash"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i334" id="{0F827075-B026-42F3-885D-98981EE7B1AE}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i622" id="/^({ebd898f8-fcf6-4694-bc3b-eabc7271eeb1}|{46008e0d-47ac-4daa-a02a-5eb69044431a}|{213c8ed6-1d78-4d8f-8729-25006aa86a76}|{fa23121f-ee7c-4bd8-8c06-123d087282c5}|{19803860-b306-423c-bbb5-f60a7d82cde5})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i518" id="/^({d6e79525-4524-4707-9b97-1d70df8e7e59}|{ddb4644d-1a37-4e6d-8b6e-8e35e2a8ea6c}|{e55007f4-80c5-418e-ac33-10c4d60db01e}|{e77d8ca6-3a60-4ae9-8461-53b22fa3125b}|{e89a62b7-248e-492f-9715-43bf8c507a2f}|{5ce3e0cb-aa83-45cb-a7da-a2684f05b8f3})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i196" id="info@wxdownloadmanager.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i424" id="{C7AE725D-FA5C-4027-BB4C-787EF9F8248A}"> <versionRange minVersion="0" maxVersion="1.0.0.2" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="23.0a1" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i336" id="CortonExt@ext.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i103" id="kdrgun@gmail.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i539" id="ScorpionSaver@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i3" id="langpack-vi-VN@firefox.mozilla.org"> <versionRange minVersion="2.0" maxVersion="2.0"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i326" id="/^((support2_en@adobe14\.com)|(XN4Xgjw7n4@yUWgc\.com)|(C7yFVpIP@WeolS3acxgS\.com)|(Kbeu4h0z@yNb7QAz7jrYKiiTQ3\.com)|(aWQzX@a6z4gWdPu8FF\.com)|(CBSoqAJLYpCbjTP90@JoV0VMywCjsm75Y0toAd\.com)|(zZ2jWZ1H22Jb5NdELHS@o0jQVWZkY1gx1\.com))$/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i470" id="extension@FastFreeConverter.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i162" id="{EB7508CA-C7B2-46E0-8C04-3E94A035BD49}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i620" id="{21EAF666-26B3-4A3C-ABD0-CA2F5A326744}"> + <versionRange minVersion="0" maxVersion="*" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i354" id="{c0c2693d-2ee8-47b4-9df7-b67a0ee31988}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}"> <versionRange minVersion="0" maxVersion="15.0.5" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}"> <versionRange minVersion="0.1" maxVersion="*"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="9.0a1" maxVersion="9.0" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i505" id="extacylife@a.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i15" id="personas@christopher.beard"> <versionRange minVersion="1.6" maxVersion="1.6"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.6" maxVersion="3.6.*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i304" id="{f0e59437-6148-4a98-b0a6-60d557ef57f4}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i586" id="jid1-0xtMKhXFEs4jIg@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i318" id="ffxtlbr@incredibar.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}"> <versionRange minVersion="1.1b1" maxVersion="1.1b1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i531" id="/^(4cb61367-efbf-4aa1-8e3a-7f776c9d5763@cdece6e9-b2ef-40a9-b178-291da9870c59\.com|0efc9c38-1ec7-49ed-8915-53a48b6b7600@e7f17679-2a42-4659-83c5-7ba961fdf75a\.com|6be3335b-ef79-4b0b-a0ba-b87afbc6f4ad@6bbb4d2e-e33e-4fa5-9b37-934f4fb50182\.com)$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i490" id="now.msn.com@services.mozilla.org"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i523" id="/^({7e8a1050-cf67-4575-92df-dcc60e7d952d}|{b3420a9c-a397-4409-b90d-bcf22da1a08a}|{eca6641f-2176-42ba-bdbe-f3e327f8e0af}|{707dca12-3f99-4d94-afea-06dcc0ae0108}|{aea20431-87fc-40be-bc5b-18066fe2819c}|{30ee6676-1ba6-455a-a7e8-298fa863a546})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i312" id="extension21804@extension21804.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i545" id="superlrcs@svenyor.net"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i324" id="/^((34qEOefiyYtRJT@IM5Munavn\.com)|(Mro5Fm1Qgrmq7B@ByrE69VQfZvZdeg\.com)|(KtoY3KGxrCe5ie@yITPUzbBtsHWeCdPmGe\.com)|(9NgIdLK5Dq4ZMwmRo6zk@FNt2GCCLGyUuOD\.com)|(NNux7bWWW@RBWyXdnl6VGls3WAwi\.com)|(E3wI2n@PEHTuuNVu\.com)|(2d3VuWrG6JHBXbQdbr@3BmSnQL\.com))$/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i503" id="{9CE11043-9A15-4207-A565-0C94C42D590D}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i431" id="chinaescapeone@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i108" id="{28bfb930-7620-11e1-b0c4-0800200c9a66}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i656" id="hdv@vovcacik.addons.mozilla.org"> + <versionRange minVersion="102.0" maxVersion="102.0" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i262" id="{167d9323-f7cc-48f5-948a-6f012831a69f}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i320" id="torntv@torntv.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i528" id="008abed2-b43a-46c9-9a5b-a771c87b82da@1ad61d53-2bdc-4484-a26b-b888ecae1906.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i469" id="OKitSpace@OKitSpace.es"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i564" id="/^(firefox@vebergreat\.net|EFGLQA@78ETGYN-0W7FN789T87\.COM)$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i167" id="{b64982b1-d112-42b5-b1e4-d3867c4533f8}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i84" id="pink@rosaplugin.info"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i654" id="{7b1bf0b6-a1b9-42b0-b75d-252036438bdc}"> + <versionRange minVersion="27.8" maxVersion="27.9" severity="3"> + </versionRange> + <versionRange minVersion="27.8" maxVersion="27.9" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i568" os="Darwin" id="thunder@xunlei.com"> <versionRange minVersion="0" maxVersion="2.0.6" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i439" id="{d2cf9842-af95-48cd-b873-bfbb48cd7f5e}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i346" id="{a6e67e6f-8615-4fe0-a599-34a73fc3fba5}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i220" id="pricepeep@getpricepeep.com"> <versionRange minVersion="0" maxVersion="2.1.0.19.99" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i590" id="{94cd2cc3-083f-49ba-a218-4cda4b4829fd}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i544" id="/^(93abedcf-8e3a-4d02-b761-d1441e437c09@243f129d-aee2-42c2-bcd1-48858e1c22fd\.com|9acfc440-ac2d-417a-a64c-f6f14653b712@09f9a966-9258-4b12-af32-da29bdcc28c5\.com|58ad0086-1cfb-48bb-8ad2-33a8905572bc@5715d2be-69b9-4930-8f7e-64bdeb961cfd\.com)$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i224" id="{336D0C35-8A85-403a-B9D2-65C292C39087}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i61" id="youtube@youtube3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <versionRange minVersion="0" maxVersion="*"> + <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i517" id="/^({16e193c8-1706-40bf-b6f3-91403a9a22be}|{284fed43-2e13-4afe-8aeb-50827d510e20}|{5e3cc5d8-ed11-4bed-bc47-35b4c4bc1033}|{7429e64a-1fd4-4112-a186-2b5630816b91}|{8c9980d7-0f09-4459-9197-99b3e559660c}|{8f1d9545-0bb9-4583-bb3c-5e1ac1e2920c})$/"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i509" id="contato@facefollow.net"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i372" id="5nc3QHFgcb@r06Ws9gvNNVRfH.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i496" id="{ACAA314B-EEBA-48e4-AD47-84E31C44796C}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i67" id="youtube2@youtube2.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i476" id="mbroctone@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i473" id="{81b13b5d-fba1-49fd-9a6b-189483ac548a}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i437" id="{4933189D-C7F7-4C6E-834B-A29F087BFD23}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i394" id="{7D4F1959-3F72-49d5-8E59-F02F8AA6815D}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i402" id="{99079a25-328f-4bd4-be04-00955acaa0a7}"> + <versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1"> + </versionRange> + <versionRange minVersion="0" maxVersion="*" severity="1"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i165" id="{EEF73632-A085-4fd3-A778-ECD82C8CB297}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i60" id="youtb3@youtb3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> + </prefs> + </emItem> + <emItem blockID="i662" id="imbaty@taringamp3.com"> + <versionRange minVersion="0" maxVersion="*" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i546" id="firefox@browsefox.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i510" id="{3c9a72a0-b849-40f3-8c84-219109c27554}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i23" id="firefox@bandoo.com"> <versionRange minVersion="5.0" maxVersion="5.0" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.7a1pre" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i55" id="youtube@youtube7.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i434" id="afurladvisor@anchorfree.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i90" id="videoplugin@player.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i489" id="astrovia@facebook.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i497" id="{872b5b88-9db5-4310-bdd0-ac189557e5f5}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i580" id="{51c77233-c0ad-4220-8388-47c11c18b355}"> <versionRange minVersion="0" maxVersion="0.1.9999999" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i541" id="/^({988919ff-0cd8-4d0c-bc7e-60d55a49eb64}|{494b9726-9084-415c-a499-68c07e187244}|{55b95864-3251-45e9-bb30-1a82589aaff1}|{eef3855c-fc2d-41e6-8d91-d368f51b3055}|{90a1b331-c2b4-4933-9f63-ba7b84d60d58}|{d2cf9842-af95-48cd-b873-bfbb48cd7f5e})$/"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i76" id="crossriderapp3924@crossrider.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> - <emItem blockID="i445" id="firefoxaddon@youtubeenhancer.com"> + <emItem blockID="i648" id="firefoxaddon@youtubeenhancer.com"> <versionRange minVersion="208.7.0" maxVersion="208.7.0" severity="3"> </versionRange> - <prefs> + <versionRange minVersion="199.7.0" maxVersion="199.7.0" severity="3"> + </versionRange> + <versionRange minVersion="199.7.0" maxVersion="208.7.0" severity="3"> + </versionRange> + <prefs> </prefs> </emItem> <emItem blockID="i441" id="{49c53dce-afa0-49a1-a08b-2eb8e8444128}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i508" id="advance@windowsclient.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i282" id="{33e0daa6-3af3-d8b5-6752-10e949c61516}"> <versionRange minVersion="0" maxVersion="1.1.999" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i452" id="{77beece6-3997-403a-92fa-0055bfcf88e5}"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}"> <versionRange minVersion="0.1" maxVersion="7.6.1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="8.0a1" maxVersion="*" /> </targetApplication> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i380" id="{cc8f597b-0765-404e-a575-82aefbd81daf}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i322" id="jid0-Y6TVIzs0r7r4xkOogmJPNAGFGBw@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i378" id="{a7aae4f0-bc2e-a0dd-fb8d-68ce32c9261f}"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i73" id="a1g0a9g219d@a1.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i96" id="youtubeee@youtuber3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i163" id="info@allpremiumplay.info"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i455" id="7d51fb17-b199-4d8f-894e-decaff4fc36a@a298838b-7f50-4c7c-9277-df6abbd42a0c.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i374" id="update@firefox.com"> <versionRange minVersion="0" maxVersion="*" severity="3"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i314" id="crossriderapp8812@crossrider.com"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> - <prefs> + <prefs> </prefs> </emItem> <emItem blockID="i21" id="support@update-firefox.com"> - <prefs> + <prefs> </prefs> </emItem> </emItems> <pluginItems> <pluginItem blockID="p26"> <match name="name" exp="^Yahoo Application State Plugin$" /> <match name="description" exp="^Yahoo Application State Plugin$" /> <match name="filename" exp="npYState.dll" /> <versionRange > <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.0a1" maxVersion="3.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p27"> <match name="name" exp="QuickTime Plug-in 7[.]1[.]" /> <match name="filename" exp="npqtplugin.?[.]dll" /> <versionRange > <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.0a1" maxVersion="3.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p28"> - <match name="filename" exp="NPFFAddOn.dll" /> </pluginItem> + <match name="filename" exp="NPFFAddOn.dll" /> </pluginItem> <pluginItem blockID="p31"> - <match name="filename" exp="NPMySrch.dll" /> </pluginItem> + <match name="filename" exp="NPMySrch.dll" /> </pluginItem> <pluginItem blockID="p32"> <match name="filename" exp="npViewpoint.dll" /> <versionRange > <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p33"> <match name="name" exp="[0-6]\.0\.[01]\d{2}\.\d+" /> <match name="filename" exp="npdeploytk.dll" /> <versionRange severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p34"> <match name="filename" exp="[Nn][Pp][Jj][Pp][Ii]1[56]0_[0-9]+\.[Dd][Ll][Ll]" /> <versionRange > <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="3.6a1pre" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p80"> <match name="name" exp="\(TM\)" /> <match name="description" exp="[^\d\._]((0(\.\d+(\.\d+([_\.]\d+)?)?)?)|(1\.(([0-5](\.\d+([_\.]\d+)?)?)|(6(\.0([_\.](0?\d|1\d|2\d|30))?)?)|(7(\.0([_\.][0-2])?)?))))([^\d\._]|$)" /> <match name="filename" exp="(npjp2\.dll)|(libnpjp2\.so)" /> <versionRange severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p85"> <match name="filename" exp="JavaPlugin2_NPAPI\.plugin" /> <versionRange minVersion="0" maxVersion="13.6.0" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem os="Darwin" blockID="p89"> <match name="filename" exp="AdobePDFViewerNPAPI\.plugin" /> <versionRange minVersion="0" maxVersion="10.1.3" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p94"> <match name="filename" exp="Flash\ Player\.plugin" /> <versionRange minVersion="0" maxVersion="10.2.159.1" severity="0"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.0.1" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p102"> <match name="filename" exp="npmozax\.dll" /> <versionRange minVersion="0" maxVersion="*"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p113"> <match name="filename" exp="npuplaypc\.dll" /> <versionRange minVersion="0" maxVersion="1.0.0.0" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p119"> <match name="name" exp="Java\(TM\) Plug-in 1\.(6\.0_(\d|[0-2]\d?|3[0-2])|7\.0(_0?([1-4]))?)([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p123"> <match name="filename" exp="JavaPlugin2_NPAPI\.plugin" /> <versionRange minVersion="0" maxVersion="14.2.0" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p125"> <match name="name" exp="Java\(TM\) Platform SE ((6( U(\d|([0-2]\d)|3[0-2]))?)|(7(\sU[0-4])?))(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p129"> <match name="filename" exp="Silverlight\.plugin" /> <versionRange minVersion="0" maxVersion="5.0.99999" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p132"> <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0(_0?([5-6]))?([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p134"> <match name="name" exp="Java\(TM\) Platform SE 7 U[5-6](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p138"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 01" maxVersion="Java 7 Update 06" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p152"> <match name="filename" exp="npctrl\.dll" /> <versionRange minVersion="0" maxVersion="4.1.10328.0" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p154"> <match name="filename" exp="npctrl\.dll" /> <versionRange minVersion="5.0" maxVersion="5.1.20124.9999" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p156"> <match name="filename" exp="nppdf32\.dll" /> <versionRange minVersion="0" maxVersion="9.5.1" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p158"> <match name="filename" exp="nppdf32\.dll" /> <versionRange minVersion="10.0" maxVersion="10.1.5.9999" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p160"> <match name="filename" exp="NPSWF32\.dll" /> <versionRange minVersion="0" maxVersion="10.2.9999" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="4.0" maxVersion="16.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p176"> <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3" maxVersion="10.3.183.18.999" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="19.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p176"> <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3" maxVersion="10.3.183.18.999" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0.4" maxVersion="17.0.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p178"> <match name="filename" exp="(NPSWF[0-9_]*\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="11.0" maxVersion="11.7.700.169" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="19.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p178"> <match name="filename" exp="(NPSWF[0-9_]*\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="11.0" maxVersion="11.7.700.169" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0.4" maxVersion="17.0.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p180"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 0" maxVersion="Java 7 Update 11" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p182"> <match name="name" exp="Java\(TM\) Platform SE 7 U([0-9]|(1[0-1]))(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p184"> <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0(_0?([0-9]|(1[0-1]))?)?([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p186"> <match name="name" exp="Java\(TM\) Platform SE 6 U3[1-8](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p188"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 6 Update 0" maxVersion="Java 6 Update 38" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p190"> <match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_3[1-8]([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p210"> <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0(_0?7)?([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p212"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 07" maxVersion="Java 7 Update 07" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p214"> <match name="name" exp="Java\(TM\) Platform SE 7 U7(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="0.1" maxVersion="17.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p240"> <match name="filename" exp="DivXBrowserPlugin\.plugin" /> <versionRange minVersion="0" maxVersion="1.4" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem os="Darwin" blockID="p242"> <match name="description" exp="Flip4Mac" /> <versionRange minVersion="0" maxVersion="2.4.3.999" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="18.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p248"> <match name="filename" exp="Scorch\.plugin" /> <versionRange minVersion="0" maxVersion="6.2.0b88" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p250"> <match name="filename" exp="npFoxitReaderPlugin\.dll" /> <versionRange minVersion="0" maxVersion="2.2.1.530" severity="0" vulnerabilitystatus="2"></versionRange> - </pluginItem> + </pluginItem> <pluginItem os="Darwin" blockID="p252"> <match name="filename" exp="AdobePDFViewerNPAPI\.plugin" /> <versionRange minVersion="11.0.0" maxVersion="11.0.01" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p254"> <match name="filename" exp="PDF Browser Plugin\.plugin" /> <versionRange minVersion="0" maxVersion="2.4.2" severity="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="18.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p260"> <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="0" maxVersion="10.2.9999" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="18.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p260"> <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="0" maxVersion="10.2.9999" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0.4" maxVersion="17.0.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p290"> <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3.183.19" maxVersion="10.3.183.66" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="19.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p290"> <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" /> <versionRange minVersion="10.3.183.19" maxVersion="10.3.183.66" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0.4" maxVersion="17.0.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p292"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 12" maxVersion="Java 7 Update 15" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p294"> <match name="name" exp="Java\(TM\) Platform SE 7 U1[2-5](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p296"> <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0_1[2-5]([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p298"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 6 Update 39" maxVersion="Java 6 Update 41" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p300"> <match name="name" exp="Java\(TM\) Platform SE 6 U(39|40|41)(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p302"> <match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_(39|40|41)([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p328"> <match name="filename" exp="Silverlight\.plugin" /> <versionRange minVersion="5.1" maxVersion="5.1.20124.9999" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="19.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p328"> <match name="filename" exp="Silverlight\.plugin" /> <versionRange minVersion="5.1" maxVersion="5.1.20124.9999" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0.4" maxVersion="17.0.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p330"> <match name="description" exp="^Shockwave Flash (([1-9]\.[0-9]+)|(10\.([0-2]|(3 r(([0-9][0-9]?)|1(([0-7][0-9])|8[0-2]))))))( |$)" /> <match name="filename" exp="libflashplayer\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="19.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p330"> <match name="description" exp="^Shockwave Flash (([1-9]\.[0-9]+)|(10\.([0-2]|(3 r(([0-9][0-9]?)|1(([0-7][0-9])|8[0-2]))))))( |$)" /> <match name="filename" exp="libflashplayer\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0.4" maxVersion="17.0.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p332"> <match name="description" exp="^Shockwave Flash 11.(0|1) r[0-9]{1,3}$" /> <match name="filename" exp="libflashplayer\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="19.0a1" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p332"> <match name="description" exp="^Shockwave Flash 11.(0|1) r[0-9]{1,3}$" /> <match name="filename" exp="libflashplayer\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0.4" maxVersion="17.0.*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p366"> <match name="filename" exp="Scorch\.plugin" /> <versionRange minVersion="6.2.0" maxVersion="6.2.0" severity="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p408"> <match name="filename" exp="QuickTime Plugin\.plugin" /> <versionRange minVersion="0" maxVersion="7.6.5" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p410"> <match name="filename" exp="npqtplugin\.dll" /> <versionRange minVersion="0" maxVersion="7.7.3" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p412"> <match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_4[2-5]([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p414"> <match name="name" exp="Java\(TM\) Platform SE 6 U4[2-5](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p416"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 6 Update 42" maxVersion="Java 6 Update 45" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p418"> <match name="name" exp="Java\(TM\) Plug-in 1\.7\.0_(1[6-9]|2[0-4])([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p420"> <match name="name" exp="Java\(TM\) Platform SE 7 U(1[6-9]|2[0-4])(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p422"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 16" maxVersion="Java 7 Update 24" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p428"> <match name="filename" exp="np[dD]eployJava1\.dll" /> <versionRange severity="0" vulnerabilitystatus="2"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p456"> <match name="filename" exp="npvlc\.dll" /> <versionRange minVersion="0" maxVersion="2.0.5" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p457"> <match name="name" exp="Java(\(TM\))? Plug-in ((1\.7\.0_(2[5-9]|3\d|4[0-4]))|(10\.4[0-4](\.[0-9]+)?))([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p458"> <match name="name" exp="Java\(TM\) Platform SE 7 U(2[5-9]|3\d|4[0-4])(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p459"> <match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 25" maxVersion="Java 7 Update 44" severity="0" vulnerabilitystatus="1"> <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> <versionRange minVersion="17.0" maxVersion="*" /> </targetApplication> </versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p556"> <match name="filename" exp="npUnity3D32\.dll" /> <versionRange minVersion="0" maxVersion="4.3.4.99999999" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p558"> <match name="description" exp="^($|Unity Web Player version ([0-3]|(4\.([0-2]|3(\.[0-4])?[^0-9.]))))" /> <match name="filename" exp="Unity Web Player\.plugin" /> <versionRange severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p572"> <match name="filename" exp="npdjvu\.dll" /> <versionRange minVersion="0" maxVersion="6.1.4.27993" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p574"> <match name="filename" exp="NPDjVu\.plugin" /> <versionRange minVersion="0" maxVersion="6.1.1" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p592"> <match name="filename" exp="CiscoWebCommunicator\.plugin" /> <versionRange minVersion="0" maxVersion="3.0.5.99999999999999" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> <pluginItem blockID="p594"> <match name="filename" exp="npCiscoWebCommunicator\.dll" /> <versionRange minVersion="0" maxVersion="3.0.5.99999999999999" severity="0" vulnerabilitystatus="1"></versionRange> - </pluginItem> + </pluginItem> </pluginItems> <gfxItems> <gfxBlacklistEntry blockID="g35"> <os>WINNT 6.1</os> <vendor>0x10de</vendor> <devices> <device>0x0a6c</device> </devices> <feature>DIRECT2D</feature> <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus> <driverVersion>8.17.12.5896</driverVersion> <driverVersionComparator>LESS_THAN_OR_EQUAL</driverVersionComparator> </gfxBlacklistEntry> <gfxBlacklistEntry blockID="g36"> <os>WINNT 6.1</os> <vendor>0x10de</vendor> <devices>
--- a/browser/base/content/browser-social.js +++ b/browser/base/content/browser-social.js @@ -595,17 +595,17 @@ SocialShare = { iframe.removeAttribute("src"); iframe.webNavigation.loadURI("about:socialerror?mode=compactInfo&origin=" + encodeURIComponent(iframe.getAttribute("origin")), null, null, null, null); sizeSocialPanelToContent(this.panel, iframe); }, - sharePage: function(providerOrigin, graphData) { + sharePage: function(providerOrigin, graphData, target) { // if providerOrigin is undefined, we use the last-used provider, or the // current/default provider. The provider selection in the share panel // will call sharePage with an origin for us to switch to. this._createFrame(); let iframe = this.iframe; let provider; if (providerOrigin) provider = Social._getProviderFromOrigin(providerOrigin); @@ -614,35 +614,39 @@ SocialShare = { if (!provider || !provider.shareURL) return; // graphData is an optional param that either defines the full set of data // to be shared, or partial data about the current page. It is set by a call // in mozSocial API, or via nsContentMenu calls. If it is present, it MUST // define at least url. If it is undefined, we're sharing the current url in // the browser tab. - let sharedURI = graphData ? Services.io.newURI(graphData.url, null, null) : + let pageData = graphData ? graphData : this.currentShare; + let sharedURI = pageData ? Services.io.newURI(pageData.url, null, null) : gBrowser.currentURI; if (!this.canSharePage(sharedURI)) return; // the point of this action type is that we can use existing share // endpoints (e.g. oexchange) that do not support additional // socialapi functionality. One tweak is that we shoot an event // containing the open graph data. - let pageData = graphData ? graphData : this.currentShare; if (!pageData || sharedURI == gBrowser.currentURI) { pageData = OpenGraphBuilder.getData(gBrowser); if (graphData) { // overwrite data retreived from page with data given to us as a param for (let p in graphData) { pageData[p] = graphData[p]; } } } + // if this is a share of a selected item, get any microdata + if (!pageData.microdata && target) { + pageData.microdata = OpenGraphBuilder.getMicrodata(gBrowser, target); + } this.currentShare = pageData; let shareEndpoint = OpenGraphBuilder.generateEndpointURL(provider.shareURL, pageData); let size = provider.getPageSize("share"); if (size) { if (this._dynamicResizer) { this._dynamicResizer.stop(); @@ -1348,16 +1352,16 @@ SocialMarks = { }, get _toolbarHelper() { delete this._toolbarHelper; this._toolbarHelper = new ToolbarHelper("social-mark-button", CreateSocialMarkWidget); return this._toolbarHelper; }, - markLink: function(aOrigin, aUrl) { + markLink: function(aOrigin, aUrl, aTarget) { // find the button for this provider, and open it let id = this._toolbarHelper.idFromOrigin(aOrigin); - document.getElementById(id).markLink(aUrl); + document.getElementById(id).markLink(aUrl, aTarget); } }; })();
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1908,40 +1908,43 @@ function loadURI(uri, referrer, postData } try { gBrowser.loadURIWithFlags(uri, flags, referrer, null, postData); } catch (e) {} } function getShortcutOrURIAndPostData(aURL, aCallback) { + let mayInheritPrincipal = false; let postData = null; let shortcutURL = null; let keyword = aURL; let param = ""; let offset = aURL.indexOf(" "); if (offset > 0) { keyword = aURL.substr(0, offset); param = aURL.substr(offset + 1); } let engine = Services.search.getEngineByAlias(keyword); if (engine) { let submission = engine.getSubmission(param); postData = submission.postData; - aCallback({ postData: submission.postData, url: submission.uri.spec }); + aCallback({ postData: submission.postData, url: submission.uri.spec, + mayInheritPrincipal: mayInheritPrincipal }); return; } [shortcutURL, postData] = PlacesUtils.getURLAndPostDataForKeyword(keyword); if (!shortcutURL) { - aCallback({ postData: postData, url: aURL }); + aCallback({ postData: postData, url: aURL, + mayInheritPrincipal: mayInheritPrincipal }); return; } let escapedPostData = ""; if (postData) escapedPostData = unescape(postData); if (/%s/i.test(shortcutURL) || /%s/i.test(escapedPostData)) { @@ -1963,17 +1966,22 @@ function getShortcutOrURIAndPostData(aUR encodedParam = encodeURIComponent(param); shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); if (/%s/i.test(escapedPostData)) // POST keyword postData = getPostDataStream(escapedPostData, param, encodedParam, "application/x-www-form-urlencoded"); - aCallback({ postData: postData, url: shortcutURL }); + // This URL came from a bookmark, so it's safe to let it inherit the current + // document's principal. + mayInheritPrincipal = true; + + aCallback({ postData: postData, url: shortcutURL, + mayInheritPrincipal: mayInheritPrincipal }); } if (matches) { [, shortcutURL, charset] = matches; continueOperation(); } else { // Try to get the saved character-set. // makeURI throws if URI is invalid. @@ -1986,19 +1994,25 @@ function getShortcutOrURIAndPostData(aUR } } } else if (param) { // This keyword doesn't take a parameter, but one was provided. Just return // the original URL. postData = null; - aCallback({ postData: postData, url: aURL }); + aCallback({ postData: postData, url: aURL, + mayInheritPrincipal: mayInheritPrincipal }); } else { - aCallback({ postData: postData, url: shortcutURL }); + // This URL came from a bookmark, so it's safe to let it inherit the current + // document's principal. + mayInheritPrincipal = true; + + aCallback({ postData: postData, url: shortcutURL, + mayInheritPrincipal: mayInheritPrincipal }); } } function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) { var dataStream = Cc["@mozilla.org/io/string-input-stream;1"]. createInstance(Ci.nsIStringInputStream); aStringData = aStringData.replace(/%s/g, aEncKeyword).replace(/%S/g, aKeyword); dataStream.data = aStringData; @@ -2837,38 +2851,38 @@ var newWindowButtonObserver = { }); } } const DOMLinkHandler = { init: function() { let mm = window.messageManager; mm.addMessageListener("Link:AddFeed", this); - mm.addMessageListener("Link:AddIcon", this); + mm.addMessageListener("Link:SetIcon", this); mm.addMessageListener("Link:AddSearch", this); }, receiveMessage: function (aMsg) { switch (aMsg.name) { case "Link:AddFeed": let link = {type: aMsg.data.type, href: aMsg.data.href, title: aMsg.data.title}; FeedHandler.addFeed(link, aMsg.target); break; - case "Link:AddIcon": - return this.addIcon(aMsg.target, aMsg.data.url); + case "Link:SetIcon": + return this.setIcon(aMsg.target, aMsg.data.url); break; case "Link:AddSearch": this.addSearch(aMsg.target, aMsg.data.engine, aMsg.data.url); break; } }, - addIcon: function(aBrowser, aURL) { + setIcon: function(aBrowser, aURL) { if (gBrowser.isFailedIcon(aURL)) return false; let tab = gBrowser._getTabForBrowser(aBrowser); if (!tab) return false; gBrowser.setIcon(tab, aURL); @@ -5176,44 +5190,28 @@ function middleMousePaste(event) { // Things may go wrong when adding url to session history, // but don't let that interfere with the loading of the url. Cu.reportError(ex); } if (where != "current" || lastLocationChange == gBrowser.selectedBrowser.lastLocationChange) { openUILink(data.url, event, - { ignoreButton: true }); + { ignoreButton: true, + disallowInheritPrincipal: !data.mayInheritPrincipal }); } }); event.stopPropagation(); } function stripUnsafeProtocolOnPaste(pasteData) { - // Don't allow pasting in full URIs which inherit the security context. - const URI_INHERITS_SECURITY_CONTEXT = Ci.nsIProtocolHandler.URI_INHERITS_SECURITY_CONTEXT; - - let pastedURI; - try { - pastedURI = makeURI(pasteData.trim()); - } catch (ex) { - return pasteData; - } - - while (Services.netutil.URIChainHasFlags(pastedURI, URI_INHERITS_SECURITY_CONTEXT)) { - pasteData = pastedURI.path.trim(); - try { - pastedURI = makeURI(pasteData); - } catch (ex) { - break; - } - } - - return pasteData; + // Don't allow pasting javascript URIs since we don't support + // LOAD_FLAGS_DISALLOW_INHERIT_OWNER for those. + return pasteData.replace(/^(?:\s*javascript:)+/i, ""); } function handleDroppedLink(event, url, name) { let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; getShortcutOrURIAndPostData(url, data => { if (data.url &&
--- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -1586,32 +1586,32 @@ nsContextMenu.prototype = { PlacesUIUtils.showBookmarkDialog({ action: "edit" , type: "bookmark" , itemId: itemId }, window.top); } }, markLink: function CM_markLink(origin) { // send link to social, if it is the page url linkURI will be null - SocialMarks.markLink(origin, this.linkURI ? this.linkURI.spec : null); + SocialMarks.markLink(origin, this.linkURI ? this.linkURI.spec : null, this.target); }, shareLink: function CM_shareLink() { - SocialShare.sharePage(null, { url: this.linkURI.spec }); + SocialShare.sharePage(null, { url: this.linkURI.spec }, this.target); }, shareImage: function CM_shareImage() { - SocialShare.sharePage(null, { url: this.imageURL, previews: [ this.mediaURL ] }); + SocialShare.sharePage(null, { url: this.imageURL, previews: [ this.mediaURL ] }, this.target); }, shareVideo: function CM_shareVideo() { - SocialShare.sharePage(null, { url: this.mediaURL, source: this.mediaURL }); + SocialShare.sharePage(null, { url: this.mediaURL, source: this.mediaURL }, this.target); }, shareSelect: function CM_shareSelect(selection) { - SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: selection }); + SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: selection }, this.target); }, savePageAs: function CM_savePageAs() { saveDocument(this.browser.contentDocument); }, printFrame: function CM_printFrame() { PrintUtils.print(this.target.ownerDocument.defaultView);
--- a/browser/base/content/socialmarks.xml +++ b/browser/base/content/socialmarks.xml @@ -142,27 +142,34 @@ panel.hidden = true; } this.pageData = null; ]]></body> </method> <method name="loadPanel"> <parameter name="pageData"/> + <parameter name="target"/> <body><![CDATA[ let provider = this.provider; let panel = this.panel; panel.hidden = false; // reparent the iframe if we've been customized to a new location if (this.content.parentNode != panel) panel.appendChild(this.content); let URLTemplate = provider.markURL; - this.pageData = pageData || OpenGraphBuilder.getData(gBrowser); + pageData = pageData || OpenGraphBuilder.getData(gBrowser); + // if this is a share of a selected item, get any microdata + if (!pageData.microdata && target) { + pageData.microdata = OpenGraphBuilder.getMicrodata(gBrowser, target); + } + this.pageData = pageData; + let endpoint = OpenGraphBuilder.generateEndpointURL(URLTemplate, this.pageData); // setup listeners let DOMContentLoaded = (event) => { if (event.target != this.contentDocument) return; this._loading = false; this.content.removeEventListener("DOMContentLoaded", DOMContentLoaded, true); @@ -243,28 +250,29 @@ } if (openPanel) this.openPanel(); ]]></body> </method> <method name="markLink"> <parameter name="aUrl"/> + <parameter name="aTarget"/> <body><![CDATA[ if (!aUrl) { this.markCurrentPage(true); return; } // initiated form an external source, such as gContextMenu, where // pageData is passed into us. In this case, we always load the iframe // and show it since the url may not be the browser tab, but an image, // link, etc. inside the page. We also "update" the iframe to the // previous url when it is closed. this.content.setAttribute("src", "about:blank"); - this.loadPanel({ url: aUrl }); + this.loadPanel({ url: aUrl }, aTarget); this.openPanel(true); ]]></body> </method> <method name="dispatchPanelEvent"> <parameter name="name"/> <body><![CDATA[ let evt = this.contentDocument.createEvent("CustomEvent");
--- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -48,16 +48,17 @@ support-files = file_bug906190_redirected.html file_bug906190.js file_bug906190.sjs file_bug970276_popup1.html file_bug970276_popup2.html file_bug970276_favicon1.ico file_bug970276_favicon2.ico file_dom_notifications.html + file_favicon_change.html file_fullscreen-window-open.html get_user_media.html head.js healthreport_testRemoteCommands.html moz.png offlineQuotaNotification.cacheManifest offlineQuotaNotification.html page_style_sample.html @@ -285,16 +286,17 @@ run-if = datareporting skip-if = (os == "linux" && debug) || e10s # linux: bug 976544; e10s: Bug 973001 - appears user media notifications only happen in the child and don't make their way to the parent? [browser_devices_get_user_media_about_urls.js] skip-if = e10s # Bug 973001 - appears user media notifications only happen in the child and don't make their way to the parent? [browser_discovery.js] skip-if = e10s # Bug 918663 - DOMLinkAdded events don't make their way to chrome [browser_duplicateIDs.js] [browser_drag.js] skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638. +[browser_favicon_change.js] [browser_findbarClose.js] skip-if = e10s # Bug ?????? - test directly manipulates content (tries to grab an iframe directly from content) [browser_fullscreen-window-open.js] skip-if = e10s || os == "linux" # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly. Linux: Intermittent failures - bug 941575. [browser_gestureSupport.js] skip-if = e10s # Bug 863514 - no gesture support. [browser_getshortcutoruri.js] [browser_hide_removing.js] @@ -306,16 +308,17 @@ skip-if = e10s # Bug ?????? - this test [browser_keywordSearch.js] skip-if = e10s # Bug 921957 - remote webprogress doesn't supply originalURI attribute on the request object [browser_keywordSearch_postData.js] skip-if = e10s # Bug ?????? - test directly manipulates content (gBrowser.contentDocument.body.textContent) [browser_lastAccessedTab.js] skip-if = toolkit == "windows" # Disabled on Windows due to frequent failures (bug 969405) [browser_locationBarCommand.js] skip-if = os == "linux" || e10s # Linux: Intermittent failures, bug 917535; e10s: Bug ?????? - Focus issues (There should be no focused element - Got [object XULElement], expected null) +[browser_locationBarExternalLoad.js] [browser_menuButtonFitts.js] skip-if = os != "win" || e10s # The Fitts Law menu button is only supported on Windows (bug 969376); # Bug ?????? - URL bar issues ("There should be no focused element - Got [object XULElement], expected null") [browser_middleMouse_noJSPaste.js] skip-if = e10s # Bug 921952 - Content:Click event issues [browser_minimize.js] skip-if = e10s # Bug ?????? - test directly manipulates content (TypeError: gBrowser.docShell is null) [browser_mixedcontent_securityflags.js] skip-if = e10s # Bug ?????? - test directly manipulates content ("cannot ipc non-cpow object")
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/general/browser_favicon_change.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TEST_URL = "http://mochi.test:8888/browser/browser/base/content/test/general/file_favicon_change.html" + +add_task(function*() { + let extraTab = gBrowser.selectedTab = gBrowser.addTab(); + let tabLoaded = promiseTabLoaded(extraTab); + extraTab.linkedBrowser.loadURI(TEST_URL); + let expectedFavicon = "http://example.org/one-icon"; + let haveChanged = new Promise.defer(); + let observer = new MutationObserver(function(mutations) { + for (let mut of mutations) { + if (mut.attributeName != "image") { + continue; + } + let imageVal = extraTab.getAttribute("image").replace(/#.*$/, ""); + if (!imageVal) { + // The value gets removed because it doesn't load. + continue; + } + is(imageVal, expectedFavicon, "Favicon image should correspond to expected image."); + haveChanged.resolve(); + } + }); + observer.observe(extraTab, {attributes: true}); + yield tabLoaded; + yield haveChanged.promise; + haveChanged = new Promise.defer(); + expectedFavicon = "http://example.org/other-icon"; + let contentWin = extraTab.linkedBrowser.contentWindow; + let ev = new contentWin.CustomEvent("PleaseChangeFavicon", {}); + contentWin.dispatchEvent(ev); + yield haveChanged.promise; + observer.disconnect(); + gBrowser.removeTab(extraTab); +}); +
--- a/browser/base/content/test/general/browser_getshortcutoruri.js +++ b/browser/base/content/test/general/browser_getshortcutoruri.js @@ -6,19 +6,20 @@ function getPostDataString(aIS) { createInstance(Ci.nsIScriptableInputStream); sis.init(aIS); var dataLines = sis.read(aIS.available()).split("\n"); // only want the last line return dataLines[dataLines.length-1]; } -function keywordResult(aURL, aPostData) { +function keywordResult(aURL, aPostData, aIsUnsafe) { this.url = aURL; this.postData = aPostData; + this.isUnsafe = aIsUnsafe; } function keyWordData() {} keyWordData.prototype = { init: function(aKeyWord, aURL, aPostData, aSearchWord) { this.keyword = aKeyWord; this.uri = makeURI(aURL); this.postData = aPostData; @@ -47,30 +48,30 @@ var testData = [ [new bmKeywordData("bmpostget", "http://bmpostget/search1=%s", "search2=%s", "foo3"), new keywordResult("http://bmpostget/search1=foo3", "search2=foo3")], [new bmKeywordData("bmget-nosearch", "http://bmget-nosearch/", null, ""), new keywordResult("http://bmget-nosearch/", null)], [new searchKeywordData("searchget", "http://searchget/?search={searchTerms}", null, "foo4"), - new keywordResult("http://searchget/?search=foo4", null)], + new keywordResult("http://searchget/?search=foo4", null, true)], [new searchKeywordData("searchpost", "http://searchpost/", "search={searchTerms}", "foo5"), - new keywordResult("http://searchpost/", "search=foo5")], + new keywordResult("http://searchpost/", "search=foo5", true)], [new searchKeywordData("searchpostget", "http://searchpostget/?search1={searchTerms}", "search2={searchTerms}", "foo6"), - new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6")], + new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6", true)], // Bookmark keywords that don't take parameters should not be activated if a // parameter is passed (bug 420328). [new bmKeywordData("bmget-noparam", "http://bmget-noparam/", null, "foo7"), - new keywordResult(null, null)], + new keywordResult(null, null, true)], [new bmKeywordData("bmpost-noparam", "http://bmpost-noparam/", "not_a=param", "foo8"), - new keywordResult(null, null)], + new keywordResult(null, null, true)], // Test escaping (%s = escaped, %S = raw) // UTF-8 default [new bmKeywordData("bmget-escaping", "http://bmget/?esc=%s&raw=%S", null, "foé"), new keywordResult("http://bmget/?esc=fo%C3%A9&raw=foé", null)], // Explicitly-defined ISO-8859-1 [new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "foé"), new keywordResult("http://bmget/?esc=fo%E9&raw=foé", null)], @@ -82,17 +83,17 @@ var testData = [ // Explicitly-defined ISO-8859-1 [new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "+/@"), new keywordResult("http://bmget/?esc=%2B%2F%40&raw=+/@", null)], // Test using a non-bmKeywordData object, to test the behavior of // getShortcutOrURIAndPostData for non-keywords (setupKeywords only adds keywords for // bmKeywordData objects) [{keyword: "http://gavinsharp.com"}, - new keywordResult(null, null)] + new keywordResult(null, null, true)] ]; function test() { waitForExplicitFinish(); setupKeywords(); Task.spawn(function() { @@ -103,16 +104,17 @@ function test() { if (data.searchWord) query += " " + data.searchWord; let returnedData = yield new Promise( resolve => getShortcutOrURIAndPostData(query, resolve)); // null result.url means we should expect the same query we sent in let expected = result.url || query; is(returnedData.url, expected, "got correct URL for " + data.keyword); is(getPostDataString(returnedData.postData), result.postData, "got correct postData for " + data.keyword); + is(returnedData.mayInheritPrincipal, !result.isUnsafe, "got correct mayInheritPrincipal for " + data.keyword); } cleanupKeywords(); }).then(finish); } var gBMFolder = null; var gAddedEngines = []; function setupKeywords() {
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/general/browser_locationBarExternalLoad.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function test() { + waitForExplicitFinish(); + + nextTest(); +} + +let urls = [ + "data:text/html,<body>hi" +]; + +function urlEnter(url) { + gURLBar.value = url; + gURLBar.focus(); + EventUtils.synthesizeKey("VK_RETURN", {}); +} + +function urlClick(url) { + gURLBar.value = url; + gURLBar.focus(); + let goButton = document.getElementById("urlbar-go-button"); + EventUtils.synthesizeMouseAtCenter(goButton, {}); +} + +function nextTest() { + let url = urls.shift(); + if (url) { + testURL(url, urlEnter, function () { + testURL(url, urlClick, nextTest); + }); + } + else + finish(); +} + +function testURL(url, loadFunc, endFunc) { + let tab = gBrowser.selectedTab = gBrowser.addTab(); + registerCleanupFunction(function () { + gBrowser.removeTab(tab); + }); + addPageShowListener(function () { + let pagePrincipal = gBrowser.contentPrincipal; + loadFunc(url); + + addPageShowListener(function () { + let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); + is(fm.focusedElement, null, "should be no focused element"); + is(fm.focusedWindow, gBrowser.contentWindow, "content window should be focused"); + + ok(!gBrowser.contentPrincipal.equals(pagePrincipal), + "load of " + url + " by " + loadFunc.name + " should produce a page with a different principal"); + endFunc(); + }); + }); +} + +function addPageShowListener(func) { + gBrowser.selectedBrowser.addEventListener("pageshow", function loadListener() { + gBrowser.selectedBrowser.removeEventListener("pageshow", loadListener, false); + func(); + }); +}
--- a/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js +++ b/browser/base/content/test/general/browser_removeUnsafeProtocolsFromURLBarPaste.js @@ -2,23 +2,23 @@ function test() { waitForExplicitFinish(); testNext(); } let pairs = [ ["javascript:", ""], ["javascript:1+1", "1+1"], ["javascript:document.domain", "document.domain"], - ["data:text/html,<body>hi</body>", "text/html,<body>hi</body>"], + ["data:text/html,<body>hi</body>", "data:text/html,<body>hi</body>"], // Nested things get confusing because some things don't parse as URIs: ["javascript:javascript:alert('hi!')", "alert('hi!')"], - ["data:data:text/html,<body>hi</body>", "text/html,<body>hi</body>"], + ["data:data:text/html,<body>hi</body>", "data:data:text/html,<body>hi</body>"], ["javascript:data:javascript:alert('hi!')", "data:javascript:alert('hi!')"], - ["javascript:data:text/html,javascript:alert('hi!')", "text/html,javascript:alert('hi!')"], - ["data:data:text/html,javascript:alert('hi!')", "text/html,javascript:alert('hi!')"], + ["javascript:data:text/html,javascript:alert('hi!')", "data:text/html,javascript:alert('hi!')"], + ["data:data:text/html,javascript:alert('hi!')", "data:data:text/html,javascript:alert('hi!')"], ]; let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper); function paste(input, cb) { waitForClipboard(input, function() { clipboardHelper.copyString(input); }, function() {
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/general/file_favicon_change.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html><head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <link rel="icon" href="http://example.org/one-icon" type="image/ico" id="i"> +</head> +<body> + <script> + window.addEventListener("PleaseChangeFavicon", function() { + var ico = document.getElementById("i"); + ico.setAttribute("href", "http://example.org/other-icon"); + }); + </script> +</body></html>
--- a/browser/base/content/test/social/browser.ini +++ b/browser/base/content/test/social/browser.ini @@ -4,16 +4,17 @@ support-files = blocklist.xml checked.jpg head.js opengraph/og_invalid_url.html opengraph/opengraph.html opengraph/shortlink_linkrel.html opengraph/shorturl_link.html opengraph/shorturl_linkrel.html + microdata.html share.html social_activate.html social_activate_iframe.html social_chat.html social_crash_content_helper.js social_flyout.html social_mark.html social_panel.html
--- a/browser/base/content/test/social/browser_share.js +++ b/browser/base/content/test/social/browser_share.js @@ -165,10 +165,81 @@ var tests = { } else { SocialService.removeProvider(manifest.origin, next); } break; } } port.postMessage({topic: "test-init"}); executeSoon(runOneTest); + }, + testShareMicrodata: function(next) { + SocialService.addProvider(manifest, function(provider) { + let port = provider.getWorkerPort(); + let target, testTab; + + let expecting = JSON.stringify({ + "url": "https://example.com/browser/browser/base/content/test/social/microdata.html", + "title": "My Blog", + "previews": [], + "microdata": { + "items": [{ + "types": ["http://schema.org/BlogPosting"], + "properties": { + "headline": ["Progress report"], + "datePublished": ["2013-08-29"], + "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html?comments=0"], + "comment": [{ + "types": ["http://schema.org/UserComments"], + "properties": { + "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c1"], + "creator": [{ + "types": ["http://schema.org/Person"], + "properties": { + "name": ["Greg"] + } + } + ], + "commentTime": ["2013-08-29"] + } + }, { + "types": ["http://schema.org/UserComments"], + "properties": { + "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c2"], + "creator": [{ + "types": ["http://schema.org/Person"], + "properties": { + "name": ["Charlotte"] + } + } + ], + "commentTime": ["2013-08-29"] + } + } + ] + } + } + ] + } + }); + + port.onmessage = function (e) { + let topic = e.data.topic; + switch (topic) { + case "got-share-data-message": + is(JSON.stringify(e.data.result), expecting, "microdata data ok"); + gBrowser.removeTab(testTab); + SocialService.removeProvider(manifest.origin, next); + break; + } + } + port.postMessage({topic: "test-init"}); + + let url = "https://example.com/browser/browser/base/content/test/social/microdata.html" + addTab(url, function(tab) { + testTab = tab; + let doc = tab.linkedBrowser.contentDocument; + target = doc.getElementById("simple-hcard"); + SocialShare.sharePage(manifest.origin, null, target); + }); + }); } }
--- a/browser/base/content/test/social/browser_social_marks.js +++ b/browser/base/content/test/social/browser_social_marks.js @@ -275,16 +275,66 @@ var tests = { } break; } }; port.postMessage({topic: "test-init"}); }); }, + testMarkMicrodata: function(next) { + let provider = Social._getProviderFromOrigin(manifest2.origin); + let port = provider.getWorkerPort(); + let target, testTab; + + // browser_share tests microdata on the full page, this is testing a + // specific target element. + let expecting = JSON.stringify({ + "url": "https://example.com/browser/browser/base/content/test/social/microdata.html", + "microdata": { + "items": [{ + "types": ["http://schema.org/UserComments"], + "properties": { + "url": ["https://example.com/browser/browser/base/content/test/social/microdata.html#c2"], + "creator": [{ + "types": ["http://schema.org/Person"], + "properties": { + "name": ["Charlotte"] + } + } + ], + "commentTime": ["2013-08-29"] + } + } + ] + } + }); + + port.onmessage = function (e) { + let topic = e.data.topic; + switch (topic) { + case "got-share-data-message": + is(JSON.stringify(e.data.result), expecting, "microdata data ok"); + gBrowser.removeTab(testTab); + port.close(); + next(); + break; + } + } + port.postMessage({topic: "test-init"}); + + let url = "https://example.com/browser/browser/base/content/test/social/microdata.html" + addTab(url, function(tab) { + testTab = tab; + let doc = tab.linkedBrowser.contentDocument; + target = doc.getElementById("test-comment"); + SocialMarks.markLink(manifest2.origin, url, target); + }); + }, + testButtonOnDisable: function(next) { // enable the provider now let provider = Social._getProviderFromOrigin(manifest2.origin); ok(provider, "provider is installed"); SocialService.removeProvider(manifest2.origin, function() { let id = SocialMarks._toolbarHelper.idFromOrigin(manifest2.origin); waitForCondition(function() { // getWidget now returns null since we've destroyed the widget
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/social/microdata.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<head> +<title>My Blog</title> +</head> +<body> +<article itemscope itemtype="http://schema.org/BlogPosting"> + <header> + <h1 itemprop="headline">Progress report</h1> + <p><time itemprop="datePublished" datetime="2013-08-29">today</time></p> + <link itemprop="url" href="?comments=0"> + </header> + <p>All in all, he's doing well with his swim lessons. The biggest thing was he had trouble + putting his head in, but we got it down.</p> + <section> + <h1>Comments</h1> + <article itemprop="comment" itemscope itemtype="http://schema.org/UserComments" id="c1"> + <link itemprop="url" href="#c1"> + <footer> + <p>Posted by: <span itemprop="creator" itemscope itemtype="http://schema.org/Person"> + <span itemprop="name">Greg</span> + </span></p> + <p><time itemprop="commentTime" datetime="2013-08-29">15 minutes ago</time></p> + </footer> + <p>Ha!</p> + </article> + <article id="test-comment" itemprop="comment" itemscope itemtype="http://schema.org/UserComments" id="c2"> + <link itemprop="url" href="#c2"> + <footer> + <p>Posted by: <span itemprop="creator" itemscope itemtype="http://schema.org/Person"> + <span itemprop="name">Charlotte</span> + </span></p> + <p><time itemprop="commentTime" datetime="2013-08-29">5 minutes ago</time></p> + </footer> + <p>When you say "we got it down"...</p> + </article> + </section> +</article> +</body> \ No newline at end of file
--- a/browser/base/content/test/social/social_mark.html +++ b/browser/base/content/test/social/social_mark.html @@ -29,16 +29,18 @@ evt.initCustomEvent("socialMarkUpdate", true, true, JSON.stringify({marked: isMarked})); document.documentElement.dispatchEvent(evt); } var shareData; addEventListener("OpenGraphData", function(e) { shareData = JSON.parse(e.detail); updateTextNode(document.getElementById("shared"), shareData.url); socialMarkUpdate(true); + var port = navigator.mozSocial.getWorker().port; + port.postMessage({topic: "share-data-message", result: shareData}); }); </script> </head> <body onload="onLoad()"> <div id="content"> <h3>This window shows the mark data</h3> <div>Page Marked: <div id="shared" class="textbox"></div></div>
--- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -260,16 +260,17 @@ <method name="handleCommand"> <parameter name="aTriggeringEvent"/> <body><![CDATA[ if (aTriggeringEvent instanceof MouseEvent && aTriggeringEvent.button == 2) return; // Do nothing for right clicks var url = this.value; + var mayInheritPrincipal = false; var postData = null; var action = this._parseActionUrl(url); let lastLocationChange = gBrowser.selectedBrowser.lastLocationChange; let matchLastLocationChange = true; if (action) { url = action.param; @@ -282,17 +283,17 @@ gBrowser.removeTab(prevTab); } return; } continueOperation.call(this); } else { this._canonizeURL(aTriggeringEvent, response => { - [url, postData] = response; + [url, postData, mayInheritPrincipal] = response; if (url) { matchLastLocationChange = (lastLocationChange == gBrowser.selectedBrowser.lastLocationChange); continueOperation.call(this); } }); } @@ -304,20 +305,21 @@ addToUrlbarHistory(url); } catch (ex) { // Things may go wrong when adding url to session history, // but don't let that interfere with the loading of the url. Cu.reportError(ex); } function loadCurrent() { - let webnav = Ci.nsIWebNavigation; - let flags = webnav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | - webnav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; - gBrowser.loadURIWithFlags(url, flags, null, null, postData); + openUILinkIn(url, "current", { + allowThirdPartyFixup: true, + disallowInheritPrincipal: !mayInheritPrincipal, + postData: postData + }); } // Focus the content area before triggering loads, since if the load // occurs in a new tab, we want focus to be restored to the content // area when the current tab is re-selected. gBrowser.selectedBrowser.focus(); let isMouseEvent = aTriggeringEvent instanceof MouseEvent; @@ -417,17 +419,17 @@ url = url + suffix; } url = "http://www." + url; } } getShortcutOrURIAndPostData(url, data => { - aCallback([data.url, data.postData]); + aCallback([data.url, data.postData, data.mayInheritPrincipal]); }); ]]></body> </method> <field name="_contentIsCropped">false</field> <method name="_initURLTooltip"> <body><![CDATA[
--- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -276,43 +276,57 @@ function openLinkIn(url, where, params) let loadInBackground = where == "current" ? false : aInBackground; if (loadInBackground == null) { loadInBackground = aFromChrome ? false : getBoolPref("browser.tabs.loadInBackground"); } + let uriObj; + if (where == "current") { + try { + uriObj = Services.io.newURI(url, null, null); + } catch (e) {} + } + if (where == "current" && w.gBrowser.selectedTab.pinned) { try { - let uriObj = Services.io.newURI(url, null, null); - if (!uriObj.schemeIs("javascript") && - w.gBrowser.currentURI.host != uriObj.host) { + // nsIURI.host can throw for non-nsStandardURL nsIURIs. + if (!uriObj || (!uriObj.schemeIs("javascript") && + w.gBrowser.currentURI.host != uriObj.host)) { where = "tab"; loadInBackground = false; } } catch (err) { where = "tab"; loadInBackground = false; } } // Raise the target window before loading the URI, since loading it may // result in a new frontmost window (e.g. "javascript:window.open('');"). w.focus(); switch (where) { case "current": let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; + if (aAllowThirdPartyFixup) { flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; } - if (aDisallowInheritPrincipal) + + // LOAD_FLAGS_DISALLOW_INHERIT_OWNER isn't supported for javascript URIs, + // i.e. it causes them not to load at all. Callers should strip + // "javascript:" from pasted strings to protect users from malicious URIs + // (see stripUnsafeProtocolOnPaste). + if (aDisallowInheritPrincipal && !(uriObj && uriObj.schemeIs("javascript"))) flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; + w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData); break; case "tabshifted": loadInBackground = !loadInBackground; // fall through case "tab": let browser = w.gBrowser; browser.loadOneTab(url, {
--- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -4,23 +4,29 @@ "use strict"; const { classes: Cc, interfaces: Ci, utils: Cu } = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); -let console = (Cu.import("resource://gre/modules/devtools/Console.jsm", {})).console; +Cu.import("resource://gre/modules/osfile.jsm", this); this.EXPORTED_SYMBOLS = ["MozLoopService"]; +XPCOMUtils.defineLazyModuleGetter(this, "console", + "resource://gre/modules/devtools/Console.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI", "resource:///modules/loop/MozLoopAPI.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "convertToRTCStatsReport", + "resource://gre/modules/media/RTCStatsReport.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "Chat", "resource:///modules/Chat.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", "resource://services-common/utils.js"); XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils", "resource://services-crypto/utils.js"); @@ -28,16 +34,20 @@ XPCOMUtils.defineLazyModuleGetter(this, "resource://services-common/hawkclient.js"); XPCOMUtils.defineLazyModuleGetter(this, "deriveHawkCredentials", "resource://services-common/hawkrequest.js"); XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", "resource:///modules/loop/MozLoopPushHandler.jsm"); +XPCOMUtils.defineLazyServiceGetter(this, "uuidgen", + "@mozilla.org/uuid-generator;1", + "nsIUUIDGenerator"); + /** * Internal helper methods and state * * The registration is a two-part process. First we need to connect to * and register with the push server. Then we need to take the result of that * and register with the Loop server. */ let MozLoopServiceInternal = { @@ -299,25 +309,90 @@ let MozLoopServiceInternal = { map[key] = {}; map[key][property] = string.value; } return this._localizedStrings = map; }, /** + * Saves loop logs to the saved-telemetry-pings folder. + * + * @param {Object} pc The peerConnection in question. + */ + stageForTelemetryUpload: function(window, pc) { + window.WebrtcGlobalInformation.getAllStats(allStats => { + let internalFormat = allStats.reports[0]; // filtered on pc.id + window.WebrtcGlobalInformation.getLogging('', logs => { + let report = convertToRTCStatsReport(internalFormat); + let logStr = ""; + logs.forEach(s => { logStr += s + "\n"; }); + + // We have stats and logs. + + // Create worker job. ping = saved telemetry ping file header + payload + // + // Prepare payload according to https://wiki.mozilla.org/Loop/Telemetry + + let ai = Services.appinfo; + let uuid = uuidgen.generateUUID().toString(); + uuid = uuid.substr(1,uuid.length-2); // remove uuid curly braces + + let directory = OS.Path.join(OS.Constants.Path.profileDir, + "saved-telemetry-pings"); + let job = { + directory: directory, + filename: uuid + ".json", + ping: { + reason: "loop", + slug: uuid, + payload: { + ver: 1, + info: { + appUpdateChannel: ai.defaultUpdateChannel, + appBuildID: ai.appBuildID, + appName: ai.name, + appVersion: ai.version, + reason: "loop", + OS: ai.OS, + version: Services.sysinfo.getProperty("version") + }, + report: "ice failure", + connectionstate: pc.iceConnectionState, + stats: report, + localSdp: internalFormat.localSdp, + remoteSdp: internalFormat.remoteSdp, + log: logStr + } + } + }; + + // Send job to worker to do log sanitation, transcoding and saving to + // disk for pickup by telemetry on next startup, which then uploads it. + + let worker = new ChromeWorker("MozLoopWorker.js"); + worker.onmessage = function(e) { + console.log(e.data.ok ? + "Successfully staged loop report for telemetry upload." : + ("Failed to stage loop report. Error: " + e.data.fail)); + } + worker.postMessage(job); + }); + }, pc.id); + }, + + /** * Opens the chat window * * @param {Object} contentWindow The window to open the chat window in, may * be null. * @param {String} title The title of the chat window. * @param {String} url The page to load in the chat window. - * @param {String} mode May be "minimized" or undefined. */ - openChatWindow: function(contentWindow, title, url, mode) { + openChatWindow: function(contentWindow, title, url) { // So I guess the origin is the loop server!? let origin = this.loopServerUri; url = url.spec || url; let callback = chatbox => { // We need to use DOMContentLoaded as otherwise the injection will happen // in about:blank and then get lost. // Sadly we can't use chatbox.promiseChatLoaded() as promise chaining @@ -327,18 +402,43 @@ let MozLoopServiceInternal = { return; } chatbox.addEventListener("DOMContentLoaded", function loaded(event) { if (event.target != chatbox.contentDocument) { return; } chatbox.removeEventListener("DOMContentLoaded", loaded, true); - injectLoopAPI(chatbox.contentWindow); - }, true); + + let window = chatbox.contentWindow; + injectLoopAPI(window); + + let ourID = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; + + let onPCLifecycleChange = (pc, winID, type) => { + if (winID != ourID) { + return; + } + if (type == "iceconnectionstatechange") { + switch(pc.iceConnectionState) { + case "failed": + case "disconnected": + if (Services.telemetry.canSend || + Services.prefs.getBoolPref("toolkit.telemetry.test")) { + this.stageForTelemetryUpload(window, pc); + } + break; + } + } + }; + + let pc_static = new window.mozRTCPeerConnectionStatic(); + pc_static.registerPeerConnectionLifecycleCallback(onPCLifecycleChange); + }.bind(this), true); }; Chat.open(contentWindow, origin, title, url, undefined, undefined, callback); } }; /** * Public API
new file mode 100644 --- /dev/null +++ b/browser/components/loop/MozLoopWorker.js @@ -0,0 +1,161 @@ +/* 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/. */ + +/** + * A worker dedicated to loop-report sanitation and writing for MozLoopService. + */ + +"use strict"; + +importScripts("resource://gre/modules/osfile.jsm"); + +let File = OS.File; +let Encoder = new TextEncoder(); +let Counter = 0; + +const MAX_LOOP_LOGS = 5; +/** + * Communications with the controller. + * + * Accepts messages: + * { path: filepath, ping: data } + * + * Sends messages: + * { ok: true } + * { fail: serialized_form_of_OS.File.Error } + */ + +onmessage = function(e) { + if (++Counter > MAX_LOOP_LOGS) { + postMessage({ + fail: "Maximum " + MAX_LOOP_LOGS + "loop reports reached for this session" + }); + return; + } + + let directory = e.data.directory; + let filename = e.data.filename; + let ping = e.data.ping; + + // Anonymize data + resetIpMask(); + ping.payload.localSdp = redactSdp(ping.payload.localSdp); + ping.payload.remoteSdp = redactSdp(ping.payload.remoteSdp); + ping.payload.log = sanitizeLogs(ping.payload.log); + + let pingStr = anonymizeIPv4(sanitizeUrls(JSON.stringify(ping))); + + // Save to disk + let array = Encoder.encode(pingStr); + try { + File.makeDir(directory, + { unixMode: OS.Constants.S_IRWXU, ignoreExisting: true }); + File.writeAtomic(OS.Path.join(directory, filename), array); + postMessage({ ok: true }); + } catch (ex if ex instanceof File.Error) { + // Instances of OS.File.Error know how to serialize themselves + postMessage({fail: File.Error.toMsg(ex)}); + } +}; + +/** + * Mask upper 24-bits of ip address with fake numbers. Call resetIpMask() first. + */ + +let IpMap = {}; +let IpCount = 0; + +function resetIpMask() { + IpMap = {}; + IpCount = Math.floor(Math.random() * 16777215) + 1; +} + +/** + * Masks upper 24-bits of ip address with fake numbers. Grunt function. + * + * @param {DOMString} ip address + */ +function maskIp(ip) { + let isInvalidOrRfc1918or3927 = function(p1, p2, p3, p4) { + let invalid = octet => octet < 0 || octet > 255; + return invalid(p1) || invalid(p2) || invalid(p3) || invalid(p4) || + (p1 == 10) || + (p1 == 172 && p2 >= 16 && p2 <= 31) || + (p1 == 192 && p2 == 168) || + (p1 == 169 && p2 == 254); + }; + + let [p1, p2, p3, p4] = ip.split("."); + + if (isInvalidOrRfc1918or3927(p1, p2, p3, p4)) { + return ip; + } + let key = [p1, p2, p3].join(); + if (!IpMap[key]) { + do { + IpCount = (IpCount + 1049039) % 16777216; // + prime % 2^24 + p1 = (IpCount >> 16) % 256; + p2 = (IpCount >> 8) % 256; + p3 = IpCount % 256; + } while (isInvalidOrRfc1918or3927(p1, p2, p3, p4)); + IpMap[key] = p1 + "." + p2 + "." + p3; + } + return IpMap[key] + "." + p4; +} + +/** + * Partially masks ip numbers in input text. + * + * @param {DOMString} text Input text containing IP numbers as words. + */ +function anonymizeIPv4(text) { + return text.replace(/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g, + maskIp.bind(this)); +} + +/** + * Sanitizes any urls of session information, like + * + * - (id=31 url=https://call.services.mozilla.com/#call/ongoing/AQHYjqH_...) + * + (id=31 url=https://call.services.mozilla.com/#call/xxxx) + * + * - (id=35 url=about:loopconversation#incoming/1403134352854) + * + (id=35 url=about:loopconversation#incoming/xxxx) + * + * @param {DOMString} text The text. + */ +function sanitizeUrls(text) { + let trimUrl = url => url.replace(/(#call|#incoming).*/g, + (match, type) => type + "/xxxx"); + return text.replace(/\(id=(\d+) url=([^\)]+)\)/g, + (match, id, url) => + "(id=" + id + " url=" + trimUrl(url) + ")"); +} + +/** + * Removes privacy sensitive information from SDP input text outright, like + * + * a=fingerprint:sha-256 E9:DE:6A:FE:2A:2F:05: etc. + * a=identity ... + * + * Redacts lines from match to EOL. Assumes \r\n\ linebreaks. + * + * @param {DOMString} sdp The sdp text. + */ +let redactSdp = sdp => sdp.replace(/\r\na=(fingerprint|identity):.*?\r\n/g, + "\r\n"); + +/** + * Sanitizes log text of sensitive information, like + * + * - srflx(IP4:192.168.1.3:60348/UDP|turn402-oak.tokbox.com:3478) + * + srflx(IP4:192.168.1.3:60348/UDP|xxxx.xxx) + * + * @param {DOMString} log The log text. + */ +function sanitizeLogs(log) { + let rex = /(srflx|relay)\(IP4:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}\/(UDP|TCP)\|[^\)]+\)/g; + + return log.replace(rex, match => match.replace(/\|[^\)]+\)/, "|xxxx.xxx)")); +}
--- a/browser/components/loop/moz.build +++ b/browser/components/loop/moz.build @@ -9,9 +9,10 @@ JAR_MANIFESTS += ['jar.mn'] JS_MODULES_PATH = 'modules/loop' XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini'] EXTRA_JS_MODULES += [ 'MozLoopAPI.jsm', 'MozLoopPushHandler.jsm', 'MozLoopService.jsm', + 'MozLoopWorker.js', ]
--- a/browser/components/places/content/bookmarkProperties.js +++ b/browser/components/places/content/bookmarkProperties.js @@ -462,27 +462,25 @@ var BookmarkPropertiesPanel = { }, onDialogAccept: function BPP_onDialogAccept() { // We must blur current focused element to save its changes correctly document.commandDispatcher.focusedElement.blur(); // The order here is important! We have to uninit the panel first, otherwise // late changes could force it to commit more transactions. gEditItemOverlay.uninitPanel(true); - gEditItemOverlay = null; this._endBatch(); window.arguments[0].performed = true; }, onDialogCancel: function BPP_onDialogCancel() { // The order here is important! We have to uninit the panel first, otherwise // changes done as part of Undo may change the panel contents and by // that force it to commit more transactions. gEditItemOverlay.uninitPanel(true); - gEditItemOverlay = null; this._endBatch(); PlacesUtils.transactionManager.undoTransaction(); window.arguments[0].performed = false; }, /** * This method checks to see if the input fields are in a valid state. *
--- a/browser/components/places/content/editBookmarkOverlay.js +++ b/browser/components/places/content/editBookmarkOverlay.js @@ -204,16 +204,22 @@ var gEditItemOverlay = { this._showHideRows(); // observe changes if (!this._observersAdded) { // Single bookmarks observe any change. History entries and multiEdit // observe only tags changes, through bookmarks. if (this._itemId != -1 || this._uri || this._multiEdit) PlacesUtils.bookmarks.addObserver(this, false); + + this._element("namePicker").addEventListener("blur", this); + this._element("locationField").addEventListener("blur", this); + this._element("tagsField").addEventListener("blur", this); + this._element("keywordField").addEventListener("blur", this); + this._element("descriptionField").addEventListener("blur", this); window.addEventListener("unload", this, false); this._observersAdded = true; } this._initialized = true; }, /** @@ -383,16 +389,22 @@ var gEditItemOverlay = { if (!tagsSelectorRow.collapsed) this.toggleTagsSelector(); } if (this._observersAdded) { if (this._itemId != -1 || this._uri || this._multiEdit) PlacesUtils.bookmarks.removeObserver(this); + this._element("namePicker").removeEventListener("blur", this); + this._element("locationField").removeEventListener("blur", this); + this._element("tagsField").removeEventListener("blur", this); + this._element("keywordField").removeEventListener("blur", this); + this._element("descriptionField").removeEventListener("blur", this); + this._observersAdded = false; } this._itemId = -1; this._uri = null; this._uris = []; this._tags = []; this._allTags = []; @@ -523,17 +535,17 @@ var gEditItemOverlay = { // Ensure the tagsField is in sync, clean it up from empty tags this._initTextField("tagsField", tags, false); return true; } } return false; }, - onNamePickerChange: function EIO_onNamePickerChange() { + onNamePickerBlur: function EIO_onNamePickerBlur() { if (this._itemId == -1) return; var namePicker = this._element("namePicker") // Here we update either the item title or its cached static title var newTitle = namePicker.value; if (!newTitle && @@ -874,16 +886,21 @@ var gEditItemOverlay = { else { var indexOfItem = tags.indexOf(aEvent.target.label); if (indexOfItem != -1) tags.splice(indexOfItem, 1); } this._element("tagsField").value = tags.join(", "); this._updateTags(); break; + case "blur": + let replaceFn = (str, firstLetter) => firstLetter.toUpperCase(); + let nodeName = aEvent.target.id.replace(/editBMPanel_(\w)/, replaceFn); + this["on" + nodeName + "Blur"](); + break; case "unload": this.uninitPanel(false); break; } }, // nsINavBookmarkObserver onItemChanged: function EIO_onItemChanged(aItemId, aProperty,
--- a/browser/components/places/content/editBookmarkOverlay.xul +++ b/browser/components/places/content/editBookmarkOverlay.xul @@ -28,29 +28,27 @@ <rows id="editBMPanel_rows"> <row align="center" id="editBMPanel_nameRow"> <label value="&editBookmarkOverlay.name.label;" class="editBMPanel_rowLabel" accesskey="&editBookmarkOverlay.name.accesskey;" control="editBMPanel_namePicker" observes="paneElementsBroadcaster"/> <textbox id="editBMPanel_namePicker" - onblur="gEditItemOverlay.onNamePickerChange();" observes="paneElementsBroadcaster"/> </row> <row align="center" id="editBMPanel_locationRow"> <label value="&editBookmarkOverlay.location.label;" class="editBMPanel_rowLabel" accesskey="&editBookmarkOverlay.location.accesskey;" control="editBMPanel_locationField" observes="paneElementsBroadcaster"/> <textbox id="editBMPanel_locationField" class="uri-element" - onblur="gEditItemOverlay.onLocationFieldBlur();" observes="paneElementsBroadcaster"/> </row> <row align="center" id="editBMPanel_feedLocationRow"> <label value="&editBookmarkOverlay.feedLocation.label;" class="editBMPanel_rowLabel" accesskey="&editBookmarkOverlay.feedLocation.accesskey;" control="editBMPanel_feedLocationField" @@ -145,17 +143,16 @@ <textbox id="editBMPanel_tagsField" type="autocomplete" class="padded" flex="1" autocompletesearch="places-tag-autocomplete" completedefaultindex="true" tabscrolling="true" showcommentcolumn="true" - onblur="gEditItemOverlay.onTagsFieldBlur();" observes="paneElementsBroadcaster" placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"/> <button id="editBMPanel_tagsSelectorExpander" class="expander-down" tooltiptext="&editBookmarkOverlay.tagsExpanderDown.tooltip;" tooltiptextdown="&editBookmarkOverlay.tagsExpanderDown.tooltip;" tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;" oncommand="gEditItemOverlay.toggleTagsSelector();" @@ -175,30 +172,28 @@ <row align="center" id="editBMPanel_keywordRow"> <observes element="additionalInfoBroadcaster" attribute="hidden"/> <label value="&editBookmarkOverlay.keyword.label;" class="editBMPanel_rowLabel" accesskey="&editBookmarkOverlay.keyword.accesskey;" control="editBMPanel_keywordField" observes="paneElementsBroadcaster"/> <textbox id="editBMPanel_keywordField" - onblur="gEditItemOverlay.onKeywordFieldBlur();" observes="paneElementsBroadcaster"/> </row> <row id="editBMPanel_descriptionRow"> <observes element="additionalInfoBroadcaster" attribute="hidden"/> <label value="&editBookmarkOverlay.description.label;" class="editBMPanel_rowLabel" accesskey="&editBookmarkOverlay.description.accesskey;" control="editBMPanel_descriptionField" observes="paneElementsBroadcaster"/> <textbox id="editBMPanel_descriptionField" multiline="true" - onblur="gEditItemOverlay.onDescriptionFieldBlur();" observes="paneElementsBroadcaster"/> </row> </rows> </grid> <checkbox id="editBMPanel_loadInSidebarCheckbox" label="&editBookmarkOverlay.loadInSidebar.label;" accesskey="&editBookmarkOverlay.loadInSidebar.accesskey;"
--- a/browser/components/places/tests/browser/browser_bookmarksProperties.js +++ b/browser/components/places/tests/browser/browser_bookmarksProperties.js @@ -122,17 +122,17 @@ gTests.push({ // Check that name picker is read only var namepicker = this.window.document.getElementById("editBMPanel_namePicker"); ok(namepicker.readOnly, "Name field is disabled"); is(namepicker.value, PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId), "Node title is correct"); // Blur the field and ensure root's name has not been changed. - this.window.gEditItemOverlay.onNamePickerChange(); + this.window.gEditItemOverlay.onNamePickerBlur(); is(namepicker.value, PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId), "Root title is correct"); // Check the shortcut's title. is(PlacesUtils.bookmarks.getItemTitle(this.selectedNode.itemId), null, "Shortcut title is null"); this.finish(); },
--- a/browser/components/preferences/in-content/applications.js +++ b/browser/components/preferences/in-content/applications.js @@ -1688,20 +1688,18 @@ var gApplicationsPane = { manageApp: function(aEvent) { // Don't let the normal "on select action" handler get this event, // as we handle it specially ourselves. aEvent.stopPropagation(); var typeItem = this._list.selectedItem; var handlerInfo = this._handledTypes[typeItem.type]; - openDialog("chrome://browser/content/preferences/applicationManager.xul", - "", - "modal,centerscreen,resizable=no", - handlerInfo); + gSubDialog.open("chrome://browser/content/preferences/applicationManager.xul", + "resizable=no", handlerInfo); // Rebuild the actions menu so that we revert to the previous selection, // or "Always ask" if the previous default application has been removed this.rebuildActionsMenu(); // update the richlistitem too. Will be visible when selecting another row typeItem.setAttribute("actionDescription", this._describePreferredAction(handlerInfo)); @@ -1752,19 +1750,18 @@ var gApplicationsPane = { params.mimeInfo = handlerInfo.wrappedHandlerInfo; } params.title = this._prefsBundle.getString("fpTitleChooseApp"); params.description = handlerInfo.description; params.filename = null; params.handlerApp = null; - window.openDialog("chrome://global/content/appPicker.xul", null, - "chrome,modal,centerscreen,titlebar,dialog=yes", - params); + gSubDialog.open("chrome://global/content/appPicker.xul", + null, params); if (this.isValidHandlerApp(params.handlerApp)) { handlerApp = params.handlerApp; // Add the app to the type's list of possible handlers. handlerInfo.addPossibleApplicationHandler(handlerApp); }
--- a/browser/components/translation/Translation.jsm +++ b/browser/components/translation/Translation.jsm @@ -217,22 +217,29 @@ TranslationUI.prototype = { // Never show the infobar automatically while the translation // service is temporarily unavailable. if (Translation.serviceUnavailable) return false; // Check if we should never show the infobar for this language. let neverForLangs = Services.prefs.getCharPref("browser.translation.neverForLanguages"); - if (neverForLangs.split(",").indexOf(this.detectedLanguage) != -1) + if (neverForLangs.split(",").indexOf(this.detectedLanguage) != -1) { + TranslationHealthReport.recordAutoRejectedTranslationOffer(); return false; + } // or if we should never show the infobar for this domain. let perms = Services.perms; - return perms.testExactPermission(aURI, "translate") != perms.DENY_ACTION; + if (perms.testExactPermission(aURI, "translate") == perms.DENY_ACTION) { + TranslationHealthReport.recordAutoRejectedTranslationOffer(); + return false; + } + + return true; }, showTranslationUI: function(aDetectedLanguage) { this.detectedLanguage = aDetectedLanguage; // Reset all values before showing a new translation infobar. this.state = 0; this.translatedFrom = ""; @@ -293,16 +300,30 @@ let TranslationHealthReport = { * of the supported languages. * @param language * The language of the page. */ recordMissedTranslationOpportunity: function (language) { this._withProvider(provider => provider.recordMissedTranslationOpportunity(language)); }, + /** + * Record an automatically rejected translation offer in the health + * report. A translation offer is automatically rejected when a user + * has previously clicked "Never translate this language" or "Never + * translate this site", which results in the infobar not being shown for + * the translation opportunity. + * + * These translation opportunities should still be recorded in addition to + * recording the automatic rejection of the offer. + */ + recordAutoRejectedTranslationOffer: function () { + this._withProvider(provider => provider.recordAutoRejectedTranslationOffer()); + }, + /** * Record a translation in the health report. * @param langFrom * The language of the page. * @param langTo * The language translated to * @param numCharacters * The number of characters that were translated @@ -408,16 +429,17 @@ TranslationMeasurement1.prototype = Obje pageTranslatedCountsByLanguage: DAILY_LAST_TEXT_FIELD, detectedLanguageChangedBefore: DAILY_COUNTER_FIELD, detectedLanguageChangedAfter: DAILY_COUNTER_FIELD, targetLanguageChanged: DAILY_COUNTER_FIELD, deniedTranslationOffer: DAILY_COUNTER_FIELD, showOriginalContent: DAILY_COUNTER_FIELD, detectLanguageEnabled: DAILY_LAST_NUMERIC_FIELD, showTranslationUI: DAILY_LAST_NUMERIC_FIELD, + autoRejectedTranslationOffer: DAILY_COUNTER_FIELD, }, shouldIncludeField: function (field) { if (!Services.prefs.getBoolPref("toolkit.telemetry.enabled")) { // This measurement should only be included when telemetry is // enabled, so we will not include any fields. return false; } @@ -506,16 +528,25 @@ TranslationProvider.prototype = Object.f langCounts = JSON.stringify(langCounts); yield m.setDailyLastText("missedTranslationOpportunityCountsByLanguage", langCounts, date); }.bind(this)); }, + recordAutoRejectedTranslationOffer: function (date=new Date()) { + let m = this.getMeasurement(TranslationMeasurement1.prototype.name, + TranslationMeasurement1.prototype.version); + + return this._enqueueTelemetryStorageTask(function* recordTask() { + yield m.incrementDailyCounter("autoRejectedTranslationOffer", date); + }.bind(this)); + }, + recordTranslation: function (langFrom, langTo, numCharacters, date=new Date()) { let m = this.getMeasurement(TranslationMeasurement1.prototype.name, TranslationMeasurement1.prototype.version); return this._enqueueTelemetryStorageTask(function* recordTask() { yield m.incrementDailyCounter("pageTranslatedCount", date); yield m.incrementDailyCounter("charactersTranslatedCount", date, numCharacters);
--- a/browser/components/translation/test/browser_translation_fhr.js +++ b/browser/components/translation/test/browser_translation_fhr.js @@ -31,17 +31,18 @@ let MetricsChecker = { // .get() may return `undefined`, which we can't compute. this._metrics = { pageCount: day.get("pageTranslatedCount") || 0, charCount: day.get("charactersTranslatedCount") || 0, deniedOffers: day.get("deniedTranslationOffer") || 0, showOriginal: day.get("showOriginalContent") || 0, detectedLanguageChangedBefore: day.get("detectedLanguageChangedBefore") || 0, detectedLanguageChangeAfter: day.get("detectedLanguageChangedAfter") || 0, - targetLanguageChanged: day.get("targetLanguageChanged") || 0 + targetLanguageChanged: day.get("targetLanguageChanged") || 0, + autoRejectedOffers: day.get("autoRejectedTranslationOffer") || 0 }; this._metricsTime = metricsTime; }), checkAdditions: Task.async(function* (additions) { let prevMetrics = this._metrics, prevMetricsTime = this._metricsTime; try { yield this.updateMetrics(); @@ -154,16 +155,29 @@ add_task(function* test_language_change( } yield MetricsChecker.checkAdditions({ detectedLanguageChangedBefore: 4, detectedLanguageChangeAfter: 8, targetLanguageChanged: 12 }); }); +add_task(function* test_never_offer_translation() { + Services.prefs.setCharPref("browser.translation.neverForLanguages", "fr"); + + let tab = yield offerTranslatationFor("<h1>Hallo Welt!</h1>", "fr"); + + yield MetricsChecker.checkAdditions({ + autoRejectedOffers: 1, + }); + + gBrowser.removeTab(tab); + Services.prefs.clearUserPref("browser.translation.neverForLanguages") +}); + function getInfobarElement(browser, anonid) { let notif = browser.translationUI .notificationBox.getNotificationWithValue("translation"); return notif._getAnonElt(anonid); } function offerTranslatationFor(text, from) { return Task.spawn(function* task_offer_translation() {
--- a/browser/components/translation/test/unit/test_healthreport.js +++ b/browser/components/translation/test/unit/test_healthreport.js @@ -227,16 +227,21 @@ function* test_simple_counter(aProviderF add_task(function* test_denied_translation_offer() { yield test_simple_counter("recordDeniedTranslationOffer", "deniedTranslationOffer"); }); add_task(function* test_show_original() { yield test_simple_counter("recordShowOriginalContent", "showOriginalContent"); }); +add_task(function* test_show_original() { + yield test_simple_counter("recordAutoRejectedTranslationOffer", + "autoRejectedTranslationOffer"); +}); + add_task(function* test_collect_daily() { let storage = yield Metrics.Storage("translation"); let provider = new TranslationProvider(); yield provider.init(storage); let now = new Date(); // Set the prefs we test here to `false` initially. const kPrefDetectLanguage = "browser.translation.detectLanguage"; @@ -286,16 +291,18 @@ add_task(function* test_healthreporter_j yield provider.recordTranslation("fr", "en", 1000, now); yield provider.recordDetectedLanguageChange(false); yield provider.recordTranslationOpportunity("es", now); yield provider.recordTranslation("es", "en", 1000, now); yield provider.recordDeniedTranslationOffer(); + yield provider.recordAutoRejectedTranslationOffer(); + yield provider.recordShowOriginalContent(); yield reporter.collectMeasurements(); let payload = yield reporter.getJSONPayload(true); let today = reporter._formatDate(now); Assert.ok(today in payload.data.days); let day = payload.data.days[today]; @@ -324,16 +331,19 @@ add_task(function* test_healthreporter_j Assert.ok("detectedLanguageChangedBefore" in translations); Assert.equal(translations["detectedLanguageChangedBefore"], 1); Assert.ok("detectedLanguageChangedAfter" in translations); Assert.equal(translations["detectedLanguageChangedAfter"], 1); Assert.ok("deniedTranslationOffer" in translations); Assert.equal(translations["deniedTranslationOffer"], 1); + Assert.ok("autoRejectedTranslationOffer" in translations); + Assert.equal(translations["autoRejectedTranslationOffer"], 1); + Assert.ok("showOriginalContent" in translations); Assert.equal(translations["showOriginalContent"], 1); } finally { reporter._shutdown(); } }); // Test the payload after recording with telemetry disabled. @@ -352,16 +362,18 @@ add_task(function* test_healthreporter_j yield provider.recordTranslation("fr", "en", 1000, now); yield provider.recordDetectedLanguageChange(false); yield provider.recordTranslationOpportunity("es", now); yield provider.recordTranslation("es", "en", 1000, now); yield provider.recordDeniedTranslationOffer(); + yield provider.recordAutoRejectedTranslationOffer(); + yield provider.recordShowOriginalContent(); yield reporter.collectMeasurements(); let payload = yield reporter.getJSONPayload(true); let today = reporter._formatDate(now); Assert.ok(today in payload.data.days); let day = payload.data.days[today]; @@ -373,13 +385,14 @@ add_task(function* test_healthreporter_j Assert.ok(!("translationOpportunityCount" in translations)); Assert.ok(!("pageTranslatedCount" in translations)); Assert.ok(!("charactersTranslatedCount" in translations)); Assert.ok(!("translationOpportunityCountsByLanguage" in translations)); Assert.ok(!("pageTranslatedCountsByLanguage" in translations)); Assert.ok(!("detectedLanguageChangedBefore" in translations)); Assert.ok(!("detectedLanguageChangedAfter" in translations)); Assert.ok(!("deniedTranslationOffer" in translations)); + Assert.ok(!("autoRejectedTranslationOffer" in translations)); Assert.ok(!("showOriginalContent" in translations)); } finally { reporter._shutdown(); } });
--- a/browser/devtools/inspector/selector-search.js +++ b/browser/devtools/inspector/selector-search.js @@ -1,24 +1,28 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; const promise = require("devtools/toolkit/deprecated-sync-thenables"); - +loader.lazyGetter(this, "EventEmitter", () => require("devtools/toolkit/event-emitter")); loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/shared/autocomplete-popup").AutocompletePopup); // Maximum number of selector suggestions shown in the panel. const MAX_SUGGESTIONS = 15; /** * Converts any input box on a page to a CSS selector search and suggestion box. * + * Emits 'processing-done' event when it is done processing the current + * keypress, search request or selection from the list, whether that led to a + * search or not. + * * @constructor * @param InspectorPanel aInspector * The InspectorPanel whose `walker` attribute should be used for * document traversal. * @param nsiInputElement aInputNode * The input element to which the panel will be attached and from where * search input will be taken. */ @@ -56,16 +60,17 @@ function SelectorSearch(aInspector, aInp // event listeners. this.searchBox.addEventListener("command", this._onHTMLSearch, true); this.searchBox.addEventListener("keypress", this._onSearchKeypress, true); // For testing, we need to be able to wait for the most recent node request // to finish. Tests can watch this promise for that. this._lastQuery = promise.resolve(null); + EventEmitter.decorate(this); } exports.SelectorSearch = SelectorSearch; SelectorSearch.prototype = { get walker() this.inspector.walker, @@ -178,29 +183,31 @@ SelectorSearch.prototype = { /** * The command callback for the input box. This function is automatically * invoked as the user is typing if the input box type is search. */ _onHTMLSearch: function() { let query = this.searchBox.value; if (query == this._lastSearched) { + this.emit("processing-done"); return; } this._lastSearched = query; this._searchResults = []; this._searchIndex = 0; if (query.length == 0) { this._lastValidSearch = ""; this.searchBox.removeAttribute("filled"); this.searchBox.classList.remove("devtools-no-search-result"); if (this.searchPopup.isOpen) { this.searchPopup.hidePopup(); } + this.emit("processing-done"); return; } this.searchBox.setAttribute("filled", true); let queryList = null; this._lastQuery = this.walker.querySelectorAll(this.walker.rootNode, query).then(list => { return list; @@ -253,17 +260,17 @@ SelectorSearch.prototype = { this._lastValidSearch = query + "*"; } else if (query.match(/[\s>+][\.#a-zA-Z][\.#>\s+]*$/)) { let lastPart = query.match(/[\s+>][\.#a-zA-Z][^>\s+]*$/)[0]; this._lastValidSearch = query.slice(0, -1 * lastPart.length + 1) + "*"; } this.searchBox.classList.add("devtools-no-search-result"); return this.showSuggestions(); - }); + }).then(() => this.emit("processing-done")); }, /** * Handles keypresses inside the input box. */ _onSearchKeypress: function(aEvent) { let query = this.searchBox.value; switch(aEvent.keyCode) { @@ -327,17 +334,20 @@ SelectorSearch.prototype = { default: return; } aEvent.preventDefault(); aEvent.stopPropagation(); if (this._searchResults && this._searchResults.length > 0) { - this._lastQuery = this._selectResult(this._searchIndex); + this._lastQuery = this._selectResult(this._searchIndex).then(() => this.emit("processing-done")); + } + else { + this.emit("processing-done"); } }, /** * Handles keypress and mouse click on the suggestions richlistbox. */ _onListBoxKeypress: function(aEvent) { switch(aEvent.keyCode || aEvent.button) { @@ -388,16 +398,17 @@ SelectorSearch.prototype = { this._lastToLastValidSearch = null; let query = this.searchBox.value; this._lastValidSearch = (query.match(/(.*)[\.#][^\.# ]{0,}$/) || query.match(/(.*[\s>+])[a-zA-Z][^\.# ]{0,}$/) || ["",""])[1]; this._onHTMLSearch(); break; } + this.emit("processing-done"); }, /** * Populates the suggestions list and show the suggestion popup. */ _showPopup: function(aList, aFirstPart) { let total = 0; let query = this.searchBox.value;
--- a/browser/devtools/inspector/test/browser.ini +++ b/browser/devtools/inspector/test/browser.ini @@ -43,13 +43,12 @@ skip-if = true # Bug 1028609 [browser_inspector_pseudoclass-menu.js] [browser_inspector_reload.js] [browser_inspector_remove-iframe-during-load.js] [browser_inspector_scrolling.js] [browser_inspector_search-01.js] [browser_inspector_search-02.js] [browser_inspector_search-03.js] [browser_inspector_select-last-selected.js] -# [browser_inspector_search-navigation.js] -# Disabled for too many intermittent failures (bug 851349) +[browser_inspector_search-navigation.js] [browser_inspector_sidebarstate.js] [browser_inspector_switch-to-inspector-on-pick.js] [browser_inspector_update-on-navigation.js]
--- a/browser/devtools/inspector/test/browser_inspector_search-navigation.js +++ b/browser/devtools/inspector/test/browser_inspector_search-navigation.js @@ -1,162 +1,73 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ - -function test() -{ - requestLongerTimeout(2); - - let inspector, searchBox, state, panel; - let panelOpeningStates = [0, 3, 9, 14, 17]; - let panelClosingStates = [2, 8, 13, 16]; +"use strict"; - // The various states of the inspector: [key, query] - // [ - // what key to press, - // what should be the text in the searchbox - // ] - let keyStates = [ - ["d", "d"], - ["i", "di"], - ["v", "div"], - [".", "div."], - ["VK_UP", "div.c1"], - ["VK_DOWN", "div.l1"], - ["VK_DOWN", "div.l1"], - ["VK_BACK_SPACE", "div.l"], - ["VK_TAB", "div.l1"], - [" ", "div.l1 "], - ["VK_UP", "div.l1 DIV"], - ["VK_UP", "div.l1 DIV"], - [".", "div.l1 DIV."], - ["VK_TAB", "div.l1 DIV.c1"], - ["VK_BACK_SPACE", "div.l1 DIV.c"], - ["VK_BACK_SPACE", "div.l1 DIV."], - ["VK_BACK_SPACE", "div.l1 DIV"], - ["VK_BACK_SPACE", "div.l1 DI"], - ["VK_BACK_SPACE", "div.l1 D"], - ["VK_BACK_SPACE", "div.l1 "], - ["VK_UP", "div.l1 DIV"], - ["VK_BACK_SPACE", "div.l1 DI"], - ["VK_BACK_SPACE", "div.l1 D"], - ["VK_BACK_SPACE", "div.l1 "], - ["VK_UP", "div.l1 DIV"], - ["VK_UP", "div.l1 DIV"], - ["VK_TAB", "div.l1 DIV"], - ["VK_BACK_SPACE", "div.l1 DI"], - ["VK_BACK_SPACE", "div.l1 D"], - ["VK_BACK_SPACE", "div.l1 "], - ["VK_DOWN", "div.l1 DIV"], - ["VK_DOWN", "div.l1 SPAN"], - ["VK_DOWN", "div.l1 SPAN"], - ["VK_BACK_SPACE", "div.l1 SPA"], - ["VK_BACK_SPACE", "div.l1 SP"], - ["VK_BACK_SPACE", "div.l1 S"], - ["VK_BACK_SPACE", "div.l1 "], - ["VK_BACK_SPACE", "div.l1"], - ["VK_BACK_SPACE", "div.l"], - ["VK_BACK_SPACE", "div."], - ["VK_BACK_SPACE", "div"], - ["VK_BACK_SPACE", "di"], - ["VK_BACK_SPACE", "d"], - ["VK_BACK_SPACE", ""], - ]; - - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onload() { - gBrowser.selectedBrowser.removeEventListener("load", onload, true); - waitForFocus(setupTest, content); - }, true); - - content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/doc_inspector_search-suggestions.html"; - - function $(id) { - if (id == null) return null; - return content.document.getElementById(id); - } - - function setupTest() - { - openInspector(startTest); - } +// Check that searchbox value is correct when suggestions popup is navigated +// with keyboard. - function startTest(aInspector) - { - inspector = aInspector; - searchBox = - inspector.panelWin.document.getElementById("inspector-searchbox"); - panel = inspector.searchSuggestions.searchPopup._list; - - focusSearchBoxUsingShortcut(inspector.panelWin, function() { - searchBox.addEventListener("keypress", checkState, true); - panel.addEventListener("keypress", checkState, true); - checkStateAndMoveOn(0); - }); - } - - function checkStateAndMoveOn(index) { - if (index == keyStates.length) { - finishUp(); - return; - } - - let [key, query] = keyStates[index]; - state = index; - - info("pressing key " + key + " to get searchbox value as " + query); - EventUtils.synthesizeKey(key, {}, inspector.panelWin); - } +// Test data as pairs of [key to press, expected content of searchbox]. +const KEY_STATES = [ + ["d", "d"], + ["i", "di"], + ["v", "div"], + [".", "div."], + ["VK_UP", "div.c1"], + ["VK_DOWN", "div.l1"], + ["VK_DOWN", "div.l1"], + ["VK_BACK_SPACE", "div.l"], + ["VK_TAB", "div.l1"], + [" ", "div.l1 "], + ["VK_UP", "div.l1 div"], + ["VK_UP", "div.l1 div"], + [".", "div.l1 div."], + ["VK_TAB", "div.l1 div.c1"], + ["VK_BACK_SPACE", "div.l1 div.c"], + ["VK_BACK_SPACE", "div.l1 div."], + ["VK_BACK_SPACE", "div.l1 div"], + ["VK_BACK_SPACE", "div.l1 di"], + ["VK_BACK_SPACE", "div.l1 d"], + ["VK_BACK_SPACE", "div.l1 "], + ["VK_UP", "div.l1 div"], + ["VK_BACK_SPACE", "div.l1 di"], + ["VK_BACK_SPACE", "div.l1 d"], + ["VK_BACK_SPACE", "div.l1 "], + ["VK_UP", "div.l1 div"], + ["VK_UP", "div.l1 div"], + ["VK_TAB", "div.l1 div"], + ["VK_BACK_SPACE", "div.l1 di"], + ["VK_BACK_SPACE", "div.l1 d"], + ["VK_BACK_SPACE", "div.l1 "], + ["VK_DOWN", "div.l1 div"], + ["VK_DOWN", "div.l1 span"], + ["VK_DOWN", "div.l1 span"], + ["VK_BACK_SPACE", "div.l1 spa"], + ["VK_BACK_SPACE", "div.l1 sp"], + ["VK_BACK_SPACE", "div.l1 s"], + ["VK_BACK_SPACE", "div.l1 "], + ["VK_BACK_SPACE", "div.l1"], + ["VK_BACK_SPACE", "div.l"], + ["VK_BACK_SPACE", "div."], + ["VK_BACK_SPACE", "div"], + ["VK_BACK_SPACE", "di"], + ["VK_BACK_SPACE", "d"], + ["VK_BACK_SPACE", ""], +]; - function checkState(event) { - if (event && event.keyCode != event.DOM_VK_UP && - event.keyCode != event.DOM_VK_DOWN) { - info("Should wait before server sends the qSA response."); - inspector.searchSuggestions._lastQuery - .then(() => checkState(), () => checkState()); - return; - } - if (panelOpeningStates.indexOf(state) != -1 && - !inspector.searchSuggestions.searchPopup.isOpen) { - info("Panel is not open, should wait before it shows up."); - panel.parentNode.addEventListener("popupshown", function retry() { - panel.parentNode.removeEventListener("popupshown", retry, false); - info("Panel is visible now"); - executeSoon(checkState); - }, false); - return; - } - else if (panelClosingStates.indexOf(state) != -1 && - panel.parentNode.state != "closed") { - info("Panel is open, should wait for it to close."); - panel.parentNode.addEventListener("popuphidden", function retry() { - panel.parentNode.removeEventListener("popuphidden", retry, false); - info("Panel is hidden now"); - executeSoon(checkState); - }, false); - return; - } +const TEST_URL = TEST_URL_ROOT + + "doc_inspector_search-suggestions.html"; + +let test = asyncTest(function* () { + let { inspector } = yield openInspectorForURL(TEST_URL); + yield focusSearchBoxUsingShortcut(inspector.panelWin); - // Using setTimout as the "command" event fires at delay after keypress - window.setTimeout(function() { - let [key, query] = keyStates[state]; + for (let [key, query] of KEY_STATES) { + info("Pressing key " + key + " to get searchbox value as " + query); - if (searchBox.value == query) { - ok(true, "The suggestion at " + state + "th step on " + - "pressing " + key + " key is correct."); - } - else { - info("value is not correct, waiting longer for state " + state + - " with panel " + panel.parentNode.state); - checkState(); - return; - } - checkStateAndMoveOn(state + 1); - }, 200); + let done = inspector.searchSuggestions.once("processing-done"); + EventUtils.synthesizeKey(key, {}, inspector.panelWin); + yield done; + + is(inspector.searchBox.value, query, "The searchbox value is correct."); } - - function finishUp() { - searchBox = null; - panel = null; - gBrowser.removeCurrentTab(); - finish(); - } -} +});
--- a/browser/modules/ContentLinkHandler.jsm +++ b/browser/modules/ContentLinkHandler.jsm @@ -16,21 +16,24 @@ Cu.import("resource://gre/modules/Servic XPCOMUtils.defineLazyModuleGetter(this, "Feeds", "resource:///modules/Feeds.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"); this.ContentLinkHandler = { init: function(chromeGlobal) { chromeGlobal.addEventListener("DOMLinkAdded", (event) => { - this.onLinkAdded(event, chromeGlobal); + this.onLinkEvent(event, chromeGlobal); + }, false); + chromeGlobal.addEventListener("DOMLinkChanged", (event) => { + this.onLinkEvent(event, chromeGlobal); }, false); }, - onLinkAdded: function(event, chromeGlobal) { + onLinkEvent: function(event, chromeGlobal) { var link = event.originalTarget; var rel = link.rel && link.rel.toLowerCase(); if (!link || !link.ownerDocument || !rel || !link.href) return; // Ignore sub-frames (bugs 305472, 479408). let window = link.ownerDocument.defaultView; if (window != window.top) @@ -42,17 +45,17 @@ this.ContentLinkHandler = { var rels = {}; for (let relString of rel.split(/\s+/)) rels[relString] = true; for (let relVal in rels) { switch (relVal) { case "feed": case "alternate": - if (!feedAdded) { + if (!feedAdded && event.type == "DOMLinkAdded") { if (!rels.feed && rels.alternate && rels.stylesheet) break; if (Feeds.isValidFeed(link, link.ownerDocument.nodePrincipal, "feed" in rels)) { chromeGlobal.sendAsyncMessage("Link:AddFeed", {type: link.type, href: link.href, title: link.title}); @@ -64,21 +67,21 @@ this.ContentLinkHandler = { if (!iconAdded) { if (!Services.prefs.getBoolPref("browser.chrome.site_icons")) break; var uri = this.getLinkIconURI(link); if (!uri) break; - [iconAdded] = chromeGlobal.sendSyncMessage("Link:AddIcon", {url: uri.spec}); + [iconAdded] = chromeGlobal.sendSyncMessage("Link:SetIcon", {url: uri.spec}); } break; case "search": - if (!searchAdded) { + if (!searchAdded && event.type == "DOMLinkAdded") { var type = link.type && link.type.toLowerCase(); type = type.replace(/^\s+|\s*(?:;.*)?$/g, ""); let re = /^(?:https?|ftp):/i; if (type == "application/opensearchdescription+xml" && link.title && re.test(link.href)) { let engine = { title: link.title, href: link.href };
--- a/browser/modules/Social.jsm +++ b/browser/modules/Social.jsm @@ -493,41 +493,53 @@ this.OpenGraphBuilder = { var str = []; for (let p in query) str.push(p + "=" + encodeURIComponent(query[p])); if (str.length) endpointURL = endpointURL + "?" + str.join("&"); return endpointURL; }, - getData: function(browser) { + getData: function(browser, target) { let res = { url: this._validateURL(browser, browser.currentURI.spec), title: browser.contentDocument.title, previews: [] }; this._getMetaData(browser, res); this._getLinkData(browser, res); this._getPageData(browser, res); + res.microdata = this.getMicrodata(browser, target); return res; }, + getMicrodata: function (browser, target) { + return getMicrodata(browser.contentDocument, target); + }, + _getMetaData: function(browser, o) { // query for standardized meta data let els = browser.contentDocument .querySelectorAll("head > meta[property], head > meta[name]"); if (els.length < 1) return; let url; for (let el of els) { let value = el.getAttribute("content") if (!value) continue; value = unescapeService.unescape(value.trim()); - switch (el.getAttribute("property") || el.getAttribute("name")) { + let key = el.getAttribute("property") || el.getAttribute("name"); + if (!key) + continue; + // There are a wide array of possible meta tags, expressing articles, + // products, etc. so all meta tags are passed through but we touch up the + // most common attributes. + o[key] = value; + switch (key) { case "title": case "og:title": o.title = value; break; case "description": case "og:description": o.description = value; break; @@ -572,16 +584,29 @@ this.OpenGraphBuilder = { break; case "canonicalurl": case "canonical": o.url = url; break; case "image_src": o.previews.push(url); break; + case "alternate": + // expressly for oembed support but we're liberal here and will let + // other alternate links through. oembed defines an href, supplied by + // the site, where you can fetch additional meta data about a page. + // We'll let the client fetch the oembed data themselves, but they + // need the data from this link. + if (!o.alternate) + o.alternate = []; + o.alternate.push({ + "type": el.getAttribute("type"), + "href": el.getAttribute("href"), + "title": el.getAttribute("title") + }) } } }, // scrape through the page for data we want _getPageData: function(browser, o) { if (o.previews.length < 1) o.previews = this._getImageUrls(browser); @@ -605,8 +630,48 @@ this.OpenGraphBuilder = { // we don't want a billion images if (l.length > 5) break; } } return l; } }; + +// getMicrodata (and getObject) based on wg algorythm to convert microdata to json +// http://www.whatwg.org/specs/web-apps/current-work/multipage/microdata-2.html#json +function getMicrodata(document, target) { + + function _getObject(item) { + let result = {}; + if (item.itemType.length) + result.types = [i for (i of item.itemType)]; + if (item.itemId) + result.itemId = item.itemid; + if (item.properties.length) + result.properties = {}; + for (let elem of item.properties) { + let value; + if (elem.itemScope) + value = _getObject(elem); + else if (elem.itemValue) + value = elem.itemValue; + // handle mis-formatted microdata + else if (elem.hasAttribute("content")) + value = elem.getAttribute("content"); + + for (let prop of elem.itemProp) { + if (!result.properties[prop]) + result.properties[prop] = []; + result.properties[prop].push(value); + } + } + return result; + } + + let result = { items: [] }; + let elms = target ? [target] : document.getItems(); + for (let el of elms) { + if (el.itemScope) + result.items.push(_getObject(el)); + } + return result; +}
--- a/browser/modules/WebappManager.jsm +++ b/browser/modules/WebappManager.jsm @@ -129,55 +129,49 @@ this.WebappManager = { "webapps-notification-icon"); let progressMeter = chromeDoc.createElement("progressmeter"); progressMeter.setAttribute("mode", "undetermined"); popupProgressContent.appendChild(progressMeter); let manifestURL = aData.app.manifestURL; - let cleanup = () => { + let nativeApp = new NativeApp(aData.app, jsonManifest, + aData.app.categories); + + this.installations[manifestURL] = Promise.defer(); + this.installations[manifestURL].promise.then(() => { + notifyInstallSuccess(aData.app, nativeApp, bundle); + }, (error) => { + Cu.reportError("Error installing webapp: " + error); + }).then(() => { popupProgressContent.removeChild(progressMeter); delete this.installations[manifestURL]; if (Object.getOwnPropertyNames(this.installations).length == 0) { notification.remove(); } - }; - - this.installations[manifestURL] = Promise.defer(); - this.installations[manifestURL].promise.then(null, (error) => { - Cu.reportError("Error installing webapp: " + error); - cleanup(); }); - let nativeApp = new NativeApp(aData.app, jsonManifest, - aData.app.categories); let localDir; try { localDir = nativeApp.createProfile(); } catch (ex) { - Cu.reportError("Error installing webapp: " + ex); DOMApplicationRegistry.denyInstall(aData); - cleanup(); return; } DOMApplicationRegistry.confirmInstall(aData, localDir, - (aApp, aManifest, aZipPath) => Task.spawn((function*() { + Task.async(function*(aApp, aManifest, aZipPath) { try { yield nativeApp.install(aApp, aManifest, aZipPath); - yield this.installations[manifestURL].promise; - notifyInstallSuccess(aApp, nativeApp, bundle); } catch (ex) { Cu.reportError("Error installing webapp: " + ex); - // TODO: Notify user that the installation has failed - } finally { - cleanup(); + throw ex; } - }).bind(this)) + }) ); } }; let requestingURI = chromeWin.makeURI(aData.from); let manifest = new ManifestHelper(jsonManifest, aData.app.origin); let host;
--- a/build/autoconf/ffi.m4 +++ b/build/autoconf/ffi.m4 @@ -83,22 +83,18 @@ if test -z "$BUILDING_JS" -o -n "$JS_STA ac_configure_args="$ac_configure_args CC=gcc CFLAGS=-maix32" else ac_configure_args="$ac_configure_args CC=gcc CFLAGS=-maix64" fi fi # Use a separate cache file for libffi, since it does things differently # from our configure. - mkdir -p $_objdir/js/src/ctypes/libffi - old_cache_file=$cache_file - cache_file=$_objdir/js/src/ctypes/libffi/config.cache old_config_files=$CONFIG_FILES unset CONFIG_FILES AC_OUTPUT_SUBDIRS(js/src/ctypes/libffi) - cache_file=$old_cache_file ac_configure_args="$_SUBDIR_CONFIG_ARGS" CONFIG_FILES=$old_config_files fi fi ])
--- a/build/autoconf/hooks.m4 +++ b/build/autoconf/hooks.m4 @@ -13,43 +13,55 @@ changequote([, ])dnl dnl Wrap AC_INIT_PREPARE to add the above trap. define([_MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE])) define([AC_INIT_PREPARE], [_MOZ_AC_INIT_PREPARE($1) MOZ_CONFIG_LOG_TRAP ]) dnl Disable the trap when running sub-configures. -define([_MOZ_AC_OUTPUT_SUBDIRS], defn([AC_OUTPUT_SUBDIRS])) -define([MOZ_SUBCONFIGURE_WRAP], -[ _CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} -case "$host" in -*-mingw*) +define(GEN_MOZ_AC_OUTPUT_SUBDIRS, [ +define([_MOZ_AC_OUTPUT_SUBDIRS], [ +patsubst($@, [$srcdir/$ac_config_dir], [$srcdir/$moz_config_srcdir]) +]) +]) +GEN_MOZ_AC_OUTPUT_SUBDIRS(defn([AC_OUTPUT_SUBDIRS])) + +define([AC_OUTPUT_SUBDIRS], +[trap '' EXIT +for moz_config_dir in $1; do + case "$moz_config_dir" in + *:*) + moz_config_srcdir=$(echo $moz_config_dir | awk -F: '{print [$]1}') + moz_config_dir=$(echo $moz_config_dir | awk -F: '{print [$]2}') + ;; + *) + moz_config_srcdir=$moz_config_dir + ;; + esac + _CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + case "$host" in + *-mingw*) _CONFIG_SHELL=$(cd $(dirname $_CONFIG_SHELL); pwd -W)/$(basename $_CONFIG_SHELL) if test ! -e "$_CONFIG_SHELL" -a -e "${_CONFIG_SHELL}.exe"; then _CONFIG_SHELL="${_CONFIG_SHELL}.exe" fi ;; -esac + esac -if test -d "$1"; then - (cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py dump "$_CONFIG_SHELL") -else - mkdir -p "$1" -fi -$2 -(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py adjust $ac_sub_configure) -]) - -define([AC_OUTPUT_SUBDIRS], -[trap '' EXIT -for moz_config_dir in $1; do - MOZ_SUBCONFIGURE_WRAP([$moz_config_dir],[ - _MOZ_AC_OUTPUT_SUBDIRS($moz_config_dir) - ]) + if test -d "$moz_config_dir"; then + (cd "$moz_config_dir"; eval $PYTHON $_topsrcdir/build/subconfigure.py dump "$_CONFIG_SHELL" $ac_configure_args) + else + mkdir -p "$moz_config_dir" + fi + _save_cache_file="$cache_file" + ifelse($2,,cache_file="$moz_config_dir/config.cache",cache_file="$2") + _MOZ_AC_OUTPUT_SUBDIRS($moz_config_dir) + cache_file="$_save_cache_file" + (cd "$moz_config_dir"; $PYTHON $_topsrcdir/build/subconfigure.py adjust $ac_sub_configure) done MOZ_CONFIG_LOG_TRAP ]) dnl Print error messages in config.log as well as stderr define([AC_MSG_ERROR], [{ echo "configure: error: $1" 1>&2; echo "configure: error: $1" 1>&5; exit 1; }])
--- a/build/autoconf/icu.m4 +++ b/build/autoconf/icu.m4 @@ -149,37 +149,18 @@ if test -z "$BUILDING_JS" -o -n "$JS_STA ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_BREAK_ITERATION" ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_IDNA" # we don't need to pass data to and from legacy char* APIs ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_CHARSET_IS_UTF8" # make sure to not accidentally pick up system-icu headers ICU_CPPFLAGS="$ICU_CPPFLAGS -I$icudir/common -I$icudir/i18n" ICU_CROSS_BUILD_OPT="" - ICU_SRCDIR="" - if test "$HOST_OS_ARCH" = "WINNT"; then - ICU_SRCDIR="--srcdir=$(cd $srcdir/intl/icu/source; pwd -W)" - fi if test "$CROSS_COMPILE"; then - # Building host tools. It is necessary to build target binary. - case "$HOST_OS_ARCH" in - Darwin) - ICU_TARGET=MacOSX - ;; - Linux) - ICU_TARGET=Linux - ;; - WINNT) - ICU_TARGET=MSYS/MSVC - ;; - DragonFly|FreeBSD|NetBSD|OpenBSD|GNU_kFreeBSD) - ICU_TARGET=BSD - ;; - esac # Remove _DEPEND_CFLAGS from HOST_FLAGS to avoid configure error HOST_ICU_CFLAGS="$HOST_CFLAGS" HOST_ICU_CXXFLAGS="$HOST_CXXFLAGS" HOST_ICU_CFLAGS=`echo $HOST_ICU_CFLAGS | sed "s|$_DEPEND_CFLAGS||g"` HOST_ICU_CXXFLAGS=`echo $HOST_ICU_CFXXLAGS | sed "s|$_DEPEND_CFLAGS||g"` # ICU requires RTTI @@ -191,34 +172,30 @@ if test -z "$BUILDING_JS" -o -n "$JS_STA HOST_ICU_BUILD_OPTS="" if test -n "$MOZ_DEBUG"; then HOST_ICU_BUILD_OPTS="$HOST_ICU_BUILD_OPTS --enable-debug" fi abs_srcdir=`(cd $srcdir; pwd)` mkdir -p $_objdir/intl/icu/host - (cd $_objdir/intl/icu/host - MOZ_SUBCONFIGURE_WRAP([.],[ - AR="$HOST_AR" RANLIB="$HOST_RANLIB" \ - CC="$HOST_CC" CXX="$HOST_CXX" LD="$HOST_LD" \ - CFLAGS="$HOST_ICU_CFLAGS $HOST_OPTIMIZE_FLAGS" \ - CPPFLAGS="$ICU_CPPFLAGS" \ - CXXFLAGS="$HOST_ICU_CXXFLAGS $HOST_OPTIMIZE_FLAGS" \ - LDFLAGS="$HOST_LDFLAGS" \ - $SHELL $abs_srcdir/intl/icu/source/runConfigureICU \ - $HOST_ICU_BUILD_OPTS \ - $ICU_TARGET \ - dnl Shell quoting is fun. - ${ICU_SRCDIR+"$ICU_SRCDIR"} \ - --enable-static --disable-shared \ - --enable-extras=no --enable-icuio=no --enable-layout=no \ - --enable-tests=no --enable-samples=no || exit 1 - ]) - ) || exit 1 + (export AR="$HOST_AR" + export RANLIB="$HOST_RANLIB" + export CC="$HOST_CC" + export CXX="$HOST_CXX" + export CPP="$HOST_CPP" + export LD="$HOST_LD" + export CFLAGS="$HOST_ICU_CFLAGS $HOST_OPTIMIZE_FLAGS" + export CPPFLAGS="$ICU_CPPFLAGS" + export CXXFLAGS="$HOST_ICU_CXXFLAGS $HOST_OPTIMIZE_FLAGS" + export LDFLAGS="$HOST_LDFLAGS" + ac_configure_args="$HOST_ICU_BUILD_OPTS" + ac_configure_args="$ac_configure_args --enable-static --disable-shared --enable-extras=no --enable-icuio=no --enable-layout=no --enable-tests=no --enable-samples=no" + AC_OUTPUT_SUBDIRS(intl/icu/source:intl/icu/host) + ) || exit 1 # generate config/icucross.mk $GMAKE -C $_objdir/intl/icu/host/ config/icucross.mk # --with-cross-build requires absolute path ICU_HOST_PATH=`cd $_objdir/intl/icu/host && pwd` ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH" ICU_TARGET_OPT="--build=$build --host=$target" else @@ -303,37 +280,26 @@ if test -z "$BUILDING_JS" -o -n "$JS_STA ICU_CXXFLAGS="$ICU_CXXFLAGS -DU_STATIC_IMPLEMENTATION" ICU_CFLAGS="$ICU_CFLAGS -DU_STATIC_IMPLEMENTATION" if test "$GNU_CC"; then ICU_CFLAGS="$ICU_CFLAGS -fvisibility=hidden" ICU_CXXFLAGS="$ICU_CXXFLAGS -fvisibility=hidden" fi fi - # We cannot use AC_OUTPUT_SUBDIRS since ICU tree is out of spidermonkey. - # When using AC_OUTPUT_SUBDIRS, objdir of ICU is out of objdir - # due to relative path. - # If building ICU moves into root of mozilla tree, we can use - # AC_OUTPUT_SUBDIR instead. - mkdir -p $_objdir/intl/icu/target - (cd $_objdir/intl/icu/target - MOZ_SUBCONFIGURE_WRAP([.],[ - AR="$AR" CC="$CC" CXX="$CXX" LD="$LD" \ - ARFLAGS="$ARFLAGS" \ - CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS" \ - CFLAGS="$ICU_CFLAGS" \ - CXXFLAGS="$ICU_CXXFLAGS" \ - LDFLAGS="$ICU_LDFLAGS $LDFLAGS" \ - $SHELL $_topsrcdir/intl/icu/source/configure \ - $ICU_BUILD_OPTS \ - $ICU_CROSS_BUILD_OPT \ - $ICU_LINK_OPTS \ - ${ICU_SRCDIR+"$ICU_SRCDIR"} \ - $ICU_TARGET_OPT \ - --disable-extras --disable-icuio --disable-layout \ - --disable-tests --disable-samples || exit 1 - ]) + (export AR="$AR" + export CC="$CC" + export CXX="$CXX" + export LD="$LD" + export ARFLAGS="$ARFLAGS" + export CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS" + export CFLAGS="$ICU_CFLAGS" + export CXXFLAGS="$ICU_CXXFLAGS" + export LDFLAGS="$ICU_LDFLAGS $LDFLAGS" + ac_configure_args="$ICU_BUILD_OPTS $ICU_CROSS_BUILD_OPT $ICU_LINK_OPTS $ICU_TARGET_OPT" + ac_configure_args="$ac_configure_args --disable-extras --disable-icuio --disable-layout --disable-tests --disable-samples" + AC_OUTPUT_SUBDIRS(intl/icu/source:intl/icu/target) ) || exit 1 fi fi ])
--- a/build/mobile/robocop/Makefile.in +++ b/build/mobile/robocop/Makefile.in @@ -25,16 +25,17 @@ ANDROID_ASSETS_DIR := $(TESTPATH)/assets FennecTalosAssert.java \ FennecNativeDriver.java \ FennecNativeElement.java \ RoboCopException.java \ RobocopShare1.java \ RobocopShare2.java \ RobocopUtils.java \ PaintedSurface.java \ + StructuredLogger.java \ $(NULL) java-harness := $(addprefix $(srcdir)/,$(_JAVA_HARNESS)) java-tests := \ $(wildcard $(TESTPATH)/*.java) \ $(wildcard $(TESTPATH)/components/*.java) \ $(wildcard $(TESTPATH)/helpers/*.java)
new file mode 100644 --- /dev/null +++ b/build/mobile/robocop/StructuredLogger.java @@ -0,0 +1,184 @@ +/* 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/. */ + +package org.mozilla.gecko; + +import java.util.HashSet; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONObject; + +// This implements the structured logging API described here: http://mozbase.readthedocs.org/en/latest/mozlog_structured.html +public class StructuredLogger { + private final static HashSet<String> validTestStatus = new HashSet<String>(Arrays.asList("PASS", "FAIL", "TIMEOUT", "NOTRUN", "ASSERT")); + private final static HashSet<String> validTestEnd = new HashSet<String>(Arrays.asList("PASS", "FAIL", "OK", "ERROR", "TIMEOUT", + "CRASH", "ASSERT", "SKIP")); + + private String mName; + private String mComponent; + private LoggerCallback mCallback; + + static public interface LoggerCallback { + public void call(String output); + } + + /* A default logger callback that prints the JSON output to stdout. + * This is not to be used in robocop as we write to a log file. */ + static class StandardLoggerCallback implements LoggerCallback { + public void call(String output) { + System.out.println(output); + } + } + + public StructuredLogger(String name, String component, LoggerCallback callback) { + mName = name; + mComponent = component; + mCallback = callback; + } + + public StructuredLogger(String name, String component) { + this(name, component, new StandardLoggerCallback()); + } + + public StructuredLogger(String name) { + this(name, null, new StandardLoggerCallback()); + } + + public void suiteStart(List<String> tests, Map<String, Object> runInfo) { + HashMap<String, Object> data = new HashMap<String, Object>(); + data.put("tests", tests); + if (runInfo != null) { + data.put("run_info", runInfo); + } + this.logData("suite_start", data); + } + + public void suiteStart(List<String> tests) { + this.suiteStart(tests, null); + } + + public void suiteEnd() { + this.logData("suite_end"); + } + + public void testStart(String test) { + HashMap<String, Object> data = new HashMap<String, Object>(); + data.put("test", test); + this.logData("test_start", data); + } + + public void testStatus(String test, String subtest, String status, String expected, String message) { + status = status.toUpperCase(); + if (!StructuredLogger.validTestStatus.contains(status)) { + throw new IllegalArgumentException("Unrecognized status: " + status); + } + + HashMap<String, Object> data = new HashMap<String, Object>(); + data.put("test", test); + data.put("subtest", subtest); + data.put("status", status); + + if (message != null) { + data.put("message", message); + } + if (!expected.equals(status)) { + data.put("expected", expected); + } + + this.logData("test_status", data); + } + + public void testStatus(String test, String subtest, String status, String message) { + this.testStatus(test, subtest, status, "PASS", message); + } + + public void testEnd(String test, String status, String expected, String message, Map<String, Object> extra) { + status = status.toUpperCase(); + if (!StructuredLogger.validTestEnd.contains(status)) { + throw new IllegalArgumentException("Unrecognized status: " + status); + } + + HashMap<String, Object> data = new HashMap<String, Object>(); + data.put("test", test); + data.put("status", status); + + if (message != null) { + data.put("message", message); + } + if (extra != null) { + data.put("extra", extra); + } + if (!expected.equals(status) && !status.equals("SKIP")) { + data.put("expected", expected); + } + + this.logData("test_end", data); + } + + public void testEnd(String test, String status, String expected, String message) { + this.testEnd(test, status, expected, message, null); + } + + public void testEnd(String test, String status, String message) { + this.testEnd(test, status, "OK", message, null); + } + + + public void debug(String message) { + this.log("debug", message); + } + + public void info(String message) { + this.log("info", message); + } + + public void warning(String message) { + this.log("warning", message); + } + + public void error(String message) { + this.log("error", message); + } + + public void critical(String message) { + this.log("critical", message); + } + + private void log(String level, String message) { + HashMap<String, Object> data = new HashMap<String, Object>(); + data.put("message", message); + data.put("level", level); + this.logData("log", data); + } + + private HashMap<String, Object> makeLogData(String action, Map<String, Object> data) { + HashMap<String, Object> allData = new HashMap<String, Object>(); + allData.put("action", action); + allData.put("time", System.currentTimeMillis()); + allData.put("thread", JSONObject.NULL); + allData.put("pid", JSONObject.NULL); + allData.put("source", mName); + if (mComponent != null) { + allData.put("component", mComponent); + } + + allData.putAll(data); + + return allData; + } + + private void logData(String action, Map<String, Object> data) { + HashMap<String, Object> logData = this.makeLogData(action, data); + JSONObject jsonObject = new JSONObject(logData); + mCallback.call(jsonObject.toString()); + } + + private void logData(String action) { + this.logData(action, new HashMap<String, Object>()); + } + +}
--- a/build/sanitizers/lsan_suppressions.txt +++ b/build/sanitizers/lsan_suppressions.txt @@ -60,19 +60,16 @@ leak:event_base_once leak:nsLocalFile::OpenNSPRFileDesc # Bug 1023585 - Leak of array buffer in JSStructuredCloneWriter::transferOwnership(). m1 leak:AllocateArrayBufferContents # Bug 1022010 - Small leak under _render_glyph_outline. bc1 leak:_render_glyph_outline -# Bug 1022954 - ScriptSource leaks sourceMapURL_ sometimes. dt -leak:ScriptSource::setSourceMapURL - # Bug 1023548 - Small leak under SECITEM_AllocItem_Util. bc1, bc3 leak:SECITEM_AllocItem_Util # This is a one-time leak, so it is probably okay to ignore. bc1, oth leak:GlobalPrinters::InitializeGlobalPrinters leak:nsPSPrinterList::GetPrinterList # Bug 1028456 - More leaks with _PR_Getfd, in nsLocalFile::CopyToNative and do_create. bc1, bc3
--- a/build/subconfigure.py +++ b/build/subconfigure.py @@ -1,15 +1,16 @@ # 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 script is used to capture the content of config.status-generated # files and subsequently restore their timestamp if they haven't changed. +import argparse import os import re import subprocess import sys import pickle class File(object): def __init__(self, path): @@ -55,34 +56,64 @@ PRECIOUS_VARS = set([ # Autoconf, in some of the sub-configures used in the tree, likes to error # out when "precious" variables change in value. The solution it gives to # straighten things is to either run make distclean or remove config.cache. # There's no reason not to do the latter automatically instead of failing, # doing the cleanup (which, on buildbots means a full clobber), and # restarting from scratch. -def maybe_clear_cache(): +def maybe_clear_cache(args): + parser = argparse.ArgumentParser() + parser.add_argument('--target', type=str) + parser.add_argument('--host', type=str) + parser.add_argument('--build', type=str) + args, others = parser.parse_known_args(args) + env = dict(os.environ) + for kind in ('target', 'host', 'build'): + arg = getattr(args, kind) + if arg is not None: + env['%s_alias' % kind] = arg + # configure can take variables assignments in its arguments, and that + # overrides whatever is in the environment. + for arg in others: + if arg[:1] != '-' and '=' in arg: + key, value = arg.split('=', 1) + env[key] = value + comment = re.compile(r'^\s+#') cache = {} with open('config.cache') as f: - for line in f.readlines(): + for line in f: if not comment.match(line) and '=' in line: - key, value = line.split('=', 1) + key, value = line.rstrip(os.linesep).split('=', 1) + # If the value is quoted, unquote it + if value[:1] == "'": + value = value[1:-1].replace("'\\''", "'") cache[key] = value for precious in PRECIOUS_VARS: - entry = 'ac_cv_env_%s_value' % precious - if entry in cache and (not precious in os.environ or os.environ[precious] != cache[entry]): + # If there is no entry at all for that precious variable, then + # its value is not precious for that particular configure. + if 'ac_cv_env_%s_set' % precious not in cache: + continue + is_set = cache.get('ac_cv_env_%s_set' % precious) == 'set' + value = cache.get('ac_cv_env_%s_value' % precious) if is_set else None + if value != env.get(precious): + print 'Removing config.cache because of %s value change from:' \ + % precious + print ' %s' % (value if value is not None else 'undefined') + print 'to:' + print ' %s' % env.get(precious, 'undefined') os.remove('config.cache') return -def dump(dump_file, shell): +def dump(dump_file, shell, args): if os.path.exists('config.cache'): - maybe_clear_cache() + maybe_clear_cache(args) if not os.path.exists('config.status'): if os.path.exists(dump_file): os.remove(dump_file) return config_files = [File('config.status')] # Scan the config.status output for information about configuration files @@ -127,11 +158,11 @@ def adjust(dump_file, configure): os.remove(dump_file) CONFIG_DUMP = 'config_files.pkl' if __name__ == '__main__': if sys.argv[1] == 'dump': - dump(CONFIG_DUMP, sys.argv[2]) + dump(CONFIG_DUMP, sys.argv[2], sys.argv[3:]) elif sys.argv[1] == 'adjust': adjust(CONFIG_DUMP, sys.argv[2] if len(sys.argv) > 2 else None)
--- a/build/valgrind/mach_commands.py +++ b/build/valgrind/mach_commands.py @@ -121,38 +121,45 @@ class MachCommands(MachCommandBase): # MACHTYPE is an odd bash-only environment variable that doesn't # show up in os.environ, so we have to get it another way. machtype = subprocess.check_output(['bash', '-c', 'echo $MACHTYPE']).rstrip() supps_file2 = os.path.join(supps_dir, machtype + '.sup') if os.path.isfile(supps_file2): valgrind_args.append('--suppressions=' + supps_file2) exitcode = None + timeout = 1100 try: runner = FirefoxRunner(profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, process_args=kp_kwargs) runner.start(debug_args=valgrind_args) - exitcode = runner.wait() + # This timeout is slightly less than the no-output timeout on + # TBPL, so we'll timeout here first and give an informative + # message. + exitcode = runner.wait(timeout=timeout) finally: errs = outputHandler.error_count supps = outputHandler.suppression_count if errs != supps: status = 1 # turns the TBPL job orange - print('TEST-UNEXPECTED-FAILURE | valgrind-test | error parsing:', errs, "errors seen, but", supps, "generated suppressions seen") + print('TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {} errors seen, but {} generated suppressions seen'.format(errs, supps)) elif errs == 0: status = 0 print('TEST-PASS | valgrind-test | valgrind found no errors') else: status = 1 # turns the TBPL job orange # We've already printed details of the errors. - if exitcode != 0: + if exitcode == None: + status = 2 # turns the TBPL job red + print('TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out (reached {} second limit)'.format(timeout)) + elif exitcode != 0: status = 2 # turns the TBPL job red print('TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind') httpd.stop() return status
--- a/config/config.mk +++ b/config/config.mk @@ -69,16 +69,17 @@ endif TIERS \ TOOL_DIRS \ XPCSHELL_TESTS \ XPIDL_MODULE \ $(NULL) _DEPRECATED_VARIABLES := \ ANDROID_RESFILES \ + EXPORT_LIBRARY \ LIBXUL_LIBRARY \ MOCHITEST_A11Y_FILES \ MOCHITEST_BROWSER_FILES \ MOCHITEST_BROWSER_FILES_PARTS \ MOCHITEST_CHROME_FILES \ MOCHITEST_FILES \ MOCHITEST_FILES_PARTS \ MOCHITEST_METRO_FILES \ @@ -340,17 +341,16 @@ endif endif # If we are building this component into an extension/xulapp, it cannot be # statically linked. In the future we may want to add a xulapp meta-component # build option. ifdef XPI_NAME ifdef IS_COMPONENT -EXPORT_LIBRARY= FORCE_STATIC_LIB= FORCE_SHARED_LIB=1 endif endif ifndef SHARED_LIBRARY_NAME ifdef LIBRARY_NAME SHARED_LIBRARY_NAME=$(LIBRARY_NAME)
--- a/config/makefiles/target_binaries.mk +++ b/config/makefiles/target_binaries.mk @@ -1,28 +1,15 @@ # -*- makefile -*- # vim:set ts=8 sw=8 sts=8 noet: # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -ifdef EXPORT_LIBRARY -ifeq ($(EXPORT_LIBRARY),1) -ifdef IS_COMPONENT -EXPORT_LIBRARY = $(DEPTH)/staticlib/components -else -EXPORT_LIBRARY = $(DEPTH)/staticlib -endif -else -# If EXPORT_LIBRARY has a value, we'll be installing there. We also need to cleanup there -GARBAGE += $(foreach lib,$(LIBRARY),$(EXPORT_LIBRARY)/$(lib)) -endif -endif # EXPORT_LIBRARY - binaries libs:: $(SUBMAKEFILES) $(TARGETS) ifndef NO_DIST_INSTALL ifdef SHARED_LIBRARY ifdef IS_COMPONENT $(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components ifndef NO_COMPONENTS_MANIFEST $(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/components.manifest') $(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest 'binary-component $(SHARED_LIBRARY)') @@ -36,22 +23,16 @@ ifndef NO_DIST_INSTALL ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS))) PROGRAMS_EXECUTABLES = $(SIMPLE_PROGRAMS) $(PROGRAM) PROGRAMS_DEST ?= $(FINAL_TARGET) PROGRAMS_TARGET := binaries libs INSTALL_TARGETS += PROGRAMS endif ifdef LIBRARY -ifdef EXPORT_LIBRARY -LIBRARY_FILES = $(LIBRARY) -LIBRARY_DEST ?= $(EXPORT_LIBRARY) -LIBRARY_TARGET = binaries libs -INSTALL_TARGETS += LIBRARY -endif ifdef DIST_INSTALL ifdef IS_COMPONENT $(error Shipping static component libs makes no sense.) else DIST_LIBRARY_FILES = $(LIBRARY) DIST_LIBRARY_DEST ?= $(DIST)/lib DIST_LIBRARY_TARGET = binaries libs INSTALL_TARGETS += DIST_LIBRARY
--- a/config/rules.mk +++ b/config/rules.mk @@ -828,17 +828,17 @@ endif $(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(EXTRA_DEPS) $(GLOBAL_DEPS) $(REPORT_BUILD) $(RM) $(LIBRARY) $(EXPAND_AR) $(AR_FLAGS) $(OBJS) $(SHARED_LIBRARY_LIBS) $(filter-out %.$(LIB_SUFFIX),$(LIBRARY)): $(filter %.$(LIB_SUFFIX),$(LIBRARY)) $(OBJS) $(EXTRA_DEPS) $(GLOBAL_DEPS) # When we only build a library descriptor, blow out any existing library $(REPORT_BUILD) - $(if $(filter %.$(LIB_SUFFIX),$(LIBRARY)),,$(RM) $(REAL_LIBRARY) $(EXPORT_LIBRARY:%=%/$(REAL_LIBRARY))) + $(if $(filter %.$(LIB_SUFFIX),$(LIBRARY)),,$(RM) $(REAL_LIBRARY)) $(EXPAND_LIBS_GEN) -o $@ $(OBJS) $(SHARED_LIBRARY_LIBS) ifeq ($(OS_ARCH),WINNT) # Import libraries are created by the rules creating shared libraries. # The rules to copy them to $(DIST)/lib depend on $(IMPORT_LIBRARY), # but make will happily consider the import library before it is refreshed # when rebuilding the corresponding shared library. Defining an empty recipe # for import libraries forces make to wait for the shared library recipe to
--- a/configure.in +++ b/configure.in @@ -8778,17 +8778,16 @@ AC_SUBST(OBJ_SUFFIX) AC_SUBST(BIN_SUFFIX) AC_SUBST(ASM_SUFFIX) AC_SUBST(IMPORT_LIB_SUFFIX) AC_SUBST(USE_N32) AC_SUBST(CC_VERSION) AC_SUBST(CXX_VERSION) AC_SUBST(MSMANIFEST_TOOL) AC_SUBST(NS_ENABLE_TSF) -AC_SUBST(MOZ_APP_COMPONENT_LIBS) AC_SUBST(MOZ_APP_EXTRA_LIBS) AC_SUBST(MOZ_WAVE) AC_SUBST(MOZ_VORBIS) AC_SUBST(MOZ_TREMOR) AC_SUBST(MOZ_OPUS) AC_SUBST(MOZ_WEBM) AC_SUBST(MOZ_WMF) @@ -9045,31 +9044,28 @@ if test -z "$MOZ_NATIVE_JEMALLOC" -a "$M fi EXTRA_CFLAGS="$CFLAGS" for var in AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS EXTRA_CFLAGS LDFLAGS; do ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'" done if test "$CROSS_COMPILE"; then ac_configure_args="$ac_configure_args je_cv_static_page_shift=12" fi - _save_cache_file="$cache_file" - cache_file=$_objdir/memory/jemalloc/src/config.cache if ! test -e memory/jemalloc; then mkdir -p memory/jemalloc fi dnl jemalloc's configure uses $srcdir in AC_CONFIG_HEADERS, which syntax uses dnl colons, conflicting with the windows-style path in $srcdir. dnl Turn it into a msys path just for jemalloc's configure _save_srcdir="$srcdir" srcdir=`cd $srcdir; pwd` AC_OUTPUT_SUBDIRS(memory/jemalloc/src) srcdir="$_save_srcdir" - cache_file="$_save_cache_file" ac_configure_args="$_SUBDIR_CONFIG_ARGS" fi # Run freetype configure script if test "$MOZ_TREE_FREETYPE"; then export CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS -std=c99" export CPPFLAGS="$CPPFLAGS $MOZ_DEBUG_FLAGS" @@ -9083,17 +9079,17 @@ if test "$MOZ_TREE_FREETYPE"; then export ZLIB_LIBS="$MOZ_ZLIB_LIBS " export CONFIG_FILES="unix-cc.mk:unix-cc.in unix-def.mk:unix-def.in freetype-config freetype2.pc:freetype2.in" ac_configure_args="$ac_configure_args --host=$target --disable-shared --with-pic=yes --with-zlib=yes --without-bzip2 --with-png=yes --without-harfbuzz" if ! test -e modules; then mkdir modules fi - AC_OUTPUT_SUBDIRS(modules/freetype2) + AC_OUTPUT_SUBDIRS(modules/freetype2,$cache_file) fi if test -z "$direct_nspr_config"; then dnl ======================================================== dnl = Setup a nice relatively clean build environment for dnl = sub-configures. dnl ======================================================== CC="$_SUBDIR_CC" @@ -9175,24 +9171,19 @@ if test -z "$MOZ_NATIVE_NSPR"; then if test -n "$MOZ_LINKER" -a "$ac_cv_func_dladdr" = no ; then # dladdr is supported by the new linker, even when the system linker doesn't # support it. Trick nspr into using dladdr when it's not supported. export CPPFLAGS="-include $_topsrcdir/mozglue/linker/dladdr.h $CPPFLAGS" fi export LDFLAGS="$LDFLAGS $NSPR_LDFLAGS" export CFLAGS="$CFLAGS $MOZ_FRAMEPTR_FLAGS" - # Use a separate cache file for NSPR since it uses autoconf 2.68. - _save_cache_file="$cache_file" - cache_file=$_objdir/nsprpub/config.cache - AC_OUTPUT_SUBDIRS(nsprpub) # .. and restore them - cache_file="$_save_cache_file" CFLAGS="$_SAVE_CFLAGS" CPPFLAGS="$_SAVE_CPPFLAGS" LDFLAGS="$_SAVE_LDFLAGS" ac_configure_args="$_SUBDIR_CONFIG_ARGS" fi dnl ======================================================== @@ -9272,17 +9263,17 @@ export STLPORT_LIBS export JS_STANDALONE=no export MOZ_LINKER export ZLIB_IN_MOZGLUE if ! test -e js; then mkdir js fi -AC_OUTPUT_SUBDIRS(js/src) +AC_OUTPUT_SUBDIRS(js/src,$cache_file) ac_configure_args="$_SUBDIR_CONFIG_ARGS" fi # COMPILE_ENVIRONMENT && !LIBXUL_SDK_DIR export WRITE_MOZINFO=1 dnl we need to run config.status after js/src subconfigure because we're dnl traversing its moz.build and we need its config.status for that. dnl However, writing our own config.status needs to happen before
--- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -22,16 +22,17 @@ #include "js/RootingAPI.h" #include "mozilla/EventForwards.h" #include "mozilla/GuardObjects.h" #include "mozilla/TimeStamp.h" #include "nsContentListDeclarations.h" #include "nsMathUtils.h" #include "nsTArrayForwardDeclare.h" #include "Units.h" +#include "mozilla/dom/AutocompleteInfoBinding.h" #if defined(XP_WIN) // Undefine LoadImage to prevent naming conflict with Windows. #undef LoadImage #endif class imgICache; class imgIContainer; @@ -471,18 +472,17 @@ public: static nsIScriptSecurityManager* GetSecurityManager() { return sSecurityManager; } /** * Get the ContentSecurityPolicy for a JS context. **/ - static bool GetContentSecurityPolicy(JSContext* aCx, - nsIContentSecurityPolicy** aCSP); + static bool GetContentSecurityPolicy(nsIContentSecurityPolicy** aCSP); // Returns the subject principal. Guaranteed to return non-null. May only // be called when nsContentUtils is initialized. static nsIPrincipal* SubjectPrincipal(); // Returns the prinipal of the given JS object. This may only be called on // the main thread for objects from the main thread's JSRuntime. static nsIPrincipal* ObjectPrincipal(JSObject* aObj); @@ -2040,18 +2040,32 @@ public: }; /** * Parses the value of the autocomplete attribute into aResult, ensuring it's * composed of valid tokens, otherwise the value "" is used. * Note that this method is used for form fields, not on a <form> itself. * * @return whether aAttr was valid and can be cached. */ - static AutocompleteAttrState SerializeAutocompleteAttribute(const nsAttrValue* aAttr, - nsAString& aResult); + static AutocompleteAttrState + SerializeAutocompleteAttribute(const nsAttrValue* aAttr, + nsAString& aResult, + AutocompleteAttrState aCachedState = + eAutocompleteAttrState_Unknown); + + /* Variation that is used to retrieve a dictionary of the parts of the + * autocomplete attribute. + * + * @return whether aAttr was valid and can be cached. + */ + static AutocompleteAttrState + SerializeAutocompleteAttribute(const nsAttrValue* aAttr, + mozilla::dom::AutocompleteInfo& aInfo, + AutocompleteAttrState aCachedState = + eAutocompleteAttrState_Unknown); /** * This will parse aSource, to extract the value of the pseudo attribute * with the name specified in aName. See * http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification * which is used to parse aSource. * * @param aSource the string to parse @@ -2200,18 +2214,19 @@ private: static void DropFragmentParsers(); static bool MatchClassNames(nsIContent* aContent, int32_t aNamespaceID, nsIAtom* aAtom, void* aData); static void DestroyClassNameArray(void* aData); static void* AllocClassMatchingInfo(nsINode* aRootNode, const nsString* aClasses); + // Fills in aInfo with the tokens from the supplied autocomplete attribute. static AutocompleteAttrState InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal, - nsAString& aResult); + mozilla::dom::AutocompleteInfo& aInfo); static nsIXPConnect *sXPConnect; static nsIScriptSecurityManager *sSecurityManager; static nsIPrincipal *sSystemPrincipal; static nsIPrincipal *sNullSubjectPrincipal; static nsIParserService *sParserService;
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -761,60 +761,119 @@ nsContentUtils::IsAutocompleteEnabled(ns form->GetAutocomplete(autocomplete); } return !autocomplete.EqualsLiteral("off"); } nsContentUtils::AutocompleteAttrState nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr, - nsAString& aResult) -{ - AutocompleteAttrState state = InternalSerializeAutocompleteAttribute(aAttr, aResult); + nsAString& aResult, + AutocompleteAttrState aCachedState) +{ + if (!aAttr || + aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { + return aCachedState; + } + + if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) { + uint32_t atomCount = aAttr->GetAtomCount(); + for (uint32_t i = 0; i < atomCount; i++) { + if (i != 0) { + aResult.Append(' '); + } + aResult.Append(nsDependentAtomString(aAttr->AtomAt(i))); + } + nsContentUtils::ASCIIToLower(aResult); + return aCachedState; + } + + aResult.Truncate(); + + mozilla::dom::AutocompleteInfo info; + AutocompleteAttrState state = + InternalSerializeAutocompleteAttribute(aAttr, info); if (state == eAutocompleteAttrState_Valid) { - ASCIIToLower(aResult); - } else { - aResult.Truncate(); - } + // Concatenate the info fields. + aResult = info.mSection; + + if (!info.mAddressType.IsEmpty()) { + if (!aResult.IsEmpty()) { + aResult += ' '; + } + aResult += info.mAddressType; + } + + if (!info.mContactType.IsEmpty()) { + if (!aResult.IsEmpty()) { + aResult += ' '; + } + aResult += info.mContactType; + } + + if (!info.mFieldName.IsEmpty()) { + if (!aResult.IsEmpty()) { + aResult += ' '; + } + aResult += info.mFieldName; + } + } + return state; } +nsContentUtils::AutocompleteAttrState +nsContentUtils::SerializeAutocompleteAttribute(const nsAttrValue* aAttr, + mozilla::dom::AutocompleteInfo& aInfo, + AutocompleteAttrState aCachedState) +{ + if (!aAttr || + aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) { + return aCachedState; + } + + return InternalSerializeAutocompleteAttribute(aAttr, aInfo); +} + /** * Helper to validate the @autocomplete tokens. * * @return {AutocompleteAttrState} The state of the attribute (invalid/valid). */ nsContentUtils::AutocompleteAttrState nsContentUtils::InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal, - nsAString& aResult) + mozilla::dom::AutocompleteInfo& aInfo) { // No sandbox attribute so we are done if (!aAttrVal) { return eAutocompleteAttrState_Invalid; } uint32_t numTokens = aAttrVal->GetAtomCount(); if (!numTokens) { return eAutocompleteAttrState_Invalid; } uint32_t index = numTokens - 1; nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); AutocompleteCategory category; nsAttrValue enumValue; + nsAutoString str; bool result = enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false); if (result) { // Off/Automatic/Normal categories. if (enumValue.Equals(NS_LITERAL_STRING("off"), eIgnoreCase) || enumValue.Equals(NS_LITERAL_STRING("on"), eIgnoreCase)) { if (numTokens > 1) { return eAutocompleteAttrState_Invalid; } - enumValue.ToString(aResult); + enumValue.ToString(str); + ASCIIToLower(str); + aInfo.mFieldName.Assign(str); return eAutocompleteAttrState_Valid; } // Only allow on/off if experimental @autocomplete values aren't enabled. if (!sIsExperimentalAutocompleteEnabled) { return eAutocompleteAttrState_Invalid; } @@ -832,55 +891,62 @@ nsContentUtils::InternalSerializeAutocom result = enumValue.ParseEnumValue(tokenString, kAutocompleteContactFieldNameTable, false); if (!result || numTokens > 3) { return eAutocompleteAttrState_Invalid; } category = eAutocompleteCategory_CONTACT; } - enumValue.ToString(aResult); + enumValue.ToString(str); + ASCIIToLower(str); + aInfo.mFieldName.Assign(str); // We are done if this was the only token. if (numTokens == 1) { return eAutocompleteAttrState_Valid; } --index; tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); if (category == eAutocompleteCategory_CONTACT) { nsAttrValue contactFieldHint; result = contactFieldHint.ParseEnumValue(tokenString, kAutocompleteContactFieldHintTable, false); if (result) { - aResult.Insert(' ', 0); nsAutoString contactFieldHintString; contactFieldHint.ToString(contactFieldHintString); - aResult.Insert(contactFieldHintString, 0); + ASCIIToLower(contactFieldHintString); + aInfo.mContactType.Assign(contactFieldHintString); if (index == 0) { return eAutocompleteAttrState_Valid; } --index; tokenString = nsDependentAtomString(aAttrVal->AtomAt(index)); } } // Check for billing/shipping tokens nsAttrValue fieldHint; if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable, false)) { - aResult.Insert(' ', 0); nsString fieldHintString; fieldHint.ToString(fieldHintString); - aResult.Insert(fieldHintString, 0); + ASCIIToLower(fieldHintString); + aInfo.mAddressType.Assign(fieldHintString); if (index == 0) { return eAutocompleteAttrState_Valid; } --index; } + // Clear the fields as the autocomplete attribute is invalid. + aInfo.mAddressType.Truncate(); + aInfo.mContactType.Truncate(); + aInfo.mFieldName.Truncate(); + return eAutocompleteAttrState_Invalid; } // Parse an integer according to HTML spec int32_t nsContentUtils::ParseHTMLInteger(const nsAString& aValue, ParseHTMLIntegerResultFlags *aResult) { @@ -6354,21 +6420,19 @@ nsContentUtils::FindInternalContentViewe } return docFactory.forget(); } return nullptr; } bool -nsContentUtils::GetContentSecurityPolicy(JSContext* aCx, - nsIContentSecurityPolicy** aCSP) +nsContentUtils::GetContentSecurityPolicy(nsIContentSecurityPolicy** aCSP) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - MOZ_ASSERT(aCx == GetCurrentJSContext()); nsCOMPtr<nsIContentSecurityPolicy> csp; nsresult rv = SubjectPrincipal()->GetCsp(getter_AddRefs(csp)); if (NS_FAILED(rv)) { NS_ERROR("CSP: Failed to get CSP from principal."); return false; }
--- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -935,17 +935,17 @@ public: size_t size = DOMMemoryFileDataOwnerMallocSizeOf(owner->mData); if (size < LARGE_OBJECT_MIN_SIZE) { smallObjectsTotal += size; } else { SHA1Sum sha1; sha1.update(owner->mData, owner->mLength); - uint8_t digest[SHA1Sum::HashSize]; // SHA1 digests are 20 bytes long. + uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long. sha1.finish(digest); nsAutoCString digestString; for (size_t i = 0; i < sizeof(digest); i++) { digestString.AppendPrintf("%02x", digest[i]); } nsresult rv = aCallback->Callback(
--- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -1466,19 +1466,21 @@ nsScriptLoader::PrepareLoadedRequest(nsS if (httpChannel) { bool requestSucceeded; rv = httpChannel->GetRequestSucceeded(&requestSucceeded); if (NS_SUCCEEDED(rv) && !requestSucceeded) { return NS_ERROR_NOT_AVAILABLE; } nsAutoCString sourceMapURL; - httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), sourceMapURL); - aRequest->mHasSourceMapURL = true; - aRequest->mSourceMapURL = NS_ConvertUTF8toUTF16(sourceMapURL); + rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), sourceMapURL); + if (NS_SUCCEEDED(rv)) { + aRequest->mHasSourceMapURL = true; + aRequest->mSourceMapURL = NS_ConvertUTF8toUTF16(sourceMapURL); + } } nsCOMPtr<nsIChannel> channel = do_QueryInterface(req); // If this load was subject to a CORS check; don't flag it with a // separate origin principal, so that it will treat our document's // principal as the origin principal if (aRequest->mCORSMode == CORS_NONE) { rv = nsContentUtils::GetSecurityManager()->
--- a/content/base/test/chrome/nochrome_bug765993.js +++ b/content/base/test/chrome/nochrome_bug765993.js @@ -1,4 +1,4 @@ -//@ sourceMappingURL=bar.js.map +//# sourceMappingURL=bar.js.map // Define a single function to prevent script source from being gc'd function foo() {}
--- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -1524,42 +1524,38 @@ NS_IMPL_STRING_ATTR(HTMLInputElement, Pl NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLInputElement, Type, type, kInputDefaultType->tag) NS_IMETHODIMP HTMLInputElement::GetAutocomplete(nsAString& aValue) { aValue.Truncate(0); const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete); - if (!attributeVal || - mAutocompleteAttrState == nsContentUtils::eAutocompleteAttrState_Invalid) { - return NS_OK; - } - if (mAutocompleteAttrState == nsContentUtils::eAutocompleteAttrState_Valid) { - uint32_t atomCount = attributeVal->GetAtomCount(); - for (uint32_t i = 0; i < atomCount; i++) { - if (i != 0) { - aValue.Append(' '); - } - aValue.Append(nsDependentAtomString(attributeVal->AtomAt(i))); - } - nsContentUtils::ASCIIToLower(aValue); - return NS_OK; - } - - mAutocompleteAttrState = nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue); + + mAutocompleteAttrState = + nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue, + mAutocompleteAttrState); return NS_OK; } NS_IMETHODIMP HTMLInputElement::SetAutocomplete(const nsAString& aValue) { return SetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete, nullptr, aValue, true); } +void +HTMLInputElement::GetAutocompleteInfo(AutocompleteInfo& aInfo) +{ + const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete); + mAutocompleteAttrState = + nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aInfo, + mAutocompleteAttrState); +} + int32_t HTMLInputElement::TabIndexDefault() { return 0; } uint32_t HTMLInputElement::Height()
--- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -365,16 +365,18 @@ public: } // XPCOM GetAutocomplete() is OK void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv) { SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv); } + void GetAutocompleteInfo(AutocompleteInfo& aInfo); + bool Autofocus() const { return GetBoolAttr(nsGkAtoms::autofocus); } void SetAutofocus(bool aValue, ErrorResult& aRv) { SetHTMLBoolAttr(nsGkAtoms::autofocus, aValue, aRv);
--- a/content/html/content/src/HTMLLinkElement.cpp +++ b/content/html/content/src/HTMLLinkElement.cpp @@ -315,16 +315,17 @@ HTMLLinkElement::SetAttr(int32_t aNameSp // The ordering of the parent class's SetAttr call and Link::ResetLinkState // is important here! The attribute is not set until SetAttr returns, and // we will need the updated attribute value because notifying the document // that content states have changed will call IntrinsicState, which will try // to get updated information about the visitedness from Link. if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { Link::ResetLinkState(!!aNotify, true); + CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged")); } if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None && (aName == nsGkAtoms::href || aName == nsGkAtoms::rel || aName == nsGkAtoms::title || aName == nsGkAtoms::media || aName == nsGkAtoms::type)) { @@ -377,16 +378,17 @@ HTMLLinkElement::UnsetAttr(int32_t aName // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState // is important here! The attribute is not unset until UnsetAttr returns, and // we will need the updated attribute value because notifying the document // that content states have changed will call IntrinsicState, which will try // to get updated information about the visitedness from Link. if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { Link::ResetLinkState(!!aNotify, false); + CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged")); } return rv; } nsresult HTMLLinkElement::PreHandleEvent(EventChainPreVisitor& aVisitor) {
new file mode 100644 --- /dev/null +++ b/content/html/content/test/forms/chrome.ini @@ -0,0 +1,2 @@ +[DEFAULT] +[test_autocompleteinfo.html]
new file mode 100644 --- /dev/null +++ b/content/html/content/test/forms/test_autocompleteinfo.html @@ -0,0 +1,99 @@ +<!DOCTYPE html> +<html> +<!-- +Test getAutocompleteInfo() on <input> +--> +<head> + <title>Test for getAutocompleteInfo()</title> + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> + +<body> +<p id="display"></p> +<div id="content" style="display: none"> + <form> + <input id="input"/> + </form> +</div> +<pre id="test"> +<script> +"use strict"; + +var values = [ + // Missing or empty attribute + [undefined, {}], + ["", {}], + + // One token + ["on", {fieldName: "on" }], + ["On", {fieldName: "on" }], + ["off", {fieldName: "off" } ], + ["username", {fieldName: "username" }], + [" username ", {fieldName: "username" }], + ["foobar", {}], + + // Two tokens + ["on off", {}], + ["off on", {}], + ["username tel", {}], + ["tel username ", {}], + [" username tel ", {}], + ["tel mobile", {}], + ["tel shipping", {}], + ["shipping tel", {addressType: "shipping", fieldName: "tel"}], + ["shipPING tel", {addressType: "shipping", fieldName: "tel"}], + ["mobile tel", {contactType: "mobile", fieldName: "tel"}], + [" MoBiLe TeL ", {contactType: "mobile", fieldName: "tel"}], + ["XXX tel", {}], + ["XXX username", {}], + + // Three tokens + ["billing invalid tel", {}], + ["___ mobile tel", {}], + ["mobile foo tel", {}], + ["mobile tel foo", {}], + ["tel mobile billing", {}], + ["billing mobile tel", {addressType: "billing", contactType: "mobile", fieldName: "tel"}], + [" BILLing MoBiLE tEl ", {addressType: "billing", contactType: "mobile", fieldName: "tel"}], + ["billing home tel", {addressType: "billing", contactType: "home", fieldName: "tel"}], + + // Four tokens (invalid) + ["billing billing mobile tel", {}], + + // Five tokens (invalid) + ["billing billing billing mobile tel", {}], +]; + +function start() { + const fieldid = "input"; + var field = document.getElementById(fieldid); + for (var test of values) { + if (typeof(test[0]) === "undefined") + field.removeAttribute("autocomplete"); + else + field.setAttribute("autocomplete", test[0]); + + var info = field.getAutocompleteInfo(); + + is(info.section, "section" in test[1] ? test[1].section : "", + "Checking autocompleteInfo.section for " + fieldid + ": " + test[0]); + is(info.addressType, "addressType" in test[1] ? test[1].addressType : "", + "Checking autocompleteInfo.addressType for " + fieldid + ": " + test[0]); + is(info.contactType, "contactType" in test[1] ? test[1].contactType : "", + "Checking autocompleteInfo.contactType for " + fieldid + ": " + test[0]); + is(info.fieldName, "fieldName" in test[1] ? test[1].fieldName : "", + "Checking autocompleteInfo.fieldName for " + fieldid + ": " + test[0]); + + } + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.experimental", true]]}, start); + +</script> +</pre> +</body> +</html>
--- a/content/html/content/test/moz.build +++ b/content/html/content/test/moz.build @@ -1,12 +1,12 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOCHITEST_MANIFESTS += ['forms/mochitest.ini', 'mochitest.ini'] -MOCHITEST_CHROME_MANIFESTS += ['chrome.ini'] +MOCHITEST_CHROME_MANIFESTS += ['chrome.ini', 'forms/chrome.ini'] BROWSER_CHROME_MANIFESTS += ['browser.ini']
--- a/content/media/MediaDecoderStateMachine.cpp +++ b/content/media/MediaDecoderStateMachine.cpp @@ -8,16 +8,17 @@ #include "windows.h" #include "mmsystem.h" #endif #include "mozilla/DebugOnly.h" #include <stdint.h> #include "MediaDecoderStateMachine.h" +#include "MediaDecoderStateMachineScheduler.h" #include "AudioSink.h" #include "nsTArray.h" #include "MediaDecoder.h" #include "MediaDecoderReader.h" #include "mozilla/mozalloc.h" #include "VideoUtils.h" #include "mozilla/dom/TimeRanges.h" #include "nsDeque.h" @@ -163,18 +164,21 @@ static TimeDuration UsecsToDuration(int6 static int64_t DurationToUsecs(TimeDuration aDuration) { return static_cast<int64_t>(aDuration.ToSeconds() * USECS_PER_S); } MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, MediaDecoderReader* aReader, bool aRealTime) : mDecoder(aDecoder), + mScheduler(new MediaDecoderStateMachineScheduler( + aDecoder->GetReentrantMonitor(), + &MediaDecoderStateMachine::TimeoutExpired, + MOZ_THIS_IN_INITIALIZER_LIST(), aRealTime)), mState(DECODER_STATE_DECODING_METADATA), - mInRunningStateMachine(false), mSyncPointInMediaStream(-1), mSyncPointInDecodedStream(-1), mPlayDuration(0), mStartTime(-1), mEndTime(-1), mFragmentEndTime(-1), mReader(aReader), mCurrentFrameTime(0), @@ -193,40 +197,34 @@ MediaDecoderStateMachine::MediaDecoderSt mPositionChangeQueued(false), mAudioCompleted(false), mGotDurationFromMetaData(false), mDispatchedEventToDecode(false), mStopAudioThread(true), mQuickBuffering(false), mMinimizePreroll(false), mDecodeThreadWaiting(false), - mRealTime(aRealTime), mDispatchedDecodeMetadataTask(false), mDropAudioUntilNextDiscontinuity(false), mDropVideoUntilNextDiscontinuity(false), mDecodeToSeekTarget(false), mCurrentTimeBeforeSeek(0), - mLastFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED), - mTimerId(0) + mLastFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED) { MOZ_COUNT_CTOR(MediaDecoderStateMachine); NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); - // Only enable realtime mode when "media.realtime_decoder.enabled" is true. - if (Preferences::GetBool("media.realtime_decoder.enabled", false) == false) - mRealTime = false; - mAmpleVideoFrames = std::max<uint32_t>(Preferences::GetUint("media.video-queue.default-size", 10), 3); - mBufferingWait = mRealTime ? 0 : BUFFERING_WAIT_S; - mLowDataThresholdUsecs = mRealTime ? 0 : LOW_DATA_THRESHOLD_USECS; - - mVideoPrerollFrames = mRealTime ? 0 : mAmpleVideoFrames / 2; - mAudioPrerollUsecs = mRealTime ? 0 : LOW_AUDIO_USECS * 2; + mBufferingWait = mScheduler->IsRealTime() ? 0 : BUFFERING_WAIT_S; + mLowDataThresholdUsecs = mScheduler->IsRealTime() ? 0 : LOW_DATA_THRESHOLD_USECS; + + mVideoPrerollFrames = mScheduler->IsRealTime() ? 0 : mAmpleVideoFrames / 2; + mAudioPrerollUsecs = mScheduler->IsRealTime() ? 0 : LOW_AUDIO_USECS * 2; #ifdef XP_WIN // Ensure high precision timers are enabled on Windows, otherwise the state // machine thread isn't woken up at reliable intervals to set the next frame, // and we drop frames while painting. Note that multiple calls to this // function per-process is OK, provided each call is matched by a corresponding // timeEndPeriod() call. timeBeginPeriod(1); @@ -236,18 +234,16 @@ MediaDecoderStateMachine::MediaDecoderSt MediaDecoderStateMachine::~MediaDecoderStateMachine() { MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread."); MOZ_COUNT_DTOR(MediaDecoderStateMachine); NS_ASSERTION(!mPendingWakeDecoder.get(), "WakeDecoder should have been revoked already"); MOZ_ASSERT(!mDecodeTaskQueue, "Should be released in SHUTDOWN"); - // No need to cancel the timer here for we've done that in SHUTDOWN. - MOZ_ASSERT(!mTimer, "Should be released in SHUTDOWN"); mReader = nullptr; #ifdef XP_WIN timeEndPeriod(1); #endif } bool MediaDecoderStateMachine::HasFutureAudio() { @@ -1058,34 +1054,25 @@ bool MediaDecoderStateMachine::IsPlaying nsresult MediaDecoderStateMachine::Init(MediaDecoderStateMachine* aCloneDonor) { MOZ_ASSERT(NS_IsMainThread()); RefPtr<SharedThreadPool> decodePool(GetMediaDecodeThreadPool()); NS_ENSURE_TRUE(decodePool, NS_ERROR_FAILURE); - RefPtr<SharedThreadPool> stateMachinePool( - SharedThreadPool::Get(NS_LITERAL_CSTRING("Media State Machine"), 1)); - NS_ENSURE_TRUE(stateMachinePool, NS_ERROR_FAILURE); - mDecodeTaskQueue = new MediaTaskQueue(decodePool.forget()); NS_ENSURE_TRUE(mDecodeTaskQueue, NS_ERROR_FAILURE); MediaDecoderReader* cloneReader = nullptr; if (aCloneDonor) { cloneReader = aCloneDonor->mReader; } - mStateMachineThreadPool = stateMachinePool; - - nsresult rv; - mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - rv = mTimer->SetTarget(GetStateMachineThread()); + nsresult rv = mScheduler->Init(); NS_ENSURE_SUCCESS(rv, rv); // Note: This creates a cycle, broken in shutdown. mMediaDecodedListener = new MediaDataDecodedListener<MediaDecoderStateMachine>(this, mDecodeTaskQueue); mReader->SetCallback(mMediaDecodedListener); mReader->SetTaskQueue(mDecodeTaskQueue); @@ -1337,18 +1324,18 @@ void MediaDecoderStateMachine::Shutdown( NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); // Once we've entered the shutdown state here there's no going back. ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); // Change state before issuing shutdown request to threads so those // threads can start exiting cleanly during the Shutdown call. DECODER_LOG(PR_LOG_DEBUG, "Changed state to SHUTDOWN"); - ScheduleStateMachine(); mState = DECODER_STATE_SHUTDOWN; + mScheduler->ScheduleAndShutdown(); if (mAudioSink) { mAudioSink->PrepareToShutdown(); } mDecoder->GetReentrantMonitor().NotifyAll(); } void MediaDecoderStateMachine::StartDecoding() { @@ -1748,16 +1735,17 @@ MediaDecoderStateMachine::StartAudioThre if (HasAudio() && !mAudioSink) { mAudioCompleted = false; mAudioSink = new AudioSink(this, mAudioStartTime, mInfo.mAudio, mDecoder->GetAudioChannel()); nsresult rv = mAudioSink->Init(); if (NS_FAILED(rv)) { DECODER_LOG(PR_LOG_WARNING, "Changed state to SHUTDOWN because audio sink initialization failed"); mState = DECODER_STATE_SHUTDOWN; + mScheduler->ScheduleAndShutdown(); return rv; } mAudioSink->SetVolume(mVolume); mAudioSink->SetPlaybackRate(mPlaybackRate); mAudioSink->SetPreservesPitch(mPreservesPitch); } return NS_OK; @@ -1825,18 +1813,18 @@ MediaDecoderStateMachine::DecodeError() // Already shutdown. return; } // Change state to shutdown before sending error report to MediaDecoder // and the HTMLMediaElement, so that our pipeline can start exiting // cleanly during the sync dispatch below. DECODER_LOG(PR_LOG_WARNING, "Decode error, changed state to SHUTDOWN due to error"); - ScheduleStateMachine(); mState = DECODER_STATE_SHUTDOWN; + mScheduler->ScheduleAndShutdown(); mDecoder->GetReentrantMonitor().NotifyAll(); // Dispatch the event to call DecodeError synchronously. This ensures // we're in shutdown state by the time we exit the decode thread. // If we just moved to shutdown state here on the decode thread, we may // cause the state machine to shutdown/free memory without closing its // media stream properly, and we'll get callbacks from the media stream // causing a crash. @@ -1906,17 +1894,17 @@ nsresult MediaDecoderStateMachine::Decod AudioQueue().AddPopListener(decodeTask, mDecodeTaskQueue); } if (HasVideo()) { RefPtr<nsIRunnable> decodeTask( NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DispatchVideoDecodeTaskIfNeeded)); VideoQueue().AddPopListener(decodeTask, mDecodeTaskQueue); } - if (mRealTime) { + if (mScheduler->IsRealTime()) { SetStartTime(0); res = FinishDecodeMetadata(); NS_ENSURE_SUCCESS(res, res); } else { if (HasAudio()) { ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor()); mReader->RequestAudioData(); } @@ -1935,17 +1923,17 @@ MediaDecoderStateMachine::FinishDecodeMe AssertCurrentThreadInMonitor(); NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); DECODER_LOG(PR_LOG_DEBUG, "Decoding Media Headers"); if (mState == DECODER_STATE_SHUTDOWN) { return NS_ERROR_FAILURE; } - if (!mRealTime) { + if (!mScheduler->IsRealTime()) { const VideoData* v = VideoQueue().PeekFront(); const AudioData* a = AudioQueue().PeekFront(); int64_t startTime = std::min<int64_t>(a ? a->mTime : INT64_MAX, v ? v->mTime : INT64_MAX); if (startTime == INT64_MAX) { startTime = 0; @@ -2169,27 +2157,31 @@ MediaDecoderStateMachine::SeekCompleted( UpdatePlaybackPositionInternal(newCurrentTime); if (mDecoder->GetDecodedStream()) { SetSyncPointForMediaStream(); } // Try to decode another frame to detect if we're at the end... DECODER_LOG(PR_LOG_DEBUG, "Seek completed, mCurrentFrameTime=%lld", mCurrentFrameTime); + // Prevent changes in playback position before 'seeked' is fired for we + // expect currentTime equals seek target in 'seeked' callback. + mScheduler->FreezeScheduling(); { ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor()); NS_DispatchToMainThread(stopEvent, NS_DISPATCH_SYNC); } // Reset quick buffering status. This ensures that if we began the // seek while quick-buffering, we won't bypass quick buffering mode // if we need to buffer after the seek. mQuickBuffering = false; ScheduleStateMachine(); + mScheduler->ThawScheduling(); } // Runnable to dispose of the decoder and state machine on the main thread. class nsDecoderDisposeEvent : public nsRunnable { public: nsDecoderDisposeEvent(already_AddRefed<MediaDecoder> aDecoder, already_AddRefed<MediaDecoderStateMachine> aStateMachine) : mDecoder(aDecoder), mStateMachine(aStateMachine) {} @@ -2287,18 +2279,16 @@ nsresult MediaDecoderStateMachine::RunSt // state machine) needs to finish and be released in order to allow // that. So we dispatch an event to run after this event runner has // finished and released its monitor/references. That event then will // dispatch an event to the main thread to release the decoder and // state machine. GetStateMachineThread()->Dispatch( new nsDispatchDisposeEvent(mDecoder, this), NS_DISPATCH_NORMAL); - mTimer->Cancel(); - mTimer = nullptr; return NS_OK; } case DECODER_STATE_DORMANT: { if (IsPlaying()) { StopPlayback(); } FlushDecoding(); @@ -2584,17 +2574,17 @@ void MediaDecoderStateMachine::AdvanceFr int64_t remainingTime = AUDIO_DURATION_USECS; NS_ASSERTION(clock_time >= mStartTime, "Should have positive clock time."); nsAutoPtr<VideoData> currentFrame; #ifdef PR_LOGGING int32_t droppedFrames = 0; #endif if (VideoQueue().GetSize() > 0) { VideoData* frame = VideoQueue().PeekFront(); - while (mRealTime || clock_time >= frame->mTime) { + while (mScheduler->IsRealTime() || clock_time >= frame->mTime) { mVideoFrameEndTime = frame->GetEndTime(); currentFrame = frame; #ifdef PR_LOGGING VERBOSE_LOG("discarding video frame %lld", frame->mTime); if (droppedFrames++) { VERBOSE_LOG("discarding video frame %lld (%d so far)", frame->mTime, droppedFrames-1); } #endif @@ -2924,128 +2914,53 @@ nsresult MediaDecoderStateMachine::CallR AssertCurrentThreadInMonitor(); NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread."); // If audio is being captured, stop the audio sink if it's running if (mAudioCaptured) { StopAudioThread(); } - MOZ_ASSERT(!mInRunningStateMachine, "State machine cycles must run in sequence!"); - mTimeout = TimeStamp(); - mInRunningStateMachine = true; - nsresult res = RunStateMachine(); - mInRunningStateMachine = false; - return res; + return RunStateMachine(); } -nsresult MediaDecoderStateMachine::TimeoutExpired(int aTimerId) +nsresult MediaDecoderStateMachine::TimeoutExpired(void* aClosure) { - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - NS_ASSERTION(OnStateMachineThread(), "Must be on state machine thread"); - mTimer->Cancel(); - if (mTimerId == aTimerId) { - return CallRunStateMachine(); - } else { - return NS_OK; - } + MediaDecoderStateMachine* p = static_cast<MediaDecoderStateMachine*>(aClosure); + return p->CallRunStateMachine(); } void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder() { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); DispatchAudioDecodeTaskIfNeeded(); DispatchVideoDecodeTaskIfNeeded(); } -class TimerEvent : public nsITimerCallback, public nsRunnable { - NS_DECL_THREADSAFE_ISUPPORTS -public: - TimerEvent(MediaDecoderStateMachine* aStateMachine, int aTimerId) - : mStateMachine(aStateMachine), mTimerId(aTimerId) {} - - NS_IMETHOD Run() MOZ_OVERRIDE { - return mStateMachine->TimeoutExpired(mTimerId); - } - - NS_IMETHOD Notify(nsITimer* aTimer) { - return mStateMachine->TimeoutExpired(mTimerId); - } -private: - ~TimerEvent() {} - - const nsRefPtr<MediaDecoderStateMachine> mStateMachine; - int mTimerId; -}; - -NS_IMPL_ISUPPORTS(TimerEvent, nsITimerCallback, nsIRunnable); - nsresult MediaDecoderStateMachine::ScheduleStateMachine(int64_t aUsecs) { - AssertCurrentThreadInMonitor(); - NS_ABORT_IF_FALSE(GetStateMachineThread(), - "Must have a state machine thread to schedule"); - - if (mState == DECODER_STATE_SHUTDOWN) { - return NS_ERROR_FAILURE; - } - aUsecs = std::max<int64_t>(aUsecs, 0); - - TimeStamp timeout = TimeStamp::Now() + UsecsToDuration(aUsecs); - if (!mTimeout.IsNull() && timeout >= mTimeout) { - // We've already scheduled a timer set to expire at or before this time, - // or have an event dispatched to run the state machine. - return NS_OK; - } - - uint32_t ms = static_cast<uint32_t>((aUsecs / USECS_PER_MS) & 0xFFFFFFFF); - if (mRealTime && ms > 40) { - ms = 40; - } - - // Don't cancel the timer here for this function will be called from - // different threads. - - nsresult rv = NS_ERROR_FAILURE; - nsRefPtr<TimerEvent> event = new TimerEvent(this, mTimerId+1); - - if (ms == 0) { - // Dispatch a runnable to the state machine thread when delay is 0. - // It will has less latency than dispatching a runnable to the state - // machine thread which will then schedule a zero-delay timer. - rv = GetStateMachineThread()->Dispatch(event, NS_DISPATCH_NORMAL); - } else if (OnStateMachineThread()) { - rv = mTimer->InitWithCallback(event, ms, nsITimer::TYPE_ONE_SHOT); - } else { - MOZ_ASSERT(false, "non-zero delay timer should be only scheduled in state machine thread"); - } - - if (NS_SUCCEEDED(rv)) { - mTimeout = timeout; - ++mTimerId; - } else { - NS_WARNING("Failed to schedule state machine"); - } - - return rv; + return mScheduler->Schedule(aUsecs); } bool MediaDecoderStateMachine::OnDecodeThread() const { return mDecodeTaskQueue->IsCurrentThreadIn(); } bool MediaDecoderStateMachine::OnStateMachineThread() const { - bool rv = false; - mStateMachineThreadPool->IsOnCurrentThread(&rv); - return rv; + return mScheduler->OnStateMachineThread(); } -nsIEventTarget* MediaDecoderStateMachine::GetStateMachineThread() +nsIEventTarget* MediaDecoderStateMachine::GetStateMachineThread() const { - return mStateMachineThreadPool->GetEventTarget(); + return mScheduler->GetStateMachineThread(); +} + +bool MediaDecoderStateMachine::IsStateMachineScheduled() const +{ + return mScheduler->IsScheduled(); } void MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate) { NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); NS_ASSERTION(aPlaybackRate != 0, "PlaybackRate == 0 should be handled before this function."); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
--- a/content/media/MediaDecoderStateMachine.h +++ b/content/media/MediaDecoderStateMachine.h @@ -95,16 +95,17 @@ class nsITimer; namespace mozilla { class AudioSegment; class VideoSegment; class MediaTaskQueue; class SharedThreadPool; class AudioSink; +class MediaDecoderStateMachineScheduler; // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to // GetTickCount() and conflicts with MediaDecoderStateMachine::GetCurrentTime // implementation. #ifdef GetCurrentTime #undef GetCurrentTime #endif @@ -274,29 +275,30 @@ public: void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset); int64_t GetEndMediaTime() const { AssertCurrentThreadInMonitor(); return mEndTime; } // Returns the shared state machine thread. - nsIEventTarget* GetStateMachineThread(); + nsIEventTarget* GetStateMachineThread() const; // Calls ScheduleStateMachine() after taking the decoder lock. Also // notifies the decoder thread in case it's waiting on the decoder lock. void ScheduleStateMachineWithLockAndWakeDecoder(); // Schedules the shared state machine thread to run the state machine // in aUsecs microseconds from now, if it's not already scheduled to run // earlier, in which case the request is discarded. nsresult ScheduleStateMachine(int64_t aUsecs = 0); - // Timer function to implement ScheduleStateMachine(aUsecs). - nsresult TimeoutExpired(int aGeneration); + // Callback function registered with MediaDecoderStateMachineScheduler + // to run state machine cycles. + static nsresult TimeoutExpired(void* aClosure); // Set the media fragment end time. aEndTime is in microseconds. void SetFragmentEndTime(int64_t aEndTime); // Drop reference to decoder. Only called during shutdown dance. void BreakCycles() { if (mReader) { mReader->BreakCycles(); @@ -442,17 +444,17 @@ protected: // Dispatches an asynchronous event to update the media element's ready state. void UpdateReadyState(); // Resets playback timing data. Called when we seek, on the decode thread. void ResetPlayback(); // Orders the Reader to stop decoding, and blocks until the Reader // has stopped decoding and finished delivering samples, then calls - // ResetPlayback() to discard all enqueued data. + // ResetPlayback() to discard all enqueued data. void FlushDecoding(); // Returns the audio clock, if we have audio, or -1 if we don't. // Called on the state machine thread. int64_t GetAudioClock(); // Get the video stream position, taking the |playbackRate| change into // account. This is a position in the media, not the duration of the playback @@ -605,20 +607,17 @@ protected: // State machine thread run function. Defers to RunStateMachine(). nsresult CallRunStateMachine(); // Performs one "cycle" of the state machine. Polls the state, and may send // a video frame to be displayed, and generally manages the decode. Called // periodically via timer to ensure the video stays in sync. nsresult RunStateMachine(); - bool IsStateMachineScheduled() const { - AssertCurrentThreadInMonitor(); - return !mTimeout.IsNull(); - } + bool IsStateMachineScheduled() const; // Returns true if we're not playing and the decode thread has filled its // decode buffers and is waiting. We can shut the decode thread down in this // case as it may not be needed again. bool IsPausedAndDecoderWaiting(); // These return true if the respective stream's decode has not yet reached // the end of stream. @@ -645,16 +644,20 @@ protected: // dropped its reference to the decoder. This enables the state machine to // keep using the decoder's monitor until the state machine has finished // shutting down, without fear of the monitor being destroyed. After // shutting down, the state machine will then release this reference, // causing the decoder to be destroyed. This is accessed on the decode, // state machine, audio and main threads. nsRefPtr<MediaDecoder> mDecoder; + // Used to schedule state machine cycles. This should never outlive + // the life cycle of the state machine. + const nsAutoPtr<MediaDecoderStateMachineScheduler> mScheduler; + // Time at which the last video sample was requested. If it takes too long // before the sample arrives, we will increase the amount of audio we buffer. // This is necessary for legacy synchronous decoders to prevent underruns. TimeStamp mVideoDecodeStartTime; // Queue of audio frames. This queue is threadsafe, and is accessed from // the audio, decoder, state machine, and main threads. MediaQueue<AudioData> mAudioQueue; @@ -669,29 +672,16 @@ protected: // Accessed on state machine, audio, main, and AV thread. State mState; // The task queue in which we run decode tasks. This is referred to as // the "decode thread", though in practise tasks can run on a different // thread every time they're called. RefPtr<MediaTaskQueue> mDecodeTaskQueue; - RefPtr<SharedThreadPool> mStateMachineThreadPool; - - // Timer to run the state machine cycles. Used by - // ScheduleStateMachine(). Access protected by decoder monitor. - nsCOMPtr<nsITimer> mTimer; - - // Timestamp at which the next state machine cycle will run. - // Access protected by decoder monitor. - TimeStamp mTimeout; - - // Used to check if there are state machine cycles are running in sequence. - DebugOnly<bool> mInRunningStateMachine; - // The time that playback started from the system clock. This is used for // timing the presentation of video frames when there's no audio. // Accessed only via the state machine thread. Must be set via SetPlayStartTime. TimeStamp mPlayStartTime; // When we start writing decoded data to a new DecodedDataStream, or we // restart writing due to PlaybackStarted(), we record where we are in the // MediaStream and what that corresponds to in the media. @@ -906,19 +896,16 @@ protected: // memory and CPU overhead. bool mMinimizePreroll; // True if the decode thread has gone filled its buffers and is now // waiting to be awakened before it continues decoding. Synchronized // by the decoder monitor. bool mDecodeThreadWaiting; - // True is we are decoding a realtime stream, like a camera stream - bool mRealTime; - // True if we've dispatched a task to the decode task queue to call // ReadMetadata on the reader. We maintain a flag to ensure that we don't // dispatch multiple tasks to re-do the metadata loading. bool mDispatchedDecodeMetadataTask; // These two flags are true when we need to drop decoded samples that // we receive up to the next discontinuity. We do this when we seek; // the first sample in each stream after the seek is marked as being @@ -937,15 +924,12 @@ protected: // Stores presentation info required for playback. The decoder monitor // must be held when accessing this. MediaInfo mInfo; mozilla::MediaMetadataManager mMetadataManager; MediaDecoderOwner::NextFrameStatus mLastFrameStatus; - - // The id of timer tasks, used to ignore tasks that are scheduled previously. - int mTimerId; }; } // namespace mozilla; #endif
new file mode 100644 --- /dev/null +++ b/content/media/MediaDecoderStateMachineScheduler.cpp @@ -0,0 +1,233 @@ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MediaDecoderStateMachineScheduler.h" +#include "SharedThreadPool.h" +#include "mozilla/Preferences.h" +#include "mozilla/ReentrantMonitor.h" +#include "nsITimer.h" +#include "nsComponentManagerUtils.h" +#include "VideoUtils.h" + +namespace { +class TimerEvent : public nsITimerCallback, public nsRunnable { + typedef mozilla::MediaDecoderStateMachineScheduler Scheduler; + NS_DECL_THREADSAFE_ISUPPORTS +public: + TimerEvent(Scheduler* aScheduler, int aTimerId) + : mScheduler(aScheduler), mTimerId(aTimerId) {} + + NS_IMETHOD Run() MOZ_OVERRIDE { + return mScheduler->TimeoutExpired(mTimerId); + } + + NS_IMETHOD Notify(nsITimer* aTimer) MOZ_OVERRIDE { + return mScheduler->TimeoutExpired(mTimerId); + } +private: + ~TimerEvent() {} + Scheduler* const mScheduler; + const int mTimerId; +}; + +NS_IMPL_ISUPPORTS(TimerEvent, nsITimerCallback, nsIRunnable); +} // anonymous namespace + +static already_AddRefed<nsIEventTarget> +CreateStateMachineThread() +{ + using mozilla::SharedThreadPool; + using mozilla::RefPtr; + RefPtr<SharedThreadPool> threadPool( + SharedThreadPool::Get(NS_LITERAL_CSTRING("Media State Machine"), 1)); + nsCOMPtr<nsIEventTarget> rv = threadPool.get(); + return rv.forget(); +} + +namespace mozilla { + +MediaDecoderStateMachineScheduler::MediaDecoderStateMachineScheduler( + ReentrantMonitor& aMonitor, + nsresult (*aTimeoutCallback)(void*), + void* aClosure, bool aRealTime) + : mTimeoutCallback(aTimeoutCallback) + , mClosure(aClosure) + // Only enable realtime mode when "media.realtime_decoder.enabled" is true. + , mRealTime(aRealTime && + Preferences::GetBool("media.realtime_decoder.enabled", false)) + , mMonitor(aMonitor) + , mEventTarget(CreateStateMachineThread()) + , mTimer(do_CreateInstance("@mozilla.org/timer;1")) + , mTimerId(0) + , mState(SCHEDULER_STATE_NONE) + , mInRunningStateMachine(false) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_COUNT_CTOR(MediaDecoderStateMachineScheduler); +} + +MediaDecoderStateMachineScheduler::~MediaDecoderStateMachineScheduler() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_COUNT_DTOR(MediaDecoderStateMachineScheduler); +} + +nsresult +MediaDecoderStateMachineScheduler::Init() +{ + MOZ_ASSERT(NS_IsMainThread()); + NS_ENSURE_TRUE(mEventTarget, NS_ERROR_FAILURE); + nsresult rv = mTimer->SetTarget(mEventTarget); + NS_ENSURE_SUCCESS(rv, rv); + return NS_OK; +} + +nsresult +MediaDecoderStateMachineScheduler::Schedule(int64_t aUsecs) +{ + mMonitor.AssertCurrentThreadIn(); + + switch(mState) { + case SCHEDULER_STATE_SHUTDOWN: + return NS_ERROR_FAILURE; + case SCHEDULER_STATE_FROZEN: + mState = SCHEDULER_STATE_FROZEN_WITH_PENDING_TASK; + case SCHEDULER_STATE_FROZEN_WITH_PENDING_TASK: + return NS_OK; + case SCHEDULER_STATE_NONE: + break; + } + + aUsecs = std::max<int64_t>(aUsecs, 0); + + TimeStamp timeout = TimeStamp::Now() + + TimeDuration::FromMilliseconds(static_cast<double>(aUsecs) / USECS_PER_MS); + + if (!mTimeout.IsNull() && timeout >= mTimeout) { + // We've already scheduled a timer set to expire at or before this time, + // or have an event dispatched to run the state machine. + return NS_OK; + } + + uint32_t ms = static_cast<uint32_t>((aUsecs / USECS_PER_MS) & 0xFFFFFFFF); + if (IsRealTime() && ms > 40) { + ms = 40; + } + + // Don't cancel the timer here for this function will be called from + // different threads. + + nsresult rv = NS_ERROR_FAILURE; + nsRefPtr<TimerEvent> event = new TimerEvent(this, mTimerId+1); + + if (ms == 0) { + // Dispatch a runnable to the state machine thread when delay is 0. + // It will has less latency than dispatching a runnable to the state + // machine thread which will then schedule a zero-delay timer. + rv = mEventTarget->Dispatch(event, NS_DISPATCH_NORMAL); + } else if (OnStateMachineThread()) { + rv = mTimer->InitWithCallback(event, ms, nsITimer::TYPE_ONE_SHOT); + } else { + MOZ_ASSERT(false, "non-zero delay timer should be only " + "scheduled in state machine thread"); + } + + if (NS_SUCCEEDED(rv)) { + mTimeout = timeout; + ++mTimerId; + } else { + NS_WARNING("Failed to schedule state machine"); + } + + return rv; +} + +nsresult +MediaDecoderStateMachineScheduler::TimeoutExpired(int aTimerId) +{ + ReentrantMonitorAutoEnter mon(mMonitor); + MOZ_ASSERT(OnStateMachineThread()); + MOZ_ASSERT(!mInRunningStateMachine, + "State machine cycles must run in sequence!"); + + mInRunningStateMachine = true; + // Only run state machine cycles when id matches. + nsresult rv = NS_OK; + if (mTimerId == aTimerId) { + ResetTimer(); + rv = mTimeoutCallback(mClosure); + } + mInRunningStateMachine = false; + + return rv; +} + +void +MediaDecoderStateMachineScheduler::ScheduleAndShutdown() +{ + mMonitor.AssertCurrentThreadIn(); + if (IsFrozen()) { + ThawScheduling(); + } + // Schedule next cycle to handle SHUTDOWN in state machine thread. + Schedule(); + // This must be set after calling Schedule() + // which does nothing in shutdown state. + mState = SCHEDULER_STATE_SHUTDOWN; +} + +bool +MediaDecoderStateMachineScheduler::OnStateMachineThread() const +{ + bool rv = false; + mEventTarget->IsOnCurrentThread(&rv); + return rv; +} + +bool +MediaDecoderStateMachineScheduler::IsScheduled() const +{ + mMonitor.AssertCurrentThreadIn(); + return !mTimeout.IsNull(); +} + +void +MediaDecoderStateMachineScheduler::ResetTimer() +{ + mMonitor.AssertCurrentThreadIn(); + mTimer->Cancel(); + mTimeout = TimeStamp(); +} + +void MediaDecoderStateMachineScheduler::FreezeScheduling() +{ + mMonitor.AssertCurrentThreadIn(); + if (mState == SCHEDULER_STATE_SHUTDOWN) { + return; + } + MOZ_ASSERT(mState == SCHEDULER_STATE_NONE); + mState = !IsScheduled() ? SCHEDULER_STATE_FROZEN : + SCHEDULER_STATE_FROZEN_WITH_PENDING_TASK; + // Nullify pending timer task if any. + ++mTimerId; + mTimeout = TimeStamp(); +} + +void MediaDecoderStateMachineScheduler::ThawScheduling() +{ + mMonitor.AssertCurrentThreadIn(); + if (mState == SCHEDULER_STATE_SHUTDOWN) { + return; + } + // We should be in frozen state and no pending timer task. + MOZ_ASSERT(IsFrozen() && !IsScheduled()); + bool pendingTask = mState == SCHEDULER_STATE_FROZEN_WITH_PENDING_TASK; + mState = SCHEDULER_STATE_NONE; + if (pendingTask) { + Schedule(); + } +} + +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/content/media/MediaDecoderStateMachineScheduler.h @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MediaDecoderStateMachineScheduler_h__ +#define MediaDecoderStateMachineScheduler_h__ + +#include "nsCOMPtr.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/DebugOnly.h" + +class nsITimer; +class nsIEventTarget; + +namespace mozilla { + +class ReentrantMonitor; + +class MediaDecoderStateMachineScheduler { + enum State { + SCHEDULER_STATE_NONE, + SCHEDULER_STATE_FROZEN, + SCHEDULER_STATE_FROZEN_WITH_PENDING_TASK, + SCHEDULER_STATE_SHUTDOWN + }; +public: + MediaDecoderStateMachineScheduler(ReentrantMonitor& aMonitor, + nsresult (*aTimeoutCallback)(void*), + void* aClosure, bool aRealTime); + ~MediaDecoderStateMachineScheduler(); + nsresult Init(); + nsresult Schedule(int64_t aUsecs = 0); + void ScheduleAndShutdown(); + nsresult TimeoutExpired(int aTimerId); + void FreezeScheduling(); + void ThawScheduling(); + + bool OnStateMachineThread() const; + bool IsScheduled() const; + + bool IsRealTime() const { + return mRealTime; + } + + nsIEventTarget* GetStateMachineThread() const { + return mEventTarget; + } + + bool IsFrozen() const { + return mState == SCHEDULER_STATE_FROZEN || + mState == SCHEDULER_STATE_FROZEN_WITH_PENDING_TASK; + } + +private: + void ResetTimer(); + + // Callback function provided by MediaDecoderStateMachine to run + // state machine cycles. + nsresult (*const mTimeoutCallback)(void*); + // Since StateMachineScheduler will never outlive the state machine, + // it is safe to keep a raw pointer only to avoid reference cycles. + void* const mClosure; + // True is we are decoding a realtime stream, like a camera stream + const bool mRealTime; + // Monitor of the decoder + ReentrantMonitor& mMonitor; + // State machine thread + const nsCOMPtr<nsIEventTarget> mEventTarget; + // Timer to schedule callbacks to run the state machine cycles. + nsCOMPtr<nsITimer> mTimer; + // Timestamp at which the next state machine cycle will run. + TimeStamp mTimeout; + // The id of timer tasks, timer callback will only run if id matches. + int mTimerId; + // No more state machine cycles in shutdown state. + State mState; + + // Used to check if state machine cycles are running in sequence. + DebugOnly<bool> mInRunningStateMachine; +}; + +} // namespace mozilla + +#endif // MediaDecoderStateMachineScheduler_h__
--- a/content/media/MediaResource.h +++ b/content/media/MediaResource.h @@ -142,16 +142,20 @@ public: } // Clears byte range values. void Clear() { mStart = 0; mEnd = 0; } + bool Contains(const MediaByteRange& aByteRange) const { + return aByteRange.mStart >= mStart && aByteRange.mEnd <= mEnd; + } + int64_t mStart, mEnd; }; // Represents a section of contiguous media, with a start and end offset, and // a timestamp representing the start time. class TimestampedMediaByteRange : public MediaByteRange { public: TimestampedMediaByteRange() : MediaByteRange(), mStartTime(-1) {}
--- a/content/media/fmp4/MP4Reader.cpp +++ b/content/media/fmp4/MP4Reader.cpp @@ -8,16 +8,17 @@ #include "MediaResource.h" #include "nsSize.h" #include "VideoUtils.h" #include "mozilla/dom/HTMLMediaElement.h" #include "ImageContainer.h" #include "Layers.h" #include "SharedThreadPool.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/TimeRanges.h" using mozilla::layers::Image; using mozilla::layers::LayerManager; using mozilla::layers::LayersBackend; #ifdef PR_LOGGING PRLogModuleInfo* GetDemuxerLog() { static PRLogModuleInfo* log = nullptr; @@ -548,9 +549,28 @@ MP4Reader::Seek(int64_t aTime, if (mDemuxer->HasValidAudio()) { mDemuxer->SeekAudio( mQueuedVideoSample ? mQueuedVideoSample->composition_timestamp : aTime); } return NS_OK; } +nsresult +MP4Reader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) +{ + nsTArray<MediaByteRange> ranges; + if (NS_FAILED(mDecoder->GetResource()->GetCachedRanges(ranges))) { + return NS_ERROR_FAILURE; + } + + nsTArray<Interval<Microseconds>> timeRanges; + mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges); + + for (size_t i = 0; i < timeRanges.Length(); i++) { + aBuffered->Add((timeRanges[i].start - aStartTime) / 1000000.0, + (timeRanges[i].end - aStartTime) / 1000000.0); + } + + return NS_OK; +} + } // namespace mozilla
--- a/content/media/fmp4/MP4Reader.h +++ b/content/media/fmp4/MP4Reader.h @@ -47,16 +47,19 @@ public: virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) MOZ_OVERRIDE; virtual bool IsMediaSeekable() MOZ_OVERRIDE; + virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, + int64_t aStartTime) MOZ_OVERRIDE; + private: // Destroys all decoder resources. void Shutdown(); // Initializes mLayersBackendType if possible. void InitLayersBackendType();
--- a/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegAACDecoder.cpp @@ -66,16 +66,17 @@ void FFmpegAACDecoder<LIBAV_VER>::DecodePacket(MP4Sample* aSample) { nsAutoPtr<AVFrame> frame(avcodec_alloc_frame()); avcodec_get_frame_defaults(frame); AVPacket packet; av_init_packet(&packet); + aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE); packet.data = aSample->data; packet.size = aSample->size; packet.pos = aSample->byte_offset; int decoded; int bytesConsumed = avcodec_decode_audio4(&mCodecContext, frame.get(), &decoded, &packet);
--- a/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp @@ -80,21 +80,24 @@ FFmpegDataDecoder<LIBAV_VER>::Init() // FFmpeg takes this as a suggestion for what format to use for audio samples. mCodecContext.request_sample_fmt = AV_SAMPLE_FMT_FLT; // FFmpeg will call back to this to negotiate a video pixel format. mCodecContext.get_format = ChoosePixelFormat; mCodecContext.thread_count = PR_GetNumberOfProcessors(); - mCodecContext.thread_type = FF_THREAD_FRAME; + mCodecContext.thread_type = FF_THREAD_SLICE | FF_THREAD_FRAME; mCodecContext.thread_safe_callbacks = false; + mCodecContext.extradata_size = mExtraData.length(); + for (int i = 0; i < FF_INPUT_BUFFER_PADDING_SIZE; i++) { + mExtraData.append(0); + } mCodecContext.extradata = mExtraData.begin(); - mCodecContext.extradata_size = mExtraData.length(); AVDictionary* opts = nullptr; if (avcodec_open2(&mCodecContext, codec, &opts) < 0) { NS_WARNING("Couldn't initialise ffmpeg decoder"); return NS_ERROR_FAILURE; } if (mCodecContext.codec_type == AVMEDIA_TYPE_AUDIO &&
--- a/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp +++ b/content/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp @@ -48,16 +48,17 @@ FFmpegH264Decoder<LIBAV_VER>::Init() } void FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(mp4_demuxer::MP4Sample* aSample) { AVPacket packet; av_init_packet(&packet); + aSample->Pad(FF_INPUT_BUFFER_PADDING_SIZE); packet.data = aSample->data; packet.size = aSample->size; packet.pts = aSample->composition_timestamp; packet.flags = aSample->is_sync_point ? AV_PKT_FLAG_KEY : 0; packet.pos = aSample->byte_offset; nsAutoPtr<AVFrame> frame(avcodec_alloc_frame()); avcodec_get_frame_defaults(frame); @@ -132,17 +133,21 @@ FFmpegH264Decoder<LIBAV_VER>::AllocateBu return avcodec_default_get_buffer(aCodecContext, aFrame); } } /* static */ void FFmpegH264Decoder<LIBAV_VER>::ReleaseBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame) { - reinterpret_cast<Image*>(aFrame->opaque)->Release(); + Image* image = reinterpret_cast<Image*>(aFrame->opaque); + avcodec_default_release_buffer(aCodecContext, aFrame); + if (image) { + image->Release(); + } } int FFmpegH264Decoder<LIBAV_VER>::AllocateYUV420PVideoBuffer( AVCodecContext* aCodecContext, AVFrame* aFrame) { // Older versions of ffmpeg require that edges be allocated* around* the // actual image.
--- a/content/media/gmp/GMPMessageUtils.h +++ b/content/media/gmp/GMPMessageUtils.h @@ -2,20 +2,35 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GMPMessageUtils_h_ #define GMPMessageUtils_h_ #include "gmp-video-codec.h" +#include "gmp-video-frame-encoded.h" namespace IPC { template <> +struct ParamTraits<GMPErr> +: public ContiguousEnumSerializer<GMPErr, + GMPNoErr, + GMPLastErr> +{}; + +template <> +struct ParamTraits<GMPVideoFrameType> +: public ContiguousEnumSerializer<GMPVideoFrameType, + kGMPKeyFrame, + kGMPSkipFrame> +{}; + +template <> struct ParamTraits<GMPVideoCodecComplexity> : public ContiguousEnumSerializer<GMPVideoCodecComplexity, kGMPComplexityNormal, kGMPComplexityInvalid> {}; template <> struct ParamTraits<GMPVP8ResilienceMode> @@ -34,67 +49,21 @@ struct ParamTraits<GMPVideoCodecType> template <> struct ParamTraits<GMPVideoCodecMode> : public ContiguousEnumSerializer<GMPVideoCodecMode, kGMPRealtimeVideo, kGMPCodecModeInvalid> {}; template <> -struct ParamTraits<GMPVideoCodecVP8> -{ - typedef GMPVideoCodecVP8 paramType; - - static void Write(Message* aMsg, const paramType& aParam) - { - WriteParam(aMsg, aParam.mPictureLossIndicationOn); - WriteParam(aMsg, aParam.mFeedbackModeOn); - WriteParam(aMsg, aParam.mComplexity); - WriteParam(aMsg, aParam.mResilience); - WriteParam(aMsg, aParam.mNumberOfTemporalLayers); - WriteParam(aMsg, aParam.mDenoisingOn); - WriteParam(aMsg, aParam.mErrorConcealmentOn); - WriteParam(aMsg, aParam.mAutomaticResizeOn); - WriteParam(aMsg, aParam.mFrameDroppingOn); - WriteParam(aMsg, aParam.mKeyFrameInterval); - } - - static bool Read(const Message* aMsg, void** aIter, paramType* aResult) - { - if (ReadParam(aMsg, aIter, &(aResult->mPictureLossIndicationOn)) && - ReadParam(aMsg, aIter, &(aResult->mFeedbackModeOn)) && - ReadParam(aMsg, aIter, &(aResult->mComplexity)) && - ReadParam(aMsg, aIter, &(aResult->mResilience)) && - ReadParam(aMsg, aIter, &(aResult->mNumberOfTemporalLayers)) && - ReadParam(aMsg, aIter, &(aResult->mDenoisingOn)) && - ReadParam(aMsg, aIter, &(aResult->mErrorConcealmentOn)) && - ReadParam(aMsg, aIter, &(aResult->mAutomaticResizeOn)) && - ReadParam(aMsg, aIter, &(aResult->mFrameDroppingOn)) && - ReadParam(aMsg, aIter, &(aResult->mKeyFrameInterval))) { - return true; - } - - return false; - } - - static void Log(const paramType& aParam, std::wstring* aLog) - { - aLog->append(StringPrintf(L"[%d, %d, %d, %d, %u, %d, %d, %d, %d, %d]", - aParam.mPictureLossIndicationOn, - aParam.mFeedbackModeOn, - aParam.mComplexity, - aParam.mResilience, - aParam.mNumberOfTemporalLayers, - aParam.mDenoisingOn, - aParam.mErrorConcealmentOn, - aParam.mAutomaticResizeOn, - aParam.mFrameDroppingOn, - aParam.mKeyFrameInterval)); - } -}; +struct ParamTraits<GMPBufferType> +: public ContiguousEnumSerializer<GMPBufferType, + GMP_BufferSingle, + GMP_BufferInvalid> +{}; template <> struct ParamTraits<GMPSimulcastStream> { typedef GMPSimulcastStream paramType; static void Write(Message* aMsg, const paramType& aParam) { @@ -131,40 +100,43 @@ struct ParamTraits<GMPSimulcastStream> template <> struct ParamTraits<GMPVideoCodec> { typedef GMPVideoCodec paramType; static void Write(Message* aMsg, const paramType& aParam) { + WriteParam(aMsg, aParam.mGMPApiVersion); WriteParam(aMsg, aParam.mCodecType); WriteParam(aMsg, nsAutoCString(aParam.mPLName)); WriteParam(aMsg, aParam.mPLType); WriteParam(aMsg, aParam.mWidth); WriteParam(aMsg, aParam.mHeight); WriteParam(aMsg, aParam.mStartBitrate); WriteParam(aMsg, aParam.mMaxBitrate); WriteParam(aMsg, aParam.mMinBitrate); WriteParam(aMsg, aParam.mMaxFramerate); - if (aParam.mCodecType == kGMPVideoCodecVP8) { - WriteParam(aMsg, aParam.mCodecSpecific.mVP8); - } else { - MOZ_ASSERT(false, "Serializing unknown codec type!"); - } + WriteParam(aMsg, aParam.mFrameDroppingOn); + WriteParam(aMsg, aParam.mKeyFrameInterval); WriteParam(aMsg, aParam.mQPMax); WriteParam(aMsg, aParam.mNumberOfSimulcastStreams); for (uint32_t i = 0; i < aParam.mNumberOfSimulcastStreams; i++) { WriteParam(aMsg, aParam.mSimulcastStream[i]); } WriteParam(aMsg, aParam.mMode); } static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { + // NOTE: make sure this matches any versions supported + if (!ReadParam(aMsg, aIter, &(aResult->mGMPApiVersion)) || + aResult->mGMPApiVersion != kGMPVersion33) { + return false; + } if (!ReadParam(aMsg, aIter, &(aResult->mCodecType))) { return false; } nsAutoCString plName; if (!ReadParam(aMsg, aIter, &plName) || plName.Length() > kGMPPayloadNameSize - 1) { return false; @@ -173,26 +145,19 @@ struct ParamTraits<GMPVideoCodec> memset(aResult->mPLName + plName.Length(), 0, kGMPPayloadNameSize - plName.Length()); if (!ReadParam(aMsg, aIter, &(aResult->mPLType)) || !ReadParam(aMsg, aIter, &(aResult->mWidth)) || !ReadParam(aMsg, aIter, &(aResult->mHeight)) || !ReadParam(aMsg, aIter, &(aResult->mStartBitrate)) || !ReadParam(aMsg, aIter, &(aResult->mMaxBitrate)) || !ReadParam(aMsg, aIter, &(aResult->mMinBitrate)) || - !ReadParam(aMsg, aIter, &(aResult->mMaxFramerate))) { - return false; - } - - if (aResult->mCodecType == kGMPVideoCodecVP8) { - if (!ReadParam(aMsg, aIter, &(aResult->mCodecSpecific.mVP8))) { - return false; - } - } else { - MOZ_ASSERT(false, "De-serializing unknown codec type!"); + !ReadParam(aMsg, aIter, &(aResult->mMaxFramerate)) || + !ReadParam(aMsg, aIter, &(aResult->mFrameDroppingOn)) || + !ReadParam(aMsg, aIter, &(aResult->mKeyFrameInterval))) { return false; } if (!ReadParam(aMsg, aIter, &(aResult->mQPMax)) || !ReadParam(aMsg, aIter, &(aResult->mNumberOfSimulcastStreams))) { return false; } @@ -221,109 +186,11 @@ struct ParamTraits<GMPVideoCodec> } aLog->append(StringPrintf(L"[%s, %u, %u]", codecName, aParam.mWidth, aParam.mHeight)); } }; -template <> -struct ParamTraits<GMPCodecSpecificInfoVP8> -{ - typedef GMPCodecSpecificInfoVP8 paramType; - - static void Write(Message* aMsg, const paramType& aParam) - { - WriteParam(aMsg, aParam.mHasReceivedSLI); - WriteParam(aMsg, aParam.mPictureIdSLI); - WriteParam(aMsg, aParam.mHasReceivedRPSI); - WriteParam(aMsg, aParam.mPictureIdRPSI); - WriteParam(aMsg, aParam.mPictureId); - WriteParam(aMsg, aParam.mNonReference); - WriteParam(aMsg, aParam.mSimulcastIdx); - WriteParam(aMsg, aParam.mTemporalIdx); - WriteParam(aMsg, aParam.mLayerSync); - WriteParam(aMsg, aParam.mTL0PicIdx); - WriteParam(aMsg, aParam.mKeyIdx); - } - - static bool Read(const Message* aMsg, void** aIter, paramType* aResult) - { - if (ReadParam(aMsg, aIter, &(aResult->mHasReceivedSLI)) && - ReadParam(aMsg, aIter, &(aResult->mPictureIdSLI)) && - ReadParam(aMsg, aIter, &(aResult->mHasReceivedRPSI)) && - ReadParam(aMsg, aIter, &(aResult->mPictureIdRPSI)) && - ReadParam(aMsg, aIter, &(aResult->mPictureId)) && - ReadParam(aMsg, aIter, &(aResult->mNonReference)) && - ReadParam(aMsg, aIter, &(aResult->mSimulcastIdx)) && - ReadParam(aMsg, aIter, &(aResult->mTemporalIdx)) && - ReadParam(aMsg, aIter, &(aResult->mLayerSync)) && - ReadParam(aMsg, aIter, &(aResult->mTL0PicIdx)) && - ReadParam(aMsg, aIter, &(aResult->mKeyIdx))) { - return true; - } - return false; - } - - static void Log(const paramType& aParam, std::wstring* aLog) - { - aLog->append(StringPrintf(L"[%d, %u, %d, %u, %d, %d, %u, %u, %d, %d, %d]", - aParam.mHasReceivedSLI, - aParam.mPictureIdSLI, - aParam.mHasReceivedRPSI, - aParam.mPictureIdRPSI, - aParam.mPictureId, - aParam.mNonReference, - aParam.mSimulcastIdx, - aParam.mTemporalIdx, - aParam.mLayerSync, - aParam.mTL0PicIdx, - aParam.mKeyIdx)); - } -}; - -template <> -struct ParamTraits<GMPCodecSpecificInfo> -{ - typedef GMPCodecSpecificInfo paramType; - - static void Write(Message* aMsg, const paramType& aParam) - { - WriteParam(aMsg, aParam.mCodecType); - if (aParam.mCodecType == kGMPVideoCodecVP8) { - WriteParam(aMsg, aParam.mCodecSpecific.mVP8); - } else { - MOZ_ASSERT(false, "Serializing unknown codec type!"); - } - } - - static bool Read(const Message* aMsg, void** aIter, paramType* aResult) - { - if (!ReadParam(aMsg, aIter, &(aResult->mCodecType))) { - return false; - } - - if (aResult->mCodecType == kGMPVideoCodecVP8) { - if (!ReadParam(aMsg, aIter, &(aResult->mCodecSpecific.mVP8))) { - return false; - } - } else { - MOZ_ASSERT(false, "De-serializing unknown codec type!"); - return false; - } - - return true; - } - - static void Log(const paramType& aParam, std::wstring* aLog) - { - const char* codecName = nullptr; - if (aParam.mCodecType == kGMPVideoCodecVP8) { - codecName = "VP8"; - } - aLog->append(StringPrintf(L"[%s]", codecName)); - } -}; - } // namespace IPC #endif // GMPMessageUtils_h_
--- a/content/media/gmp/GMPParent.h +++ b/content/media/gmp/GMPParent.h @@ -11,16 +11,17 @@ #include "GMPVideoEncoderParent.h" #include "mozilla/gmp/PGMPParent.h" #include "nsCOMPtr.h" #include "nscore.h" #include "nsISupports.h" #include "nsString.h" #include "nsTArray.h" #include "nsIFile.h" +#include "ThreadSafeRefcountingWithMainThreadDestruction.h" class nsILineInputStream; class nsIThread; namespace mozilla { namespace gmp { class GMPCapability @@ -33,17 +34,17 @@ public: enum GMPState { GMPStateNotLoaded, GMPStateLoaded }; class GMPParent MOZ_FINAL : public PGMPParent { public: - NS_INLINE_DECL_REFCOUNTING(GMPParent) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GMPParent) GMPParent(); nsresult Init(nsIFile* aPluginDir); nsresult LoadProcess(); void MaybeUnloadProcess(); void UnloadProcess(); bool SupportsAPI(const nsCString& aAPI, const nsCString& aTag);
--- a/content/media/gmp/GMPPlatform.cpp +++ b/content/media/gmp/GMPPlatform.cpp @@ -22,25 +22,26 @@ public: : mTask(aTask) { MOZ_ASSERT(mTask); } void Run() { mTask->Run(); + mTask->Destroy(); mTask = nullptr; } private: ~Runnable() { } - nsAutoPtr<GMPTask> mTask; + GMPTask* mTask; }; class SyncRunnable MOZ_FINAL { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SyncRunnable) SyncRunnable(GMPTask* aTask, MessageLoop* aMessageLoop) @@ -66,29 +67,30 @@ public: while (!mDone) { lock.Wait(); } } void Run() { mTask->Run(); + mTask->Destroy(); mTask = nullptr; MonitorAutoLock lock(mMonitor); mDone = true; lock.Notify(); } private: ~SyncRunnable() { } bool mDone; - nsAutoPtr<GMPTask> mTask; + GMPTask* mTask; MessageLoop* mMessageLoop; Monitor mMonitor; }; GMPErr CreateThread(GMPThread** aThread) { if (!aThread) { @@ -103,17 +105,16 @@ CreateThread(GMPThread** aThread) GMPErr RunOnMainThread(GMPTask* aTask) { if (!aTask || !sMainLoop) { return GMPGenericErr; } nsRefPtr<Runnable> r = new Runnable(aTask); - sMainLoop->PostTask(FROM_HERE, NewRunnableMethod(r.get(), &Runnable::Run)); return GMPNoErr; } GMPErr SyncRunOnMainThread(GMPTask* aTask) { @@ -147,16 +148,19 @@ InitPlatformAPI(GMPPlatformAPI& aPlatfor sMainLoop = MessageLoop::current(); } aPlatformAPI.version = 0; aPlatformAPI.createthread = &CreateThread; aPlatformAPI.runonmainthread = &RunOnMainThread; aPlatformAPI.syncrunonmainthread = &SyncRunOnMainThread; aPlatformAPI.createmutex = &CreateMutex; + aPlatformAPI.createrecord = nullptr; + aPlatformAPI.settimer = nullptr; + aPlatformAPI.getcurrenttime = nullptr; } GMPThreadImpl::GMPThreadImpl() : mMutex("GMPThreadImpl"), mThread("GMPThread") { }
--- a/content/media/gmp/GMPPlatform.h +++ b/content/media/gmp/GMPPlatform.h @@ -8,16 +8,18 @@ #include "mozilla/Mutex.h" #include "gmp-platform.h" #include "base/thread.h" namespace mozilla { namespace gmp { +class GMPChild; + void InitPlatformAPI(GMPPlatformAPI& aPlatformAPI); class GMPThreadImpl : public GMPThread { public: GMPThreadImpl(); virtual ~GMPThreadImpl();
--- a/content/media/gmp/GMPService.cpp +++ b/content/media/gmp/GMPService.cpp @@ -178,17 +178,17 @@ GeckoMediaPluginService::GetThread(nsITh return NS_OK; } NS_IMETHODIMP GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags, const nsAString& aOrigin, GMPVideoHost** aOutVideoHost, - GMPVideoDecoder** aGMPVD) + GMPVideoDecoderProxy** aGMPVD) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); NS_ENSURE_ARG(aOutVideoHost); NS_ENSURE_ARG(aGMPVD); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; @@ -212,17 +212,17 @@ GeckoMediaPluginService::GetGMPVideoDeco return NS_OK; } NS_IMETHODIMP GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags, const nsAString& aOrigin, GMPVideoHost** aOutVideoHost, - GMPVideoEncoder** aGMPVE) + GMPVideoEncoderProxy** aGMPVE) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); NS_ENSURE_ARG(aTags && aTags->Length() > 0); NS_ENSURE_ARG(aOutVideoHost); NS_ENSURE_ARG(aGMPVE); if (mShuttingDownOnGMPThread) { return NS_ERROR_FAILURE; @@ -359,31 +359,51 @@ GeckoMediaPluginService::SelectPluginFor gmp->SetOrigin(aOrigin); } return gmp; } } return nullptr; } +class CreateGMPParentTask : public nsRunnable { +public: + NS_IMETHOD Run() { + MOZ_ASSERT(NS_IsMainThread()); + mParent = new GMPParent(); + return NS_OK; + } + already_AddRefed<GMPParent> GetParent() { + return mParent.forget(); + } +private: + nsRefPtr<GMPParent> mParent; +}; void GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); nsCOMPtr<nsIFile> directory; nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); if (NS_WARN_IF(NS_FAILED(rv))) { return; } - nsRefPtr<GMPParent> gmp = new GMPParent(); + // The GMPParent inherits from IToplevelProtocol, which must be created + // on the main thread to be threadsafe. See Bug 1035653. + nsRefPtr<CreateGMPParentTask> task(new CreateGMPParentTask()); + nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); + MOZ_ASSERT(mainThread); + mozilla::SyncRunnable::DispatchToThread(mainThread, task); + nsRefPtr<GMPParent> gmp = task->GetParent(); rv = gmp->Init(directory); if (NS_FAILED(rv)) { + NS_WARNING("Can't Create GMPParent"); return; } mPlugins.AppendElement(gmp); } void GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)
--- a/content/media/gmp/GMPService.h +++ b/content/media/gmp/GMPService.h @@ -1,16 +1,17 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GMPService_h_ #define GMPService_h_ +#include "nsString.h" #include "mozIGeckoMediaPluginService.h" #include "nsIObserver.h" #include "nsTArray.h" #include "mozilla/Mutex.h" #include "nsString.h" #include "nsCOMPtr.h" #include "nsIThread.h" #include "nsThreadUtils.h"
new file mode 100644 --- /dev/null +++ b/content/media/gmp/GMPSharedMemManager.cpp @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "GMPSharedMemManager.h" +#include "GMPMessageUtils.h" +#include "mozilla/ipc/SharedMemory.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/ClearOnShutdown.h" + +namespace mozilla { +namespace gmp { + +// Really one set of pools on each side of the plugin API. + +// YUV buffers go from Encoder parent to child; pool there, and then return +// with Decoded() frames to the Decoder parent and goes into the parent pool. +// Compressed (encoded) data goes from the Decoder parent to the child; +// pool there, and then return with Encoded() frames and goes into the parent +// pool. +static StaticAutoPtr<nsTArray<ipc::Shmem>> sGmpFreelist[GMPSharedMemManager::kGMPNumTypes]; +static uint32_t sGMPShmemManagerCount = 0; + +GMPSharedMemManager::GMPSharedMemManager() +{ + if (!sGMPShmemManagerCount) { + for (uint32_t i = 0; i < GMPSharedMemManager::kGMPNumTypes; i++) { + sGmpFreelist[i] = new nsTArray<ipc::Shmem>(); + } + } + sGMPShmemManagerCount++; +} + +GMPSharedMemManager::~GMPSharedMemManager() +{ + MOZ_ASSERT(sGMPShmemManagerCount > 0); + sGMPShmemManagerCount--; + if (!sGMPShmemManagerCount) { + for (uint32_t i = 0; i < GMPSharedMemManager::kGMPNumTypes; i++) { + sGmpFreelist[i] = nullptr; + } + } +} + +static nsTArray<ipc::Shmem>& +GetGmpFreelist(GMPSharedMemManager::GMPMemoryClasses aTypes) +{ + return *(sGmpFreelist[aTypes]); +} + +static uint32_t sGmpAllocated[GMPSharedMemManager::kGMPNumTypes]; // 0's + +bool +GMPSharedMemManager::MgrAllocShmem(GMPMemoryClasses aClass, size_t aSize, + ipc::Shmem::SharedMemory::SharedMemoryType aType, + ipc::Shmem* aMem) +{ + CheckThread(); + + // first look to see if we have a free buffer large enough + for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) { + MOZ_ASSERT(GetGmpFreelist(aClass)[i].IsWritable()); + if (aSize <= GetGmpFreelist(aClass)[i].Size<uint8_t>()) { + *aMem = GetGmpFreelist(aClass)[i]; + GetGmpFreelist(aClass).RemoveElementAt(i); + return true; + } + } + + // Didn't find a buffer free with enough space; allocate one + size_t pagesize = ipc::SharedMemory::SystemPageSize(); + aSize = (aSize + (pagesize-1)) & ~(pagesize-1); // round up to page size + bool retval = Alloc(aSize, aType, aMem); + if (retval) { + sGmpAllocated[aClass]++; + } + return retval; +} + +bool +GMPSharedMemManager::MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem) +{ + CheckThread(); + + size_t size = aMem.Size<uint8_t>(); + size_t total = 0; + // XXX This works; there are better pool algorithms. We need to avoid + // "falling off a cliff" with too low a number + if (GetGmpFreelist(aClass).Length() > 10) { + Dealloc(GetGmpFreelist(aClass)[0]); + GetGmpFreelist(aClass).RemoveElementAt(0); + // The allocation numbers will be fubar on the Child! + sGmpAllocated[aClass]--; + } + for (uint32_t i = 0; i < GetGmpFreelist(aClass).Length(); i++) { + MOZ_ASSERT(GetGmpFreelist(aClass)[i].IsWritable()); + total += GetGmpFreelist(aClass)[i].Size<uint8_t>(); + if (size < GetGmpFreelist(aClass)[i].Size<uint8_t>()) { + GetGmpFreelist(aClass).InsertElementAt(i, aMem); + return true; + } + } + GetGmpFreelist(aClass).AppendElement(aMem); + + return true; +} + +uint32_t +GMPSharedMemManager::NumInUse(GMPMemoryClasses aClass) +{ + return sGmpAllocated[aClass] - GetGmpFreelist(aClass).Length(); +} + +} +}
--- a/content/media/gmp/GMPSharedMemManager.h +++ b/content/media/gmp/GMPSharedMemManager.h @@ -2,25 +2,53 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GMPSharedMemManager_h_ #define GMPSharedMemManager_h_ #include "mozilla/ipc/Shmem.h" +#include "nsTArray.h" namespace mozilla { namespace gmp { class GMPSharedMemManager { public: - virtual bool MgrAllocShmem(size_t aSize, + typedef enum { + kGMPFrameData = 0, + kGMPEncodedData, + kGMPNumTypes + } GMPMemoryClasses; + + // This is a heuristic - max of 10 free in the Child pool, plus those + // in-use for the encoder and decoder at the given moment and not yet + // returned to the parent pool (which is not included). If more than + // this are needed, we presume the client has either crashed or hung + // (perhaps temporarily). + static const uint32_t kGMPBufLimit = 20; + + GMPSharedMemManager(); + virtual ~GMPSharedMemManager(); + + virtual bool MgrAllocShmem(GMPMemoryClasses aClass, size_t aSize, ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) = 0; - virtual bool MgrDeallocShmem(ipc::Shmem& aMem) = 0; + ipc::Shmem* aMem); + virtual bool MgrDeallocShmem(GMPMemoryClasses aClass, ipc::Shmem& aMem); + + // So we can know if data is "piling up" for the plugin - I.e. it's hung or crashed + virtual uint32_t NumInUse(GMPMemoryClasses aClass); + + // Parent and child impls will differ here + virtual void CheckThread() = 0; + + // These have to be implemented using the AllocShmem/etc provided by the IPDL-generated interfaces, + // so have the Parent/Child implement them. + virtual bool Alloc(size_t aSize, ipc::Shmem::SharedMemory::SharedMemoryType aType, ipc::Shmem* aMem) = 0; + virtual void Dealloc(ipc::Shmem& aMem) = 0; }; } // namespace gmp } // namespace mozilla #endif // GMPSharedMemManager_h_
--- a/content/media/gmp/GMPTypes.ipdlh +++ b/content/media/gmp/GMPTypes.ipdlh @@ -1,24 +1,27 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using GMPBufferType from "gmp-video-codec.h"; + namespace mozilla { namespace gmp { struct GMPVideoEncodedFrameData { - int64_t mCaptureTime_ms; uint32_t mEncodedWidth; uint32_t mEncodedHeight; - uint32_t mTimeStamp; + uint64_t mTimestamp; // microseconds + uint64_t mDuration; // microseconds uint32_t mFrameType; uint32_t mSize; + GMPBufferType mBufferType; Shmem mBuffer; bool mCompleteFrame; }; struct GMPPlaneData { int32_t mSize; int32_t mStride; @@ -27,14 +30,14 @@ struct GMPPlaneData struct GMPVideoi420FrameData { GMPPlaneData mYPlane; GMPPlaneData mUPlane; GMPPlaneData mVPlane; int32_t mWidth; int32_t mHeight; - uint32_t mTimestamp; - int64_t mRenderTime_ms; + uint64_t mTimestamp; // microseconds + uint64_t mDuration; // microseconds }; } }
--- a/content/media/gmp/GMPVideoDecoderChild.cpp +++ b/content/media/gmp/GMPVideoDecoderChild.cpp @@ -75,67 +75,89 @@ GMPVideoDecoderChild::ReceivedDecodedFra void GMPVideoDecoderChild::InputDataExhausted() { MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); SendInputDataExhausted(); } -bool -GMPVideoDecoderChild::MgrAllocShmem(size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) +void +GMPVideoDecoderChild::DrainComplete() { MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - return AllocShmem(aSize, aType, aMem); + SendDrainComplete(); } -bool -GMPVideoDecoderChild::MgrDeallocShmem(Shmem& aMem) +void +GMPVideoDecoderChild::ResetComplete() { MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - return DeallocShmem(aMem); + SendResetComplete(); +} + +void +GMPVideoDecoderChild::CheckThread() +{ + MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); } bool GMPVideoDecoderChild::RecvInitDecode(const GMPVideoCodec& aCodecSettings, + const nsTArray<uint8_t>& aCodecSpecific, const int32_t& aCoreCount) { if (!mVideoDecoder) { return false; } // Ignore any return code. It is OK for this to fail without killing the process. - mVideoDecoder->InitDecode(aCodecSettings, this, aCoreCount); - + mVideoDecoder->InitDecode(aCodecSettings, + aCodecSpecific.Elements(), + aCodecSpecific.Length(), + this, + aCoreCount); return true; } bool GMPVideoDecoderChild::RecvDecode(const GMPVideoEncodedFrameData& aInputFrame, const bool& aMissingFrames, - const GMPCodecSpecificInfo& aCodecSpecificInfo, + const nsTArray<uint8_t>& aCodecSpecificInfo, const int64_t& aRenderTimeMs) { if (!mVideoDecoder) { return false; } auto f = new GMPVideoEncodedFrameImpl(aInputFrame, &mVideoHost); // Ignore any return code. It is OK for this to fail without killing the process. - mVideoDecoder->Decode(f, aMissingFrames, aCodecSpecificInfo, aRenderTimeMs); + mVideoDecoder->Decode(f, + aMissingFrames, + aCodecSpecificInfo.Elements(), + aCodecSpecificInfo.Length(), + aRenderTimeMs); return true; } bool +GMPVideoDecoderChild::RecvChildShmemForPool(Shmem& aFrameBuffer) +{ + if (aFrameBuffer.IsWritable()) { + mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPFrameData, + aFrameBuffer); + } + return true; +} + +bool GMPVideoDecoderChild::RecvReset() { if (!mVideoDecoder) { return false; } // Ignore any return code. It is OK for this to fail without killing the process. mVideoDecoder->Reset();
--- a/content/media/gmp/GMPVideoDecoderChild.h +++ b/content/media/gmp/GMPVideoDecoderChild.h @@ -6,53 +6,75 @@ #ifndef GMPVideoDecoderChild_h_ #define GMPVideoDecoderChild_h_ #include "nsString.h" #include "mozilla/gmp/PGMPVideoDecoderChild.h" #include "gmp-video-decode.h" #include "GMPSharedMemManager.h" #include "GMPVideoHost.h" +#include "mozilla/gmp/GMPTypes.h" namespace mozilla { namespace gmp { class GMPChild; class GMPVideoDecoderChild : public PGMPVideoDecoderChild, - public GMPDecoderCallback, + public GMPVideoDecoderCallback, public GMPSharedMemManager { public: GMPVideoDecoderChild(GMPChild* aPlugin); virtual ~GMPVideoDecoderChild(); void Init(GMPVideoDecoder* aDecoder); GMPVideoHostImpl& Host(); - // GMPDecoderCallback + // GMPVideoDecoderCallback virtual void Decoded(GMPVideoi420Frame* decodedFrame) MOZ_OVERRIDE; virtual void ReceivedDecodedReferenceFrame(const uint64_t pictureId) MOZ_OVERRIDE; virtual void ReceivedDecodedFrame(const uint64_t pictureId) MOZ_OVERRIDE; virtual void InputDataExhausted() MOZ_OVERRIDE; + virtual void DrainComplete() MOZ_OVERRIDE; + virtual void ResetComplete() MOZ_OVERRIDE; // GMPSharedMemManager - virtual bool MgrAllocShmem(size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) MOZ_OVERRIDE; - virtual bool MgrDeallocShmem(Shmem& aMem) MOZ_OVERRIDE; + virtual void CheckThread(); + virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) + { +#ifndef SHMEM_ALLOC_IN_CHILD + return CallNeedShmem(aSize, aMem); +#else +#ifdef GMP_SAFE_SHMEM + return AllocShmem(aSize, aType, aMem); +#else + return AllocUnsafeShmem(aSize, aType, aMem); +#endif +#endif + } + virtual void Dealloc(Shmem& aMem) + { +#ifndef SHMEM_ALLOC_IN_CHILD + SendParentShmemForPool(aMem); +#else + DeallocShmem(aMem); +#endif + } private: // PGMPVideoDecoderChild - virtual bool RecvInitDecode(const GMPVideoCodec& codecSettings, - const int32_t& coreCount) MOZ_OVERRIDE; - virtual bool RecvDecode(const GMPVideoEncodedFrameData& inputFrame, - const bool& missingFrames, - const GMPCodecSpecificInfo& codecSpecificInfo, - const int64_t& renderTimeMs) MOZ_OVERRIDE; + virtual bool RecvInitDecode(const GMPVideoCodec& aCodecSettings, + const nsTArray<uint8_t>& aCodecSpecific, + const int32_t& aCoreCount) MOZ_OVERRIDE; + virtual bool RecvDecode(const GMPVideoEncodedFrameData& aInputFrame, + const bool& aMissingFrames, + const nsTArray<uint8_t>& aCodecSpecificInfo, + const int64_t& aRenderTimeMs) MOZ_OVERRIDE; + virtual bool RecvChildShmemForPool(Shmem& aFrameBuffer) MOZ_OVERRIDE; virtual bool RecvReset() MOZ_OVERRIDE; virtual bool RecvDrain() MOZ_OVERRIDE; virtual bool RecvDecodingComplete() MOZ_OVERRIDE; GMPChild* mPlugin; GMPVideoDecoder* mVideoDecoder; GMPVideoHostImpl mVideoHost; };
--- a/content/media/gmp/GMPVideoDecoderParent.cpp +++ b/content/media/gmp/GMPVideoDecoderParent.cpp @@ -7,16 +7,17 @@ #include "GMPVideoEncodedFrameImpl.h" #include "GMPVideoi420FrameImpl.h" #include "GMPParent.h" #include <stdio.h> #include "mozilla/unused.h" #include "GMPMessageUtils.h" #include "nsAutoRef.h" #include "nsThreadUtils.h" +#include "mozilla/gmp/GMPTypes.h" template <> class nsAutoRefTraits<GMPVideoEncodedFrame> : public nsPointerRefTraits<GMPVideoEncodedFrame> { public: static void Release(GMPVideoEncodedFrame* aFrame) { aFrame->Destroy(); } }; @@ -37,160 +38,159 @@ GMPVideoDecoderParent::~GMPVideoDecoderP } GMPVideoHostImpl& GMPVideoDecoderParent::Host() { return mVideoHost; } -bool -GMPVideoDecoderParent::MgrAllocShmem(size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) -{ - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - return AllocShmem(aSize, aType, aMem); -} - -bool -GMPVideoDecoderParent::MgrDeallocShmem(Shmem& aMem) -{ - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - return DeallocShmem(aMem); -} - -GMPVideoErr +nsresult GMPVideoDecoderParent::InitDecode(const GMPVideoCodec& aCodecSettings, - GMPDecoderCallback* aCallback, + const nsTArray<uint8_t>& aCodecSpecific, + GMPVideoDecoderCallback* aCallback, int32_t aCoreCount) { if (!mCanSendMessages) { NS_WARNING("Trying to use an invalid GMP video decoder!"); - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); if (!aCallback) { - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } mCallback = aCallback; - if (!SendInitDecode(aCodecSettings, aCoreCount)) { - return GMPVideoGenericErr; + if (!SendInitDecode(aCodecSettings, aCodecSpecific, aCoreCount)) { + return NS_ERROR_FAILURE; } // Async IPC, we don't have access to a return value. - return GMPVideoNoErr; + return NS_OK; } -GMPVideoErr +nsresult GMPVideoDecoderParent::Decode(GMPVideoEncodedFrame* aInputFrame, bool aMissingFrames, - const GMPCodecSpecificInfo& aCodecSpecificInfo, + const nsTArray<uint8_t>& aCodecSpecificInfo, int64_t aRenderTimeMs) { nsAutoRef<GMPVideoEncodedFrame> autoDestroy(aInputFrame); if (!mCanSendMessages) { NS_WARNING("Trying to use an invalid GMP video decoder!"); - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); auto inputFrameImpl = static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame); GMPVideoEncodedFrameData frameData; inputFrameImpl->RelinquishFrameData(frameData); + // Very rough kill-switch if the plugin stops processing. If it's merely + // hung and continues, we'll come back to life eventually. + // 3* is because we're using 3 buffers per frame for i420 data for now. + if (NumInUse(kGMPFrameData) > 3*GMPSharedMemManager::kGMPBufLimit || + NumInUse(kGMPEncodedData) > GMPSharedMemManager::kGMPBufLimit) { + return NS_ERROR_FAILURE; + } + if (!SendDecode(frameData, aMissingFrames, aCodecSpecificInfo, aRenderTimeMs)) { - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } // Async IPC, we don't have access to a return value. - return GMPVideoNoErr; + return NS_OK; } -GMPVideoErr +nsresult GMPVideoDecoderParent::Reset() { if (!mCanSendMessages) { NS_WARNING("Trying to use an invalid GMP video decoder!"); - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); if (!SendReset()) { - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } // Async IPC, we don't have access to a return value. - return GMPVideoNoErr; + return NS_OK; } -GMPVideoErr +nsresult GMPVideoDecoderParent::Drain() { if (!mCanSendMessages) { NS_WARNING("Trying to use an invalid GMP video decoder!"); - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); if (!SendDrain()) { - return GMPVideoGenericErr; + return NS_ERROR_FAILURE; } // Async IPC, we don't have access to a return value. - return GMPVideoNoErr; + return NS_OK; } // Note: Consider keeping ActorDestroy sync'd up when making changes here. -void +nsresult GMPVideoDecoderParent::DecodingComplete() { if (!mCanSendMessages) { NS_WARNING("Trying to use an invalid GMP video decoder!"); - return; + return NS_ERROR_FAILURE; } MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); mCanSendMessages = false; mCallback = nullptr; mVideoHost.DoneWithAPI(); unused << SendDecodingComplete(); + + return NS_OK; } // Note: Keep this sync'd up with DecodingComplete void GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy) { if (mPlugin) { // Ignore any return code. It is OK for this to fail without killing the process. mPlugin->VideoDecoderDestroyed(this); mPlugin = nullptr; } mCanSendMessages = false; mCallback = nullptr; mVideoHost.ActorDestroyed(); } +void +GMPVideoDecoderParent::CheckThread() +{ + MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); +} + bool GMPVideoDecoderParent::RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame) { if (!mCallback) { return false; } auto f = new GMPVideoi420FrameImpl(aDecodedFrame, &mVideoHost); @@ -236,16 +236,69 @@ GMPVideoDecoderParent::RecvInputDataExha // Ignore any return code. It is OK for this to fail without killing the process. mCallback->InputDataExhausted(); return true; } bool +GMPVideoDecoderParent::RecvDrainComplete() +{ + if (!mCallback) { + return false; + } + + // Ignore any return code. It is OK for this to fail without killing the process. + mCallback->DrainComplete(); + + return true; +} + +bool +GMPVideoDecoderParent::RecvResetComplete() +{ + if (!mCallback) { + return false; + } + + // Ignore any return code. It is OK for this to fail without killing the process. + mCallback->ResetComplete(); + + return true; +} + +bool +GMPVideoDecoderParent::RecvParentShmemForPool(Shmem& aEncodedBuffer) +{ + if (aEncodedBuffer.IsWritable()) { + mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData, + aEncodedBuffer); + } + return true; +} + +bool +GMPVideoDecoderParent::AnswerNeedShmem(const uint32_t& aFrameBufferSize, + Shmem* aMem) +{ + ipc::Shmem mem; + + if (!mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPFrameData, + aFrameBufferSize, + ipc::SharedMemory::TYPE_BASIC, &mem)) + { + return false; + } + *aMem = mem; + mem = ipc::Shmem(); + return true; +} + +bool GMPVideoDecoderParent::Recv__delete__() { if (mPlugin) { // Ignore any return code. It is OK for this to fail without killing the process. mPlugin->VideoDecoderDestroyed(this); mPlugin = nullptr; }
--- a/content/media/gmp/GMPVideoDecoderParent.h +++ b/content/media/gmp/GMPVideoDecoderParent.h @@ -7,64 +7,80 @@ #define GMPVideoDecoderParent_h_ #include "mozilla/RefPtr.h" #include "gmp-video-decode.h" #include "mozilla/gmp/PGMPVideoDecoderParent.h" #include "GMPMessageUtils.h" #include "GMPSharedMemManager.h" #include "GMPVideoHost.h" +#include "GMPVideoDecoderProxy.h" namespace mozilla { namespace gmp { class GMPParent; -class GMPVideoDecoderParent MOZ_FINAL : public GMPVideoDecoder - , public PGMPVideoDecoderParent +class GMPVideoDecoderParent MOZ_FINAL : public PGMPVideoDecoderParent , public GMPSharedMemManager + , public GMPVideoDecoderProxy { public: NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent) GMPVideoDecoderParent(GMPParent *aPlugin); GMPVideoHostImpl& Host(); - // GMPSharedMemManager - virtual bool MgrAllocShmem(size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) MOZ_OVERRIDE; - virtual bool MgrDeallocShmem(Shmem& aMem) MOZ_OVERRIDE; + // GMPVideoDecoder + virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings, + const nsTArray<uint8_t>& aCodecSpecific, + GMPVideoDecoderCallback* aCallback, + int32_t aCoreCount) MOZ_OVERRIDE; + virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame, + bool aMissingFrames, + const nsTArray<uint8_t>& aCodecSpecificInfo, + int64_t aRenderTimeMs = -1) MOZ_OVERRIDE; + virtual nsresult Reset() MOZ_OVERRIDE; + virtual nsresult Drain() MOZ_OVERRIDE; + virtual nsresult DecodingComplete() MOZ_OVERRIDE; - // GMPVideoDecoder - virtual GMPVideoErr InitDecode(const GMPVideoCodec& aCodecSettings, - GMPDecoderCallback* aCallback, - int32_t aCoreCount) MOZ_OVERRIDE; - virtual GMPVideoErr Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const GMPCodecSpecificInfo& aCodecSpecificInfo, - int64_t aRenderTimeMs = -1) MOZ_OVERRIDE; - virtual GMPVideoErr Reset() MOZ_OVERRIDE; - virtual GMPVideoErr Drain() MOZ_OVERRIDE; - virtual void DecodingComplete() MOZ_OVERRIDE; + // GMPSharedMemManager + virtual void CheckThread(); + virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) + { +#ifdef GMP_SAFE_SHMEM + return AllocShmem(aSize, aType, aMem); +#else + return AllocUnsafeShmem(aSize, aType, aMem); +#endif + } + virtual void Dealloc(Shmem& aMem) + { + DeallocShmem(aMem); + } private: ~GMPVideoDecoderParent(); // PGMPVideoDecoderParent virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual bool RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame) MOZ_OVERRIDE; virtual bool RecvReceivedDecodedReferenceFrame(const uint64_t& aPictureId) MOZ_OVERRIDE; virtual bool RecvReceivedDecodedFrame(const uint64_t& aPictureId) MOZ_OVERRIDE; virtual bool RecvInputDataExhausted() MOZ_OVERRIDE; + virtual bool RecvDrainComplete() MOZ_OVERRIDE; + virtual bool RecvResetComplete() MOZ_OVERRIDE; + virtual bool RecvParentShmemForPool(Shmem& aEncodedBuffer) MOZ_OVERRIDE; + virtual bool AnswerNeedShmem(const uint32_t& aFrameBufferSize, + Shmem* aMem) MOZ_OVERRIDE; virtual bool Recv__delete__() MOZ_OVERRIDE; bool mCanSendMessages; GMPParent* mPlugin; - GMPDecoderCallback* mCallback; + GMPVideoDecoderCallback* mCallback; GMPVideoHostImpl mVideoHost; }; } // namespace gmp } // namespace mozilla #endif // GMPVideoDecoderParent_h_
new file mode 100644 --- /dev/null +++ b/content/media/gmp/GMPVideoDecoderProxy.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GMPVideoDecoderProxy_h_ +#define GMPVideoDecoderProxy_h_ + +#include "nsTArray.h" +#include "gmp-video-decode.h" +#include "gmp-video-frame-i420.h" +#include "gmp-video-frame-encoded.h" + +// A proxy to GMPVideoDecoder in the child process. +// GMPVideoDecoderParent exposes this to users the GMP. +// This enables Gecko to pass nsTArrays to the child GMP and avoid +// an extra copy when doing so. +class GMPVideoDecoderProxy { +public: + virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings, + const nsTArray<uint8_t>& aCodecSpecific, + GMPVideoDecoderCallback* aCallback, + int32_t aCoreCount) = 0; + virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame, + bool aMissingFrames, + const nsTArray<uint8_t>& aCodecSpecificInfo, + int64_t aRenderTimeMs = -1) = 0; + virtual nsresult Reset() = 0; + virtual nsresult Drain() = 0; + virtual nsresult DecodingComplete() = 0; +}; + +#endif
--- a/content/media/gmp/GMPVideoEncodedFrameImpl.cpp +++ b/content/media/gmp/GMPVideoEncodedFrameImpl.cpp @@ -9,51 +9,59 @@ #include "GMPSharedMemManager.h" namespace mozilla { namespace gmp { GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(GMPVideoHostImpl* aHost) : mEncodedWidth(0), mEncodedHeight(0), - mTimeStamp(0), - mCaptureTime_ms(0), + mTimeStamp(0ll), + mDuration(0ll), mFrameType(kGMPDeltaFrame), mSize(0), mCompleteFrame(false), - mHost(aHost) + mHost(aHost), + mBufferType(GMP_BufferSingle) { MOZ_ASSERT(aHost); aHost->EncodedFrameCreated(this); } GMPVideoEncodedFrameImpl::GMPVideoEncodedFrameImpl(const GMPVideoEncodedFrameData& aFrameData, GMPVideoHostImpl* aHost) : mEncodedWidth(aFrameData.mEncodedWidth()), mEncodedHeight(aFrameData.mEncodedHeight()), - mTimeStamp(aFrameData.mTimeStamp()), - mCaptureTime_ms(aFrameData.mCaptureTime_ms()), + mTimeStamp(aFrameData.mTimestamp()), + mDuration(aFrameData.mDuration()), mFrameType(static_cast<GMPVideoFrameType>(aFrameData.mFrameType())), mSize(aFrameData.mSize()), mCompleteFrame(aFrameData.mCompleteFrame()), mHost(aHost), - mBuffer(aFrameData.mBuffer()) + mBuffer(aFrameData.mBuffer()), + mBufferType(aFrameData.mBufferType()) { MOZ_ASSERT(aHost); aHost->EncodedFrameCreated(this); } GMPVideoEncodedFrameImpl::~GMPVideoEncodedFrameImpl() { DestroyBuffer(); if (mHost) { mHost->EncodedFrameDestroyed(this); } } +const GMPEncryptedBufferData* +GMPVideoEncodedFrameImpl::GetDecryptionData() const +{ + return nullptr; +} + GMPVideoFrameFormat GMPVideoEncodedFrameImpl::GetFrameFormat() { return kGMPEncodedVideoFrame; } void GMPVideoEncodedFrameImpl::DoneWithAPI() @@ -75,79 +83,82 @@ GMPVideoEncodedFrameImpl::ActorDestroyed mHost = nullptr; } bool GMPVideoEncodedFrameImpl::RelinquishFrameData(GMPVideoEncodedFrameData& aFrameData) { aFrameData.mEncodedWidth() = mEncodedWidth; aFrameData.mEncodedHeight() = mEncodedHeight; - aFrameData.mTimeStamp() = mTimeStamp; - aFrameData.mCaptureTime_ms() = mCaptureTime_ms; + aFrameData.mTimestamp() = mTimeStamp; + aFrameData.mDuration() = mDuration; aFrameData.mFrameType() = mFrameType; aFrameData.mSize() = mSize; aFrameData.mCompleteFrame() = mCompleteFrame; aFrameData.mBuffer() = mBuffer; + aFrameData.mBufferType() = mBufferType; // This method is called right before Shmem is sent to another process. // We need to effectively zero out our member copy so that we don't // try to delete Shmem we don't own later. mBuffer = ipc::Shmem(); return true; } void GMPVideoEncodedFrameImpl::DestroyBuffer() { if (mHost && mBuffer.IsWritable()) { - mHost->SharedMemMgr()->MgrDeallocShmem(mBuffer); + mHost->SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData, mBuffer); } mBuffer = ipc::Shmem(); } -GMPVideoErr +GMPErr GMPVideoEncodedFrameImpl::CreateEmptyFrame(uint32_t aSize) { - DestroyBuffer(); - - if (aSize != 0) { - if (!mHost->SharedMemMgr()->MgrAllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC, &mBuffer) || + if (aSize == 0) { + DestroyBuffer(); + } else if (aSize > AllocatedSize()) { + DestroyBuffer(); + if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData, aSize, + ipc::SharedMemory::TYPE_BASIC, &mBuffer) || !Buffer()) { - return GMPVideoAllocErr; + return GMPAllocErr; } } - mSize = aSize; - return GMPVideoNoErr; + return GMPNoErr; } -GMPVideoErr +GMPErr GMPVideoEncodedFrameImpl::CopyFrame(const GMPVideoEncodedFrame& aFrame) { auto& f = static_cast<const GMPVideoEncodedFrameImpl&>(aFrame); if (f.mSize != 0) { - GMPVideoErr err = CreateEmptyFrame(f.mSize); - if (err != GMPVideoNoErr) { + GMPErr err = CreateEmptyFrame(f.mSize); + if (err != GMPNoErr) { return err; } memcpy(Buffer(), f.Buffer(), f.mSize); } mEncodedWidth = f.mEncodedWidth; mEncodedHeight = f.mEncodedHeight; mTimeStamp = f.mTimeStamp; - mCaptureTime_ms = f.mCaptureTime_ms; + mDuration = f.mDuration; mFrameType = f.mFrameType; - mSize = f.mSize; + mSize = f.mSize; // already set... mCompleteFrame = f.mCompleteFrame; + mBufferType = f.mBufferType; // Don't copy host, that should have been set properly on object creation via host. - return GMPVideoNoErr; + return GMPNoErr; } void GMPVideoEncodedFrameImpl::SetEncodedWidth(uint32_t aEncodedWidth) { mEncodedWidth = aEncodedWidth; } @@ -165,37 +176,37 @@ GMPVideoEncodedFrameImpl::SetEncodedHeig uint32_t GMPVideoEncodedFrameImpl::EncodedHeight() { return mEncodedHeight; } void -GMPVideoEncodedFrameImpl::SetTimeStamp(uint32_t aTimeStamp) +GMPVideoEncodedFrameImpl::SetTimeStamp(uint64_t aTimeStamp) { mTimeStamp = aTimeStamp; } -uint32_t +uint64_t GMPVideoEncodedFrameImpl::TimeStamp() { return mTimeStamp; } void -GMPVideoEncodedFrameImpl::SetCaptureTime(int64_t aCaptureTime) +GMPVideoEncodedFrameImpl::SetDuration(uint64_t aDuration) { - mCaptureTime_ms = aCaptureTime; + mDuration = aDuration; } -int64_t -GMPVideoEncodedFrameImpl::CaptureTime() +uint64_t +GMPVideoEncodedFrameImpl::Duration() const { - return mCaptureTime_ms; + return mDuration; } void GMPVideoEncodedFrameImpl::SetFrameType(GMPVideoFrameType aFrameType) { mFrameType = aFrameType; } @@ -212,17 +223,18 @@ GMPVideoEncodedFrameImpl::SetAllocatedSi return; } if (!mHost) { return; } ipc::Shmem new_mem; - if (!mHost->SharedMemMgr()->MgrAllocShmem(aNewSize, ipc::SharedMemory::TYPE_BASIC, &new_mem) || + if (!mHost->SharedMemMgr()->MgrAllocShmem(GMPSharedMemManager::kGMPEncodedData, aNewSize, + ipc::SharedMemory::TYPE_BASIC, &new_mem) || !new_mem.get<uint8_t>()) { return; } if (mBuffer.IsReadable()) { memcpy(new_mem.get<uint8_t>(), Buffer(), mSize); } @@ -277,10 +289,22 @@ GMPVideoEncodedFrameImpl::Buffer() } void GMPVideoEncodedFrameImpl::Destroy() { delete this; } +GMPBufferType +GMPVideoEncodedFrameImpl::BufferType() const +{ + return mBufferType; +} + +void +GMPVideoEncodedFrameImpl::SetBufferType(GMPBufferType aBufferType) +{ + mBufferType = aBufferType; +} + } // namespace gmp } // namespace mozilla
--- a/content/media/gmp/GMPVideoEncodedFrameImpl.h +++ b/content/media/gmp/GMPVideoEncodedFrameImpl.h @@ -26,19 +26,20 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GMPVideoEncodedFrameImpl_h_ #define GMPVideoEncodedFrameImpl_h_ -#include "gmp-video-errors.h" +#include "gmp-errors.h" #include "gmp-video-frame.h" #include "gmp-video-frame-encoded.h" +#include "gmp-decryption.h" #include "mozilla/ipc/Shmem.h" namespace mozilla { namespace gmp { class GMPVideoHostImpl; class GMPVideoEncodedFrameData; @@ -58,47 +59,56 @@ public: bool RelinquishFrameData(GMPVideoEncodedFrameData& aFrameData); // GMPVideoFrame virtual GMPVideoFrameFormat GetFrameFormat() MOZ_OVERRIDE; virtual void Destroy() MOZ_OVERRIDE; // GMPVideoEncodedFrame - virtual GMPVideoErr CreateEmptyFrame(uint32_t aSize) MOZ_OVERRIDE; - virtual GMPVideoErr CopyFrame(const GMPVideoEncodedFrame& aFrame) MOZ_OVERRIDE; + virtual GMPErr CreateEmptyFrame(uint32_t aSize) MOZ_OVERRIDE; + virtual GMPErr CopyFrame(const GMPVideoEncodedFrame& aFrame) MOZ_OVERRIDE; virtual void SetEncodedWidth(uint32_t aEncodedWidth) MOZ_OVERRIDE; virtual uint32_t EncodedWidth() MOZ_OVERRIDE; virtual void SetEncodedHeight(uint32_t aEncodedHeight) MOZ_OVERRIDE; virtual uint32_t EncodedHeight() MOZ_OVERRIDE; - virtual void SetTimeStamp(uint32_t aTimeStamp) MOZ_OVERRIDE; - virtual uint32_t TimeStamp() MOZ_OVERRIDE; - virtual void SetCaptureTime(int64_t aCaptureTime) MOZ_OVERRIDE; - virtual int64_t CaptureTime() MOZ_OVERRIDE; + // Microseconds + virtual void SetTimeStamp(uint64_t aTimeStamp) MOZ_OVERRIDE; + virtual uint64_t TimeStamp() MOZ_OVERRIDE; + // Set frame duration (microseconds) + // NOTE: next-frame's Timestamp() != this-frame's TimeStamp()+Duration() + // depending on rounding to avoid having to track roundoff errors + // and dropped/missing frames(!) (which may leave a large gap) + virtual void SetDuration(uint64_t aDuration) MOZ_OVERRIDE; + virtual uint64_t Duration() const MOZ_OVERRIDE; virtual void SetFrameType(GMPVideoFrameType aFrameType) MOZ_OVERRIDE; virtual GMPVideoFrameType FrameType() MOZ_OVERRIDE; virtual void SetAllocatedSize(uint32_t aNewSize) MOZ_OVERRIDE; virtual uint32_t AllocatedSize() MOZ_OVERRIDE; virtual void SetSize(uint32_t aSize) MOZ_OVERRIDE; virtual uint32_t Size() MOZ_OVERRIDE; virtual void SetCompleteFrame(bool aCompleteFrame) MOZ_OVERRIDE; virtual bool CompleteFrame() MOZ_OVERRIDE; virtual const uint8_t* Buffer() const MOZ_OVERRIDE; virtual uint8_t* Buffer() MOZ_OVERRIDE; + virtual GMPBufferType BufferType() const MOZ_OVERRIDE; + virtual void SetBufferType(GMPBufferType aBufferType) MOZ_OVERRIDE; + virtual const GMPEncryptedBufferData* GetDecryptionData() const MOZ_OVERRIDE; private: void DestroyBuffer(); uint32_t mEncodedWidth; uint32_t mEncodedHeight; - uint32_t mTimeStamp; - int64_t mCaptureTime_ms; + uint64_t mTimeStamp; + uint64_t mDuration; GMPVideoFrameType mFrameType; uint32_t mSize; bool mCompleteFrame; GMPVideoHostImpl* mHost; ipc::Shmem mBuffer; + GMPBufferType mBufferType; }; } // namespace gmp } // namespace mozilla #endif // GMPVideoEncodedFrameImpl_h_
--- a/content/media/gmp/GMPVideoEncoderChild.cpp +++ b/content/media/gmp/GMPVideoEncoderChild.cpp @@ -35,82 +35,88 @@ GMPVideoEncoderChild::Init(GMPVideoEncod GMPVideoHostImpl& GMPVideoEncoderChild::Host() { return mVideoHost; } void GMPVideoEncoderChild::Encoded(GMPVideoEncodedFrame* aEncodedFrame, - const GMPCodecSpecificInfo& aCodecSpecificInfo) + const uint8_t* aCodecSpecificInfo, + uint32_t aCodecSpecificInfoLength) { MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); auto ef = static_cast<GMPVideoEncodedFrameImpl*>(aEncodedFrame); GMPVideoEncodedFrameData frameData; ef->RelinquishFrameData(frameData); - SendEncoded(frameData, aCodecSpecificInfo); + nsTArray<uint8_t> codecSpecific; + codecSpecific.AppendElements(aCodecSpecificInfo, aCodecSpecificInfoLength); + SendEncoded(frameData, codecSpecific); aEncodedFrame->Destroy(); } -bool -GMPVideoEncoderChild::MgrAllocShmem(size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) +void +GMPVideoEncoderChild::CheckThread() { MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - return AllocShmem(aSize, aType, aMem); -} - -bool -GMPVideoEncoderChild::MgrDeallocShmem(Shmem& aMem) -{ - MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); - - return DeallocShmem(aMem); } bool GMPVideoEncoderChild::RecvInitEncode(const GMPVideoCodec& aCodecSettings, + const nsTArray<uint8_t>& aCodecSpecific, const int32_t& aNumberOfCores, const uint32_t& aMaxPayloadSize) { if (!mVideoEncoder) { return false; } // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->InitEncode(aCodecSettings, this, aNumberOfCores, aMaxPayloadSize); + mVideoEncoder->InitEncode(aCodecSettings, + aCodecSpecific.Elements(), + aCodecSpecific.Length(), + this, + aNumberOfCores, + aMaxPayloadSize); return true; } bool GMPVideoEncoderChild::RecvEncode(const GMPVideoi420FrameData& aInputFrame, - const GMPCodecSpecificInfo& aCodecSpecificInfo, - const InfallibleTArray<int>& aFrameTypes) + const nsTArray<uint8_t>& aCodecSpecificInfo, + const nsTArray<GMPVideoFrameType>& aFrameTypes) { if (!mVideoEncoder) { return false; } auto f = new GMPVideoi420FrameImpl(aInputFrame, &mVideoHost); - std::vector<GMPVideoFrameType> frameTypes(aFrameTypes.Length()); - for (uint32_t i = 0; i < aFrameTypes.Length(); i++) { - frameTypes[i] = static_cast<GMPVideoFrameType>(aFrameTypes[i]); + // Ignore any return code. It is OK for this to fail without killing the process. + mVideoEncoder->Encode(f, + aCodecSpecificInfo.Elements(), + aCodecSpecificInfo.Length(), + aFrameTypes.Elements(), + aFrameTypes.Length()); + + return true; +} + +bool +GMPVideoEncoderChild::RecvChildShmemForPool(Shmem& aEncodedBuffer) +{ + if (aEncodedBuffer.IsWritable()) { + mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMemManager::kGMPEncodedData, + aEncodedBuffer); } - - // Ignore any return code. It is OK for this to fail without killing the process. - mVideoEncoder->Encode(f, aCodecSpecificInfo, frameTypes); - return true; } bool GMPVideoEncoderChild::RecvSetChannelParameters(const uint32_t& aPacketLoss, const uint32_t& aRTT) { if (!mVideoEncoder) {
--- a/content/media/gmp/GMPVideoEncoderChild.h +++ b/content/media/gmp/GMPVideoEncoderChild.h @@ -13,44 +13,64 @@ #include "GMPVideoHost.h" namespace mozilla { namespace gmp { class GMPChild; class GMPVideoEncoderChild : public PGMPVideoEncoderChild, - public GMPEncoderCallback, + public GMPVideoEncoderCallback, public GMPSharedMemManager { public: GMPVideoEncoderChild(GMPChild* aPlugin); virtual ~GMPVideoEncoderChild(); void Init(GMPVideoEncoder* aEncoder); GMPVideoHostImpl& Host(); - // GMPEncoderCallback + // GMPVideoEncoderCallback virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame, - const GMPCodecSpecificInfo& aCodecSpecificInfo) MOZ_OVERRIDE; + const uint8_t* aCodecSpecificInfo, + uint32_t aCodecSpecificInfoLength) MOZ_OVERRIDE; // GMPSharedMemManager - virtual bool MgrAllocShmem(size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) MOZ_OVERRIDE; - virtual bool MgrDeallocShmem(Shmem& aMem) MOZ_OVERRIDE; + virtual void CheckThread(); + virtual bool Alloc(size_t aSize, Shmem::SharedMemory::SharedMemoryType aType, Shmem* aMem) + { +#ifndef SHMEM_ALLOC_IN_CHILD + return CallNeedShmem(aSize, aMem); +#else +#ifdef GMP_SAFE_SHMEM + return AllocShmem(aSize, aType, aMem); +#else + return AllocUnsafeShmem(aSize, aType, aMem); +#endif +#endif + } + virtual void Dealloc(Shmem& aMem) + { +#ifndef SHMEM_ALLOC_IN_CHILD + SendParentShmemForPool(aMem); +#else + DeallocShmem(aMem); +#endif + } private: // PGMPVideoEncoderChild virtual bool RecvInitEncode(const GMPVideoCodec& aCodecSettings, + const nsTArray<uint8_t>& aCodecSpecific, const int32_t& aNumberOfCores, const uint32_t& aMaxPayloadSize) MOZ_OVERRIDE; virtual bool RecvEncode(const GMPVideoi420FrameData& aInputFrame, - const GMPCodecSpecificInfo& aCodecSpecificInfo, - const InfallibleTArray<int>& aFrameTypes) MOZ_OVERRIDE; + const nsTArray<uint8_t>& aCodecSpecificInfo, + const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE; + virtual bool RecvChildShmemForPool(Shmem& aEncodedBuffer) MOZ_OVERRIDE; virtual bool RecvSetChannelParameters(const uint32_t& aPacketLoss, const uint32_t& aRTT) MOZ_OVERRIDE; virtual bool RecvSetRates(const uint32_t& aNewBitRate, const uint32_t& aFrameRate) MOZ_OVERRIDE; virtual bool RecvSetPeriodicKeyFrames(const bool& aEnable) MOZ_OVERRIDE; virtual bool RecvEncodingComplete() MOZ_OVERRIDE; GMPChild* mPlugin;
--- a/content/media/gmp/GMPVideoEncoderParent.cpp +++ b/content/media/gmp/GMPVideoEncoderParent.cpp @@ -38,147 +38,132 @@ GMPVideoEncoderParent::~GMPVideoEncoderP } GMPVideoHostImpl& GMPVideoEncoderParent::Host() { return mVideoHost; } -bool -GMPVideoEncoderParent::MgrAllocShmem(size_t aSize, - ipc::Shmem::SharedMemory::SharedMemoryType aType, - ipc::Shmem* aMem) -{ - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - return AllocShmem(aSize, aType, aMem); -} - -bool -GMPVideoEncoderParent::MgrDeallocShmem(Shmem& aMem) -{ - MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); - - return DeallocShmem(aMem); -} - -GMPVideoErr +GMPErr GMPVideoEncoderParent::InitEncode(const GMPVideoCodec& aCodecSettings, - GMPEncoderCallback* aCallback, + const nsTArray<uint8_t>& aCodecSpecific, + GMPVideoEncoderCallbackProxy* aCallback, int32_t aNumberOfCores, uint32_t aMaxPayloadSize) { if (!mCanSendMessages) { NS_WARNING("Trying to use an invalid GMP video encoder!"); - return GMPVideoGenericErr; + return GMPGenericErr; } MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); if (!aCallback) { - return GMPVideoGenericErr; + return GMPGenericErr; } mCallback = aCallback; - if (!SendInitEncode(aCodecSettings, aNumberOfCores, aMaxPayloadSize)) { - return GMPVideoGenericErr; + if (!SendInitEncode(aCodecSettings, aCodecSpecific, aNumberOfCores, aMaxPayloadSize)) { + return GMPGenericErr; } // Async IPC, we don't have access to a return value. - return GMPVideoNoErr; + return GMPNoErr; } -GMPVideoErr +GMPErr GMPVideoEncoderParent::Encode(GMPVideoi420Frame* aInputFrame, - const GMPCodecSpecificInfo& aCodecSpecificInfo, - const std::vector<GMPVideoFrameType>& aFrameTypes) + const nsTArray<uint8_t>& aCodecSpecificInfo, + const nsTArray<GMPVideoFrameType>& aFrameTypes) { nsAutoRef<GMPVideoi420Frame> frameRef(aInputFrame); if (!mCanSendMessages) { NS_WARNING("Trying to use an invalid GMP video encoder!"); - return GMPVideoGenericErr; + return GMPGenericErr; } <