зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
b63d7b04fc
5
CLOBBER
5
CLOBBER
|
@ -22,7 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1108782 - Follow-up: clobber. r=me
|
||||
|
||||
There's all kinds fail waiting at the end of these dependency changes.
|
||||
Definitely clobber needed!
|
||||
Bug 1205242 - Changed toolchain, needs clobber
|
||||
|
|
|
@ -2071,6 +2071,10 @@ DocAccessible::ValidateARIAOwned()
|
|||
nsIContent* childEl = childEls->ElementAt(idx);
|
||||
Accessible* child = GetAccessible(childEl);
|
||||
if (child && child->IsInDocument() && !child->GetFrame()) {
|
||||
if (!child->Parent()) {
|
||||
NS_ERROR("An element in the document doesn't have a parent?");
|
||||
continue;
|
||||
}
|
||||
UpdateTreeOnRemoval(child->Parent(), childEl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@ child:
|
|||
prio(high) sync MaxValue(uint64_t aID) returns(double aValue);
|
||||
prio(high) sync Step(uint64_t aID) returns(double aStep);
|
||||
|
||||
prio(high) sync TakeFocus(uint64_t aID);
|
||||
async TakeFocus(uint64_t aID);
|
||||
prio(high) sync EmbeddedChildCount(uint64_t aID) returns(uint32_t aCount);
|
||||
prio(high) sync IndexOfEmbeddedChild(uint64_t aID, uint64_t aChildID)
|
||||
returns(uint32_t childIdx);
|
||||
|
|
|
@ -1872,6 +1872,9 @@ pref("privacy.trackingprotection.ui.enabled", false);
|
|||
pref("privacy.trackingprotection.introCount", 0);
|
||||
pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tracking-protection/start/");
|
||||
|
||||
// Enable Contextual Identity Containers
|
||||
pref("privacy.userContext.enabled", false);
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
// At the moment, autostart.2 is used, while autostart.1 is unused.
|
||||
// We leave it here set to false to reset users' defaults and allow
|
||||
|
|
|
@ -11,12 +11,44 @@
|
|||
style="border:0px;padding:0px;margin:0px;-moz-appearance:none">
|
||||
<menu id="file-menu" label="&fileMenu.label;"
|
||||
accesskey="&fileMenu.accesskey;">
|
||||
<menupopup id="menu_FilePopup">
|
||||
<menupopup id="menu_FilePopup"
|
||||
onpopupshowing="updateUserContextUIVisibility();">
|
||||
<menuitem id="menu_newNavigatorTab"
|
||||
label="&tabCmd.label;"
|
||||
command="cmd_newNavigatorTab"
|
||||
key="key_newNavigatorTab"
|
||||
accesskey="&tabCmd.accesskey;"/>
|
||||
<menu id="menu_newUserContext"
|
||||
label="&newUserContext.label;"
|
||||
accesskey="&newUserContext.accesskey;"
|
||||
hidden="true">
|
||||
<menupopup>
|
||||
<menuitem id="menu_newUserContextTabPersonal"
|
||||
usercontextid="1"
|
||||
class="menuitem-iconic"
|
||||
label="&userContextPersonal.label;"
|
||||
command="Browser:NewUserContextTab"
|
||||
accesskey="&userContextPersonal.accesskey;"/>
|
||||
<menuitem id="menu_newUserContextTabWork"
|
||||
usercontextid="2"
|
||||
class="menuitem-iconic"
|
||||
label="&userContextWork.label;"
|
||||
command="Browser:NewUserContextTab"
|
||||
accesskey="&userContextWork.accesskey;"/>
|
||||
<menuitem id="menu_newUserContextTabBanking"
|
||||
usercontextid="3"
|
||||
class="menuitem-iconic"
|
||||
label="&userContextBanking.label;"
|
||||
command="Browser:NewUserContextTab"
|
||||
accesskey="&userContextBanking.accesskey;"/>
|
||||
<menuitem id="menu_newUserContextTabShopping"
|
||||
usercontextid="4"
|
||||
class="menuitem-iconic"
|
||||
label="&userContextShopping.label;"
|
||||
command="Browser:NewUserContextTab"
|
||||
accesskey="&userContextShopping.accesskey;"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem id="menu_newNavigator"
|
||||
label="&newNavigatorCmd.label;"
|
||||
accesskey="&newNavigatorCmd.accesskey;"
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
<command id="cmd_gestureRotateEnd" oncommand="gGestureSupport.rotateEnd()"/>
|
||||
<command id="Browser:OpenLocation" oncommand="openLocation();"/>
|
||||
<command id="Browser:RestoreLastSession" oncommand="restoreLastSession();" disabled="true"/>
|
||||
<command id="Browser:NewUserContextTab" oncommand="openNewUserContextTab(event.sourceEvent);" reserved="true"/>
|
||||
|
||||
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
|
||||
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
|
||||
|
|
|
@ -4060,6 +4060,31 @@ function updateEditUIVisibility()
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new tab with the userContextId specified as an attribute of
|
||||
* sourceEvent. This attribute is propagated to the top level originAttributes
|
||||
* living on the tab's docShell.
|
||||
*
|
||||
* @param event
|
||||
* A click event on a userContext File Menu option
|
||||
*/
|
||||
function openNewUserContextTab(event)
|
||||
{
|
||||
openUILinkIn(BROWSER_NEW_TAB_URL, "tab", {
|
||||
userContextId: event.target.getAttribute('usercontextid'),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates File Menu User Context UI visibility depending on
|
||||
* privacy.userContext.enabled pref state.
|
||||
*/
|
||||
function updateUserContextUIVisibility()
|
||||
{
|
||||
let userContextEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
|
||||
document.getElementById("menu_newUserContext").hidden = !userContextEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the Character Encoding menu enabled or disabled as appropriate.
|
||||
* To be called when the View menu or the app menu is opened.
|
||||
|
|
|
@ -1415,6 +1415,7 @@
|
|||
var aSkipAnimation;
|
||||
var aForceNotRemote;
|
||||
var aNoReferrer;
|
||||
var aUserContextId;
|
||||
if (arguments.length == 2 &&
|
||||
typeof arguments[1] == "object" &&
|
||||
!(arguments[1] instanceof Ci.nsIURI)) {
|
||||
|
@ -1431,6 +1432,7 @@
|
|||
aSkipAnimation = params.skipAnimation;
|
||||
aForceNotRemote = params.forceNotRemote;
|
||||
aNoReferrer = params.noReferrer;
|
||||
aUserContextId = params.userContextId;
|
||||
}
|
||||
|
||||
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
|
||||
|
@ -1448,7 +1450,8 @@
|
|||
skipAnimation: aSkipAnimation,
|
||||
allowMixedContent: aAllowMixedContent,
|
||||
forceNotRemote: aForceNotRemote,
|
||||
noReferrer: aNoReferrer });
|
||||
noReferrer: aNoReferrer,
|
||||
userContextId: aUserContextId });
|
||||
if (!bgLoad)
|
||||
this.selectedTab = tab;
|
||||
|
||||
|
@ -1690,6 +1693,7 @@
|
|||
let remote = aParams && aParams.remote;
|
||||
let uriIsAboutBlank = aParams && aParams.uriIsAboutBlank;
|
||||
let isPreloadBrowser = aParams && aParams.isPreloadBrowser;
|
||||
let userContextId = aParams && aParams.userContextId;
|
||||
|
||||
let b = document.createElementNS(NS_XUL, "browser");
|
||||
b.permanentKey = {};
|
||||
|
@ -1699,6 +1703,9 @@
|
|||
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
|
||||
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
|
||||
|
||||
if (userContextId)
|
||||
b.setAttribute("usercontextid", userContextId);
|
||||
|
||||
if (remote)
|
||||
b.setAttribute("remote", "true");
|
||||
|
||||
|
@ -1767,6 +1774,7 @@
|
|||
var aAllowMixedContent;
|
||||
var aForceNotRemote;
|
||||
var aNoReferrer;
|
||||
var aUserContextId;
|
||||
if (arguments.length == 2 &&
|
||||
typeof arguments[1] == "object" &&
|
||||
!(arguments[1] instanceof Ci.nsIURI)) {
|
||||
|
@ -1783,6 +1791,7 @@
|
|||
aAllowMixedContent = params.allowMixedContent;
|
||||
aForceNotRemote = params.forceNotRemote;
|
||||
aNoReferrer = params.noReferrer;
|
||||
aUserContextId = params.userContextId;
|
||||
}
|
||||
|
||||
// if we're adding tabs, we're past interrupt mode, ditch the owner
|
||||
|
@ -1831,16 +1840,18 @@
|
|||
let b;
|
||||
let usingPreloadedContent = false;
|
||||
|
||||
// If we open a new tab with the newtab URL,
|
||||
// check if there is a preloaded browser ready.
|
||||
if (aURI == BROWSER_NEW_TAB_URL) {
|
||||
// If we open a new tab with the newtab URL in the default
|
||||
// userContext, check if there is a preloaded browser ready.
|
||||
if (aURI == BROWSER_NEW_TAB_URL && !aUserContextId) {
|
||||
b = this._getPreloadedBrowser();
|
||||
usingPreloadedContent = !!b;
|
||||
}
|
||||
|
||||
if (!b) {
|
||||
// No preloaded browser found, create one.
|
||||
b = this._createBrowser({remote, uriIsAboutBlank});
|
||||
b = this._createBrowser({remote: remote,
|
||||
uriIsAboutBlank: uriIsAboutBlank,
|
||||
userContextId: aUserContextId});
|
||||
}
|
||||
|
||||
let notificationbox = this.getNotificationBox(b);
|
||||
|
@ -2486,6 +2497,11 @@
|
|||
if (ourBrowser.isRemoteBrowser != otherBrowser.isRemoteBrowser)
|
||||
return;
|
||||
|
||||
// Keep the userContextId if set on other browser
|
||||
if (otherBrowser.hasAttribute("usercontextid")) {
|
||||
ourBrowser.setAttribute("usercontextid", otherBrowser.getAttribute("usercontextid"));
|
||||
}
|
||||
|
||||
// That's gBrowser for the other window, not the tab's browser!
|
||||
var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser;
|
||||
var isPending = aOtherTab.hasAttribute("pending");
|
||||
|
|
|
@ -18,6 +18,7 @@ function onTabModalDialogLoaded(node) {
|
|||
}
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
// Listen for the dialog being created
|
||||
Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
const TEST_PAGE = "http://mochi.test:8888/browser/browser/base/content/test/general/file_double_close_tab.html";
|
||||
var testTab;
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
function waitForDialog(callback) {
|
||||
function onTabModalDialogLoaded(node) {
|
||||
Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
const FIRST_TAB = getRootDirectory(gTestPath) + "close_beforeunload_opens_second_tab.html";
|
||||
const SECOND_TAB = getRootDirectory(gTestPath) + "close_beforeunload.html";
|
||||
|
||||
|
|
|
@ -173,6 +173,7 @@ function whereToOpenLink( e, ignoreButton, ignoreAlt )
|
|||
* skipTabAnimation (boolean)
|
||||
* allowPinnedTabHostChange (boolean)
|
||||
* allowPopups (boolean)
|
||||
* userContextId (unsigned int)
|
||||
*/
|
||||
function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
|
||||
var params;
|
||||
|
@ -216,6 +217,7 @@ function openLinkIn(url, where, params) {
|
|||
var aAllowPinnedTabHostChange = !!params.allowPinnedTabHostChange;
|
||||
var aNoReferrer = params.noReferrer;
|
||||
var aAllowPopups = !!params.allowPopups;
|
||||
var aUserContextId = params.userContextId;
|
||||
|
||||
if (where == "save") {
|
||||
if (!aInitiatingDoc) {
|
||||
|
@ -357,7 +359,8 @@ function openLinkIn(url, where, params) {
|
|||
relatedToCurrent: aRelatedToCurrent,
|
||||
skipAnimation: aSkipTabAnimation,
|
||||
allowMixedContent: aAllowMixedContent,
|
||||
noReferrer: aNoReferrer
|
||||
noReferrer: aNoReferrer,
|
||||
userContextId: aUserContextId
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
|
||||
'function(e){e.returnValue="?"}</script>';
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
showTabView(onTabViewShown);
|
||||
|
|
|
@ -15,6 +15,8 @@ const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
|
|||
var contentWindow;
|
||||
var activeGroup;
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
Components.utils.import("resource://gre/modules/Promise.jsm", this);
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r241406"
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 100307285,
|
||||
"digest": "4d147d0072a928945fc1e938f39a5d0a9d3c676399c09e092c8750b2f973cdbbebda8d94d4d05805fae74a5c49c54263dc22b8b443c23c9a0ae830a261d3cf30",
|
||||
"size": 93197192,
|
||||
"digest": "6ebd8994ac76cf6694c3d9054104219836f47578223c799cb9ba9669cfdee00112e9de56aea9d1e6d9d50ee94a201970555de19794b5fbb7546f58fdf8e59a99",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r241406"
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 83297360,
|
||||
"digest": "18e3deaf608b58a9153d647e1acbe6e93b7d6461bd4f86f24d13f4b6818b048a65063200d7acb100fa41eb5a7e66dfe6bdc89770c15c87e32a3e9a50d97094c6",
|
||||
"size": 93197192,
|
||||
"digest": "6ebd8994ac76cf6694c3d9054104219836f47578223c799cb9ba9669cfdee00112e9de56aea9d1e6d9d50ee94a201970555de19794b5fbb7546f58fdf8e59a99",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r241406"
|
||||
},
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 83297360,
|
||||
"digest": "18e3deaf608b58a9153d647e1acbe6e93b7d6461bd4f86f24d13f4b6818b048a65063200d7acb100fa41eb5a7e66dfe6bdc89770c15c87e32a3e9a50d97094c6",
|
||||
"size": 93197192,
|
||||
"digest": "6ebd8994ac76cf6694c3d9054104219836f47578223c799cb9ba9669cfdee00112e9de56aea9d1e6d9d50ee94a201970555de19794b5fbb7546f58fdf8e59a99",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r241406"
|
||||
},
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 86465808,
|
||||
"digest": "947eaaf11ac8cbe12e11b48c8b052721e018d31fb8ce20f8bf14b117b6623c56513b1422d8d9c8011bc0b0b985ef74d8f181e7200c6d7a05d79a1bce0d75ddee",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"size": 97314461,
|
||||
"digest": "9a74670fa917f760a4767923485d5166bbd258a8023c8aeb899b8c4d22f2847be76508ac5f26d7d2193318a2bb368a71bc62888d1bfe9d81eb45329a60451aa4",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
[
|
||||
{
|
||||
"clang_version": "r241406"
|
||||
"clang_version": "r247539"
|
||||
},
|
||||
{
|
||||
"size": 100307285,
|
||||
"digest": "4d147d0072a928945fc1e938f39a5d0a9d3c676399c09e092c8750b2f973cdbbebda8d94d4d05805fae74a5c49c54263dc22b8b443c23c9a0ae830a261d3cf30",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 80458572,
|
||||
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gcc.tar.xz",
|
||||
"size": 93197192,
|
||||
"digest": "6ebd8994ac76cf6694c3d9054104219836f47578223c799cb9ba9669cfdee00112e9de56aea9d1e6d9d50ee94a201970555de19794b5fbb7546f58fdf8e59a99",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
|
|
|
@ -308,6 +308,16 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
|
||||
<!ENTITY fileMenu.label "File">
|
||||
<!ENTITY fileMenu.accesskey "F">
|
||||
<!ENTITY newUserContext.label "New Container Tab">
|
||||
<!ENTITY newUserContext.accesskey "C">
|
||||
<!ENTITY userContextPersonal.label "Personal">
|
||||
<!ENTITY userContextPersonal.accesskey "P">
|
||||
<!ENTITY userContextWork.label "Work">
|
||||
<!ENTITY userContextWork.accesskey "W">
|
||||
<!ENTITY userContextBanking.label "Banking">
|
||||
<!ENTITY userContextBanking.accesskey "B">
|
||||
<!ENTITY userContextShopping.label "Shopping">
|
||||
<!ENTITY userContextShopping.accesskey "S">
|
||||
<!ENTITY newNavigatorCmd.label "New Window">
|
||||
<!ENTITY newNavigatorCmd.key "N">
|
||||
<!ENTITY newNavigatorCmd.accesskey "N">
|
||||
|
|
|
@ -152,8 +152,15 @@
|
|||
locale/browser/syncQuota.properties (%chrome/browser/syncQuota.properties)
|
||||
#endif
|
||||
% resource search-plugins chrome://browser/locale/searchplugins/
|
||||
# little trick to make the test below work
|
||||
#define en_US en-US
|
||||
#if AB_CD == en_US
|
||||
locale/browser/searchplugins/list.txt (%searchplugins/list.txt)
|
||||
locale/browser/searchplugins/ (%searchplugins/*.xml)
|
||||
#else
|
||||
locale/browser/searchplugins/list.txt (.deps/generated_@AB_CD@/list.txt)
|
||||
locale/browser/searchplugins/ (.deps/generated_@AB_CD@/*.xml)
|
||||
#endif
|
||||
% locale browser-region @AB_CD@ %locale/browser-region/
|
||||
locale/browser-region/region.properties (%chrome/browser-region/region.properties)
|
||||
# the following files are browser-specific overrides
|
||||
|
|
|
@ -166,7 +166,7 @@ PluginContent.prototype = {
|
|||
pluginName = BrowserUtils.makeNicePluginName(pluginTag.name);
|
||||
|
||||
// Convert this from nsIPluginTag so it can be serialized.
|
||||
let properties = ["name", "description", "filename", "version", "enabledState"];
|
||||
let properties = ["name", "description", "filename", "version", "enabledState", "niceName"];
|
||||
let pluginTagCopy = {};
|
||||
for (let prop of properties) {
|
||||
pluginTagCopy[prop] = pluginTag[prop];
|
||||
|
@ -422,6 +422,7 @@ PluginContent.prototype = {
|
|||
break;
|
||||
|
||||
case "PluginInstantiated":
|
||||
Services.telemetry.getKeyedHistogramById('PLUGIN_ACTIVATION_COUNT').add(this._getPluginInfo(plugin).pluginTag.niceName);
|
||||
shouldShowNotification = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1969,3 +1969,5 @@ chatbox {
|
|||
.browser-action-panel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
%include ../shared/usercontext/usercontext.inc.css
|
||||
|
|
|
@ -142,6 +142,10 @@ browser.jar:
|
|||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
|
||||
skin/classic/browser/usercontext/personal.svg (../shared/usercontext/personal.svg)
|
||||
skin/classic/browser/usercontext/work.svg (../shared/usercontext/work.svg)
|
||||
skin/classic/browser/usercontext/banking.svg (../shared/usercontext/banking.svg)
|
||||
skin/classic/browser/usercontext/shopping.svg (../shared/usercontext/shopping.svg)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
|
|
|
@ -3655,3 +3655,5 @@ window > chatbox {
|
|||
.browser-action-panel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
%include ../shared/usercontext/usercontext.inc.css
|
||||
|
|
|
@ -229,6 +229,10 @@ browser.jar:
|
|||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
|
||||
skin/classic/browser/usercontext/personal.svg (../shared/usercontext/personal.svg)
|
||||
skin/classic/browser/usercontext/work.svg (../shared/usercontext/work.svg)
|
||||
skin/classic/browser/usercontext/banking.svg (../shared/usercontext/banking.svg)
|
||||
skin/classic/browser/usercontext/shopping.svg (../shared/usercontext/shopping.svg)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#7dc14c" d="M17.3857868,14.0527919 C14.2304569,13.0862944 13.4913706,12.4609137 13.4913706,11.0964467 C13.4913706,9.61827411 14.7137056,8.85076142 16.4192893,8.85076142 C17.9827411,8.85076142 19.3187817,9.33401015 20.5979695,10.4994924 L22.4456853,8.42436548 C21.1664975,7.20203046 19.3187819,6.26535905 17,6.00952148 L17,2 L15,2 L15,6.00952148 C12.3827412,6.43591742 9.76751269,8.53807107 9.76751269,11.3238579 C9.76751269,14.1664975 11.4730964,15.786802 15.4812183,17.0091371 C18.4375635,17.9187817 19.2335025,18.6294416 19.2335025,20.2213198 C19.2335025,22.0690355 17.7553299,23.035533 15.7370558,23.035533 C13.7756345,23.035533 12.2406091,22.3248731 10.9329949,21.1025381 L9,23.2345178 C10.4213198,24.6274112 12.8659899,25.8324934 15,26.0030518 L15,30 L17,30 L17,26.0030518 C20.7116753,25.4060974 22.9857868,22.893401 22.9857868,20.022335 C22.9857868,16.4690355 20.7116751,15.1045685 17.3857868,14.0527919 Z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#00a7e0" d="M7.17741905,12 C7.10965537,12 7.041327,11.9953181 6.97243393,11.985018 C6.33263187,11.8918489 5.90515601,11.3862071 6.01809547,10.8552833 C7.41798011,4.26321358 12.2613889,2.57493207 15.0238882,2.15590491 C19.6448063,1.45690206 24.3408291,3.21541158 25.8344535,5.29743816 C26.1664955,5.76047488 25.9835336,6.35881757 25.4244832,6.63364321 C24.8654329,6.9098734 24.1437497,6.75583996 23.8122724,6.29327142 C22.8923805,5.01043967 19.1749781,3.51130562 15.4479759,4.07406612 C12.8080159,4.474834 9.43056132,6.03623689 8.33561323,11.1942506 C8.23453242,11.666651 7.73816348,12 7.17741905,12 Z M16.63127,26 C16.1452186,26 15.6509104,25.9658335 15.147795,25.8938767 C10.637921,25.257137 6.71207921,21.8114952 6.01575422,17.8807924 C5.91171832,17.2932317 6.33391695,16.7382846 6.95813239,16.6404441 C7.58454965,16.5343208 8.17298555,16.9406954 8.27757192,17.5272206 C8.80876054,20.5255916 11.9766264,23.26409 15.4885263,23.7610576 C17.3975027,24.02766 20.959494,23.8221432 23.3220449,19.3789425 C24.4625867,17.2331815 23.0049831,11.881462 19.9521622,9.34692739 C18.2380468,7.92384005 16.4573263,7.76905536 14.6628445,8.89499751 C13.26469,9.77142052 11.8070864,12.2857658 11.8665355,14.6287608 C11.9127737,16.4835887 12.8386382,17.9325598 14.6171568,18.9363308 C15.2210054,19.2764429 16.9411759,19.4933486 17.9424527,18.8296898 C18.7257495,18.3104622 18.9591422,17.2761485 18.6365758,15.7583267 C18.3822659,14.5650869 17.2219077,12.4452096 16.6664991,12.3711821 C16.6692513,12.3722175 16.4666841,12.4312324 16.1276041,12.9095636 C15.8545786,13.2936782 15.58981,14.7297074 15.9476054,15.3581643 C16.0142104,15.4761941 16.0725586,15.5465978 16.3202632,15.5465978 C16.9532859,15.5465978 17.46686,16.0290705 17.46686,16.6249139 C17.46686,17.2207573 16.9543868,17.7042653 16.3213641,17.7042653 C15.2644914,17.7042653 14.4140391,17.2336992 13.9268868,16.3774655 C13.1083609,14.9388479 13.5536787,12.6548678 14.2202791,11.7137354 C15.2540327,10.2564816 16.3631986,10.1151564 17.1123672,10.2564816 C19.7066595,10.7389543 20.8763754,15.2908666 20.8857331,15.3359043 C21.5303153,18.3648181 20.3594985,19.8665919 19.264094,20.593407 C17.4151172,21.8192603 14.6920186,21.493643 13.4380832,20.7859819 C10.3280151,19.0310652 9.62013053,16.497566 9.5744428,14.6805283 C9.49022326,11.3643051 11.4779146,8.30018945 13.391845,7.10021984 C16.0417332,5.43848454 18.9877658,5.66781436 21.4714167,7.72919442 C25.1176276,10.7565552 27.0871539,17.1229168 25.3746898,20.3433702 C23.4326862,23.9950465 20.2983981,26 16.63127,26 Z M16.0845157,30 C14.9348455,30 13.9050564,29.8557557 13.0394288,29.6610017 C10.2114238,29.0257442 7.58700058,27.4599412 6.18892823,25.5735955 C5.84440518,25.1078371 5.98426642,24.4803503 6.50105099,24.1700066 C7.01675554,23.8596629 7.71552172,23.986423 8.06112477,24.4507244 C9.89498097,26.9252176 15.9397944,29.9781448 22.2508301,26.1937972 C22.7676147,25.8844249 23.4658409,26.0087566 23.8109039,26.474515 C24.155427,26.9397877 24.0161057,27.5672745 23.4993212,27.8776182 C20.7987573,29.4963593 18.2315746,30 16.0845157,30 Z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.3 KiB |
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#ee5195" fill-rule="evenodd" d="M20.8195396,14 L15.1804604,14 L15.1804604,14 L15.8471271,18 L20.1528729,18 L20.8195396,14 Z M22.8471271,14 L27.6125741,14 L27.6125741,14 L26.2792408,18 L22.1804604,18 L22.8471271,14 Z M21.1528729,12 L14.8471271,12 L14.8471271,12 L14.1804604,8 L21.8195396,8 L21.1528729,12 Z M23.1804604,12 L28.2792408,12 L28.2792408,12 L29.6125741,8 L23.8471271,8 L23.1804604,12 Z M13.1528729,14 L8.47703296,14 L10.077033,18 L10.077033,18 L13.8195396,18 L13.1528729,14 Z M12.8195396,12 L7.67703296,12 L6.07703296,8 L12.1528729,8 L12.8195396,12 L12.8195396,12 Z M31.7207592,8 L32,8 L32,6 L31,6 L5.27703296,6 L5.27703296,6 L4,2.8074176 L4,2 L3,2 L1,2 L0,2 L0,4 L1,4 L2.32296704,4 L9.78931928,22.6658806 L9.78931928,22.6658806 C8.71085924,23.3823847 8,24.6081773 8,26 C8,28.209139 9.790861,30 12,30 C14.209139,30 16,28.209139 16,26 C16,25.2714257 15.8052114,24.5883467 15.4648712,24 L22.5351288,24 C22.1947886,24.5883467 22,25.2714257 22,26 C22,28.209139 23.790861,30 26,30 C28.209139,30 30,28.209139 30,26 C30,23.790861 28.209139,22 26,22 L11.677033,22 L10.877033,20 L27,20 L28,20 L28,19.1622777 L31.7207592,8 L31.7207592,8 Z M26,28 C27.1045695,28 28,27.1045695 28,26 C28,24.8954305 27.1045695,24 26,24 C24.8954305,24 24,24.8954305 24,26 C24,27.1045695 24.8954305,28 26,28 Z M12,28 C13.1045695,28 14,27.1045695 14,26 C14,24.8954305 13.1045695,24 12,24 C10.8954305,24 10,24.8954305 10,26 C10,27.1045695 10.8954305,28 12,28 Z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.8 KiB |
|
@ -0,0 +1,17 @@
|
|||
/* User Context UI browser styles */
|
||||
|
||||
#menu_newUserContextTabPersonal {
|
||||
list-style-image: url("chrome://browser/skin/usercontext/personal.svg");
|
||||
}
|
||||
|
||||
#menu_newUserContextTabWork {
|
||||
list-style-image: url("chrome://browser/skin/usercontext/work.svg");
|
||||
}
|
||||
|
||||
#menu_newUserContextTabBanking {
|
||||
list-style-image: url("chrome://browser/skin/usercontext/banking.svg");
|
||||
}
|
||||
|
||||
#menu_newUserContextTabShopping {
|
||||
list-style-image: url("chrome://browser/skin/usercontext/shopping.svg");
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#f89c24" fill-rule="evenodd" d="M22,9.99887085 L21.635468,10 L29.0034652,10 C29.5538362,10 30,10.4449463 30,10.9933977 L30,27.0066023 C30,27.5552407 29.5601869,28 29.0034652,28 L2.99653482,28 C2.44616384,28 2,27.5550537 2,27.0066023 L2,10.9933977 C2,10.4447593 2.43981314,10 2.99653482,10 L8,10 L8,7.99922997 C8,5.79051625 10.0426627,4 12.5635454,4 L19.4364546,4 C21.9568311,4 24,5.79246765 24,7.99922997 L24,9.99267578 L22,9.99887085 L22,10 L10,10 L10,7.99922997 C10,6.89421235 11.0713286,6 12.3917227,6 L19.6082773,6 C20.9273761,6 22,6.89552665 22,7.99922997 L22,9.99887085 Z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 941 B |
|
@ -2842,3 +2842,5 @@ chatbox {
|
|||
.browser-action-panel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
%include ../shared/usercontext/usercontext.inc.css
|
||||
|
|
|
@ -254,6 +254,10 @@ browser.jar:
|
|||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
skin/classic/browser/tabview/tabview-inverted.png (tabview/tabview-inverted.png)
|
||||
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
|
||||
skin/classic/browser/usercontext/personal.svg (../shared/usercontext/personal.svg)
|
||||
skin/classic/browser/usercontext/work.svg (../shared/usercontext/work.svg)
|
||||
skin/classic/browser/usercontext/banking.svg (../shared/usercontext/banking.svg)
|
||||
skin/classic/browser/usercontext/shopping.svg (../shared/usercontext/shopping.svg)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16.png
|
||||
skin/classic/browser/sync-32.png
|
||||
|
|
|
@ -39,7 +39,7 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
|
|||
LLVM_LDFLAGS=`$LLVMCONFIG --system-libs | xargs`
|
||||
LLVM_LDFLAGS="$LLVM_LDFLAGS `$LLVMCONFIG --ldflags --libs core mc analysis asmparser mcparser bitreader option | xargs`"
|
||||
|
||||
if test "${OS_ARCH}" = "Darwin"; then
|
||||
if test "${HOST_OS_ARCH}" = "Darwin"; then
|
||||
CLANG_LDFLAGS="-lclangFrontend -lclangDriver -lclangSerialization"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangParse -lclangSema -lclangAnalysis"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangEdit -lclangAST -lclangLex"
|
||||
|
|
|
@ -222,3 +222,15 @@ MOZ_RUN_CONFIG_STATUS()],
|
|||
define([AC_CONFIG_HEADER],
|
||||
[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
|
||||
])
|
||||
|
||||
define([MOZ_BUILD_BACKEND],
|
||||
[
|
||||
BUILD_BACKENDS="RecursiveMake"
|
||||
|
||||
MOZ_ARG_ENABLE_STRING(build-backend,
|
||||
[ --enable-build-backend={AndroidEclipse,CppEclipse,VisualStudio,FasterMake,CompileDB}
|
||||
Enable additional build backends],
|
||||
[ BUILD_BACKENDS="RecursiveMake `echo $enableval | sed 's/,/ /g'`"])
|
||||
|
||||
AC_SUBST_LIST([BUILD_BACKENDS])
|
||||
])
|
||||
|
|
|
@ -14,6 +14,17 @@ OS_COMPILE_CXXFLAGS :=
|
|||
OS_LDFLAGS := $(LLVM_LDFLAGS) $(CLANG_LDFLAGS)
|
||||
DSO_LDOPTS := -shared
|
||||
|
||||
ifeq ($(HOST_OS_ARCH)_$(OS_ARCH),Linux_Darwin)
|
||||
# Use the host compiler instead of the target compiler.
|
||||
CXX := $(HOST_CXX)
|
||||
# expandlibs doesn't know the distinction between host and target toolchains,
|
||||
# and on cross linux/darwin builds, the options to give to the linker for file
|
||||
# lists differ between both, so don't use file lists.
|
||||
EXPAND_MKSHLIB_ARGS :=
|
||||
# Don't pass OSX linker arguments.
|
||||
MOZ_FIX_LINK_PATHS :=
|
||||
endif
|
||||
|
||||
# Use the default OS X deployment target to enable using the libc++ headers
|
||||
# correctly. Note that the binary produced here is a host tool and doesn't need
|
||||
# to be distributed.
|
||||
|
|
|
@ -13,6 +13,11 @@ SOURCES += [
|
|||
DISABLE_STL_WRAPPING = True
|
||||
NO_VISIBILITY_FLAGS = True
|
||||
|
||||
# libc++ is required to build plugins against clang on OS X.
|
||||
if CONFIG['HOST_OS_ARCH'] == 'Darwin':
|
||||
CXXFLAGS += ['-stdlib=libc++']
|
||||
LDFLAGS += ['-lc++']
|
||||
|
||||
DIRS += [
|
||||
'tests',
|
||||
]
|
||||
|
|
|
@ -131,6 +131,7 @@ MACH_MODULES = [
|
|||
'python/mozbuild/mozbuild/mach_commands.py',
|
||||
'python/mozbuild/mozbuild/backend/mach_commands.py',
|
||||
'python/mozbuild/mozbuild/compilation/codecomplete.py',
|
||||
'python/mozbuild/mozbuild/compilation/database.py',
|
||||
'python/mozbuild/mozbuild/frontend/mach_commands.py',
|
||||
'services/common/tests/mach_commands.py',
|
||||
'testing/luciddream/mach_commands.py',
|
||||
|
|
|
@ -38,10 +38,9 @@ export OTOOL=${TOOLCHAIN_PREFIX}otool
|
|||
export GENISOIMAGE=$topsrcdir/genisoimage/genisoimage
|
||||
export DMG_TOOL=$topsrcdir/dmg/dmg
|
||||
|
||||
# The system gcc installed on CentOS 6 is 4.4, which our
|
||||
# build system rejects.
|
||||
export HOST_CC="$topsrcdir/gcc/bin/gcc"
|
||||
export HOST_CXX="$topsrcdir/gcc/bin/g++"
|
||||
export HOST_CC="$topsrcdir/clang/bin/clang"
|
||||
export HOST_CXX="$topsrcdir/clang/bin/clang++"
|
||||
export HOST_CPP="$topsrcdir/clang/bin/clang -E"
|
||||
export HOST_LDFLAGS="-g"
|
||||
|
||||
ac_add_options --target=x86_64-apple-darwin
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"llvm_revision": "241406",
|
||||
"llvm_revision": "247539",
|
||||
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
|
||||
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
|
||||
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
|
||||
|
|
|
@ -45,7 +45,9 @@ ifndef JS_STANDALONE
|
|||
ifndef MOZ_PROFILE_USE
|
||||
# Generate a new buildid every time we "export" in config... that's only
|
||||
# supposed to be once per-build!
|
||||
export::
|
||||
export:: buildid
|
||||
|
||||
buildid: FORCE
|
||||
ifdef MOZ_BUILD_DATE
|
||||
printf '%s' $(MOZ_BUILD_DATE) > buildid
|
||||
else
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
# 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/.
|
||||
|
||||
# /!\ Please make sure to update the following comment when you touch this
|
||||
# file. Thank you /!\
|
||||
|
||||
# The traditional Mozilla build system relied on going through the entire
|
||||
# build tree a number of times with different targets, and many of the
|
||||
# things happening at each step required other things happening in previous
|
||||
# steps without any documentation of those dependencies.
|
||||
#
|
||||
# This new build system tries to start afresh by establishing what files or
|
||||
# operations are needed for the build, and applying the necessary rules to
|
||||
# have those in place, relying on make dependencies to get them going.
|
||||
#
|
||||
# As of writing, only building non-compiled parts of Firefox is supported
|
||||
# here (a few other things are also left out). This is a starting point, with
|
||||
# the intent to grow this build system to make it more complete.
|
||||
#
|
||||
# This file contains rules and dependencies to get things working. The intent
|
||||
# is for a Makefile to define some dependencies and variables, and include
|
||||
# this file. What needs to be defined there, and ends up being generated by
|
||||
# python/mozbuild/mozbuild/backend/fastermake.py is the following:
|
||||
# - TOPSRCDIR/TOPOBJDIR, respectively the top source directory and the top
|
||||
# object directory
|
||||
# - PYTHON, the path to the python executable
|
||||
# - ACDEFINES, which contains a set of -Dvar=name to be used during
|
||||
# preprocessing
|
||||
# - MOZ_CHROME_FILE_FORMAT, which defines whether to use file copies or
|
||||
# symbolic links
|
||||
# - JAR_MN_TARGETS, which defines the targets to use for jar manifest
|
||||
# processing, see further below
|
||||
# - PP_TARGETS, which defines the file paths of preprocessed files, see
|
||||
# further below
|
||||
# - INSTALL_MANIFESTS, which defines the list of base directories handled
|
||||
# by install manifests, see further below
|
||||
# - MANIFEST_TARGETS, which defines the file paths of chrome manifests, see
|
||||
# further below
|
||||
#
|
||||
# A convention used between this file and the Makefile including it is that
|
||||
# global Make variables names are uppercase, while "local" Make variables
|
||||
# applied to specific targets are lowercase.
|
||||
|
||||
# Targets to be triggered for a default build
|
||||
default: $(addprefix install-,$(INSTALL_MANIFESTS))
|
||||
default: $(addprefix jar-,$(JAR_MN_TARGETS))
|
||||
|
||||
# Explicit files to be built for a default build
|
||||
default: $(addprefix $(TOPOBJDIR)/,$(PP_TARGETS))
|
||||
default: $(addprefix $(TOPOBJDIR)/,$(MANIFEST_TARGETS))
|
||||
default: $(TOPOBJDIR)/dist/bin/greprefs.js
|
||||
default: $(TOPOBJDIR)/dist/bin/platform.ini
|
||||
default: $(TOPOBJDIR)/dist/bin/webapprt/webapprt.ini
|
||||
|
||||
.PHONY: FORCE
|
||||
|
||||
# Extra define to trigger some workarounds. We should strive to limit the
|
||||
# use of those. As of writing the only one is in
|
||||
# toolkit/content/buildconfig.html.
|
||||
ACDEFINES += -DBUILD_FASTER
|
||||
|
||||
# Generic rule to fall back to the recursive make backend
|
||||
$(TOPOBJDIR)/%: FORCE
|
||||
$(MAKE) -C $(dir $@) $(notdir $@)
|
||||
|
||||
# Files under the faster/ sub-directory, however, are not meant to use the
|
||||
# fallback
|
||||
$(TOPOBJDIR)/faster/%: ;
|
||||
|
||||
# And files under dist/ are meant to be copied from their first dependency
|
||||
# if there is no other rule.
|
||||
$(TOPOBJDIR)/dist/%:
|
||||
rm -f $@
|
||||
cp $< $@
|
||||
|
||||
# Install files using install manifests
|
||||
#
|
||||
# The list of base directories is given in INSTALL_MANIFESTS. The
|
||||
# corresponding install manifests are named correspondingly, with forward
|
||||
# slashes replaced with underscores, and prefixed with `install_`. That is,
|
||||
# the install manifest for `dist/bin` would be `install_dist_bin`.
|
||||
$(addprefix install-,$(INSTALL_MANIFESTS)): install-%:
|
||||
$(PYTHON) -m mozbuild.action.process_install_manifest \
|
||||
--no-remove \
|
||||
--no-remove-empty-directories \
|
||||
$(TOPOBJDIR)/$* \
|
||||
install_$(subst /,_,$*)
|
||||
|
||||
# Preprocessed files. Ideally they would be using install manifests but
|
||||
# right now, it's not possible because of things like APP_BUILDID or
|
||||
# nsURLFormatter.js.
|
||||
# Things missing:
|
||||
# - XULPPFLAGS
|
||||
#
|
||||
# The list of preprocessed files is defined in PP_TARGETS. The list is
|
||||
# relative to TOPOBJDIR.
|
||||
# The source file for each of those preprocessed files is defined as a Make
|
||||
# dependency for the $(TOPOBJDIR)/path target. For example:
|
||||
# PP_TARGETS = foo/bar
|
||||
# $(TOPOBJDIR)/foo/bar: /path/to/source/for/foo/bar.in
|
||||
# The file name for the source doesn't need to be different.
|
||||
# Additionally, extra defines can be specified for a given preprocessing
|
||||
# by setting the `defines` variable specifically for the given target.
|
||||
# For example:
|
||||
# $(TOPOBJDIR)/foo/bar: defines = -Dqux=foobar
|
||||
$(addprefix $(TOPOBJDIR)/,$(PP_TARGETS)): Makefile
|
||||
$(addprefix $(TOPOBJDIR)/,$(PP_TARGETS)): $(TOPOBJDIR)/%:
|
||||
$(PYTHON) -m mozbuild.action.preprocessor \
|
||||
--depend $(TOPOBJDIR)/faster/.deps/$(subst /,_,$*) \
|
||||
-DAB_CD=en-US \
|
||||
$(defines) \
|
||||
$(ACDEFINES) \
|
||||
$< \
|
||||
-o $@
|
||||
|
||||
# Include the dependency files from the above preprocessed files rule.
|
||||
$(foreach pp_target,$(PP_TARGETS), \
|
||||
$(eval -include $(TOPOBJDIR)/faster/.deps/$(subst /,_,$(pp_target))))
|
||||
|
||||
# Install files from jar manifests. Ideally, they would be using install
|
||||
# manifests, but the code to read jar manifests and emit appropriate
|
||||
# install manifests is not there yet.
|
||||
# Things missing:
|
||||
# - XULPPFLAGS
|
||||
# - DEFINES from config/config.mk
|
||||
# - L10N
|
||||
# - -e when USE_EXTENSION_MANIFEST is set in moz.build
|
||||
#
|
||||
# The list given in JAR_MN_TARGETS corresponds to the list of `jar-%` targets
|
||||
# to be processed, with the `jar-` prefix stripped.
|
||||
# The Makefile is expected to specify the source jar manifest as a dependency
|
||||
# to each target. There is no expectation that the `jar-%` target name matches
|
||||
# the source file name in any way. For example:
|
||||
# JAR_MN_TARGETS = foo
|
||||
# jar-foo: /path/to/some/jar.mn
|
||||
# Additionally, extra defines can be specified for the processing of the jar
|
||||
# manifest by settig the `defines` variable specifically for the given target.
|
||||
# For example:
|
||||
# jar-foo: defines = -Dqux=foo
|
||||
# The default base path where files are going to be installed is `dist/bin`.
|
||||
# It is possible to use a different path by setting the `install_target`
|
||||
# variable. For example:
|
||||
# jar-foo: install_target = dist/bin/foo
|
||||
# When processing jar manifests, relative paths given inside a jar manifest
|
||||
# can be resolved from an object directory. The default path for that object
|
||||
# directory is the translation of the jar manifest directory path from the
|
||||
# source directory to the object directory. That is, for
|
||||
# $(TOPSRCDIR)/path/to/jar.mn, the default would be $(TOPOBJDIR)/path/to.
|
||||
# In case a different path must be used for the object directory, the `objdir`
|
||||
# variable can be set. For example:
|
||||
# jar-foo: objdir=/some/other/path
|
||||
jar-%: objdir ?= $(dir $(patsubst $(TOPSRCDIR)%,$(TOPOBJDIR)%,$<))
|
||||
jar-%: install_target ?= dist/bin
|
||||
jar-%:
|
||||
cd $(objdir) && \
|
||||
$(PYTHON) -m mozbuild.action.jar_maker \
|
||||
-j $(TOPOBJDIR)/$(install_target)/chrome \
|
||||
-t $(TOPSRCDIR) \
|
||||
-f $(MOZ_CHROME_FILE_FORMAT) \
|
||||
-c $(dir $<)/en-US \
|
||||
-DAB_CD=en-US \
|
||||
$(defines) \
|
||||
$(ACDEFINES) \
|
||||
$<
|
||||
|
||||
# Create some chrome manifests
|
||||
# This rule is forced to run every time because it may be updating files that
|
||||
# already exit.
|
||||
#
|
||||
# The list of chrome manifests is given in MANIFEST_TARGETS, relative to the
|
||||
# top object directory. The content for those manifests is given in the
|
||||
# `content` variable associated with the target. For example:
|
||||
# MANIFEST_TARGETS = foo
|
||||
# $(TOPOBJDIR)/foo: content = "manifest foo.manifest" "manifest bar.manifest"
|
||||
$(addprefix $(TOPOBJDIR)/,$(MANIFEST_TARGETS)): FORCE
|
||||
$(PYTHON) -m mozbuild.action.buildlist \
|
||||
$@ \
|
||||
$(content)
|
||||
|
||||
# ============================================================================
|
||||
# Below is a set of additional dependencies and variables used to build things
|
||||
# that are not supported by data in moz.build.
|
||||
|
||||
# GENERATED_FILES are not supported yet, and even if they were, the
|
||||
# dependencies are missing information.
|
||||
$(foreach p,linux osx windows,jar-browser-themes-$(p)-jar.mn): \
|
||||
jar-browser-themes-%-jar.mn: \
|
||||
$(TOPOBJDIR)/browser/themes/%/tab-selected-end.svg \
|
||||
$(TOPOBJDIR)/browser/themes/%/tab-selected-start.svg
|
||||
|
||||
# These files are manually generated from
|
||||
# toolkit/components/urlformatter/Makefile.in and are force-included so that
|
||||
# the corresponding defines don't end up in the command lines.
|
||||
KEYS = mozilla_api_key google_api_key google_oauth_api_key bing_api_key
|
||||
$(TOPOBJDIR)/dist/bin/components/nsURLFormatter.js: \
|
||||
$(addprefix $(TOPOBJDIR)/toolkit/components/urlformatter/, $(KEYS))
|
||||
$(TOPOBJDIR)/dist/bin/components/nsURLFormatter.js: defines += \
|
||||
$(addprefix -I $(TOPOBJDIR)/toolkit/components/urlformatter/,$(KEYS))
|
||||
|
||||
# Extra dependencies and/or definitions for preprocessed files.
|
||||
$(TOPOBJDIR)/dist/bin/application.ini: $(TOPOBJDIR)/config/buildid
|
||||
$(TOPOBJDIR)/dist/bin/application.ini: defines += \
|
||||
-DAPP_BUILDID=$(shell cat $(TOPOBJDIR)/config/buildid)
|
||||
|
||||
# Files to build with the recursive backend and simply copy
|
||||
$(TOPOBJDIR)/dist/bin/greprefs.js: $(TOPOBJDIR)/modules/libpref/greprefs.js
|
||||
$(TOPOBJDIR)/dist/bin/platform.ini: $(TOPOBJDIR)/toolkit/xre/platform.ini
|
||||
$(TOPOBJDIR)/dist/bin/webapprt/webapprt.ini: $(TOPOBJDIR)/webapprt/webapprt.ini
|
|
@ -1,202 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 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/.
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Name: glibcversion.sh - Print __GLIBC__ version if gnu libc 2 is
|
||||
## found.
|
||||
##
|
||||
## Description: This script is needed by the mozilla build system. It needs
|
||||
## to determine whether the current platform (mostly the
|
||||
## various linux "platforms") are based on the gnu libc2. This
|
||||
## information is later used in mozilla to determine whether
|
||||
## gnu libc 2 specific "features" need to be handled, such
|
||||
## as broken locales.
|
||||
##
|
||||
## Author: Ramiro Estrugo <ramiro@netscape.com>
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
##
|
||||
## Command Line Flags Supported:
|
||||
##
|
||||
## -g | --is-glibc2: Print True/False if detected __GLIBC__.
|
||||
##
|
||||
## -v | --print-version: Print value of __GLIBC__ if found, or none.
|
||||
##
|
||||
## -o | --set-object-name: Set object name for current system.
|
||||
## -cc | --set-compiler: Set compiler for building test program.
|
||||
##
|
||||
|
||||
|
||||
##
|
||||
## Constants
|
||||
##
|
||||
GLIBC_PROG_PREFIX=./get_glibc_info
|
||||
|
||||
##
|
||||
## Defaults
|
||||
##
|
||||
GLIBC_PRINT_IS_GLIBC2=False
|
||||
|
||||
GLIBC_PRINT_VERSION=False
|
||||
|
||||
GLIBC_OBJECT_NAME=`uname`-`uname -r`
|
||||
GLIBC_CC=cc
|
||||
|
||||
function glibc_usage()
|
||||
{
|
||||
echo
|
||||
echo "Usage: `basename $0` [options]"
|
||||
echo
|
||||
echo " -g, --is-glibc2: Print True/False if detected __GLIBC__."
|
||||
echo
|
||||
echo " -v, --print-version: Print value of __GLIBC__ if found, or none."
|
||||
echo
|
||||
echo " -o, --set-object-name: Set object name for current system."
|
||||
echo " -cc, --set-compiler: Set compiler for building test program."
|
||||
echo
|
||||
echo " -h, --help: Print this blurb."
|
||||
echo
|
||||
echo "The default is '-v' if no options are given."
|
||||
echo
|
||||
}
|
||||
|
||||
##
|
||||
## Parse the command line
|
||||
##
|
||||
while [ "$*" ]; do
|
||||
case $1 in
|
||||
-h | --help)
|
||||
shift
|
||||
glibc_usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
-g | --is-glibc2)
|
||||
shift
|
||||
GLIBC_PRINT_IS_GLIBC2=True
|
||||
;;
|
||||
|
||||
-v | --print-version)
|
||||
shift
|
||||
GLIBC_PRINT_VERSION=True
|
||||
;;
|
||||
|
||||
-o | --set-object-name)
|
||||
shift
|
||||
GLIBC_OBJECT_NAME="$1"
|
||||
shift
|
||||
;;
|
||||
|
||||
-cc | --set-compiler)
|
||||
shift
|
||||
GLIBC_CC="$1"
|
||||
shift
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo "`basename $0`: invalid option '$1'"
|
||||
shift
|
||||
glibc_usage
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
##
|
||||
## Motif info program name
|
||||
##
|
||||
GLIBC_PROG="$GLIBC_PROG_PREFIX"_"$GLIBC_OBJECT_NAME"
|
||||
GLIBC_SRC="$GLIBC_PROG_PREFIX"_"$GLIBC_OBJECT_NAME.c"
|
||||
|
||||
##
|
||||
## Cleanup the dummy test source/program
|
||||
##
|
||||
function glibc_cleanup()
|
||||
{
|
||||
true
|
||||
|
||||
# rm -f $GLIBC_PROG
|
||||
# rm -f $GLIBC_SRC
|
||||
|
||||
}
|
||||
|
||||
glibc_cleanup
|
||||
|
||||
if [ ! -f $GLIBC_SRC ]
|
||||
then
|
||||
cat << EOF > $GLIBC_SRC
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
fprintf(stdout,"%d\n",__GLIBC__);
|
||||
#else
|
||||
fprintf(stdout,"none\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ ! -f $GLIBC_SRC ]
|
||||
then
|
||||
echo
|
||||
echo "Could not create test program source $GLIBC_SRC."
|
||||
echo
|
||||
|
||||
glibc_cleanup
|
||||
|
||||
exit
|
||||
fi
|
||||
|
||||
##
|
||||
## Compile the dummy test program if needed
|
||||
##
|
||||
if [ ! -x $GLIBC_PROG ]
|
||||
then
|
||||
$GLIBC_CC -o $GLIBC_PROG $GLIBC_SRC
|
||||
fi
|
||||
|
||||
if [ ! -x $GLIBC_PROG ]
|
||||
then
|
||||
echo
|
||||
echo "Could not create test program $GLIBC_PROG."
|
||||
echo
|
||||
|
||||
glibc_cleanup
|
||||
|
||||
exit
|
||||
fi
|
||||
|
||||
##
|
||||
## Execute the dummy test program
|
||||
##
|
||||
GLIBC_PROG_OUTPUT=`$GLIBC_PROG`
|
||||
|
||||
##
|
||||
## -g | --is-glibc2
|
||||
##
|
||||
if [ "$GLIBC_PRINT_IS_GLIBC2" = "True" ]
|
||||
then
|
||||
if [ "$GLIBC_PROG_OUTPUT" = "2" ]
|
||||
then
|
||||
echo True
|
||||
else
|
||||
echo False
|
||||
fi
|
||||
|
||||
glibc_cleanup
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo $GLIBC_PROG_OUTPUT
|
||||
|
||||
glibc_cleanup
|
|
@ -137,6 +137,8 @@ MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd`
|
|||
|
||||
MOZ_PYTHON
|
||||
|
||||
MOZ_BUILD_BACKEND
|
||||
|
||||
MOZ_DEFAULT_COMPILER
|
||||
|
||||
COMPILE_ENVIRONMENT=1
|
||||
|
|
|
@ -49,7 +49,7 @@ function* testPressingEscapeRevertsChanges(view) {
|
|||
yield ruleEditor.rule._applyingModifications;
|
||||
|
||||
yield waitForComputedStyleProperty("body", null, "animation-timing-function",
|
||||
"cubic-bezier(0, 0, 1, 1)");
|
||||
"linear");
|
||||
is(propEditor.valueSpan.textContent, "linear",
|
||||
"Got expected property value.");
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ const URL2 = MAIN_DOMAIN + "navigate-second.html";
|
|||
var events = require("sdk/event/core");
|
||||
var client;
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
// State machine to check events order
|
||||
var i = 0;
|
||||
function assertEvent(event, data) {
|
||||
|
|
|
@ -6,6 +6,8 @@ var stayingOnPage = true;
|
|||
var TEST_PAGE = "http://mochi.test:8888/browser/docshell/test/browser/file_bug1046022.html";
|
||||
var TARGETED_PAGE = "data:text/html," + encodeURIComponent("<body>Shouldn't be seeing this</body>");
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
var loadExpected = TEST_PAGE;
|
||||
var testTab;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "AnimationCommon.h"
|
||||
#include "nsCSSPropertySet.h"
|
||||
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
|
||||
#include "nsStyleUtil.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -17,11 +18,12 @@ void
|
|||
ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
|
||||
{
|
||||
mType = aFunction.mType;
|
||||
if (mType == nsTimingFunction::Function) {
|
||||
if (nsTimingFunction::IsSplineType(mType)) {
|
||||
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
|
||||
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
|
||||
} else {
|
||||
mSteps = aFunction.mSteps;
|
||||
mStepSyntax = aFunction.mStepSyntax;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,23 +37,67 @@ StepEnd(uint32_t aSteps, double aPortion)
|
|||
|
||||
double
|
||||
ComputedTimingFunction::GetValue(double aPortion) const
|
||||
{
|
||||
if (HasSpline()) {
|
||||
return mTimingFunction.GetSplineValue(aPortion);
|
||||
}
|
||||
if (mType == nsTimingFunction::Type::StepStart) {
|
||||
// There are diagrams in the spec that seem to suggest this check
|
||||
// and the bounds point should not be symmetric with StepEnd, but
|
||||
// should actually step up at rather than immediately after the
|
||||
// fraction points. However, we rely on rounding negative values
|
||||
// up to zero, so we can't do that. And it's not clear the spec
|
||||
// really meant it.
|
||||
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
|
||||
}
|
||||
MOZ_ASSERT(mType == nsTimingFunction::Type::StepEnd, "bad type");
|
||||
return StepEnd(mSteps, aPortion);
|
||||
}
|
||||
|
||||
int32_t
|
||||
ComputedTimingFunction::Compare(const ComputedTimingFunction& aRhs) const
|
||||
{
|
||||
if (mType != aRhs.mType) {
|
||||
return int32_t(mType) - int32_t(aRhs.mType);
|
||||
}
|
||||
|
||||
if (mType == nsTimingFunction::Type::CubicBezier) {
|
||||
int32_t order = mTimingFunction.Compare(aRhs.mTimingFunction);
|
||||
if (order != 0) {
|
||||
return order;
|
||||
}
|
||||
} else if (mType == nsTimingFunction::Type::StepStart ||
|
||||
mType == nsTimingFunction::Type::StepEnd) {
|
||||
if (mSteps != aRhs.mSteps) {
|
||||
return int32_t(mSteps) - int32_t(aRhs.mSteps);
|
||||
}
|
||||
if (mStepSyntax != aRhs.mStepSyntax) {
|
||||
return int32_t(mStepSyntax) - int32_t(aRhs.mStepSyntax);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ComputedTimingFunction::AppendToString(nsAString& aResult) const
|
||||
{
|
||||
switch (mType) {
|
||||
case nsTimingFunction::Function:
|
||||
return mTimingFunction.GetSplineValue(aPortion);
|
||||
case nsTimingFunction::StepStart:
|
||||
// There are diagrams in the spec that seem to suggest this check
|
||||
// and the bounds point should not be symmetric with StepEnd, but
|
||||
// should actually step up at rather than immediately after the
|
||||
// fraction points. However, we rely on rounding negative values
|
||||
// up to zero, so we can't do that. And it's not clear the spec
|
||||
// really meant it.
|
||||
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
|
||||
case nsTimingFunction::Type::CubicBezier:
|
||||
nsStyleUtil::AppendCubicBezierTimingFunction(mTimingFunction.X1(),
|
||||
mTimingFunction.Y1(),
|
||||
mTimingFunction.X2(),
|
||||
mTimingFunction.Y2(),
|
||||
aResult);
|
||||
break;
|
||||
case nsTimingFunction::Type::StepStart:
|
||||
case nsTimingFunction::Type::StepEnd:
|
||||
nsStyleUtil::AppendStepsTimingFunction(mType, mSteps, mStepSyntax,
|
||||
aResult);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "bad type");
|
||||
// fall through
|
||||
case nsTimingFunction::StepEnd:
|
||||
return StepEnd(mSteps, aPortion);
|
||||
nsStyleUtil::AppendCubicBezierKeywordTimingFunction(mType, aResult);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,5 +502,116 @@ KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
|
|||
}
|
||||
}
|
||||
|
||||
struct KeyframeValueEntry
|
||||
{
|
||||
float mOffset;
|
||||
nsCSSProperty mProperty;
|
||||
nsString mValue;
|
||||
const ComputedTimingFunction* mTimingFunction;
|
||||
|
||||
bool operator==(const KeyframeValueEntry& aRhs) const
|
||||
{
|
||||
NS_ASSERTION(mOffset != aRhs.mOffset || mProperty != aRhs.mProperty,
|
||||
"shouldn't have duplicate (offset, property) pairs");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator<(const KeyframeValueEntry& aRhs) const
|
||||
{
|
||||
NS_ASSERTION(mOffset != aRhs.mOffset || mProperty != aRhs.mProperty,
|
||||
"shouldn't have duplicate (offset, property) pairs");
|
||||
|
||||
// First, sort by offset.
|
||||
if (mOffset != aRhs.mOffset) {
|
||||
return mOffset < aRhs.mOffset;
|
||||
}
|
||||
|
||||
// Second, by timing function.
|
||||
int32_t order = mTimingFunction->Compare(*aRhs.mTimingFunction);
|
||||
if (order != 0) {
|
||||
return order < 0;
|
||||
}
|
||||
|
||||
// Last, by property IDL name.
|
||||
return nsCSSProps::PropertyIDLNameSortPosition(mProperty) <
|
||||
nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
|
||||
nsTArray<JSObject*>& aResult,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Collect tuples of the form (offset, property, value, easing) from
|
||||
// mProperties, then sort them so we can generate one ComputedKeyframe per
|
||||
// offset/easing pair. We sort secondarily by property IDL name so that we
|
||||
// have a uniform order that we set properties on the ComputedKeyframe
|
||||
// object.
|
||||
nsAutoTArray<KeyframeValueEntry,4> entries;
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (property.mSegments.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (size_t i = 0, n = property.mSegments.Length(); i < n; i++) {
|
||||
const AnimationPropertySegment& segment = property.mSegments[i];
|
||||
KeyframeValueEntry* entry = entries.AppendElement();
|
||||
entry->mOffset = segment.mFromKey;
|
||||
entry->mProperty = property.mProperty;
|
||||
entry->mTimingFunction = &segment.mTimingFunction;
|
||||
StyleAnimationValue::UncomputeValue(property.mProperty,
|
||||
segment.mFromValue,
|
||||
entry->mValue);
|
||||
}
|
||||
const AnimationPropertySegment& segment = property.mSegments.LastElement();
|
||||
KeyframeValueEntry* entry = entries.AppendElement();
|
||||
entry->mOffset = segment.mToKey;
|
||||
entry->mProperty = property.mProperty;
|
||||
// We don't have the an appropriate animation-timing-function value to use,
|
||||
// either from the element or from the 100% keyframe, so we just set it to
|
||||
// the animation-timing-value value used on the previous segment.
|
||||
entry->mTimingFunction = &segment.mTimingFunction;
|
||||
StyleAnimationValue::UncomputeValue(property.mProperty,
|
||||
segment.mToValue,
|
||||
entry->mValue);
|
||||
}
|
||||
entries.Sort();
|
||||
|
||||
for (size_t i = 0, n = entries.Length(); i < n; ) {
|
||||
// Create a JS object with the explicit ComputedKeyframe dictionary members.
|
||||
ComputedKeyframe keyframeDict;
|
||||
keyframeDict.mOffset.SetValue(entries[i].mOffset);
|
||||
keyframeDict.mComputedOffset.Construct(entries[i].mOffset);
|
||||
keyframeDict.mEasing.Truncate();
|
||||
entries[i].mTimingFunction->AppendToString(keyframeDict.mEasing);
|
||||
keyframeDict.mComposite.SetValue(CompositeOperation::Replace);
|
||||
|
||||
JS::Rooted<JS::Value> keyframeValue(aCx);
|
||||
if (!ToJSValue(aCx, keyframeDict, &keyframeValue)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> keyframe(aCx, &keyframeValue.toObject());
|
||||
|
||||
// Set the property name/value pairs on the JS object.
|
||||
do {
|
||||
const KeyframeValueEntry& entry = entries[i];
|
||||
const char* name = nsCSSProps::PropertyIDLName(entry.mProperty);
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!ToJSValue(aCx, entry.mValue, &value) ||
|
||||
!JS_DefineProperty(aCx, keyframe, name, value, JSPROP_ENUMERATE)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
++i;
|
||||
} while (i < n &&
|
||||
entries[i].mOffset == entries[i - 1].mOffset &&
|
||||
*entries[i].mTimingFunction == *entries[i - 1].mTimingFunction);
|
||||
|
||||
aResult.AppendElement(keyframe);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/AnimationEffectReadOnly.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/KeyframeBinding.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "nsSMILKeySpline.h"
|
||||
#include "nsStyleStruct.h" // for nsTimingFunction
|
||||
|
@ -109,28 +110,35 @@ class ComputedTimingFunction
|
|||
{
|
||||
public:
|
||||
typedef nsTimingFunction::Type Type;
|
||||
typedef nsTimingFunction::StepSyntax StepSyntax;
|
||||
void Init(const nsTimingFunction &aFunction);
|
||||
double GetValue(double aPortion) const;
|
||||
const nsSMILKeySpline* GetFunction() const {
|
||||
NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch");
|
||||
NS_ASSERTION(HasSpline(), "Type mismatch");
|
||||
return &mTimingFunction;
|
||||
}
|
||||
Type GetType() const { return mType; }
|
||||
bool HasSpline() const { return nsTimingFunction::IsSplineType(mType); }
|
||||
uint32_t GetSteps() const { return mSteps; }
|
||||
StepSyntax GetStepSyntax() const { return mStepSyntax; }
|
||||
bool operator==(const ComputedTimingFunction& aOther) const {
|
||||
return mType == aOther.mType &&
|
||||
(mType == nsTimingFunction::Function ?
|
||||
(HasSpline() ?
|
||||
mTimingFunction == aOther.mTimingFunction :
|
||||
mSteps == aOther.mSteps);
|
||||
(mSteps == aOther.mSteps &&
|
||||
mStepSyntax == aOther.mStepSyntax));
|
||||
}
|
||||
bool operator!=(const ComputedTimingFunction& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
int32_t Compare(const ComputedTimingFunction& aRhs) const;
|
||||
void AppendToString(nsAString& aResult) const;
|
||||
|
||||
private:
|
||||
Type mType;
|
||||
nsSMILKeySpline mTimingFunction;
|
||||
uint32_t mSteps;
|
||||
StepSyntax mStepSyntax;
|
||||
};
|
||||
|
||||
struct AnimationPropertySegment
|
||||
|
@ -225,6 +233,9 @@ public:
|
|||
" pseudo-element is not yet supported.");
|
||||
return mTarget;
|
||||
}
|
||||
void GetFrames(JSContext*& aCx,
|
||||
nsTArray<JSObject*>& aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// Temporary workaround to return both the target element and pseudo-type
|
||||
// until we implement PseudoElement (bug 1174575).
|
||||
|
|
|
@ -30,8 +30,11 @@ UNIFIED_SOURCES += [
|
|||
'PendingAnimationTracker.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
|
|
@ -0,0 +1,455 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="../testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim-empty { }
|
||||
|
||||
@keyframes anim-empty-frames {
|
||||
from { }
|
||||
to { }
|
||||
}
|
||||
|
||||
@keyframes anim-only-timing {
|
||||
from { animation-timing-function: linear; }
|
||||
to { }
|
||||
}
|
||||
|
||||
@keyframes anim-only-non-animatable {
|
||||
from { display: none; }
|
||||
to { display: inline; }
|
||||
}
|
||||
|
||||
@keyframes anim-simple {
|
||||
from { color: black; }
|
||||
to { color: white; }
|
||||
}
|
||||
|
||||
@keyframes anim-simple-timing {
|
||||
from { color: black; animation-timing-function: linear; }
|
||||
50% { color: blue; animation-timing-function: ease-in-out; }
|
||||
to { color: white; animation-timing-function: step-end; }
|
||||
}
|
||||
|
||||
@keyframes anim-simple-timing-some {
|
||||
from { color: black; animation-timing-function: linear; }
|
||||
50% { color: blue; }
|
||||
to { color: white; }
|
||||
}
|
||||
|
||||
@keyframes anim-simple-shorthand {
|
||||
from { margin: 8px; }
|
||||
to { margin: 16px; }
|
||||
}
|
||||
|
||||
@keyframes anim-omit-to {
|
||||
from { color: blue; }
|
||||
}
|
||||
|
||||
@keyframes anim-omit-from {
|
||||
to { color: blue; }
|
||||
}
|
||||
|
||||
@keyframes anim-omit-from-to {
|
||||
50% { color: blue; }
|
||||
}
|
||||
|
||||
@keyframes anim-different-props {
|
||||
from { color: black; margin-top: 8px; }
|
||||
25% { color: blue; }
|
||||
75% { margin-top: 12px; }
|
||||
to { color: white; margin-top: 16px }
|
||||
}
|
||||
|
||||
@keyframes anim-different-props-and-easing {
|
||||
from { color: black; margin-top: 8px; animation-timing-function: linear; }
|
||||
25% { color: blue; animation-timing-function: step-end; }
|
||||
75% { margin-top: 12px; animation-timing-function: ease-in; }
|
||||
to { color: white; margin-top: 16px }
|
||||
}
|
||||
|
||||
@keyframes anim-merge-offset {
|
||||
from { color: black; }
|
||||
to { color: white; }
|
||||
from { margin-top: 8px; }
|
||||
to { margin-top: 16px; }
|
||||
}
|
||||
|
||||
@keyframes anim-merge-offset-and-easing {
|
||||
from { color: black; animation-timing-function: step-end; }
|
||||
to { color: white; }
|
||||
from { margin-top: 8px; animation-timing-function: linear; }
|
||||
to { margin-top: 16px; }
|
||||
from { font-size: 16px; animation-timing-function: step-end; }
|
||||
to { font-size: 32px; }
|
||||
from { padding-left: 2px; animation-timing-function: linear; }
|
||||
to { padding-left: 4px; }
|
||||
}
|
||||
|
||||
@keyframes anim-no-merge-equiv-easing {
|
||||
from { margin-top: 0px; animation-timing-function: steps(1, end); }
|
||||
from { margin-right: 0px; animation-timing-function: step-end; }
|
||||
from { margin-bottom: 0px; animation-timing-function: steps(1); }
|
||||
50% { margin-top: 10px; animation-timing-function: step-end; }
|
||||
50% { margin-right: 10px; animation-timing-function: step-end; }
|
||||
50% { margin-bottom: 10px; animation-timing-function: step-end; }
|
||||
to { margin-top: 20px; margin-right: 20px; margin-bottom: 20px; }
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
function getFrames(e) {
|
||||
return e.getAnimations()[0].effect.getFrames();
|
||||
}
|
||||
|
||||
function assert_frames_equal(a, b, name) {
|
||||
assert_equals(Object.keys(a).sort().toString(),
|
||||
Object.keys(b).sort().toString(),
|
||||
"properties on " + name);
|
||||
for (var p in a) {
|
||||
assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// animation-timing-function values to test with, where the value
|
||||
// is exactly the same as its serialization, sorted by the order
|
||||
// getFrames() will group frames with the same easing function
|
||||
// together (by nsTimingFunction::Compare).
|
||||
const kTimingFunctionValues = [
|
||||
"ease",
|
||||
"linear",
|
||||
"ease-in",
|
||||
"ease-out",
|
||||
"ease-in-out",
|
||||
"step-start",
|
||||
"steps(1, start)",
|
||||
"steps(2, start)",
|
||||
"step-end",
|
||||
"steps(1)",
|
||||
"steps(1, end)",
|
||||
"steps(2)",
|
||||
"steps(2, end)",
|
||||
"cubic-bezier(0, 0, 1, 1)",
|
||||
"cubic-bezier(0, 0.25, 0.75, 1)",
|
||||
];
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
var frames;
|
||||
|
||||
div.style.animation = 'anim-empty 100s';
|
||||
assert_equals(getFrames(div).length, 0,
|
||||
"number of frames with empty @keyframes");
|
||||
|
||||
div.style.animation = 'anim-empty-frames 100s';
|
||||
assert_equals(getFrames(div).length, 0,
|
||||
"number of frames when @keyframes has empty keyframes");
|
||||
|
||||
div.style.animation = 'anim-only-timing 100s';
|
||||
assert_equals(getFrames(div).length, 0,
|
||||
"number of frames when @keyframes only has keyframes with " +
|
||||
"animation-timing-function");
|
||||
|
||||
div.style.animation = 'anim-only-non-animatable 100s';
|
||||
assert_equals(getFrames(div).length, 0,
|
||||
"number of frames when @keyframes only has frames with " +
|
||||
"non-animatable properties");
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns no frames for various kinds ' +
|
||||
'of empty enimations');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-simple 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
color: "rgb(0, 0, 0)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
color: "rgb(255, 255, 255)" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
|
||||
'animation');
|
||||
|
||||
test(function(t) {
|
||||
kTimingFunctionValues.forEach(function(easing) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-simple 100s ' + easing;
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_equals(frames[i].easing, easing,
|
||||
"value for 'easing' on ComputedKeyframe #" + i);
|
||||
}
|
||||
});
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
|
||||
'values, when the easing comes from animation-timing-function on the ' +
|
||||
'element');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-simple-timing 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 3, "number of frames");
|
||||
assert_equals(frames[0].easing, "linear",
|
||||
"value of 'easing' on ComputedKeyframe #0");
|
||||
assert_equals(frames[1].easing, "ease-in-out",
|
||||
"value of 'easing' on ComputedKeyframe #1");
|
||||
assert_equals(frames[2].easing, "ease-in-out",
|
||||
"value of 'easing' on ComputedKeyframe #2");
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
|
||||
'values, when the easing is specified on each keyframe');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-simple-timing-some 100s step-start';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 3, "number of frames");
|
||||
assert_equals(frames[0].easing, "linear",
|
||||
"value of 'easing' on ComputedKeyframe #0");
|
||||
assert_equals(frames[1].easing, "step-start",
|
||||
"value of 'easing' on ComputedKeyframe #1");
|
||||
assert_equals(frames[2].easing, "step-start",
|
||||
"value of 'easing' on ComputedKeyframe #2");
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
|
||||
'values, when the easing is specified on some keyframes');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-simple-shorthand 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
marginTop: "8px", marginRight: "8px",
|
||||
marginBottom: "8px", marginLeft: "8px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
marginTop: "16px", marginRight: "16px",
|
||||
marginBottom: "16px", marginLeft: "16px" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
|
||||
'animation that specifies a single shorthand property');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-omit-to 100s';
|
||||
div.style.color = 'white';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
color: "rgb(0, 0, 255)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
color: "rgb(255, 255, 255)" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with a 0% keyframe and no 100% keyframe');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-omit-from 100s';
|
||||
div.style.color = 'white';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
color: "rgb(255, 255, 255)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
color: "rgb(0, 0, 255)" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with a 100% keyframe and no 0% keyframe');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-omit-from-to 100s';
|
||||
div.style.color = 'white';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 3, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
color: "rgb(255, 255, 255)" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "ease", composite: "replace",
|
||||
color: "rgb(0, 0, 255)" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
color: "rgb(255, 255, 255)" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with no 0% or 100% keyframe but with a 50% keyframe');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-different-props 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 4, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
color: "rgb(0, 0, 0)", marginTop: "8px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "ease", composite: "replace",
|
||||
color: "rgb(0, 0, 255)" },
|
||||
{ offset: 0.75, computedOffset: 0.75, easing: "ease", composite: "replace",
|
||||
marginTop: "12px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
color: "rgb(255, 255, 255)", marginTop: "16px" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with different properties on different keyframes, all ' +
|
||||
'with the same easing function');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-different-props-and-easing 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 5, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
|
||||
color: "rgb(0, 0, 0)", marginTop: "8px" },
|
||||
{ offset: 0.25, computedOffset: 0.25, easing: "step-end", composite: "replace",
|
||||
color: "rgb(0, 0, 255)" },
|
||||
{ offset: 0.75, computedOffset: 0.75, easing: "ease-in", composite: "replace",
|
||||
marginTop: "12px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease-in", composite: "replace",
|
||||
marginTop: "16px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "step-end", composite: "replace",
|
||||
color: "rgb(255, 255, 255)", },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with different properties on different keyframes, with ' +
|
||||
'a different easing function on each');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-merge-offset 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
color: "rgb(0, 0, 0)", marginTop: "8px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
color: "rgb(255, 255, 255)", marginTop: "16px" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with multiple keyframes for the same time, and all with ' +
|
||||
'the same easing function');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-merge-offset-and-easing 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 4, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "linear", composite: "replace",
|
||||
marginTop: "8px", paddingLeft: "2px" },
|
||||
{ offset: 0, computedOffset: 0, easing: "step-end", composite: "replace",
|
||||
color: "rgb(0, 0, 0)", fontSize: "16px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "linear", composite: "replace",
|
||||
marginTop: "16px", paddingLeft: "4px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "step-end", composite: "replace",
|
||||
color: "rgb(255, 255, 255)", fontSize: "32px" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with multiple keyframes for the same time and with ' +
|
||||
'different easing functions');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-no-merge-equiv-easing 100s';
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 5, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "step-end", composite: "replace",
|
||||
marginRight: "0px" },
|
||||
{ offset: 0, computedOffset: 0, easing: "steps(1)", composite: "replace",
|
||||
marginBottom: "0px" },
|
||||
{ offset: 0, computedOffset: 0, easing: "steps(1, end)", composite: "replace",
|
||||
marginTop: "0px" },
|
||||
{ offset: 0.5, computedOffset: 0.5, easing: "step-end", composite: "replace",
|
||||
marginTop: "10px", marginRight: "10px", marginBottom: "10px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "step-end", composite: "replace",
|
||||
marginTop: "20px", marginRight: "20px", marginBottom: "20px" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
|
||||
'animation with multiple keyframes for the same time and with ' +
|
||||
'different but equivalent easing functions');
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
setup({explicit_done: true});
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["dom.animations-api.core.enabled", true]]},
|
||||
function() {
|
||||
window.open("file_keyframeeffect-getframes.html");
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,73 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="../testcommon.js"></script>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function getFrames(e) {
|
||||
return e.getAnimations()[0].effect.getFrames();
|
||||
}
|
||||
|
||||
function assert_frames_equal(a, b, name) {
|
||||
assert_equals(Object.keys(a).sort().toString(),
|
||||
Object.keys(b).sort().toString(),
|
||||
"properties on " + name);
|
||||
for (var p in a) {
|
||||
assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
|
||||
}
|
||||
}
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.left = '0px';
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
div.style.transition = 'left 100s';
|
||||
div.style.left = '100px';
|
||||
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease", composite: "replace",
|
||||
left: "0px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease", composite: "replace",
|
||||
left: "100px" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
|
||||
'transition');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.left = '0px';
|
||||
window.getComputedStyle(div).transitionProperty;
|
||||
div.style.transition = 'left 100s steps(2,end)';
|
||||
div.style.left = '100px';
|
||||
|
||||
var frames = getFrames(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "steps(2, end)", composite: "replace",
|
||||
left: "0px" },
|
||||
{ offset: 1, computedOffset: 1, easing: "steps(2, end)", composite: "replace",
|
||||
left: "100px" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
|
||||
'transition with a non-default easing function');
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
setup({explicit_done: true});
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["dom.animations-api.core.enabled", true]]},
|
||||
function() {
|
||||
window.open("file_keyframeeffect-getframes.html");
|
||||
});
|
||||
</script>
|
|
@ -32,6 +32,8 @@ support-files = css-animations/file_animation-reverse.html
|
|||
support-files = css-animations/file_animation-starttime.html
|
||||
[css-animations/test_cssanimation-animationname.html]
|
||||
support-files = css-animations/file_cssanimation-animationname.html
|
||||
[css-animations/test_keyframeeffect-getframes.html]
|
||||
support-files = css-animations/file_keyframeeffect-getframes.html
|
||||
[css-animations/test_effect-target.html]
|
||||
support-files = css-animations/file_effect-target.html
|
||||
[css-animations/test_element-get-animations.html]
|
||||
|
@ -53,6 +55,8 @@ support-files = css-transitions/file_animation-ready.html
|
|||
support-files = css-transitions/file_animation-starttime.html
|
||||
[css-transitions/test_csstransition-transitionproperty.html]
|
||||
support-files = css-transitions/file_csstransition-transitionproperty.html
|
||||
[css-transitions/test_keyframeeffect-getframes.html]
|
||||
support-files = css-transitions/file_keyframeeffect-getframes.html
|
||||
[css-transitions/test_effect-target.html]
|
||||
support-files = css-transitions/file_effect-target.html
|
||||
[css-transitions/test_element-get-animations.html]
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsCRT.h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsIAuthPrompt.h"
|
||||
#include "nsIAuthPrompt2.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIPromptFactory.h"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "mozilla/dom/FileList.h"
|
||||
#include "mozilla/dom/FileListBinding.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "MessageEvent.h"
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileList.h"
|
||||
#include "mozilla/dom/FileListBinding.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
#include "nsIRunnable.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
|
@ -4,9 +4,18 @@
|
|||
|
||||
#include "ScreenOrientation.h"
|
||||
#include "nsIDeviceSensors.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsScreen.h"
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ScreenOrientation,
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef nsCopySupport_h__
|
||||
#define nsCopySupport_h__
|
||||
|
||||
#include "nsError.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
class nsINode;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "nsICategoryManager.h"
|
||||
#include "nsIComponentRegistrar.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "xptcall.h"
|
||||
|
|
|
@ -213,6 +213,12 @@ nsDOMDataChannel::BufferedAmount() const
|
|||
return mDataChannel->GetBufferedAmount();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsDOMDataChannel::BufferedAmountLowThreshold() const
|
||||
{
|
||||
return mDataChannel->GetBufferedAmountLowThreshold();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDataChannel::GetBufferedAmount(uint32_t* aBufferedAmount)
|
||||
{
|
||||
|
@ -220,6 +226,12 @@ nsDOMDataChannel::GetBufferedAmount(uint32_t* aBufferedAmount)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDataChannel::SetBufferedAmountLowThreshold(uint32_t aThreshold)
|
||||
{
|
||||
mDataChannel->SetBufferedAmountLowThreshold(aThreshold);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDOMDataChannel::GetBinaryType(nsAString & aBinaryType)
|
||||
{
|
||||
switch (mBinaryType) {
|
||||
|
@ -468,6 +480,14 @@ nsDOMDataChannel::OnChannelClosed(nsISupports* aContext)
|
|||
return OnSimpleEvent(aContext, NS_LITERAL_STRING("close"));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMDataChannel::OnBufferLow(nsISupports* aContext)
|
||||
{
|
||||
LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
|
||||
|
||||
return OnSimpleEvent(aContext, NS_LITERAL_STRING("bufferedamountlow"));
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDataChannel::AppReady()
|
||||
{
|
||||
|
|
|
@ -54,11 +54,14 @@ public:
|
|||
bool Reliable() const;
|
||||
mozilla::dom::RTCDataChannelState ReadyState() const;
|
||||
uint32_t BufferedAmount() const;
|
||||
uint32_t BufferedAmountLowThreshold() const;
|
||||
void SetBufferedAmountLowThreshold(uint32_t aThreshold);
|
||||
IMPL_EVENT_HANDLER(open)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
IMPL_EVENT_HANDLER(close)
|
||||
// Uses XPIDL Close.
|
||||
IMPL_EVENT_HANDLER(message)
|
||||
IMPL_EVENT_HANDLER(bufferedamountlow)
|
||||
mozilla::dom::RTCDataChannelType BinaryType() const
|
||||
{
|
||||
return static_cast<mozilla::dom::RTCDataChannelType>(
|
||||
|
@ -97,6 +100,9 @@ public:
|
|||
virtual nsresult
|
||||
OnChannelClosed(nsISupports* aContext) override;
|
||||
|
||||
virtual nsresult
|
||||
OnBufferLow(nsISupports* aContext) override;
|
||||
|
||||
virtual void
|
||||
AppReady();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsError.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsTextFragment.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using mozilla::dom::TreeOrderComparator;
|
||||
using mozilla::dom::Animation;
|
||||
|
||||
nsAutoTArray<nsRefPtr<nsDOMMutationObserver>, 4>*
|
||||
|
|
|
@ -1532,7 +1532,8 @@ nsIDocument::nsIDocument()
|
|||
mGetUserFontSetCalled(false),
|
||||
mPostedFlushUserFontSet(false),
|
||||
mPartID(0),
|
||||
mDidFireDOMContentLoaded(true)
|
||||
mDidFireDOMContentLoaded(true),
|
||||
mUserHasInteracted(false)
|
||||
{
|
||||
SetInDocument();
|
||||
|
||||
|
|
|
@ -1343,7 +1343,7 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, int32_t aFlags,
|
|||
nsCOMPtr<nsIDocShell> docShell = newWindow->GetDocShell();
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
||||
if (presShell)
|
||||
if (presShell && presShell->DidInitialize())
|
||||
ScrollIntoView(presShell, contentToFocus, aFlags);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "prenv.h"
|
||||
|
||||
#include "mozIApplication.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsIDOMHTMLFrameElement.h"
|
||||
#include "nsIDOMMozBrowserFrame.h"
|
||||
|
|
|
@ -699,6 +699,7 @@ GK_ATOM(onblocked, "onblocked")
|
|||
GK_ATOM(onblur, "onblur")
|
||||
GK_ATOM(onbroadcast, "onbroadcast")
|
||||
GK_ATOM(onbusy, "onbusy")
|
||||
GK_ATOM(onbufferedamountlow, "onbufferedamountlow")
|
||||
GK_ATOM(oncached, "oncached")
|
||||
GK_ATOM(oncallschanged, "oncallschanged")
|
||||
GK_ATOM(oncancel, "oncancel")
|
||||
|
|
|
@ -2602,6 +2602,16 @@ public:
|
|||
|
||||
void PropagateUseCounters(nsIDocument* aParentDocument);
|
||||
|
||||
void SetUserHasInteracted(bool aUserHasInteracted)
|
||||
{
|
||||
mUserHasInteracted = aUserHasInteracted;
|
||||
}
|
||||
|
||||
bool UserHasInteracted()
|
||||
{
|
||||
return mUserHasInteracted;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||
{
|
||||
|
@ -3007,6 +3017,9 @@ protected:
|
|||
// Flags for whether we've notified our top-level "page" of a use counter
|
||||
// for this child document.
|
||||
std::bitset<mozilla::eUseCounter_Count> mNotifiedPageForUseCounter;
|
||||
|
||||
// Whether the user has interacted with the document or not:
|
||||
bool mUserHasInteracted;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIExternalProtocolHandler.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
|
|
|
@ -1473,6 +1473,37 @@ nsObjectLoadingContent::CheckJavaCodebase()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsObjectLoadingContent::IsYoutubeEmbed()
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ASSERTION(thisContent, "Must be an instance of content");
|
||||
|
||||
// We're only interested in switching out embed tags
|
||||
if (!thisContent->NodeInfo()->Equals(nsGkAtoms::embed)) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIEffectiveTLDService> tldService =
|
||||
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
|
||||
// If we can't analyze the URL, just pass on through.
|
||||
if(!tldService) {
|
||||
NS_WARNING("Could not get TLD service!");
|
||||
return false;
|
||||
}
|
||||
nsAutoCString currentBaseDomain;
|
||||
bool ok = NS_SUCCEEDED(tldService->GetBaseDomain(mURI, 0, currentBaseDomain));
|
||||
if (!ok) {
|
||||
NS_WARNING("Could not parse plugin domain!");
|
||||
return false;
|
||||
}
|
||||
nsAutoCString domain("youtube.com");
|
||||
if (StringEndsWith(domain, currentBaseDomain)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsObjectLoadingContent::CheckLoadPolicy(int16_t *aContentPolicy)
|
||||
{
|
||||
|
@ -2122,6 +2153,11 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check whether this is a youtube embed.
|
||||
if (IsYoutubeEmbed()) {
|
||||
Telemetry::Accumulate(Telemetry::YOUTUBE_EMBED_SEEN, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Security checks
|
||||
//
|
||||
|
|
|
@ -519,6 +519,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
*/
|
||||
nsPluginFrame* GetExistingFrame();
|
||||
|
||||
bool IsYoutubeEmbed();
|
||||
|
||||
// Helper class for SetupProtoChain
|
||||
class SetupProtoChainRunner final : public nsIRunnable
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsLWBrkCIID.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsParserConstants.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
|
|
|
@ -503,6 +503,8 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
mouseEvent->mMessage != eMouseEnterIntoWidget &&
|
||||
mouseEvent->mMessage != eMouseExitFromWidget) ||
|
||||
aEvent->mClass == eWheelEventClass ||
|
||||
aEvent->mClass == ePointerEventClass ||
|
||||
aEvent->mClass == eTouchEventClass ||
|
||||
aEvent->mClass == eKeyboardEventClass)) {
|
||||
if (gMouseOrKeyboardEventCounter == 0) {
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
|
@ -513,6 +515,20 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
++gMouseOrKeyboardEventCounter;
|
||||
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aTargetContent);
|
||||
if (node &&
|
||||
(aEvent->mMessage == eKeyUp || aEvent->mMessage == eMouseUp ||
|
||||
aEvent->mMessage == eWheel || aEvent->mMessage == eTouchEnd ||
|
||||
aEvent->mMessage == ePointerUp)) {
|
||||
nsIDocument* doc = node->OwnerDoc();
|
||||
while (doc && !doc->UserHasInteracted()) {
|
||||
doc->SetUserHasInteracted(true);
|
||||
doc = nsContentUtils::IsChildOfSameType(doc) ?
|
||||
doc->GetParentDocument() : nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WheelTransaction::OnEvent(aEvent);
|
||||
|
|
|
@ -1411,7 +1411,9 @@ MediaFormatReader::Seek(int64_t aTime, int64_t aUnused)
|
|||
|
||||
nsRefPtr<SeekPromise> p = mSeekPromise.Ensure(__func__);
|
||||
|
||||
AttemptSeek();
|
||||
RefPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethod(this, &MediaFormatReader::AttemptSeek));
|
||||
OwnerThread()->Dispatch(task.forget());
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -1420,6 +1422,13 @@ void
|
|||
MediaFormatReader::AttemptSeek()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
if (mPendingSeekTime.isNothing()) {
|
||||
return;
|
||||
}
|
||||
// An internal seek may be pending due to Seek queueing multiple tasks calling
|
||||
// AttemptSeek ; we can ignore those by resetting any pending demuxer's seek.
|
||||
mAudio.mSeekRequest.DisconnectIfExists();
|
||||
mVideo.mSeekRequest.DisconnectIfExists();
|
||||
if (HasVideo()) {
|
||||
DoVideoSeek();
|
||||
} else if (HasAudio()) {
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "nsIRandomGenerator.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -369,4 +372,98 @@ CreateFlushableMediaDecodeTaskQueue()
|
|||
return queue.forget();
|
||||
}
|
||||
|
||||
void
|
||||
SimpleTimer::Cancel() {
|
||||
if (mTimer) {
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIEventTarget> target;
|
||||
mTimer->GetTarget(getter_AddRefs(target));
|
||||
nsCOMPtr<nsIThread> thread(do_QueryInterface(target));
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == thread);
|
||||
#endif
|
||||
mTimer->Cancel();
|
||||
mTimer = nullptr;
|
||||
}
|
||||
mTask = nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SimpleTimer::Notify(nsITimer *timer) {
|
||||
nsRefPtr<SimpleTimer> deathGrip(this);
|
||||
if (mTask) {
|
||||
mTask->Run();
|
||||
mTask = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SimpleTimer::Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Get target thread first, so we don't have to cancel the timer if it fails.
|
||||
nsCOMPtr<nsIThread> target;
|
||||
if (aTarget) {
|
||||
target = aTarget;
|
||||
} else {
|
||||
rv = NS_GetMainThread(getter_AddRefs(target));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
// Note: set target before InitWithCallback in case the timer fires before
|
||||
// we change the event target.
|
||||
rv = timer->SetTarget(aTarget);
|
||||
if (NS_FAILED(rv)) {
|
||||
timer->Cancel();
|
||||
return rv;
|
||||
}
|
||||
rv = timer->InitWithCallback(this, aTimeoutMs, nsITimer::TYPE_ONE_SHOT);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mTimer = timer.forget();
|
||||
mTask = aTask;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(SimpleTimer, nsITimerCallback)
|
||||
|
||||
already_AddRefed<SimpleTimer>
|
||||
SimpleTimer::Create(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget)
|
||||
{
|
||||
nsRefPtr<SimpleTimer> t(new SimpleTimer());
|
||||
if (NS_FAILED(t->Init(aTask, aTimeoutMs, aTarget))) {
|
||||
return nullptr;
|
||||
}
|
||||
return t.forget();
|
||||
}
|
||||
|
||||
void
|
||||
LogToBrowserConsole(const nsAString& aMsg)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
nsAutoString msg(aMsg);
|
||||
nsCOMPtr<nsIRunnable> task =
|
||||
NS_NewRunnableFunction([msg]() { LogToBrowserConsole(msg); });
|
||||
NS_DispatchToMainThread(task.forget(), NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIConsoleService> console(
|
||||
do_GetService("@mozilla.org/consoleservice;1"));
|
||||
if (!console) {
|
||||
NS_WARNING("Failed to log message to console.");
|
||||
return;
|
||||
}
|
||||
nsAutoString msg(aMsg);
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
} // end namespace mozilla
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "prtime.h"
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "TimeUnits.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
using mozilla::CheckedInt64;
|
||||
using mozilla::CheckedUint64;
|
||||
|
@ -301,6 +303,32 @@ nsRefPtr<GenericPromise> InvokeUntil(Work aWork, Condition aCondition) {
|
|||
return p.forget();
|
||||
}
|
||||
|
||||
// Simple timer to run a runnable after a timeout.
|
||||
class SimpleTimer : public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// Create a new timer to run aTask after aTimeoutMs milliseconds
|
||||
// on thread aTarget. If aTarget is null, task is run on the main thread.
|
||||
static already_AddRefed<SimpleTimer> Create(nsIRunnable* aTask,
|
||||
uint32_t aTimeoutMs,
|
||||
nsIThread* aTarget = nullptr);
|
||||
void Cancel();
|
||||
|
||||
NS_IMETHOD Notify(nsITimer *timer) override;
|
||||
|
||||
private:
|
||||
virtual ~SimpleTimer() {}
|
||||
nsresult Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget);
|
||||
|
||||
nsRefPtr<nsIRunnable> mTask;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
|
||||
void
|
||||
LogToBrowserConsole(const nsAString& aMsg);
|
||||
|
||||
} // end namespace mozilla
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/EMEUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -110,19 +108,6 @@ ParseKeySystem(const nsAString& aInputKeySystem,
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
LogToBrowserConsole(const nsAString& aMsg)
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> console(
|
||||
do_GetService("@mozilla.org/consoleservice;1"));
|
||||
if (!console) {
|
||||
NS_WARNING("Failed to log message to console.");
|
||||
return;
|
||||
}
|
||||
nsAutoString msg(aMsg);
|
||||
console->LogStringMessage(msg.get());
|
||||
}
|
||||
|
||||
void
|
||||
ConstructKeySystem(const nsAString& aKeySystem,
|
||||
const nsAString& aCDMVersion,
|
||||
|
|
|
@ -51,9 +51,6 @@ bool ParseKeySystem(const nsAString& aKeySystem,
|
|||
nsAString& aOutKeySystem,
|
||||
int32_t& aOutMinCDMVersion);
|
||||
|
||||
void
|
||||
LogToBrowserConsole(const nsAString& aMsg);
|
||||
|
||||
void
|
||||
ConstructKeySystem(const nsAString& aKeySystem,
|
||||
const nsAString& aCDMVersion,
|
||||
|
|
|
@ -50,6 +50,7 @@ GMPVideoDecoderParent::GMPVideoDecoderParent(GMPContentParent* aPlugin)
|
|||
, mCallback(nullptr)
|
||||
, mVideoHost(this)
|
||||
, mPluginId(aPlugin->GetPluginId())
|
||||
, mFrameCount(0)
|
||||
{
|
||||
MOZ_ASSERT(mPlugin);
|
||||
}
|
||||
|
@ -157,6 +158,7 @@ GMPVideoDecoderParent::Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
|
|||
aRenderTimeMs)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mFrameCount++;
|
||||
|
||||
// Async IPC, we don't have access to a return value.
|
||||
return NS_OK;
|
||||
|
@ -180,14 +182,33 @@ GMPVideoDecoderParent::Reset()
|
|||
|
||||
mIsAwaitingResetComplete = true;
|
||||
|
||||
nsRefPtr<GMPVideoDecoderParent> self(this);
|
||||
nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self]() -> void
|
||||
{
|
||||
LOGD(("GMPVideoDecoderParent[%p]::ResetCompleteTimeout() timed out waiting for ResetComplete", self.get()));
|
||||
self->mResetCompleteTimeout = nullptr;
|
||||
LogToBrowserConsole(NS_LITERAL_STRING("GMPVideoDecoderParent timed out waiting for ResetComplete()"));
|
||||
});
|
||||
CancelResetCompleteTimeout();
|
||||
mResetCompleteTimeout = SimpleTimer::Create(task, 5000, mPlugin->GMPThread());
|
||||
|
||||
// Async IPC, we don't have access to a return value.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
GMPVideoDecoderParent::CancelResetCompleteTimeout()
|
||||
{
|
||||
if (mResetCompleteTimeout) {
|
||||
mResetCompleteTimeout->Cancel();
|
||||
mResetCompleteTimeout = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
GMPVideoDecoderParent::Drain()
|
||||
{
|
||||
LOGD(("GMPVideoDecoderParent[%p]::Drain()", this));
|
||||
LOGD(("GMPVideoDecoderParent[%p]::Drain() frameCount=%d", this, mFrameCount));
|
||||
|
||||
if (!mIsOpen) {
|
||||
NS_WARNING("Trying to use an dead GMP video decoder");
|
||||
|
@ -280,8 +301,9 @@ GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
|
|||
bool
|
||||
GMPVideoDecoderParent::RecvDecoded(const GMPVideoi420FrameData& aDecodedFrame)
|
||||
{
|
||||
LOGV(("GMPVideoDecoderParent[%p]::RecvDecoded() timestamp=%lld",
|
||||
this, aDecodedFrame.mTimestamp()));
|
||||
--mFrameCount;
|
||||
LOGV(("GMPVideoDecoderParent[%p]::RecvDecoded() timestamp=%lld frameCount=%d",
|
||||
this, aDecodedFrame.mTimestamp(), mFrameCount));
|
||||
|
||||
if (!mCallback) {
|
||||
return false;
|
||||
|
@ -345,8 +367,11 @@ GMPVideoDecoderParent::RecvInputDataExhausted()
|
|||
bool
|
||||
GMPVideoDecoderParent::RecvDrainComplete()
|
||||
{
|
||||
LOGD(("GMPVideoDecoderParent[%p]::RecvDrainComplete()", this));
|
||||
|
||||
LOGD(("GMPVideoDecoderParent[%p]::RecvDrainComplete() frameCount=%d", this, mFrameCount));
|
||||
nsAutoString msg;
|
||||
msg.AppendLiteral("GMPVideoDecoderParent::RecvDrainComplete() outstanding frames=");
|
||||
msg.AppendInt(mFrameCount);
|
||||
LogToBrowserConsole(msg);
|
||||
if (!mCallback) {
|
||||
return false;
|
||||
}
|
||||
|
@ -367,6 +392,8 @@ GMPVideoDecoderParent::RecvResetComplete()
|
|||
{
|
||||
LOGD(("GMPVideoDecoderParent[%p]::RecvResetComplete()", this));
|
||||
|
||||
CancelResetCompleteTimeout();
|
||||
|
||||
if (!mCallback) {
|
||||
return false;
|
||||
}
|
||||
|
@ -375,6 +402,7 @@ GMPVideoDecoderParent::RecvResetComplete()
|
|||
return true;
|
||||
}
|
||||
mIsAwaitingResetComplete = false;
|
||||
mFrameCount = 0;
|
||||
|
||||
// Ignore any return code. It is OK for this to fail without killing the process.
|
||||
mCallback->ResetComplete();
|
||||
|
@ -457,7 +485,9 @@ GMPVideoDecoderParent::Recv__delete__()
|
|||
void
|
||||
GMPVideoDecoderParent::UnblockResetAndDrain()
|
||||
{
|
||||
LOGD(("GMPVideoDecoderParent[%p]::UnblockResetAndDrain()", this));
|
||||
LOGD(("GMPVideoDecoderParent[%p]::UnblockResetAndDrain() "
|
||||
"awaitingResetComplete=%d awaitingDrainComplete=%d",
|
||||
this, mIsAwaitingResetComplete, mIsAwaitingDrainComplete));
|
||||
|
||||
if (!mCallback) {
|
||||
MOZ_ASSERT(!mIsAwaitingResetComplete);
|
||||
|
@ -472,6 +502,7 @@ GMPVideoDecoderParent::UnblockResetAndDrain()
|
|||
mIsAwaitingDrainComplete = false;
|
||||
mCallback->DrainComplete();
|
||||
}
|
||||
CancelResetCompleteTimeout();
|
||||
}
|
||||
|
||||
} // namespace gmp
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "GMPUtils.h"
|
||||
#include "GMPVideoHost.h"
|
||||
#include "GMPVideoDecoderProxy.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
@ -80,6 +81,7 @@ private:
|
|||
virtual bool Recv__delete__() override;
|
||||
|
||||
void UnblockResetAndDrain();
|
||||
void CancelResetCompleteTimeout();
|
||||
|
||||
bool mIsOpen;
|
||||
bool mShuttingDown;
|
||||
|
@ -90,6 +92,8 @@ private:
|
|||
GMPVideoDecoderCallbackProxy* mCallback;
|
||||
GMPVideoHostImpl mVideoHost;
|
||||
const uint32_t mPluginId;
|
||||
int32_t mFrameCount;
|
||||
nsRefPtr<SimpleTimer> mResetCompleteTimeout;
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
|
|
|
@ -309,7 +309,7 @@ MediaSourceTrackDemuxer::Reset()
|
|||
nsRefPtr<MediaSourceTrackDemuxer> self = this;
|
||||
nsCOMPtr<nsIRunnable> task =
|
||||
NS_NewRunnableFunction([self] () {
|
||||
self->mManager->Seek(self->mType, TimeUnit());
|
||||
self->mManager->Seek(self->mType, TimeUnit(), TimeUnit());
|
||||
{
|
||||
MonitorAutoLock mon(self->mMonitor);
|
||||
self->mNextRandomAccessPoint =
|
||||
|
@ -364,7 +364,8 @@ MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
|
|||
return SeekPromise::CreateAndReject(DemuxerFailureReason::WAITING_FOR_DATA,
|
||||
__func__);
|
||||
}
|
||||
TimeUnit seekTime = mManager->Seek(mType, aTime);
|
||||
TimeUnit seekTime =
|
||||
mManager->Seek(mType, aTime, TimeUnit::FromMicroseconds(EOS_FUZZ_US));
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mNextRandomAccessPoint = mManager->GetNextRandomAccessPoint(mType);
|
||||
|
|
|
@ -1660,11 +1660,14 @@ TrackBuffersManager::InsertFrames(TrackBuffer& aSamples,
|
|||
}
|
||||
|
||||
// Adjust our demuxing index if necessary.
|
||||
if (trackBuffer.mNextGetSampleIndex.isSome() &&
|
||||
(trackBuffer.mNextInsertionIndex.ref() < trackBuffer.mNextGetSampleIndex.ref() ||
|
||||
(trackBuffer.mNextInsertionIndex.ref() == trackBuffer.mNextGetSampleIndex.ref() &&
|
||||
aIntervals.GetEnd() < trackBuffer.mNextSampleTime))) {
|
||||
trackBuffer.mNextGetSampleIndex.ref() += aSamples.Length();
|
||||
if (trackBuffer.mNextGetSampleIndex.isSome()) {
|
||||
if (trackBuffer.mNextInsertionIndex.ref() == trackBuffer.mNextGetSampleIndex.ref() &&
|
||||
aIntervals.GetEnd() >= trackBuffer.mNextSampleTime) {
|
||||
MSE_DEBUG("Next sample to be played got overwritten");
|
||||
trackBuffer.mNextGetSampleIndex.reset();
|
||||
} else if (trackBuffer.mNextInsertionIndex.ref() <= trackBuffer.mNextGetSampleIndex.ref()) {
|
||||
trackBuffer.mNextGetSampleIndex.ref() += aSamples.Length();
|
||||
}
|
||||
}
|
||||
|
||||
TrackBuffer& data = trackBuffer.mBuffers.LastElement();
|
||||
|
@ -1890,36 +1893,82 @@ TrackBuffersManager::GetTrackBuffer(TrackInfo::TrackType aTrack)
|
|||
return GetTracksData(aTrack).mBuffers.LastElement();
|
||||
}
|
||||
|
||||
uint32_t TrackBuffersManager::FindSampleIndex(const TrackBuffer& aTrackBuffer,
|
||||
const TimeInterval& aInterval)
|
||||
{
|
||||
TimeUnit target = aInterval.mStart - aInterval.mFuzz;
|
||||
|
||||
for (uint32_t i = 0; i < aTrackBuffer.Length(); i++) {
|
||||
const nsRefPtr<MediaRawData>& sample = aTrackBuffer[i];
|
||||
if (sample->mTime >= target.ToMicroseconds() ||
|
||||
sample->GetEndTime() > target.ToMicroseconds()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(false, "FindSampleIndex called with invalid arguments");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TimeUnit
|
||||
TrackBuffersManager::Seek(TrackInfo::TrackType aTrack,
|
||||
const TimeUnit& aTime)
|
||||
const TimeUnit& aTime,
|
||||
const TimeUnit& aFuzz)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
auto& trackBuffer = GetTracksData(aTrack);
|
||||
const TrackBuffersManager::TrackBuffer& track = GetTrackBuffer(aTrack);
|
||||
TimeUnit lastKeyFrameTime;
|
||||
|
||||
if (!track.Length()) {
|
||||
// This a reset. It will be followed by another valid seek.
|
||||
trackBuffer.mNextGetSampleIndex = Some(uint32_t(0));
|
||||
trackBuffer.mNextSampleTimecode = TimeUnit();
|
||||
trackBuffer.mNextSampleTime = TimeUnit();
|
||||
return TimeUnit();
|
||||
}
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
if (aTime != TimeUnit()) {
|
||||
// Determine the interval of samples we're attempting to seek to.
|
||||
TimeIntervals buffered = trackBuffer.mBufferedRanges;
|
||||
TimeIntervals::IndexType index = buffered.Find(aTime);
|
||||
buffered.SetFuzz(aFuzz);
|
||||
index = buffered.Find(aTime);
|
||||
MOZ_ASSERT(index != TimeIntervals::NoIndex);
|
||||
|
||||
TimeInterval target = buffered[index];
|
||||
i = FindSampleIndex(track, target);
|
||||
}
|
||||
|
||||
Maybe<TimeUnit> lastKeyFrameTime;
|
||||
TimeUnit lastKeyFrameTimecode;
|
||||
uint32_t lastKeyFrameIndex = 0;
|
||||
for (uint32_t i = 0; i < track.Length(); i++) {
|
||||
for (; i < track.Length(); i++) {
|
||||
const nsRefPtr<MediaRawData>& sample = track[i];
|
||||
TimeUnit sampleTime = TimeUnit::FromMicroseconds(sample->mTime);
|
||||
if (sampleTime > aTime) {
|
||||
if (sampleTime > aTime && lastKeyFrameTime.isSome()) {
|
||||
break;
|
||||
}
|
||||
if (sample->mKeyframe) {
|
||||
lastKeyFrameTimecode = TimeUnit::FromMicroseconds(sample->mTimecode);
|
||||
lastKeyFrameTime = sampleTime;
|
||||
lastKeyFrameTime = Some(sampleTime);
|
||||
lastKeyFrameIndex = i;
|
||||
}
|
||||
if (sampleTime == aTime) {
|
||||
if (sampleTime == aTime ||
|
||||
(sampleTime > aTime && lastKeyFrameTime.isSome())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
MSE_DEBUG("Keyframe %s found at %lld",
|
||||
lastKeyFrameTime.isSome() ? "" : "not",
|
||||
lastKeyFrameTime.refOr(TimeUnit()).ToMicroseconds());
|
||||
|
||||
trackBuffer.mNextGetSampleIndex = Some(lastKeyFrameIndex);
|
||||
trackBuffer.mNextSampleTimecode = lastKeyFrameTimecode;
|
||||
trackBuffer.mNextSampleTime = lastKeyFrameTime;
|
||||
trackBuffer.mNextSampleTime = lastKeyFrameTime.refOr(TimeUnit());
|
||||
|
||||
return lastKeyFrameTime;
|
||||
return lastKeyFrameTime.refOr(TimeUnit());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -88,7 +88,8 @@ public:
|
|||
return mEnded;
|
||||
}
|
||||
media::TimeUnit Seek(TrackInfo::TrackType aTrack,
|
||||
const media::TimeUnit& aTime);
|
||||
const media::TimeUnit& aTime,
|
||||
const media::TimeUnit& aFuzz);
|
||||
uint32_t SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack,
|
||||
const media::TimeUnit& aTimeThreadshold,
|
||||
bool& aFound);
|
||||
|
@ -262,6 +263,8 @@ private:
|
|||
nsRefPtr<SharedTrackInfo> mLastInfo;
|
||||
|
||||
// If set, position of the next sample to be retrieved by GetSample().
|
||||
// If the position is equal to the TrackBuffer's length, it indicates that
|
||||
// we've reached EOS.
|
||||
Maybe<uint32_t> mNextGetSampleIndex;
|
||||
// Approximation of the next sample's decode timestamp.
|
||||
media::TimeUnit mNextSampleTimecode;
|
||||
|
@ -290,6 +293,9 @@ private:
|
|||
void RemoveFrames(const media::TimeIntervals& aIntervals,
|
||||
TrackData& aTrackData,
|
||||
uint32_t aStartIndex);
|
||||
// Find index of sample. Return a negative value if not found.
|
||||
uint32_t FindSampleIndex(const TrackBuffer& aTrackBuffer,
|
||||
const media::TimeInterval& aInterval);
|
||||
void UpdateBufferedRanges();
|
||||
void RejectProcessing(nsresult aRejectValue, const char* aName);
|
||||
void ResolveProcessing(bool aResolveValue, const char* aName);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "nsPromiseFlatString.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
|
@ -34,10 +33,21 @@ namespace mozilla {
|
|||
NS_WARNING("callback not set"); \
|
||||
}
|
||||
|
||||
static const char* TranslateMimeType(const nsACString& aMimeType)
|
||||
{
|
||||
if (aMimeType.EqualsLiteral("video/webm; codecs=vp8")) {
|
||||
return "video/x-vnd.on2.vp8";
|
||||
} else if (aMimeType.EqualsLiteral("video/webm; codecs=vp9")) {
|
||||
return "video/x-vnd.on2.vp9";
|
||||
}
|
||||
return PromiseFlatCString(aMimeType).get();
|
||||
}
|
||||
|
||||
static MediaCodec::LocalRef CreateDecoder(const nsACString& aMimeType)
|
||||
{
|
||||
MediaCodec::LocalRef codec;
|
||||
NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(PromiseFlatCString(aMimeType).get(), &codec), nullptr);
|
||||
NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(TranslateMimeType(aMimeType),
|
||||
&codec), nullptr);
|
||||
return codec;
|
||||
}
|
||||
|
||||
|
@ -76,8 +86,10 @@ public:
|
|||
}
|
||||
|
||||
bool WantCopy() {
|
||||
// Allocating a texture is incredibly slow on PowerVR
|
||||
return mGLContext->Vendor() != GLVendor::Imagination;
|
||||
// Allocating a texture is incredibly slow on PowerVR and may fail on
|
||||
// emulators, see bug 1190379.
|
||||
return mGLContext->Vendor() != GLVendor::Imagination &&
|
||||
mGLContext->Renderer() != GLRenderer::AndroidEmulator;
|
||||
}
|
||||
|
||||
EGLImage CopySurface(layers::Image* img) {
|
||||
|
@ -287,7 +299,7 @@ AndroidDecoderModule::CreateVideoDecoder(
|
|||
MediaFormat::LocalRef format;
|
||||
|
||||
NS_ENSURE_SUCCESS(MediaFormat::CreateVideoFormat(
|
||||
aConfig.mMimeType,
|
||||
TranslateMimeType(aConfig.mMimeType),
|
||||
aConfig.mDisplay.width,
|
||||
aConfig.mDisplay.height,
|
||||
&format), nullptr);
|
||||
|
|
|
@ -168,9 +168,24 @@ var commandsCheckDataChannel = [
|
|||
}
|
||||
];
|
||||
|
||||
var commandsCheckLargeXfer = [
|
||||
function SEND_BIG_BUFFER(test) {
|
||||
var size = 512*1024; // SCTP internal buffer is 256K, so we'll have ~256K queued
|
||||
var buffer = new ArrayBuffer(size);
|
||||
// note: type received is always blob for binary data
|
||||
var options = {};
|
||||
options.bufferedAmountLowThreshold = 64*1024;
|
||||
return test.send(buffer, options).then(result => {
|
||||
ok(result.data instanceof Blob, "Received data is of instance Blob");
|
||||
is(result.data.size, size, "Received data has the correct size.");
|
||||
});
|
||||
},
|
||||
];
|
||||
|
||||
function addInitialDataChannel(chain) {
|
||||
chain.insertBefore('PC_LOCAL_CREATE_OFFER', commandsCreateDataChannel);
|
||||
chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS', commandsWaitForDataChannel);
|
||||
chain.removeAfter('PC_REMOTE_CHECK_ICE_CONNECTIONS');
|
||||
chain.append(commandsCheckLargeXfer);
|
||||
chain.append(commandsCheckDataChannel);
|
||||
}
|
||||
|
|
|
@ -214,11 +214,21 @@ PeerConnectionTest.prototype.send = function(data, options) {
|
|||
this.pcLocal.dataChannels[this.pcLocal.dataChannels.length - 1];
|
||||
var target = options.targetChannel ||
|
||||
this.pcRemote.dataChannels[this.pcRemote.dataChannels.length - 1];
|
||||
var bufferedamount = options.bufferedAmountLowThreshold || 0;
|
||||
var bufferlow_fired = true; // to make testing later easier
|
||||
if (bufferedamount != 0) {
|
||||
source.bufferedAmountLowThreshold = bufferedamount;
|
||||
bufferlow_fired = false;
|
||||
source.onbufferedamountlow = function() {
|
||||
bufferlow_fired = true;
|
||||
};
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
// Register event handler for the target channel
|
||||
target.onmessage = e => {
|
||||
resolve({ channel: target, data: e.data });
|
||||
target.onmessage = e => {
|
||||
ok(bufferlow_fired, "bufferedamountlow event fired");
|
||||
resolve({ channel: target, data: e.data });
|
||||
};
|
||||
|
||||
source.send(data);
|
||||
|
@ -563,6 +573,7 @@ function DataChannelWrapper(dataChannel, peerConnectionWrapper) {
|
|||
createOneShotEventWrapper(this, this._channel, 'close');
|
||||
createOneShotEventWrapper(this, this._channel, 'error');
|
||||
createOneShotEventWrapper(this, this._channel, 'message');
|
||||
createOneShotEventWrapper(this, this._channel, 'bufferedamountlow');
|
||||
|
||||
this.opened = timerGuard(new Promise(resolve => {
|
||||
this._channel.onopen = () => {
|
||||
|
@ -640,6 +651,16 @@ DataChannelWrapper.prototype = {
|
|||
return this._channel.readyState;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the bufferlowthreshold of the channel
|
||||
*
|
||||
* @param {integer} amoutn
|
||||
* The new threshold for the chanel
|
||||
*/
|
||||
set bufferedAmountLowThreshold(amount) {
|
||||
this._channel.bufferedAmountLowThreshold = amount;
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the data channel
|
||||
*/
|
||||
|
|
|
@ -289,7 +289,7 @@ WebMDemuxer::ReadMetadata()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
int type = nestegg_track_type(mContext, track);
|
||||
if (type == NESTEGG_TRACK_VIDEO) {
|
||||
if (type == NESTEGG_TRACK_VIDEO && !mHasVideo) {
|
||||
nestegg_video_params params;
|
||||
r = nestegg_track_video_params(mContext, track, ¶ms);
|
||||
if (r == -1) {
|
||||
|
@ -364,7 +364,7 @@ WebMDemuxer::ReadMetadata()
|
|||
if (!r) {
|
||||
mInfo.mVideo.mDuration = media::TimeUnit::FromNanoseconds(duration).ToMicroseconds();
|
||||
}
|
||||
} else if (type == NESTEGG_TRACK_AUDIO) {
|
||||
} else if (type == NESTEGG_TRACK_AUDIO && !mHasAudio) {
|
||||
nestegg_audio_params params;
|
||||
r = nestegg_track_audio_params(mContext, track, ¶ms);
|
||||
if (r == -1) {
|
||||
|
|
|
@ -209,12 +209,20 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
|
|||
}
|
||||
|
||||
case nsIContentPolicy::TYPE_WEBSOCKET:
|
||||
case nsIContentPolicy::TYPE_CSP_REPORT:
|
||||
case nsIContentPolicy::TYPE_XSLT: {
|
||||
case nsIContentPolicy::TYPE_CSP_REPORT: {
|
||||
MOZ_ASSERT(false, "contentPolicyType not supported yet");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIContentPolicy::TYPE_XSLT: {
|
||||
mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
|
||||
requestingContext = aLoadInfo->LoadingNode();
|
||||
MOZ_ASSERT(!requestingContext ||
|
||||
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
|
||||
"type_xslt requires requestingContext of type Document");
|
||||
break;
|
||||
}
|
||||
|
||||
case nsIContentPolicy::TYPE_BEACON: {
|
||||
mimeTypeGuess = EmptyCString();
|
||||
requestingContext = aLoadInfo->LoadingNode();
|
||||
|
|
|
@ -57,6 +57,13 @@ public:
|
|||
bool operator!=(const nsSMILKeySpline& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
int32_t Compare(const nsSMILKeySpline& aRhs) const {
|
||||
if (mX1 != aRhs.mX1) return mX1 < aRhs.mX1 ? -1 : 1;
|
||||
if (mY1 != aRhs.mY1) return mY1 < aRhs.mY1 ? -1 : 1;
|
||||
if (mX2 != aRhs.mX2) return mX2 < aRhs.mX2 ? -1 : 1;
|
||||
if (mY2 != aRhs.mY2) return mY2 < aRhs.mY2 ? -1 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
|
|
|
@ -49,6 +49,8 @@ const kSameTab = "same tab";
|
|||
const kNewWin = "new window";
|
||||
const kNewTab = "new tab";
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
// The following "matrices" represent the result of content attempting to
|
||||
|
|
|
@ -21,11 +21,13 @@ interface DataChannel : EventTarget
|
|||
readonly attribute boolean reliable;
|
||||
readonly attribute RTCDataChannelState readyState;
|
||||
readonly attribute unsigned long bufferedAmount;
|
||||
attribute unsigned long bufferedAmountLowThreshold;
|
||||
attribute EventHandler onopen;
|
||||
attribute EventHandler onerror;
|
||||
attribute EventHandler onclose;
|
||||
void close();
|
||||
attribute EventHandler onmessage;
|
||||
attribute EventHandler onbufferedamountlow;
|
||||
attribute RTCDataChannelType binaryType;
|
||||
[Throws]
|
||||
void send(DOMString data);
|
||||
|
|
|
@ -392,6 +392,12 @@ partial interface Document {
|
|||
void removeAnonymousContent(AnonymousContent aContent);
|
||||
};
|
||||
|
||||
// Extension to give chrome JS the ability to determine whether
|
||||
// the user has interacted with the document or not.
|
||||
partial interface Document {
|
||||
[ChromeOnly] readonly attribute boolean userHasInteracted;
|
||||
};
|
||||
|
||||
Document implements XPathEvaluator;
|
||||
Document implements GlobalEventHandlers;
|
||||
Document implements TouchEventHandlers;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/web-animations/#the-compositeoperation-enumeration
|
||||
* https://w3c.github.io/web-animations/#the-keyframe-dictionary
|
||||
* https://w3c.github.io/web-animations/#the-computedkeyframe-dictionary
|
||||
*
|
||||
* Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
enum CompositeOperation { "replace", "add", "accumulate" };
|
||||
|
||||
dictionary Keyframe {
|
||||
double? offset = null;
|
||||
DOMString easing = "linear";
|
||||
CompositeOperation? composite = null;
|
||||
};
|
||||
|
||||
dictionary ComputedKeyframe : Keyframe {
|
||||
double computedOffset;
|
||||
};
|
|
@ -19,5 +19,8 @@ interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
|
|||
// readonly attribute CompositeOperation composite;
|
||||
// readonly attribute DOMString spacing;
|
||||
// KeyframeEffect clone();
|
||||
// sequence<ComputedKeyframe> getFrames ();
|
||||
|
||||
// We use object instead of ComputedKeyframe so that we can put the
|
||||
// property-value pairs on the object.
|
||||
[Throws] sequence<object> getFrames();
|
||||
};
|
||||
|
|
|
@ -274,6 +274,7 @@ WEBIDL_FILES = [
|
|||
'KeyAlgorithm.webidl',
|
||||
'KeyboardEvent.webidl',
|
||||
'KeyEvent.webidl',
|
||||
'Keyframe.webidl',
|
||||
'KeyframeEffect.webidl',
|
||||
'KillSwitch.webidl',
|
||||
'LegacyQueryInterface.webidl',
|
||||
|
|
|
@ -575,6 +575,13 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHOD Cancel() override
|
||||
{
|
||||
// We need to run regardless.
|
||||
Run();
|
||||
return WorkerRunnable::Cancel();
|
||||
}
|
||||
|
||||
virtual void
|
||||
PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
|
||||
override
|
||||
|
@ -1230,6 +1237,13 @@ private:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHOD Cancel() override
|
||||
{
|
||||
// We need to run regardless.
|
||||
Run();
|
||||
return WorkerRunnable::Cancel();
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateRuntimeOptionsRunnable final : public WorkerControlRunnable
|
||||
|
@ -3823,6 +3837,7 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
|
|||
, mRunningExpiredTimeouts(false)
|
||||
, mCloseHandlerStarted(false)
|
||||
, mCloseHandlerFinished(false)
|
||||
, mPendingEventQueueClearing(false)
|
||||
, mMemoryReporterRunning(false)
|
||||
, mBlockedForMemoryReporter(false)
|
||||
, mCancelAllPendingRunnables(false)
|
||||
|
@ -4651,6 +4666,7 @@ WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot)
|
|||
AssertIsOnWorkerThread();
|
||||
MOZ_ASSERT(mChildWorkers.IsEmpty());
|
||||
MOZ_ASSERT(mSyncLoopStack.IsEmpty());
|
||||
MOZ_ASSERT(!mPendingEventQueueClearing);
|
||||
|
||||
ClearMainEventQueue(aRanOrNot);
|
||||
#ifdef DEBUG
|
||||
|
@ -4881,6 +4897,7 @@ WorkerPrivate::ClearMainEventQueue(WorkerRanOrNot aRanOrNot)
|
|||
{
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
MOZ_ASSERT(!mSyncLoopStack.Length());
|
||||
MOZ_ASSERT(!mCancelAllPendingRunnables);
|
||||
mCancelAllPendingRunnables = true;
|
||||
|
||||
|
@ -5243,6 +5260,11 @@ WorkerPrivate::DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread)
|
|||
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aThread->PopEventQueue(nestedEventTarget)));
|
||||
|
||||
if (!mSyncLoopStack.Length() && mPendingEventQueueClearing) {
|
||||
ClearMainEventQueue(WorkerRan);
|
||||
mPendingEventQueueClearing = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -5509,7 +5531,13 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
|||
// If this is the first time our status has changed then we need to clear the
|
||||
// main event queue.
|
||||
if (previousStatus == Running) {
|
||||
ClearMainEventQueue(WorkerRan);
|
||||
// NB: If we're in a sync loop, we can't clear the queue immediately,
|
||||
// because this is the wrong queue. So we have to defer it until later.
|
||||
if (mSyncLoopStack.Length()) {
|
||||
mPendingEventQueueClearing = true;
|
||||
} else {
|
||||
ClearMainEventQueue(WorkerRan);
|
||||
}
|
||||
}
|
||||
|
||||
// If we've run the close handler, we don't need to do anything else.
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче