зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
aa2bc77d7f
|
@ -66,33 +66,14 @@ tasks:
|
||||||
env:
|
env:
|
||||||
# checkout-gecko uses these to check out the source; the inputs
|
# checkout-gecko uses these to check out the source; the inputs
|
||||||
# to `mach taskgraph decision` are all on the command line.
|
# to `mach taskgraph decision` are all on the command line.
|
||||||
GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-central'
|
GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-unified'
|
||||||
GECKO_HEAD_REPOSITORY: '{{{url}}}'
|
GECKO_HEAD_REPOSITORY: '{{{url}}}'
|
||||||
GECKO_HEAD_REF: '{{revision}}'
|
GECKO_HEAD_REF: '{{revision}}'
|
||||||
GECKO_HEAD_REV: '{{revision}}'
|
GECKO_HEAD_REV: '{{revision}}'
|
||||||
|
# Arguments passed into `mach taskgraph decision`
|
||||||
cache:
|
# TODO use mozilla-unified for the base repository once the tc-vcs
|
||||||
level-{{level}}-{{project}}-tc-vcs-public-sources: /home/worker/.tc-vcs/
|
# tar.gz archives are created or tc-vcs isn't being used.
|
||||||
level-{{level}}-{{project}}-gecko-decision: /home/worker/workspace
|
DECISION_ARGS: >
|
||||||
|
|
||||||
features:
|
|
||||||
taskclusterProxy: true
|
|
||||||
|
|
||||||
# Note: This task is built server side without the context or tooling that
|
|
||||||
# exist in tree so we must hard code the version
|
|
||||||
image: 'taskcluster/decision:0.1.0'
|
|
||||||
|
|
||||||
maxRunTime: 1800
|
|
||||||
|
|
||||||
command:
|
|
||||||
- /bin/bash
|
|
||||||
- -cx
|
|
||||||
- >
|
|
||||||
mkdir -p /home/worker/artifacts &&
|
|
||||||
checkout-gecko workspace &&
|
|
||||||
cd workspace/gecko &&
|
|
||||||
ln -s /home/worker/artifacts artifacts &&
|
|
||||||
./mach taskgraph decision
|
|
||||||
--pushlog-id='{{pushlog_id}}'
|
--pushlog-id='{{pushlog_id}}'
|
||||||
--project='{{project}}'
|
--project='{{project}}'
|
||||||
--message='{{comment}}'
|
--message='{{comment}}'
|
||||||
|
@ -104,6 +85,22 @@ tasks:
|
||||||
--head-rev='{{revision}}'
|
--head-rev='{{revision}}'
|
||||||
--revision-hash='{{revision_hash}}'
|
--revision-hash='{{revision_hash}}'
|
||||||
|
|
||||||
|
cache:
|
||||||
|
level-{{level}}-hg-shared: /home/worker/hg-shared
|
||||||
|
level-{{level}}-{{project}}-gecko-decision: /home/worker/workspace
|
||||||
|
|
||||||
|
features:
|
||||||
|
taskclusterProxy: true
|
||||||
|
|
||||||
|
# Note: This task is built server side without the context or tooling that
|
||||||
|
# exist in tree so we must hard code the version
|
||||||
|
image: 'taskcluster/decision:0.1.2'
|
||||||
|
|
||||||
|
maxRunTime: 1800
|
||||||
|
|
||||||
|
command:
|
||||||
|
- /home/worker/bin/run-decision
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
'public':
|
'public':
|
||||||
type: 'directory'
|
type: 'directory'
|
||||||
|
|
|
@ -7452,7 +7452,7 @@ var gRemoteTabsUI = {
|
||||||
* passed via this object.
|
* passed via this object.
|
||||||
* This object also allows:
|
* This object also allows:
|
||||||
* - 'ignoreFragment' property to be set to true to exclude fragment-portion
|
* - 'ignoreFragment' property to be set to true to exclude fragment-portion
|
||||||
* matching when comparing URIs.
|
* matching when comparing URIs. Fragment will be replaced.
|
||||||
* - 'ignoreQueryString' property to be set to true to exclude query string
|
* - 'ignoreQueryString' property to be set to true to exclude query string
|
||||||
* matching when comparing URIs.
|
* matching when comparing URIs.
|
||||||
* - 'replaceQueryString' property to be set to true to exclude query string
|
* - 'replaceQueryString' property to be set to true to exclude query string
|
||||||
|
@ -7488,32 +7488,42 @@ function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Remove the query string, fragment, both, or neither from a given url.
|
||||||
|
function cleanURL(url, removeQuery, removeFragment) {
|
||||||
|
let ret = url;
|
||||||
|
if (removeFragment) {
|
||||||
|
ret = ret.split("#")[0];
|
||||||
|
if (removeQuery) {
|
||||||
|
// This removes a query, if present before the fragment.
|
||||||
|
ret = ret.split("?")[0];
|
||||||
|
}
|
||||||
|
} else if (removeQuery) {
|
||||||
|
// This is needed in case there is a fragment after the query.
|
||||||
|
let fragment = ret.split("#")[1];
|
||||||
|
ret = ret.split("?")[0].concat(
|
||||||
|
(fragment != undefined) ? "#".concat(fragment) : "");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to handle nsSimpleURIs here too (e.g. about:...), which don't
|
||||||
|
// work correctly with URL objects - so treat them as strings
|
||||||
|
let requestedCompare = cleanURL(
|
||||||
|
aURI.spec, ignoreQueryString || replaceQueryString, ignoreFragment);
|
||||||
let browsers = aWindow.gBrowser.browsers;
|
let browsers = aWindow.gBrowser.browsers;
|
||||||
for (let i = 0; i < browsers.length; i++) {
|
for (let i = 0; i < browsers.length; i++) {
|
||||||
let browser = browsers[i];
|
let browser = browsers[i];
|
||||||
if (ignoreFragment ? browser.currentURI.equalsExceptRef(aURI) :
|
let browserCompare = cleanURL(
|
||||||
browser.currentURI.equals(aURI)) {
|
browser.currentURI.spec, ignoreQueryString || replaceQueryString, ignoreFragment);
|
||||||
// Focus the matching window & tab
|
if (requestedCompare == browserCompare) {
|
||||||
aWindow.focus();
|
aWindow.focus();
|
||||||
if (ignoreFragment) {
|
if (ignoreFragment || replaceQueryString) {
|
||||||
let spec = aURI.spec;
|
|
||||||
browser.loadURI(spec);
|
|
||||||
}
|
|
||||||
aWindow.gBrowser.tabContainer.selectedIndex = i;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (ignoreQueryString || replaceQueryString) {
|
|
||||||
if (browser.currentURI.spec.split("?")[0] == aURI.spec.split("?")[0]) {
|
|
||||||
// Focus the matching window & tab
|
|
||||||
aWindow.focus();
|
|
||||||
if (replaceQueryString) {
|
|
||||||
browser.loadURI(aURI.spec);
|
browser.loadURI(aURI.spec);
|
||||||
}
|
}
|
||||||
aWindow.gBrowser.tabContainer.selectedIndex = i;
|
aWindow.gBrowser.tabContainer.selectedIndex = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
add_task(function test_ignoreFragment() {
|
add_task(function *test_ignoreFragment() {
|
||||||
let tabRefAboutHome = gBrowser.addTab("about:home#1");
|
let tabRefAboutHome = gBrowser.addTab("about:home#1");
|
||||||
yield promiseTabLoaded(tabRefAboutHome);
|
yield promiseTabLoaded(tabRefAboutHome);
|
||||||
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
||||||
|
@ -35,7 +35,7 @@ add_task(function test_ignoreFragment() {
|
||||||
cleanupTestTabs();
|
cleanupTestTabs();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function test_ignoreQueryString() {
|
add_task(function* test_ignoreQueryString() {
|
||||||
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
|
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
|
||||||
yield promiseTabLoaded(tabRefAboutHome);
|
yield promiseTabLoaded(tabRefAboutHome);
|
||||||
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
||||||
|
@ -52,7 +52,7 @@ add_task(function test_ignoreQueryString() {
|
||||||
cleanupTestTabs();
|
cleanupTestTabs();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function test_replaceQueryString() {
|
add_task(function* test_replaceQueryString() {
|
||||||
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
|
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
|
||||||
yield promiseTabLoaded(tabRefAboutHome);
|
yield promiseTabLoaded(tabRefAboutHome);
|
||||||
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
||||||
|
@ -72,6 +72,38 @@ add_task(function test_replaceQueryString() {
|
||||||
cleanupTestTabs();
|
cleanupTestTabs();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_task(function* test_replaceQueryStringAndFragment() {
|
||||||
|
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox#aaa");
|
||||||
|
yield promiseTabLoaded(tabRefAboutHome);
|
||||||
|
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla?hello=firefoxos#aaa");
|
||||||
|
yield promiseTabLoaded(tabRefAboutMozilla);
|
||||||
|
gBrowser.selectedTab = tabRefAboutMozilla;
|
||||||
|
|
||||||
|
switchTab("about:home", false);
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
switchTab("about:home?hello=firefox#aaa", true);
|
||||||
|
is(tabRefAboutHome, gBrowser.selectedTab, "Selected tab should be the initial about:home tab");
|
||||||
|
switchTab("about:mozilla?hello=firefox#bbb", true, { replaceQueryString: true, ignoreFragment: true });
|
||||||
|
is(tabRefAboutMozilla, gBrowser.selectedTab, "Selected tab should be the initial about:mozilla tab");
|
||||||
|
switchTab("about:home?hello=firefoxos#bbb", true, { ignoreQueryString: true, ignoreFragment: true });
|
||||||
|
is(tabRefAboutHome, gBrowser.selectedTab, "Selected tab should be the initial about:home tab");
|
||||||
|
cleanupTestTabs();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* test_ignoreQueryStringIgnoresFragment() {
|
||||||
|
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox#aaa");
|
||||||
|
yield promiseTabLoaded(tabRefAboutHome);
|
||||||
|
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla?hello=firefoxos#aaa");
|
||||||
|
yield promiseTabLoaded(tabRefAboutMozilla);
|
||||||
|
gBrowser.selectedTab = tabRefAboutMozilla;
|
||||||
|
|
||||||
|
switchTab("about:home?hello=firefox#bbb", false, { ignoreQueryString: true });
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
switchTab("about:home?hello=firefoxos#aaa", true, { ignoreQueryString: true });
|
||||||
|
is(tabRefAboutHome, gBrowser.selectedTab, "Selected tab should be the initial about:home tab");
|
||||||
|
cleanupTestTabs();
|
||||||
|
});
|
||||||
|
|
||||||
// Begin helpers
|
// Begin helpers
|
||||||
|
|
||||||
function cleanupTestTabs() {
|
function cleanupTestTabs() {
|
||||||
|
|
|
@ -627,7 +627,7 @@ function openPreferences(paneID, extraArgs)
|
||||||
win = Services.ww.openWindow(null, Services.prefs.getCharPref("browser.chromeURL"),
|
win = Services.ww.openWindow(null, Services.prefs.getCharPref("browser.chromeURL"),
|
||||||
"_blank", "chrome,dialog=no,all", windowArguments);
|
"_blank", "chrome,dialog=no,all", windowArguments);
|
||||||
} else {
|
} else {
|
||||||
newLoad = !win.switchToTabHavingURI(preferencesURL, true, {ignoreFragment: true});
|
newLoad = !win.switchToTabHavingURI(preferencesURL, true, { ignoreFragment: true, replaceQueryString: true });
|
||||||
browser = win.gBrowser.selectedBrowser;
|
browser = win.gBrowser.selectedBrowser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,12 +140,24 @@ toolbarbutton.bookmark-item:not(.subviewbutton):not(:hover):not(:active):not([op
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolbarbutton.bookmark-item:not(.subviewbutton) {
|
||||||
|
-moz-appearance: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 2px;
|
||||||
|
transition-property: background-color, border-color;
|
||||||
|
transition-duration: 150ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbarbutton.bookmark-item:not(.subviewbutton):hover:not([open]) {
|
||||||
|
background-color: var(--toolbarbutton-hover-background);
|
||||||
|
border-color: var(--toolbarbutton-hover-bordercolor);
|
||||||
|
}
|
||||||
|
|
||||||
toolbarbutton.bookmark-item:not(.subviewbutton):hover:active,
|
toolbarbutton.bookmark-item:not(.subviewbutton):hover:active,
|
||||||
toolbarbutton.bookmark-item[open="true"] {
|
toolbarbutton.bookmark-item[open="true"] {
|
||||||
padding-top: 3px;
|
background: var(--toolbarbutton-active-background);
|
||||||
padding-bottom: 1px;
|
box-shadow: var(--toolbarbutton-active-boxshadow);
|
||||||
padding-inline-start: 4px;
|
border-color: var(--toolbarbutton-active-bordercolor);
|
||||||
padding-inline-end: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmark-item > .toolbarbutton-icon,
|
.bookmark-item > .toolbarbutton-icon,
|
||||||
|
@ -1670,7 +1682,7 @@ toolbarbutton.chevron {
|
||||||
list-style-image: url("chrome://global/skin/toolbar/chevron.gif") !important;
|
list-style-image: url("chrome://global/skin/toolbar/chevron.gif") !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
toolbar[brighttext] toolbarbutton.chevron:not(:hover):not([open="true"]) {
|
toolbar[brighttext] toolbarbutton.chevron {
|
||||||
list-style-image: url("chrome://global/skin/toolbar/chevron-inverted.png") !important;
|
list-style-image: url("chrome://global/skin/toolbar/chevron-inverted.png") !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -464,14 +464,20 @@ toolbarbutton.bookmark-item:not(.subviewbutton),
|
||||||
#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder {
|
#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px 3px;
|
padding: 2px 3px;
|
||||||
|
-moz-appearance: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
toolbarbutton.bookmark-item:not([disabled="true"]):not(.subviewbutton):hover:active,
|
toolbarbutton.bookmark-item:not(.subviewbutton):hover:not([disabled="true"]):not([open]) {
|
||||||
|
border-color: var(--toolbarbutton-hover-bordercolor);
|
||||||
|
background: var(--toolbarbutton-hover-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
toolbarbutton.bookmark-item:not(.subviewbutton):hover:active:not([disabled="true"]),
|
||||||
toolbarbutton.bookmark-item[open="true"] {
|
toolbarbutton.bookmark-item[open="true"] {
|
||||||
padding-top: 3px;
|
border-color: var(--toolbarbutton-active-bordercolor);
|
||||||
padding-bottom: 1px;
|
box-shadow: var(--toolbarbutton-active-boxshadow);
|
||||||
padding-inline-start: 4px;
|
background: var(--toolbarbutton-active-background);
|
||||||
padding-inline-end: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmark-item > .toolbarbutton-icon,
|
.bookmark-item > .toolbarbutton-icon,
|
||||||
|
|
|
@ -147,18 +147,6 @@ if test "$CLANG_CXX"; then
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) actually is a C++ compiler])
|
|
||||||
AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
_SAVE_LIBS=$LIBS
|
|
||||||
LIBS=
|
|
||||||
AC_TRY_LINK([#include <new>], [int *foo = new int;],,
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
AC_MSG_ERROR([$CXX $CXXFLAGS $LDFLAGS failed to compile and link a simple C++ source.]))
|
|
||||||
LIBS=$_SAVE_LIBS
|
|
||||||
AC_LANG_RESTORE
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
|
|
||||||
if test -n "$DEVELOPER_OPTIONS"; then
|
if test -n "$DEVELOPER_OPTIONS"; then
|
||||||
MOZ_FORCE_GOLD=1
|
MOZ_FORCE_GOLD=1
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -117,6 +117,7 @@ export MOZ_DEBUG_SYMBOLS
|
||||||
|
|
||||||
DEFAULT_GMAKE_FLAGS =
|
DEFAULT_GMAKE_FLAGS =
|
||||||
DEFAULT_GMAKE_FLAGS += CC='$(CC)'
|
DEFAULT_GMAKE_FLAGS += CC='$(CC)'
|
||||||
|
DEFAULT_GMAKE_FLAGS += MT='$(MT)'
|
||||||
DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST)
|
DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST)
|
||||||
DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR)
|
DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR)
|
||||||
DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST)
|
DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST)
|
||||||
|
|
|
@ -662,14 +662,14 @@ ifdef MSMANIFEST_TOOL
|
||||||
@if test -f $@.manifest; then \
|
@if test -f $@.manifest; then \
|
||||||
if test -f '$(srcdir)/$@.manifest'; then \
|
if test -f '$(srcdir)/$@.manifest'; then \
|
||||||
echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
|
echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
|
||||||
mt.exe -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||||
else \
|
else \
|
||||||
echo 'Embedding manifest from $@.manifest'; \
|
echo 'Embedding manifest from $@.manifest'; \
|
||||||
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||||
fi; \
|
fi; \
|
||||||
elif test -f '$(srcdir)/$@.manifest'; then \
|
elif test -f '$(srcdir)/$@.manifest'; then \
|
||||||
echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
|
echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
|
||||||
mt.exe -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
||||||
fi
|
fi
|
||||||
endif # MSVC with manifest tool
|
endif # MSVC with manifest tool
|
||||||
ifdef MOZ_PROFILE_GENERATE
|
ifdef MOZ_PROFILE_GENERATE
|
||||||
|
@ -697,14 +697,14 @@ ifdef MSMANIFEST_TOOL
|
||||||
@if test -f $@.manifest; then \
|
@if test -f $@.manifest; then \
|
||||||
if test -f '$(srcdir)/$@.manifest'; then \
|
if test -f '$(srcdir)/$@.manifest'; then \
|
||||||
echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
|
echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
|
||||||
mt.exe -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||||
else \
|
else \
|
||||||
echo 'Embedding manifest from $@.manifest'; \
|
echo 'Embedding manifest from $@.manifest'; \
|
||||||
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||||
fi; \
|
fi; \
|
||||||
elif test -f '$(srcdir)/$@.manifest'; then \
|
elif test -f '$(srcdir)/$@.manifest'; then \
|
||||||
echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
|
echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
|
||||||
mt.exe -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
||||||
fi
|
fi
|
||||||
endif # MSVC with manifest tool
|
endif # MSVC with manifest tool
|
||||||
else
|
else
|
||||||
|
@ -732,7 +732,7 @@ ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
|
||||||
$(EXPAND_LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
|
$(EXPAND_LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
|
||||||
ifdef MSMANIFEST_TOOL
|
ifdef MSMANIFEST_TOOL
|
||||||
@if test -f $@.manifest; then \
|
@if test -f $@.manifest; then \
|
||||||
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||||
rm -f $@.manifest; \
|
rm -f $@.manifest; \
|
||||||
fi
|
fi
|
||||||
endif # MSVC with manifest tool
|
endif # MSVC with manifest tool
|
||||||
|
@ -833,7 +833,7 @@ ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
|
||||||
ifdef MSMANIFEST_TOOL
|
ifdef MSMANIFEST_TOOL
|
||||||
ifdef EMBED_MANIFEST_AT
|
ifdef EMBED_MANIFEST_AT
|
||||||
@if test -f $@.manifest; then \
|
@if test -f $@.manifest; then \
|
||||||
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
|
$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
|
||||||
rm -f $@.manifest; \
|
rm -f $@.manifest; \
|
||||||
fi
|
fi
|
||||||
endif # EMBED_MANIFEST_AT
|
endif # EMBED_MANIFEST_AT
|
||||||
|
|
|
@ -11,5 +11,10 @@
|
||||||
"synthesizeKeyFromKeyTag": true,
|
"synthesizeKeyFromKeyTag": true,
|
||||||
"TargetFactory": true,
|
"TargetFactory": true,
|
||||||
"waitForTick": true,
|
"waitForTick": true,
|
||||||
}
|
},
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
// Tests can always import anything.
|
||||||
|
"mozilla/reject-some-requires": 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,7 @@
|
||||||
"block-scoped-var": 0,
|
"block-scoped-var": 0,
|
||||||
// Allow run_test to be unused in xpcshell
|
// Allow run_test to be unused in xpcshell
|
||||||
"no-unused-vars": [2, { "varsIgnorePattern": "run_test" }],
|
"no-unused-vars": [2, { "varsIgnorePattern": "run_test" }],
|
||||||
|
// Tests can always import anything.
|
||||||
|
"mozilla/reject-some-requires": 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
// Extend from the devtools eslintrc.
|
||||||
|
"extends": "../../.eslintrc",
|
||||||
|
|
||||||
|
"rules": {
|
||||||
|
// The inspector is being migrated to HTML and cleaned of
|
||||||
|
// chrome-privileged code, so this rule disallows requiring chrome
|
||||||
|
// code. Some files in the inspector disable this rule still. The
|
||||||
|
// goal is to enable the rule globally on all files.
|
||||||
|
"mozilla/reject-some-requires": [2, "^(chrome|chrome:.*|resource:.*|devtools/server/.*|.*\\.jsm)$"],
|
||||||
|
},
|
||||||
|
}
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Ci} = require("chrome");
|
const {Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const promise = require("promise");
|
const promise = require("promise");
|
||||||
const FocusManager = Services.focus;
|
const FocusManager = Services.focus;
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Cc, Ci} = require("chrome");
|
const {Cc, Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
|
|
||||||
const ToolDefinitions = require("devtools/client/definitions").Tools;
|
const ToolDefinitions = require("devtools/client/definitions").Tools;
|
||||||
const CssLogic = require("devtools/shared/inspector/css-logic");
|
const CssLogic = require("devtools/shared/inspector/css-logic");
|
||||||
|
@ -20,7 +22,9 @@ const {OutputParser} = require("devtools/client/shared/output-parser");
|
||||||
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
|
const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
|
||||||
const {createChild} = require("devtools/client/inspector/shared/utils");
|
const {createChild} = require("devtools/client/inspector/shared/utils");
|
||||||
const {gDevTools} = require("devtools/client/framework/devtools");
|
const {gDevTools} = require("devtools/client/framework/devtools");
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||||
|
|
||||||
loader.lazyRequireGetter(this, "overlays",
|
loader.lazyRequireGetter(this, "overlays",
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
const l10n = require("gcli/l10n");
|
const l10n = require("gcli/l10n");
|
||||||
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
|
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {EyeDropper, HighlighterEnvironment} = require("devtools/server/actors/highlighters");
|
const {EyeDropper, HighlighterEnvironment} = require("devtools/server/actors/highlighters");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const Telemetry = require("devtools/client/shared/telemetry");
|
const Telemetry = require("devtools/client/shared/telemetry");
|
||||||
|
|
||||||
exports.items = [{
|
exports.items = [{
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Cc, Ci} = require("chrome");
|
const {Cc, Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
|
|
||||||
var Services = require("Services");
|
var Services = require("Services");
|
||||||
var promise = require("promise");
|
var promise = require("promise");
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Ci} = require("chrome");
|
const {Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const promise = require("promise");
|
const promise = require("promise");
|
||||||
const {Task} = require("devtools/shared/task");
|
const {Task} = require("devtools/shared/task");
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Cc, Ci} = require("chrome");
|
const {Cc, Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const {Task} = require("devtools/shared/task");
|
const {Task} = require("devtools/shared/task");
|
||||||
const {InplaceEditor, editableItem} =
|
const {InplaceEditor, editableItem} =
|
||||||
require("devtools/client/shared/inplace-editor");
|
require("devtools/client/shared/inplace-editor");
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Cc, Ci} = require("chrome");
|
const {Cc, Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
|
|
||||||
// Page size for pageup/pagedown
|
// Page size for pageup/pagedown
|
||||||
const PAGE_SIZE = 10;
|
const PAGE_SIZE = 10;
|
||||||
|
@ -54,7 +56,9 @@ const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
|
||||||
const {template} = require("devtools/shared/gcli/templater");
|
const {template} = require("devtools/shared/gcli/templater");
|
||||||
const nodeConstants = require("devtools/shared/dom-node-constants");
|
const nodeConstants = require("devtools/shared/dom-node-constants");
|
||||||
const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants");
|
const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants");
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
|
|
||||||
loader.lazyRequireGetter(this, "CSS", "CSS");
|
loader.lazyRequireGetter(this, "CSS", "CSS");
|
||||||
loader.lazyGetter(this, "AutocompletePopup", () => {
|
loader.lazyGetter(this, "AutocompletePopup", () => {
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Ci} = require("chrome");
|
const {Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const promise = require("promise");
|
const promise = require("promise");
|
||||||
const CssLogic = require("devtools/shared/inspector/css-logic");
|
const CssLogic = require("devtools/shared/inspector/css-logic");
|
||||||
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
|
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
|
||||||
|
|
|
@ -6,10 +6,14 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Cc, Ci} = require("chrome");
|
const {Cc, Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const {escapeCSSComment} = require("devtools/shared/css-parsing-utils");
|
const {escapeCSSComment} = require("devtools/shared/css-parsing-utils");
|
||||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "domUtils", function () {
|
XPCOMUtils.defineLazyGetter(this, "domUtils", function () {
|
||||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||||
|
|
|
@ -7,11 +7,15 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Cc, Ci} = require("chrome");
|
const {Cc, Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const promise = require("promise");
|
const promise = require("promise");
|
||||||
const defer = require("devtools/shared/defer");
|
const defer = require("devtools/shared/defer");
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const {Task} = require("devtools/shared/task");
|
const {Task} = require("devtools/shared/task");
|
||||||
const {Tools} = require("devtools/client/definitions");
|
const {Tools} = require("devtools/client/definitions");
|
||||||
const {l10n} = require("devtools/shared/inspector/css-logic");
|
const {l10n} = require("devtools/shared/inspector/css-logic");
|
||||||
|
|
|
@ -4,8 +4,12 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Ci} = require("chrome");
|
const {Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const {l10n} = require("devtools/shared/inspector/css-logic");
|
const {l10n} = require("devtools/shared/inspector/css-logic");
|
||||||
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
|
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
|
||||||
const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
|
const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Ci} = require("chrome");
|
const {Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const {l10n} = require("devtools/shared/inspector/css-logic");
|
const {l10n} = require("devtools/shared/inspector/css-logic");
|
||||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||||
const {InplaceEditor, editableField} =
|
const {InplaceEditor, editableField} =
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
const {Ci} = require("chrome");
|
const {Ci} = require("chrome");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
const {parseDeclarations} = require("devtools/shared/css-parsing-utils");
|
const {parseDeclarations} = require("devtools/shared/css-parsing-utils");
|
||||||
const promise = require("promise");
|
const promise = require("promise");
|
||||||
const {getCSSLexer} = require("devtools/shared/css-lexer");
|
const {getCSSLexer} = require("devtools/shared/css-lexer");
|
||||||
|
|
|
@ -10,7 +10,9 @@ var Services = require("Services");
|
||||||
var EventEmitter = require("devtools/shared/event-emitter");
|
var EventEmitter = require("devtools/shared/event-emitter");
|
||||||
var Telemetry = require("devtools/client/shared/telemetry");
|
var Telemetry = require("devtools/client/shared/telemetry");
|
||||||
var { Task } = require("devtools/shared/task");
|
var { Task } = require("devtools/shared/task");
|
||||||
|
/* eslint-disable mozilla/reject-some-requires */
|
||||||
var { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
var { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
/* eslint-enable mozilla/reject-some-requires */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This object represents replacement for ToolSidebar
|
* This object represents replacement for ToolSidebar
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
<!-- 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
|
- 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/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#aaa">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="#0b0b0b">
|
||||||
|
<style>
|
||||||
|
/* Use a fill that's visible on both light and dark themes for filter inputs */
|
||||||
|
#filterinput:target + #icon {
|
||||||
|
fill: #aaa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<g id="filterinput"/>
|
||||||
|
<g id="icon">
|
||||||
<path fill-opacity=".3" d="M6.6 8.4c0-.6-1.7.3-1.7-.3 0-.4-1.7-2.7-1.7-2.7H13s-1.8 2-1.8 2.7c0 .3-2.1-.1-2.1.3v6.1H7s-.4-4.1-.4-6.1z"/>
|
<path fill-opacity=".3" d="M6.6 8.4c0-.6-1.7.3-1.7-.3 0-.4-1.7-2.7-1.7-2.7H13s-1.8 2-1.8 2.7c0 .3-2.1-.1-2.1.3v6.1H7s-.4-4.1-.4-6.1z"/>
|
||||||
<path d="M2 2v2.3L4.7 9H6v5.4l2.1 1 1.8-.9V9h1.3L14 4.3V2H2zm11 2l-2.2 4H9v5.8l-.9.4-1.1-.5V8H5.2L3 4V3h10v1z"/>
|
<path d="M2 2v2.3L4.7 9H6v5.4l2.1 1 1.8-.9V9h1.3L14 4.3V2H2zm11 2l-2.2 4H9v5.8l-.9.4-1.1-.5V8H5.2L3 4V3h10v1z"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
До Ширина: | Высота: | Размер: 568 B После Ширина: | Высота: | Размер: 785 B |
|
@ -364,7 +364,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.devtools-filterinput {
|
.devtools-filterinput {
|
||||||
background-image: var(--filter-image);
|
background-image: url(images/filter.svg#filterinput);
|
||||||
}
|
}
|
||||||
|
|
||||||
.devtools-searchinput:-moz-locale-dir(rtl),
|
.devtools-searchinput:-moz-locale-dir(rtl),
|
||||||
|
|
|
@ -5,24 +5,46 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function (factory) {
|
(function (factory) {
|
||||||
|
// This file can be loaded in several different ways. It can be
|
||||||
|
// require()d, either from the main thread or from a worker thread;
|
||||||
|
// or it can be imported via Cu.import. These different forms
|
||||||
|
// explain some of the hairiness of this code.
|
||||||
|
//
|
||||||
|
// It's important for the devtools-as-html project that a require()
|
||||||
|
// on the main thread not use any chrome privileged APIs. Instead,
|
||||||
|
// the body of the main function can only require() (not Cu.import)
|
||||||
|
// modules that are available in the devtools content mode. This,
|
||||||
|
// plus the lack of |console| in workers, results in some gyrations
|
||||||
|
// in the definition of |console|.
|
||||||
if (this.module && module.id.indexOf("event-emitter") >= 0) {
|
if (this.module && module.id.indexOf("event-emitter") >= 0) {
|
||||||
// require
|
let console;
|
||||||
factory.call(this, require, exports, module);
|
if (isWorker) {
|
||||||
|
console = {
|
||||||
|
error: () => {}
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
// Cu.import
|
console = this.console;
|
||||||
|
}
|
||||||
|
// require
|
||||||
|
factory.call(this, require, exports, module, console);
|
||||||
|
} else {
|
||||||
|
// Cu.import. This snippet implements a sort of miniature loader,
|
||||||
|
// which is responsible for appropriately translating require()
|
||||||
|
// requests from the client function. This code can use
|
||||||
|
// Cu.import, because it is never run in the devtools-in-content
|
||||||
|
// mode.
|
||||||
this.isWorker = false;
|
this.isWorker = false;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
let console = Cu.import("resource://gre/modules/Console.jsm", {}).console;
|
||||||
// Bug 1259045: This module is loaded early in firefox startup as a JSM,
|
// Bug 1259045: This module is loaded early in firefox startup as a JSM,
|
||||||
// but it doesn't depends on any real module. We can save a few cycles
|
// but it doesn't depends on any real module. We can save a few cycles
|
||||||
// and bytes by not loading Loader.jsm.
|
// and bytes by not loading Loader.jsm.
|
||||||
let require = function (module) {
|
let require = function (module) {
|
||||||
const Cu = Components.utils;
|
|
||||||
switch (module) {
|
switch (module) {
|
||||||
case "devtools/shared/defer":
|
case "devtools/shared/defer":
|
||||||
return Cu.import("resource://gre/modules/Promise.jsm", {}).Promise.defer;
|
return Cu.import("resource://gre/modules/Promise.jsm", {}).Promise.defer;
|
||||||
case "Services":
|
case "Services":
|
||||||
return Cu.import("resource://gre/modules/Services.jsm", {}).Services;
|
return Cu.import("resource://gre/modules/Services.jsm", {}).Services;
|
||||||
case "resource://gre/modules/Console.jsm":
|
|
||||||
return Cu.import("resource://gre/modules/Console.jsm", {});
|
|
||||||
case "chrome":
|
case "chrome":
|
||||||
return {
|
return {
|
||||||
Cu,
|
Cu,
|
||||||
|
@ -31,10 +53,13 @@
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
factory.call(this, require, this, { exports: this });
|
factory.call(this, require, this, { exports: this }, console);
|
||||||
this.EXPORTED_SYMBOLS = ["EventEmitter"];
|
this.EXPORTED_SYMBOLS = ["EventEmitter"];
|
||||||
}
|
}
|
||||||
}).call(this, function (require, exports, module) {
|
}).call(this, function (require, exports, module, console) {
|
||||||
|
// ⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠
|
||||||
|
// After this point the code may not use Cu.import, and should only
|
||||||
|
// require() modules that are "clean-for-content".
|
||||||
let EventEmitter = this.EventEmitter = function () {};
|
let EventEmitter = this.EventEmitter = function () {};
|
||||||
module.exports = EventEmitter;
|
module.exports = EventEmitter;
|
||||||
|
|
||||||
|
@ -44,18 +69,13 @@
|
||||||
const defer = require("devtools/shared/defer");
|
const defer = require("devtools/shared/defer");
|
||||||
let loggingEnabled = true;
|
let loggingEnabled = true;
|
||||||
|
|
||||||
let console = {};
|
|
||||||
if (!isWorker) {
|
if (!isWorker) {
|
||||||
console = require("resource://gre/modules/Console.jsm").console;
|
|
||||||
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
|
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
|
||||||
Services.prefs.addObserver("devtools.dump.emit", {
|
Services.prefs.addObserver("devtools.dump.emit", {
|
||||||
observe: () => {
|
observe: () => {
|
||||||
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
|
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
} else {
|
|
||||||
// Workers can't load JSMs, so we can't import Console.jsm here.
|
|
||||||
console.error = () => {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -507,19 +507,6 @@ KeyframeEffectReadOnly::GetAnimationOfProperty(nsCSSProperty aProperty) const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
KeyframeEffectReadOnly::HasAnimationOfProperties(
|
|
||||||
const nsCSSProperty* aProperties,
|
|
||||||
size_t aPropertyCount) const
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < aPropertyCount; i++) {
|
|
||||||
if (HasAnimationOfProperty(aProperties[i])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool
|
bool
|
||||||
SpecifiedKeyframeArraysAreEqual(const nsTArray<Keyframe>& aA,
|
SpecifiedKeyframeArraysAreEqual(const nsTArray<Keyframe>& aA,
|
||||||
|
|
|
@ -294,8 +294,6 @@ public:
|
||||||
bool HasAnimationOfProperty(nsCSSProperty aProperty) const {
|
bool HasAnimationOfProperty(nsCSSProperty aProperty) const {
|
||||||
return GetAnimationOfProperty(aProperty) != nullptr;
|
return GetAnimationOfProperty(aProperty) != nullptr;
|
||||||
}
|
}
|
||||||
bool HasAnimationOfProperties(const nsCSSProperty* aProperties,
|
|
||||||
size_t aPropertyCount) const;
|
|
||||||
const InfallibleTArray<AnimationProperty>& Properties() const {
|
const InfallibleTArray<AnimationProperty>& Properties() const {
|
||||||
return mProperties;
|
return mProperties;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Bug 1272475 - scale function with an extreme large value</title>
|
||||||
|
<script>
|
||||||
|
function test() {
|
||||||
|
var div = document.createElement("div");
|
||||||
|
div.setAttribute("style", "width: 1px; height: 1px; " +
|
||||||
|
"background: red;");
|
||||||
|
document.body.appendChild(div);
|
||||||
|
div.animate([ { "transform": "scale(8)" },
|
||||||
|
{ "transform": "scale(9.5e+307)" },
|
||||||
|
{ "transform": "scale(32)" } ],
|
||||||
|
{ "duration": 1000, "fill": "both" });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="test()">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Bug 1272475 - rotate function with an extreme large value</title>
|
||||||
|
<script>
|
||||||
|
function test() {
|
||||||
|
var div = document.createElement("div");
|
||||||
|
div.setAttribute("style", "width: 100px; height: 100px; " +
|
||||||
|
"background: red;");
|
||||||
|
document.body.appendChild(div);
|
||||||
|
div.animate([ { "transform": "rotate(8rad)" },
|
||||||
|
{ "transform": "rotate(9.5e+307rad)" },
|
||||||
|
{ "transform": "rotate(32rad)" } ],
|
||||||
|
{ "duration": 1000, "fill": "both" });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="test()">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -6,5 +6,7 @@ pref(dom.animations-api.core.enabled,true) load 1216842-3.html
|
||||||
pref(dom.animations-api.core.enabled,true) load 1216842-4.html
|
pref(dom.animations-api.core.enabled,true) load 1216842-4.html
|
||||||
pref(dom.animations-api.core.enabled,true) load 1216842-5.html
|
pref(dom.animations-api.core.enabled,true) load 1216842-5.html
|
||||||
pref(dom.animations-api.core.enabled,true) load 1216842-6.html
|
pref(dom.animations-api.core.enabled,true) load 1216842-6.html
|
||||||
|
pref(dom.animations-api.core.enabled,true) load 1272475-1.html
|
||||||
|
pref(dom.animations-api.core.enabled,true) load 1272475-2.html
|
||||||
pref(dom.animations-api.core.enabled,true) load 1278485-1.html
|
pref(dom.animations-api.core.enabled,true) load 1278485-1.html
|
||||||
pref(dom.animations-api.core.enabled,true) load 1277272-1.html
|
pref(dom.animations-api.core.enabled,true) load 1277272-1.html
|
||||||
|
|
|
@ -41,6 +41,7 @@ support-files =
|
||||||
mozilla/file_document-timeline-origin-time-range.html
|
mozilla/file_document-timeline-origin-time-range.html
|
||||||
mozilla/file_hide_and_show.html
|
mozilla/file_hide_and_show.html
|
||||||
mozilla/file_partial_keyframes.html
|
mozilla/file_partial_keyframes.html
|
||||||
|
mozilla/file_transform_limits.html
|
||||||
style/file_animation-seeking-with-current-time.html
|
style/file_animation-seeking-with-current-time.html
|
||||||
style/file_animation-seeking-with-start-time.html
|
style/file_animation-seeking-with-start-time.html
|
||||||
testcommon.js
|
testcommon.js
|
||||||
|
@ -89,5 +90,6 @@ skip-if = (toolkit == 'gonk' && debug)
|
||||||
[mozilla/test_hide_and_show.html]
|
[mozilla/test_hide_and_show.html]
|
||||||
[mozilla/test_partial_keyframes.html]
|
[mozilla/test_partial_keyframes.html]
|
||||||
[mozilla/test_set-easing.html]
|
[mozilla/test_set-easing.html]
|
||||||
|
[mozilla/test_transform_limits.html]
|
||||||
[style/test_animation-seeking-with-current-time.html]
|
[style/test_animation-seeking-with-current-time.html]
|
||||||
[style/test_animation-seeking-with-start-time.html]
|
[style/test_animation-seeking-with-start-time.html]
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// We clamp +infinity or -inifinity value in floating point to
|
||||||
|
// maximum floating point value or -maximum floating point value.
|
||||||
|
const max_float = 3.40282e+38;
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = addDiv(t);
|
||||||
|
div.style = "width: 1px; height: 1px;";
|
||||||
|
var anim = div.animate([ { transform: 'scale(1)' },
|
||||||
|
{ transform: 'scale(3.5e+38)'},
|
||||||
|
{ transform: 'scale(3)' } ], 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
anim.pause();
|
||||||
|
anim.currentTime = 50 * MS_PER_SEC;
|
||||||
|
assert_equals(getComputedStyle(div).transform,
|
||||||
|
'matrix(' + max_float + ', 0, 0, ' + max_float + ', 0, 0)');
|
||||||
|
}, 'Test that the parameter of transform scale is clamped' );
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = addDiv(t);
|
||||||
|
div.style = "width: 1px; height: 1px;";
|
||||||
|
var anim = div.animate([ { transform: 'translate(1px)' },
|
||||||
|
{ transform: 'translate(3.5e+38px)'},
|
||||||
|
{ transform: 'translate(3px)' } ], 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
anim.pause();
|
||||||
|
anim.currentTime = 50 * MS_PER_SEC;
|
||||||
|
assert_equals(getComputedStyle(div).transform,
|
||||||
|
'matrix(1, 0, 0, 1, ' + max_float + ', 0)');
|
||||||
|
}, 'Test that the parameter of transform translate is clamped' );
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = addDiv(t);
|
||||||
|
div.style = "width: 1px; height: 1px;";
|
||||||
|
var anim = div.animate([ { transform: 'matrix(0.5, 0, 0, 0.5, 0, 0)' },
|
||||||
|
{ transform: 'matrix(2, 0, 0, 2, 3.5e+38, 0)'},
|
||||||
|
{ transform: 'matrix(0, 2, 0, -2, 0, 0)' } ],
|
||||||
|
100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
anim.pause();
|
||||||
|
anim.currentTime = 50 * MS_PER_SEC;
|
||||||
|
assert_equals(getComputedStyle(div).transform,
|
||||||
|
'matrix(2, 0, 0, 2, ' + max_float + ', 0)');
|
||||||
|
}, 'Test that the parameter of transform matrix is clamped' );
|
||||||
|
|
||||||
|
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_transform_limits.html");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -293,7 +293,7 @@ MediaDecoder::NotifyOwnerActivityChanged(bool aIsVisible)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,9 +323,8 @@ MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mShuttingDown ||
|
if (IsShutdown() ||
|
||||||
!mDecoderStateMachine ||
|
!mDecoderStateMachine ||
|
||||||
mPlayState == PLAY_STATE_SHUTDOWN ||
|
|
||||||
!mOwner->GetVideoFrameContainer() ||
|
!mOwner->GetVideoFrameContainer() ||
|
||||||
(mOwner->GetMediaElement() && mOwner->GetMediaElement()->IsBeingDestroyed()) ||
|
(mOwner->GetMediaElement() && mOwner->GetMediaElement()->IsBeingDestroyed()) ||
|
||||||
!mDormantSupported)
|
!mDormantSupported)
|
||||||
|
@ -372,20 +371,8 @@ MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsDormant) {
|
DECODER_LOG("UpdateDormantState() %s DORMANT state", mIsDormant ? "entering" : "exiting");
|
||||||
DECODER_LOG("UpdateDormantState() entering DORMANT state");
|
mDecoderStateMachine->DispatchSetDormant(mIsDormant);
|
||||||
// enter dormant state
|
|
||||||
mDecoderStateMachine->DispatchSetDormant(true);
|
|
||||||
if (IsEnded()) {
|
|
||||||
mWasEndedWhenEnteredDormant = true;
|
|
||||||
}
|
|
||||||
mNextState = mPlayState;
|
|
||||||
ChangeState(PLAY_STATE_LOADING);
|
|
||||||
} else {
|
|
||||||
DECODER_LOG("UpdateDormantState() leaving DORMANT state");
|
|
||||||
// exit dormant state
|
|
||||||
mDecoderStateMachine->DispatchSetDormant(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -407,7 +394,7 @@ MediaDecoder::StartDormantTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsHeuristicDormant ||
|
if (mIsHeuristicDormant ||
|
||||||
mShuttingDown ||
|
IsShutdown() ||
|
||||||
mIsVisible ||
|
mIsVisible ||
|
||||||
(mPlayState != PLAY_STATE_PAUSED &&
|
(mPlayState != PLAY_STATE_PAUSED &&
|
||||||
!IsEnded()))
|
!IsEnded()))
|
||||||
|
@ -437,12 +424,13 @@ void
|
||||||
MediaDecoder::Pause()
|
MediaDecoder::Pause()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mPlayState == PLAY_STATE_LOADING ||
|
if (IsShutdown()) {
|
||||||
IsEnded()) {
|
return;
|
||||||
|
}
|
||||||
|
if (mPlayState == PLAY_STATE_LOADING || IsEnded()) {
|
||||||
mNextState = PLAY_STATE_PAUSED;
|
mNextState = PLAY_STATE_PAUSED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeState(PLAY_STATE_PAUSED);
|
ChangeState(PLAY_STATE_PAUSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,13 +476,13 @@ void
|
||||||
MediaDecoder::SetInfinite(bool aInfinite)
|
MediaDecoder::SetInfinite(bool aInfinite)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
mInfiniteStream = aInfinite;
|
mInfiniteStream = aInfinite;
|
||||||
DurationChanged();
|
DurationChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MediaDecoder::IsInfinite()
|
MediaDecoder::IsInfinite() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
return mInfiniteStream;
|
return mInfiniteStream;
|
||||||
|
@ -516,13 +504,11 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
||||||
, mVideoFrameContainer(aOwner->GetVideoFrameContainer())
|
, mVideoFrameContainer(aOwner->GetVideoFrameContainer())
|
||||||
, mPlaybackStatistics(new MediaChannelStatistics())
|
, mPlaybackStatistics(new MediaChannelStatistics())
|
||||||
, mPinnedForSeek(false)
|
, mPinnedForSeek(false)
|
||||||
, mShuttingDown(false)
|
|
||||||
, mPausedForPlaybackRateNull(false)
|
, mPausedForPlaybackRateNull(false)
|
||||||
, mMinimizePreroll(false)
|
, mMinimizePreroll(false)
|
||||||
, mMediaTracksConstructed(false)
|
, mMediaTracksConstructed(false)
|
||||||
, mFiredMetadataLoaded(false)
|
, mFiredMetadataLoaded(false)
|
||||||
, mIsDormant(false)
|
, mIsDormant(false)
|
||||||
, mWasEndedWhenEnteredDormant(false)
|
|
||||||
, mIsHeuristicDormantSupported(
|
, mIsHeuristicDormantSupported(
|
||||||
Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false))
|
Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false))
|
||||||
, mHeuristicDormantTimeout(
|
, mHeuristicDormantTimeout(
|
||||||
|
@ -620,12 +606,10 @@ MediaDecoder::Shutdown()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mShuttingDown = true;
|
|
||||||
|
|
||||||
// Unwatch all watch targets to prevent further notifications.
|
// Unwatch all watch targets to prevent further notifications.
|
||||||
mWatchManager.Shutdown();
|
mWatchManager.Shutdown();
|
||||||
|
|
||||||
|
@ -820,7 +804,7 @@ nsresult
|
||||||
MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType, dom::Promise* aPromise /*=nullptr*/)
|
MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType, dom::Promise* aPromise /*=nullptr*/)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
NS_ENSURE_TRUE(!mShuttingDown, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(!IsShutdown(), NS_ERROR_FAILURE);
|
||||||
|
|
||||||
UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
|
UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
|
||||||
|
|
||||||
|
@ -830,7 +814,6 @@ MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType, dom::Promise* aProm
|
||||||
int64_t timeUsecs = TimeUnit::FromSeconds(aTime).ToMicroseconds();
|
int64_t timeUsecs = TimeUnit::FromSeconds(aTime).ToMicroseconds();
|
||||||
|
|
||||||
mLogicalPosition = aTime;
|
mLogicalPosition = aTime;
|
||||||
mWasEndedWhenEnteredDormant = false;
|
|
||||||
|
|
||||||
mLogicallySeeking = true;
|
mLogicallySeeking = true;
|
||||||
SeekTarget target = SeekTarget(timeUsecs, aSeekType);
|
SeekTarget target = SeekTarget(timeUsecs, aSeekType);
|
||||||
|
@ -924,7 +907,7 @@ MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||||
MediaDecoderEventVisibility aEventVisibility)
|
MediaDecoderEventVisibility aEventVisibility)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
|
|
||||||
DECODER_LOG("MetadataLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
|
DECODER_LOG("MetadataLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
|
||||||
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
||||||
|
@ -997,7 +980,7 @@ MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||||
MediaDecoderEventVisibility aEventVisibility)
|
MediaDecoderEventVisibility aEventVisibility)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
|
|
||||||
DECODER_LOG("FirstFrameLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d mPlayState=%s mIsDormant=%d",
|
DECODER_LOG("FirstFrameLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d mPlayState=%s mIsDormant=%d",
|
||||||
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
||||||
|
@ -1030,7 +1013,7 @@ nsresult
|
||||||
MediaDecoder::FinishDecoderSetup(MediaResource* aResource)
|
MediaDecoder::FinishDecoderSetup(MediaResource* aResource)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
HTMLMediaElement* element = mOwner->GetMediaElement();
|
HTMLMediaElement* element = mOwner->GetMediaElement();
|
||||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||||
element->FinishDecoderSetup(this, aResource);
|
element->FinishDecoderSetup(this, aResource);
|
||||||
|
@ -1041,7 +1024,7 @@ void
|
||||||
MediaDecoder::ResetConnectionState()
|
MediaDecoder::ResetConnectionState()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
|
|
||||||
// Notify the media element that connection gets lost.
|
// Notify the media element that connection gets lost.
|
||||||
mOwner->ResetConnectionState();
|
mOwner->ResetConnectionState();
|
||||||
|
@ -1056,7 +1039,7 @@ void
|
||||||
MediaDecoder::NetworkError()
|
MediaDecoder::NetworkError()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mShuttingDown)
|
if (IsShutdown())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mOwner->NetworkError();
|
mOwner->NetworkError();
|
||||||
|
@ -1067,7 +1050,7 @@ void
|
||||||
MediaDecoder::DecodeError()
|
MediaDecoder::DecodeError()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mShuttingDown)
|
if (IsShutdown())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mOwner->DecodeError();
|
mOwner->DecodeError();
|
||||||
|
@ -1092,14 +1075,14 @@ bool
|
||||||
MediaDecoder::IsEndedOrShutdown() const
|
MediaDecoder::IsEndedOrShutdown() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
return IsEnded() || mPlayState == PLAY_STATE_SHUTDOWN;
|
return IsEnded() || IsShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MediaDecoder::OwnerHasError() const
|
MediaDecoder::OwnerHasError() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
return mShuttingDown || mOwner->HasError();
|
return IsShutdown() || mOwner->HasError();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MediaElementGMPCrashHelper : public GMPCrashHelper
|
class MediaElementGMPCrashHelper : public GMPCrashHelper
|
||||||
|
@ -1134,8 +1117,14 @@ bool
|
||||||
MediaDecoder::IsEnded() const
|
MediaDecoder::IsEnded() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
return mPlayState == PLAY_STATE_ENDED ||
|
return mPlayState == PLAY_STATE_ENDED;
|
||||||
(mWasEndedWhenEnteredDormant && (mPlayState != PLAY_STATE_SHUTDOWN));
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MediaDecoder::IsShutdown() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
return mPlayState == PLAY_STATE_SHUTDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1143,7 +1132,7 @@ MediaDecoder::PlaybackEnded()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mShuttingDown ||
|
if (IsShutdown() ||
|
||||||
mLogicallySeeking ||
|
mLogicallySeeking ||
|
||||||
mPlayState == PLAY_STATE_LOADING) {
|
mPlayState == PLAY_STATE_LOADING) {
|
||||||
return;
|
return;
|
||||||
|
@ -1220,7 +1209,7 @@ void
|
||||||
MediaDecoder::NotifySuspendedStatusChanged()
|
MediaDecoder::NotifySuspendedStatusChanged()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
if (mResource) {
|
if (mResource) {
|
||||||
bool suspended = mResource->IsSuspendedByCache();
|
bool suspended = mResource->IsSuspendedByCache();
|
||||||
mOwner->NotifySuspendedByCache(suspended);
|
mOwner->NotifySuspendedByCache(suspended);
|
||||||
|
@ -1231,7 +1220,7 @@ void
|
||||||
MediaDecoder::NotifyBytesDownloaded()
|
MediaDecoder::NotifyBytesDownloaded()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UpdatePlaybackRate();
|
UpdatePlaybackRate();
|
||||||
|
@ -1242,7 +1231,7 @@ void
|
||||||
MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
|
MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
|
|
||||||
DECODER_LOG("NotifyDownloadEnded, status=%x", aStatus);
|
DECODER_LOG("NotifyDownloadEnded, status=%x", aStatus);
|
||||||
|
|
||||||
|
@ -1268,7 +1257,7 @@ void
|
||||||
MediaDecoder::NotifyPrincipalChanged()
|
MediaDecoder::NotifyPrincipalChanged()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
nsCOMPtr<nsIPrincipal> newPrincipal = GetCurrentPrincipal();
|
nsCOMPtr<nsIPrincipal> newPrincipal = GetCurrentPrincipal();
|
||||||
mMediaPrincipalHandle = MakePrincipalHandle(newPrincipal);
|
mMediaPrincipalHandle = MakePrincipalHandle(newPrincipal);
|
||||||
mOwner->NotifyDecoderPrincipalChanged();
|
mOwner->NotifyDecoderPrincipalChanged();
|
||||||
|
@ -1278,7 +1267,7 @@ void
|
||||||
MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
|
|
||||||
if (mIgnoreProgressData) {
|
if (mIgnoreProgressData) {
|
||||||
return;
|
return;
|
||||||
|
@ -1297,7 +1286,7 @@ MediaDecoder::OnSeekResolved(SeekResolveValue aVal)
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
mSeekRequest.Complete();
|
mSeekRequest.Complete();
|
||||||
|
|
||||||
if (mShuttingDown)
|
if (IsShutdown())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool fireEnded = false;
|
bool fireEnded = false;
|
||||||
|
@ -1337,7 +1326,7 @@ void
|
||||||
MediaDecoder::SeekingStarted(MediaDecoderEventVisibility aEventVisibility)
|
MediaDecoder::SeekingStarted(MediaDecoderEventVisibility aEventVisibility)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mShuttingDown)
|
if (IsShutdown())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
|
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
|
||||||
|
@ -1349,15 +1338,12 @@ void
|
||||||
MediaDecoder::ChangeState(PlayState aState)
|
MediaDecoder::ChangeState(PlayState aState)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(!IsShutdown(), "SHUTDOWN is the final state.");
|
||||||
|
|
||||||
if (mNextState == aState) {
|
if (mNextState == aState) {
|
||||||
mNextState = PLAY_STATE_PAUSED;
|
mNextState = PLAY_STATE_PAUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPlayState == PLAY_STATE_SHUTDOWN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DECODER_LOG("ChangeState %s => %s", PlayStateStr(), ToPlayStateStr(aState));
|
DECODER_LOG("ChangeState %s => %s", PlayStateStr(), ToPlayStateStr(aState));
|
||||||
mPlayState = aState;
|
mPlayState = aState;
|
||||||
|
|
||||||
|
@ -1376,7 +1362,7 @@ void
|
||||||
MediaDecoder::UpdateLogicalPositionInternal(MediaDecoderEventVisibility aEventVisibility)
|
MediaDecoder::UpdateLogicalPositionInternal(MediaDecoderEventVisibility aEventVisibility)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1401,7 +1387,7 @@ MediaDecoder::DurationChanged()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1681,7 +1667,7 @@ MediaDecoder::NotifyDataArrived() {
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
// Don't publish events since task queues might be shutting down.
|
// Don't publish events since task queues might be shutting down.
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1699,7 +1685,7 @@ void
|
||||||
MediaDecoder::FireTimeUpdate()
|
MediaDecoder::FireTimeUpdate()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mOwner->FireTimeUpdate(true);
|
mOwner->FireTimeUpdate(true);
|
||||||
|
@ -1879,7 +1865,7 @@ MediaDecoder::GetOwner()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
// mOwner is valid until shutdown.
|
// mOwner is valid until shutdown.
|
||||||
return !mShuttingDown ? mOwner : nullptr;
|
return !IsShutdown() ? mOwner : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1887,7 +1873,7 @@ MediaDecoder::ConstructMediaTracks()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mShuttingDown || mMediaTracksConstructed || !mInfo) {
|
if (IsShutdown() || mMediaTracksConstructed || !mInfo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1923,7 +1909,7 @@ MediaDecoder::RemoveMediaTracks()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1964,16 +1950,16 @@ void
|
||||||
MediaDecoder::DumpDebugInfo()
|
MediaDecoder::DumpDebugInfo()
|
||||||
{
|
{
|
||||||
DUMP_LOG("metadata: channels=%u rate=%u hasAudio=%d hasVideo=%d, "
|
DUMP_LOG("metadata: channels=%u rate=%u hasAudio=%d hasVideo=%d, "
|
||||||
"state: mPlayState=%s mIsDormant=%d, mShuttingDown=%d",
|
"state: mPlayState=%s mIsDormant=%d, IsShutdown()=%d",
|
||||||
mInfo ? mInfo->mAudio.mChannels : 0, mInfo ? mInfo->mAudio.mRate : 0,
|
mInfo ? mInfo->mAudio.mChannels : 0, mInfo ? mInfo->mAudio.mRate : 0,
|
||||||
mInfo ? mInfo->HasAudio() : 0, mInfo ? mInfo->HasVideo() : 0,
|
mInfo ? mInfo->HasAudio() : 0, mInfo ? mInfo->HasVideo() : 0,
|
||||||
PlayStateStr(), mIsDormant, mShuttingDown);
|
PlayStateStr(), mIsDormant, IsShutdown());
|
||||||
|
|
||||||
nsString str;
|
nsString str;
|
||||||
GetMozDebugReaderData(str);
|
GetMozDebugReaderData(str);
|
||||||
DUMP_LOG("reader data:\n%s", NS_ConvertUTF16toUTF8(str).get());
|
DUMP_LOG("reader data:\n%s", NS_ConvertUTF16toUTF8(str).get());
|
||||||
|
|
||||||
if (!mShuttingDown && GetStateMachine()) {
|
if (!IsShutdown() && GetStateMachine()) {
|
||||||
GetStateMachine()->DumpDebugInfo();
|
GetStateMachine()->DumpDebugInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1981,7 +1967,7 @@ MediaDecoder::DumpDebugInfo()
|
||||||
void
|
void
|
||||||
MediaDecoder::NotifyAudibleStateChanged()
|
MediaDecoder::NotifyAudibleStateChanged()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!mShuttingDown);
|
MOZ_ASSERT(!IsShutdown());
|
||||||
mOwner->SetAudibleState(mIsAudioDataAudible);
|
mOwner->SetAudibleState(mIsAudioDataAudible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,7 +220,7 @@ public:
|
||||||
virtual double GetDuration();
|
virtual double GetDuration();
|
||||||
|
|
||||||
// Return true if the stream is infinite (see SetInfinite).
|
// Return true if the stream is infinite (see SetInfinite).
|
||||||
virtual bool IsInfinite();
|
bool IsInfinite() const;
|
||||||
|
|
||||||
// Called by MediaResource when some data has been received.
|
// Called by MediaResource when some data has been received.
|
||||||
// Call on the main thread only.
|
// Call on the main thread only.
|
||||||
|
@ -232,12 +232,12 @@ public:
|
||||||
|
|
||||||
// Return true if we are currently seeking in the media resource.
|
// Return true if we are currently seeking in the media resource.
|
||||||
// Call on the main thread only.
|
// Call on the main thread only.
|
||||||
virtual bool IsSeeking() const;
|
bool IsSeeking() const;
|
||||||
|
|
||||||
// Return true if the decoder has reached the end of playback or the decoder
|
// Return true if the decoder has reached the end of playback or the decoder
|
||||||
// has shutdown.
|
// has shutdown.
|
||||||
// Call on the main thread only.
|
// Call on the main thread only.
|
||||||
virtual bool IsEndedOrShutdown() const;
|
bool IsEndedOrShutdown() const;
|
||||||
|
|
||||||
// Return true if the MediaDecoderOwner's error attribute is not null.
|
// Return true if the MediaDecoderOwner's error attribute is not null.
|
||||||
// If the MediaDecoder is shutting down, OwnerHasError will return true.
|
// If the MediaDecoder is shutting down, OwnerHasError will return true.
|
||||||
|
@ -493,7 +493,7 @@ private:
|
||||||
void UpdateReadyState()
|
void UpdateReadyState()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (!mShuttingDown) {
|
if (!IsShutdown()) {
|
||||||
mOwner->UpdateReadyState();
|
mOwner->UpdateReadyState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,6 +528,8 @@ protected:
|
||||||
// Return true if the decoder has reached the end of playback
|
// Return true if the decoder has reached the end of playback
|
||||||
bool IsEnded() const;
|
bool IsEnded() const;
|
||||||
|
|
||||||
|
bool IsShutdown() const;
|
||||||
|
|
||||||
// Called by the state machine to notify the decoder that the duration
|
// Called by the state machine to notify the decoder that the duration
|
||||||
// has changed.
|
// has changed.
|
||||||
void DurationChanged();
|
void DurationChanged();
|
||||||
|
@ -682,12 +684,6 @@ protected:
|
||||||
// while seeking.
|
// while seeking.
|
||||||
bool mPinnedForSeek;
|
bool mPinnedForSeek;
|
||||||
|
|
||||||
// True if the decoder is being shutdown. At this point all events that
|
|
||||||
// are currently queued need to return immediately to prevent javascript
|
|
||||||
// being run that operates on the element and decoder during shutdown.
|
|
||||||
// Read/Write from the main thread only.
|
|
||||||
bool mShuttingDown;
|
|
||||||
|
|
||||||
// True if the playback is paused because the playback rate member is 0.0.
|
// True if the playback is paused because the playback rate member is 0.0.
|
||||||
bool mPausedForPlaybackRateNull;
|
bool mPausedForPlaybackRateNull;
|
||||||
|
|
||||||
|
@ -715,12 +711,6 @@ protected:
|
||||||
// True if MediaDecoder is in dormant state.
|
// True if MediaDecoder is in dormant state.
|
||||||
bool mIsDormant;
|
bool mIsDormant;
|
||||||
|
|
||||||
// True if MediaDecoder was PLAY_STATE_ENDED state, when entering to dormant.
|
|
||||||
// When MediaCodec is in dormant during PLAY_STATE_ENDED state, PlayState
|
|
||||||
// becomes different from PLAY_STATE_ENDED. But the MediaDecoder need to act
|
|
||||||
// as in PLAY_STATE_ENDED state to MediaDecoderOwner.
|
|
||||||
bool mWasEndedWhenEnteredDormant;
|
|
||||||
|
|
||||||
// True if heuristic dormant is supported.
|
// True if heuristic dormant is supported.
|
||||||
const bool mIsHeuristicDormantSupported;
|
const bool mIsHeuristicDormantSupported;
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ MediaOmxCommonDecoder::ResumeStateMachine()
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
DECODER_LOG(LogLevel::Debug, ("%s current time %f", __PRETTY_FUNCTION__, mLogicalPosition));
|
DECODER_LOG(LogLevel::Debug, ("%s current time %f", __PRETTY_FUNCTION__, mLogicalPosition));
|
||||||
|
|
||||||
if (mShuttingDown) {
|
if (IsShutdown()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,8 +156,6 @@ MediaOmxCommonDecoder::ResumeStateMachine()
|
||||||
// Call Seek of MediaDecoderStateMachine to suppress seek events.
|
// Call Seek of MediaDecoderStateMachine to suppress seek events.
|
||||||
GetStateMachine()->InvokeSeek(target);
|
GetStateMachine()->InvokeSeek(target);
|
||||||
|
|
||||||
mNextState = mPlayState;
|
|
||||||
ChangeState(PLAY_STATE_LOADING);
|
|
||||||
// exit dormant state
|
// exit dormant state
|
||||||
GetStateMachine()->DispatchSetDormant(false);
|
GetStateMachine()->DispatchSetDormant(false);
|
||||||
UpdateLogicalPosition();
|
UpdateLogicalPosition();
|
||||||
|
|
|
@ -795,6 +795,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||||
'IccChangeEvent.webidl',
|
'IccChangeEvent.webidl',
|
||||||
'ImageCaptureErrorEvent.webidl',
|
'ImageCaptureErrorEvent.webidl',
|
||||||
'MediaStreamEvent.webidl',
|
'MediaStreamEvent.webidl',
|
||||||
|
'MediaStreamTrackEvent.webidl',
|
||||||
'MozCellBroadcastEvent.webidl',
|
'MozCellBroadcastEvent.webidl',
|
||||||
'MozClirModeEvent.webidl',
|
'MozClirModeEvent.webidl',
|
||||||
'MozContactChangeEvent.webidl',
|
'MozContactChangeEvent.webidl',
|
||||||
|
@ -836,7 +837,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||||
|
|
||||||
if CONFIG['MOZ_WEBRTC']:
|
if CONFIG['MOZ_WEBRTC']:
|
||||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||||
'MediaStreamTrackEvent.webidl',
|
|
||||||
'RTCDataChannelEvent.webidl',
|
'RTCDataChannelEvent.webidl',
|
||||||
'RTCPeerConnectionIceEvent.webidl',
|
'RTCPeerConnectionIceEvent.webidl',
|
||||||
'RTCTrackEvent.webidl',
|
'RTCTrackEvent.webidl',
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#define MOZ_GL_DEBUG 1
|
#define MOZ_GL_DEBUG 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../mfbt/Maybe.h"
|
|
||||||
#include "../../mfbt/RefPtr.h"
|
#include "../../mfbt/RefPtr.h"
|
||||||
#include "../../mfbt/UniquePtr.h"
|
#include "../../mfbt/UniquePtr.h"
|
||||||
|
|
||||||
|
@ -3303,13 +3302,6 @@ public:
|
||||||
|
|
||||||
GLuint GetFB();
|
GLuint GetFB();
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieves the size of the native windowing system drawable.
|
|
||||||
*/
|
|
||||||
virtual Maybe<gfx::IntSize> GetTargetSize() {
|
|
||||||
return Maybe<gfx::IntSize>();
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
|
void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
|
||||||
switch (precisiontype) {
|
switch (precisiontype) {
|
||||||
|
|
|
@ -66,8 +66,6 @@ public:
|
||||||
// Undoes the effect of a drawable override.
|
// Undoes the effect of a drawable override.
|
||||||
bool RestoreDrawable();
|
bool RestoreDrawable();
|
||||||
|
|
||||||
virtual Maybe<gfx::IntSize> GetTargetSize() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GLContextProviderGLX;
|
friend class GLContextProviderGLX;
|
||||||
|
|
||||||
|
|
|
@ -987,20 +987,6 @@ GLContextGLX::SwapBuffers()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<gfx::IntSize>
|
|
||||||
GLContextGLX::GetTargetSize()
|
|
||||||
{
|
|
||||||
unsigned int width = 0, height = 0;
|
|
||||||
Window root;
|
|
||||||
int x, y;
|
|
||||||
unsigned int border, depth;
|
|
||||||
XGetGeometry(mDisplay, mDrawable, &root, &x, &y, &width, &height,
|
|
||||||
&border, &depth);
|
|
||||||
Maybe<gfx::IntSize> size;
|
|
||||||
size.emplace(width, height);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GLContextGLX::OverrideDrawable(GLXDrawable drawable)
|
GLContextGLX::OverrideDrawable(GLXDrawable drawable)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "CompositingRenderTargetOGL.h"
|
#include "CompositingRenderTargetOGL.h"
|
||||||
#include "GLContext.h"
|
#include "GLContext.h"
|
||||||
#include "GLReadTexImageHelper.h"
|
#include "GLReadTexImageHelper.h"
|
||||||
|
#include "ScopedGLHelpers.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -69,7 +70,9 @@ CompositingRenderTargetOGL::BindRenderTarget()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsClear) {
|
if (needsClear) {
|
||||||
mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height);
|
ScopedGLState scopedScissorTestState(mGL, LOCAL_GL_SCISSOR_TEST, true);
|
||||||
|
ScopedScissorRect autoScissorRect(mGL, 0, 0, mInitParams.mSize.width,
|
||||||
|
mInitParams.mSize.height);
|
||||||
mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
|
mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
mGL->fClearDepth(0.0);
|
mGL->fClearDepth(0.0);
|
||||||
mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
|
@ -703,19 +703,9 @@ CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||||
LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA);
|
LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA);
|
||||||
mGLContext->fEnable(LOCAL_GL_BLEND);
|
mGLContext->fEnable(LOCAL_GL_BLEND);
|
||||||
|
|
||||||
// Make sure SCISSOR is enabled before setting the render target, since the RT
|
|
||||||
// assumes scissor is enabled while it does clears.
|
|
||||||
mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
|
|
||||||
|
|
||||||
// Prefer the native windowing system's provided window size for the viewport.
|
|
||||||
IntSize viewportSize =
|
|
||||||
mGLContext->GetTargetSize().valueOr(mWidgetSize.ToUnknownSize());
|
|
||||||
if (viewportSize != mWidgetSize.ToUnknownSize()) {
|
|
||||||
mGLContext->fScissor(0, 0, viewportSize.width, viewportSize.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<CompositingRenderTargetOGL> rt =
|
RefPtr<CompositingRenderTargetOGL> rt =
|
||||||
CompositingRenderTargetOGL::RenderTargetForWindow(this, viewportSize);
|
CompositingRenderTargetOGL::RenderTargetForWindow(this,
|
||||||
|
IntSize(width, height));
|
||||||
SetRenderTarget(rt);
|
SetRenderTarget(rt);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -1060,7 +1050,8 @@ CompositorOGL::DrawQuad(const Rect& aRect,
|
||||||
clipRect.MoveBy(mRenderOffset.x, mRenderOffset.y);
|
clipRect.MoveBy(mRenderOffset.x, mRenderOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl()->fScissor(clipRect.x, FlipY(clipRect.y + clipRect.height),
|
ScopedGLState scopedScissorTestState(mGLContext, LOCAL_GL_SCISSOR_TEST, true);
|
||||||
|
ScopedScissorRect autoScissorRect(mGLContext, clipRect.x, FlipY(clipRect.y + clipRect.height),
|
||||||
clipRect.width, clipRect.height);
|
clipRect.width, clipRect.height);
|
||||||
|
|
||||||
MaskType maskType;
|
MaskType maskType;
|
||||||
|
@ -1501,21 +1492,13 @@ CompositorOGL::EndFrame()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCurrentRenderTarget = nullptr;
|
||||||
|
|
||||||
if (mTexturePool) {
|
if (mTexturePool) {
|
||||||
mTexturePool->EndFrame();
|
mTexturePool->EndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If our window size changed during composition, we should discard the frame.
|
|
||||||
// We don't need to worry about rescheduling a composite, as widget
|
|
||||||
// implementations handle this in their expose event listeners.
|
|
||||||
// See bug 1184534. TODO: implement this for single-buffered targets?
|
|
||||||
IntSize targetSize = mGLContext->GetTargetSize().valueOr(mViewportSize);
|
|
||||||
if (!(mCurrentRenderTarget->IsWindow() && targetSize != mViewportSize)) {
|
|
||||||
mGLContext->SwapBuffers();
|
mGLContext->SwapBuffers();
|
||||||
}
|
|
||||||
|
|
||||||
mCurrentRenderTarget = nullptr;
|
|
||||||
|
|
||||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
// Unbind all textures
|
// Unbind all textures
|
||||||
|
|
|
@ -241,7 +241,8 @@ case "$target" in
|
||||||
|
|
||||||
dnl Ensure that mt.exe is 'Microsoft (R) Manifest Tool',
|
dnl Ensure that mt.exe is 'Microsoft (R) Manifest Tool',
|
||||||
dnl not something else like "magnetic tape manipulation utility".
|
dnl not something else like "magnetic tape manipulation utility".
|
||||||
MSMT_TOOL=`${MT-mt} 2>&1|grep 'Microsoft (R) Manifest Tool'`
|
MT=${MT-mt.exe}
|
||||||
|
MSMT_TOOL=`${MT} 2>&1|grep 'Microsoft (R) Manifest Tool'`
|
||||||
if test -z "$MSMT_TOOL"; then
|
if test -z "$MSMT_TOOL"; then
|
||||||
AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.])
|
AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.])
|
||||||
fi
|
fi
|
||||||
|
@ -256,6 +257,7 @@ case "$target" in
|
||||||
|
|
||||||
MSMANIFEST_TOOL=1
|
MSMANIFEST_TOOL=1
|
||||||
unset MSMT_TOOL
|
unset MSMT_TOOL
|
||||||
|
AC_SUBST(MT)
|
||||||
|
|
||||||
# Check linker version
|
# Check linker version
|
||||||
_LD_FULL_VERSION=`"${LD}" -v 2>&1 | sed -nre "$_MSVC_VER_FILTER"`
|
_LD_FULL_VERSION=`"${LD}" -v 2>&1 | sed -nre "$_MSVC_VER_FILTER"`
|
||||||
|
|
|
@ -823,7 +823,6 @@ XPCConvert::NativeInterface2JSObject(MutableHandleValue d,
|
||||||
|
|
||||||
// Go ahead and create an XPCWrappedNative for this object.
|
// Go ahead and create an XPCWrappedNative for this object.
|
||||||
AutoMarkingNativeInterfacePtr iface(cx);
|
AutoMarkingNativeInterfacePtr iface(cx);
|
||||||
if (iid) {
|
|
||||||
if (Interface)
|
if (Interface)
|
||||||
iface = *Interface;
|
iface = *Interface;
|
||||||
|
|
||||||
|
@ -835,7 +834,6 @@ XPCConvert::NativeInterface2JSObject(MutableHandleValue d,
|
||||||
if (Interface)
|
if (Interface)
|
||||||
*Interface = iface;
|
*Interface = iface;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<XPCWrappedNative> wrapper;
|
RefPtr<XPCWrappedNative> wrapper;
|
||||||
nsresult rv = XPCWrappedNative::GetNewOrUsed(aHelper, xpcscope, iface,
|
nsresult rv = XPCWrappedNative::GetNewOrUsed(aHelper, xpcscope, iface,
|
||||||
|
|
|
@ -446,7 +446,7 @@ ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
|
||||||
if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) {
|
if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) {
|
||||||
return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
|
return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
|
||||||
}
|
}
|
||||||
return nsLayoutUtils::HasCurrentAnimationsForProperties(aFrame, &aProperty, 1);
|
return nsLayoutUtils::HasCurrentAnimationOfProperty(aFrame, aProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
|
|
@ -2050,6 +2050,15 @@ FrameLayerBuilder::GetDebugSingleOldPaintedLayerForFrame(nsIFrame* aFrame)
|
||||||
return layer->AsPaintedLayer();
|
return layer->AsPaintedLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset state that should not persist when a layer is recycled.
|
||||||
|
static void
|
||||||
|
ResetLayerStateForRecycling(Layer* aLayer) {
|
||||||
|
// Currently, this clears the mask layer and ancestor mask layers.
|
||||||
|
// Other cleanup may be added here.
|
||||||
|
aLayer->SetMaskLayer(nullptr);
|
||||||
|
aLayer->SetAncestorMaskLayers({});
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<ColorLayer>
|
already_AddRefed<ColorLayer>
|
||||||
ContainerState::CreateOrRecycleColorLayer(PaintedLayer *aPainted)
|
ContainerState::CreateOrRecycleColorLayer(PaintedLayer *aPainted)
|
||||||
{
|
{
|
||||||
|
@ -2057,7 +2066,7 @@ ContainerState::CreateOrRecycleColorLayer(PaintedLayer *aPainted)
|
||||||
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
|
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
|
||||||
RefPtr<ColorLayer> layer = data->mColorLayer;
|
RefPtr<ColorLayer> layer = data->mColorLayer;
|
||||||
if (layer) {
|
if (layer) {
|
||||||
layer->SetMaskLayer(nullptr);
|
ResetLayerStateForRecycling(layer);
|
||||||
layer->ClearExtraDumpInfo();
|
layer->ClearExtraDumpInfo();
|
||||||
} else {
|
} else {
|
||||||
// Create a new layer
|
// Create a new layer
|
||||||
|
@ -2081,7 +2090,7 @@ ContainerState::CreateOrRecycleImageLayer(PaintedLayer *aPainted)
|
||||||
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
|
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
|
||||||
RefPtr<ImageLayer> layer = data->mImageLayer;
|
RefPtr<ImageLayer> layer = data->mImageLayer;
|
||||||
if (layer) {
|
if (layer) {
|
||||||
layer->SetMaskLayer(nullptr);
|
ResetLayerStateForRecycling(layer);
|
||||||
layer->ClearExtraDumpInfo();
|
layer->ClearExtraDumpInfo();
|
||||||
} else {
|
} else {
|
||||||
// Create a new layer
|
// Create a new layer
|
||||||
|
@ -2268,8 +2277,7 @@ ContainerState::RecyclePaintedLayer(PaintedLayer* aLayer,
|
||||||
{
|
{
|
||||||
// Clear clip rect and mask layer so we don't accidentally stay clipped.
|
// Clear clip rect and mask layer so we don't accidentally stay clipped.
|
||||||
// We will reapply any necessary clipping.
|
// We will reapply any necessary clipping.
|
||||||
aLayer->SetMaskLayer(nullptr);
|
ResetLayerStateForRecycling(aLayer);
|
||||||
aLayer->SetAncestorMaskLayers({});
|
|
||||||
aLayer->ClearExtraDumpInfo();
|
aLayer->ClearExtraDumpInfo();
|
||||||
|
|
||||||
PaintedDisplayItemLayerUserData* data =
|
PaintedDisplayItemLayerUserData* data =
|
||||||
|
@ -5230,8 +5238,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||||
NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER,
|
NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER,
|
||||||
"Wrong layer type");
|
"Wrong layer type");
|
||||||
containerLayer = static_cast<ContainerLayer*>(oldLayer);
|
containerLayer = static_cast<ContainerLayer*>(oldLayer);
|
||||||
containerLayer->SetMaskLayer(nullptr);
|
ResetLayerStateForRecycling(containerLayer);
|
||||||
containerLayer->SetAncestorMaskLayers({});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5417,7 +5424,7 @@ FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
|
||||||
// layer rendering.
|
// layer rendering.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
layer->SetMaskLayer(nullptr);
|
ResetLayerStateForRecycling(layer);
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -495,20 +495,6 @@ nsLayoutUtils::HasCurrentTransitions(const nsIFrame* aFrame)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
nsLayoutUtils::HasCurrentAnimationsForProperties(const nsIFrame* aFrame,
|
|
||||||
const nsCSSProperty* aProperties,
|
|
||||||
size_t aPropertyCount)
|
|
||||||
{
|
|
||||||
return HasMatchingAnimations(aFrame,
|
|
||||||
[&aProperties, &aPropertyCount](KeyframeEffectReadOnly& aEffect)
|
|
||||||
{
|
|
||||||
return aEffect.IsCurrent() &&
|
|
||||||
aEffect.HasAnimationOfProperties(aProperties, aPropertyCount);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsLayoutUtils::HasRelevantAnimationOfProperty(const nsIFrame* aFrame,
|
nsLayoutUtils::HasRelevantAnimationOfProperty(const nsIFrame* aFrame,
|
||||||
nsCSSProperty aProperty)
|
nsCSSProperty aProperty)
|
||||||
|
|
|
@ -2245,14 +2245,6 @@ public:
|
||||||
*/
|
*/
|
||||||
static bool HasCurrentTransitions(const nsIFrame* aFrame);
|
static bool HasCurrentTransitions(const nsIFrame* aFrame);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the frame has any current animations or transitions
|
|
||||||
* for any of the specified properties.
|
|
||||||
*/
|
|
||||||
static bool HasCurrentAnimationsForProperties(const nsIFrame* aFrame,
|
|
||||||
const nsCSSProperty* aProperties,
|
|
||||||
size_t aPropertyCount);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the frame has current or in-effect (i.e. in before phase,
|
* Returns true if the frame has current or in-effect (i.e. in before phase,
|
||||||
* running or filling) animations or transitions for the
|
* running or filling) animations or transitions for the
|
||||||
|
|
|
@ -1082,12 +1082,14 @@ AddCSSValueAngle(double aCoeff1, const nsCSSValue &aValue1,
|
||||||
{
|
{
|
||||||
if (aValue1.GetUnit() == aValue2.GetUnit()) {
|
if (aValue1.GetUnit() == aValue2.GetUnit()) {
|
||||||
// To avoid floating point error, if the units match, maintain the unit.
|
// To avoid floating point error, if the units match, maintain the unit.
|
||||||
aResult.SetFloatValue(aCoeff1 * aValue1.GetFloatValue() +
|
aResult.SetFloatValue(
|
||||||
aCoeff2 * aValue2.GetFloatValue(),
|
EnsureNotNan(aCoeff1 * aValue1.GetFloatValue() +
|
||||||
|
aCoeff2 * aValue2.GetFloatValue()),
|
||||||
aValue1.GetUnit());
|
aValue1.GetUnit());
|
||||||
} else {
|
} else {
|
||||||
aResult.SetFloatValue(aCoeff1 * aValue1.GetAngleValueInRadians() +
|
aResult.SetFloatValue(
|
||||||
aCoeff2 * aValue2.GetAngleValueInRadians(),
|
EnsureNotNan(aCoeff1 * aValue1.GetAngleValueInRadians() +
|
||||||
|
aCoeff2 * aValue2.GetAngleValueInRadians()),
|
||||||
eCSSUnit_Radian);
|
eCSSUnit_Radian);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1254,7 +1256,7 @@ AddTransformScale(double aCoeff1, const nsCSSValue &aValue1,
|
||||||
float v1 = aValue1.GetFloatValue() - 1.0f,
|
float v1 = aValue1.GetFloatValue() - 1.0f,
|
||||||
v2 = aValue2.GetFloatValue() - 1.0f;
|
v2 = aValue2.GetFloatValue() - 1.0f;
|
||||||
float result = v1 * aCoeff1 + v2 * aCoeff2;
|
float result = v1 * aCoeff1 + v2 * aCoeff2;
|
||||||
aResult.SetFloatValue(result + 1.0f, eCSSUnit_Number);
|
aResult.SetFloatValue(EnsureNotNan(result + 1.0f), eCSSUnit_Number);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ already_AddRefed<nsCSSValue::Array>
|
/* static */ already_AddRefed<nsCSSValue::Array>
|
||||||
|
|
|
@ -15417,6 +15417,16 @@ CSSParserImpl::ParseFunctionInternals(const uint32_t aVariantMask[],
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nsCSSValue::IsFloatUnit(newValue.GetUnit())) {
|
||||||
|
// Clamp infinity or -infinity values to max float or -max float to avoid
|
||||||
|
// calculations with infinity.
|
||||||
|
newValue.SetFloatValue(
|
||||||
|
mozilla::clamped(newValue.GetFloatValue(),
|
||||||
|
-std::numeric_limits<float>::max(),
|
||||||
|
std::numeric_limits<float>::max()),
|
||||||
|
newValue.GetUnit());
|
||||||
|
}
|
||||||
|
|
||||||
aOutput.AppendElement(newValue);
|
aOutput.AppendElement(newValue);
|
||||||
|
|
||||||
if (ExpectSymbol(',', true)) {
|
if (ExpectSymbol(',', true)) {
|
||||||
|
|
|
@ -413,9 +413,9 @@ void nsCSSValue::SetPercentValue(float aValue)
|
||||||
|
|
||||||
void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit)
|
void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(eCSSUnit_Number <= aUnit, "not a float value");
|
MOZ_ASSERT(IsFloatUnit(aUnit), "not a float value");
|
||||||
Reset();
|
Reset();
|
||||||
if (eCSSUnit_Number <= aUnit) {
|
if (IsFloatUnit(aUnit)) {
|
||||||
mUnit = aUnit;
|
mUnit = aUnit;
|
||||||
mValue.mFloat = aValue;
|
mValue.mFloat = aValue;
|
||||||
MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
|
MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
|
||||||
|
|
|
@ -516,6 +516,8 @@ public:
|
||||||
{ return eCSSUnit_Point <= aUnit && aUnit <= eCSSUnit_Pixel; }
|
{ return eCSSUnit_Point <= aUnit && aUnit <= eCSSUnit_Pixel; }
|
||||||
bool IsPixelLengthUnit() const
|
bool IsPixelLengthUnit() const
|
||||||
{ return IsPixelLengthUnit(mUnit); }
|
{ return IsPixelLengthUnit(mUnit); }
|
||||||
|
static bool IsFloatUnit(nsCSSUnit aUnit)
|
||||||
|
{ return eCSSUnit_Number <= aUnit; }
|
||||||
bool IsAngularUnit() const
|
bool IsAngularUnit() const
|
||||||
{ return eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Turn; }
|
{ return eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Turn; }
|
||||||
bool IsFrequencyUnit() const
|
bool IsFrequencyUnit() const
|
||||||
|
|
|
@ -4184,12 +4184,11 @@ inline uint32_t ListLength(const T* aList)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static already_AddRefed<nsCSSShadowArray>
|
||||||
|
GetShadowData(const nsCSSValueList* aList,
|
||||||
already_AddRefed<nsCSSShadowArray>
|
|
||||||
nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
|
||||||
nsStyleContext* aContext,
|
nsStyleContext* aContext,
|
||||||
bool aIsBoxShadow,
|
bool aIsBoxShadow,
|
||||||
|
nsPresContext* aPresContext,
|
||||||
RuleNodeCacheConditions& aConditions)
|
RuleNodeCacheConditions& aConditions)
|
||||||
{
|
{
|
||||||
uint32_t arrayLength = ListLength(aList);
|
uint32_t arrayLength = ListLength(aList);
|
||||||
|
@ -4213,13 +4212,13 @@ nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
||||||
// OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
|
// OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
|
||||||
unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(),
|
unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(),
|
||||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
||||||
aContext, mPresContext, aConditions);
|
aContext, aPresContext, aConditions);
|
||||||
NS_ASSERTION(unitOK, "unexpected unit");
|
NS_ASSERTION(unitOK, "unexpected unit");
|
||||||
item->mXOffset = tempCoord.GetCoordValue();
|
item->mXOffset = tempCoord.GetCoordValue();
|
||||||
|
|
||||||
unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(),
|
unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(),
|
||||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
||||||
aContext, mPresContext, aConditions);
|
aContext, aPresContext, aConditions);
|
||||||
NS_ASSERTION(unitOK, "unexpected unit");
|
NS_ASSERTION(unitOK, "unexpected unit");
|
||||||
item->mYOffset = tempCoord.GetCoordValue();
|
item->mYOffset = tempCoord.GetCoordValue();
|
||||||
|
|
||||||
|
@ -4228,7 +4227,7 @@ nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
||||||
unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(),
|
unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(),
|
||||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY |
|
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY |
|
||||||
SETCOORD_CALC_CLAMP_NONNEGATIVE,
|
SETCOORD_CALC_CLAMP_NONNEGATIVE,
|
||||||
aContext, mPresContext, aConditions);
|
aContext, aPresContext, aConditions);
|
||||||
NS_ASSERTION(unitOK, "unexpected unit");
|
NS_ASSERTION(unitOK, "unexpected unit");
|
||||||
item->mRadius = tempCoord.GetCoordValue();
|
item->mRadius = tempCoord.GetCoordValue();
|
||||||
} else {
|
} else {
|
||||||
|
@ -4239,7 +4238,7 @@ nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
||||||
if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) {
|
if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) {
|
||||||
unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(),
|
unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(),
|
||||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
||||||
aContext, mPresContext, aConditions);
|
aContext, aPresContext, aConditions);
|
||||||
NS_ASSERTION(unitOK, "unexpected unit");
|
NS_ASSERTION(unitOK, "unexpected unit");
|
||||||
item->mSpread = tempCoord.GetCoordValue();
|
item->mSpread = tempCoord.GetCoordValue();
|
||||||
} else {
|
} else {
|
||||||
|
@ -4249,7 +4248,7 @@ nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
||||||
if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
|
if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
|
||||||
item->mHasColor = true;
|
item->mHasColor = true;
|
||||||
// 2nd argument can be bogus since inherit is not a valid color
|
// 2nd argument can be bogus since inherit is not a valid color
|
||||||
unitOK = SetColor(arr->Item(4), 0, mPresContext, aContext, item->mColor,
|
unitOK = SetColor(arr->Item(4), 0, aPresContext, aContext, item->mColor,
|
||||||
aConditions);
|
aConditions);
|
||||||
NS_ASSERTION(unitOK, "unexpected unit");
|
NS_ASSERTION(unitOK, "unexpected unit");
|
||||||
}
|
}
|
||||||
|
@ -4452,7 +4451,7 @@ nsRuleNode::ComputeTextData(void* aStartStruct,
|
||||||
textShadowValue->GetUnit() == eCSSUnit_ListDep) {
|
textShadowValue->GetUnit() == eCSSUnit_ListDep) {
|
||||||
// List of arrays
|
// List of arrays
|
||||||
text->mTextShadow = GetShadowData(textShadowValue->GetListValue(),
|
text->mTextShadow = GetShadowData(textShadowValue->GetListValue(),
|
||||||
aContext, false, conditions);
|
aContext, false, mPresContext, conditions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9549,8 +9548,8 @@ nsRuleNode::ComputeSVGData(void* aStartStruct,
|
||||||
COMPUTE_END_INHERITED(SVG, svg)
|
COMPUTE_END_INHERITED(SVG, svg)
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsStyleBasicShape>
|
static already_AddRefed<nsStyleBasicShape>
|
||||||
nsRuleNode::GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
|
GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
|
||||||
nsStyleContext* aStyleContext,
|
nsStyleContext* aStyleContext,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
RuleNodeCacheConditions& aConditions)
|
RuleNodeCacheConditions& aConditions)
|
||||||
|
@ -9698,8 +9697,8 @@ nsRuleNode::GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
|
||||||
return basicShape.forget();
|
return basicShape.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||||
const nsCSSValue* aValue,
|
const nsCSSValue* aValue,
|
||||||
nsStyleContext* aStyleContext,
|
nsStyleContext* aStyleContext,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
|
@ -9740,8 +9739,8 @@ nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
|
// Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
|
||||||
bool
|
static bool
|
||||||
nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
||||||
const nsCSSValue& aValue,
|
const nsCSSValue& aValue,
|
||||||
nsStyleContext* aStyleContext,
|
nsStyleContext* aStyleContext,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
|
@ -9773,6 +9772,7 @@ nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
||||||
filterFunction->Item(1).GetListValue(),
|
filterFunction->Item(1).GetListValue(),
|
||||||
aStyleContext,
|
aStyleContext,
|
||||||
false,
|
false,
|
||||||
|
aPresContext,
|
||||||
aConditions);
|
aConditions);
|
||||||
aStyleFilter->SetDropShadow(shadowArray);
|
aStyleFilter->SetDropShadow(shadowArray);
|
||||||
return true;
|
return true;
|
||||||
|
@ -10161,7 +10161,7 @@ nsRuleNode::ComputeEffectsData(void* aStartStruct,
|
||||||
case eCSSUnit_List:
|
case eCSSUnit_List:
|
||||||
case eCSSUnit_ListDep:
|
case eCSSUnit_ListDep:
|
||||||
effects->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(),
|
effects->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(),
|
||||||
aContext, true, conditions);
|
aContext, true, mPresContext, conditions);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -783,27 +783,6 @@ protected:
|
||||||
inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID,
|
inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID,
|
||||||
const nsRuleData* aRuleData);
|
const nsRuleData* aRuleData);
|
||||||
|
|
||||||
already_AddRefed<nsCSSShadowArray>
|
|
||||||
GetShadowData(const nsCSSValueList* aList,
|
|
||||||
nsStyleContext* aContext,
|
|
||||||
bool aIsBoxShadow,
|
|
||||||
mozilla::RuleNodeCacheConditions& aConditions);
|
|
||||||
already_AddRefed<nsStyleBasicShape>
|
|
||||||
GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
|
|
||||||
nsStyleContext* aStyleContext,
|
|
||||||
nsPresContext* aPresContext,
|
|
||||||
mozilla::RuleNodeCacheConditions& aConditions);
|
|
||||||
bool SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
|
||||||
const nsCSSValue& aValue,
|
|
||||||
nsStyleContext* aStyleContext,
|
|
||||||
nsPresContext* aPresContext,
|
|
||||||
mozilla::RuleNodeCacheConditions& aConditions);
|
|
||||||
void SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
|
||||||
const nsCSSValue* aValue,
|
|
||||||
nsStyleContext* aStyleContext,
|
|
||||||
nsPresContext* aPresContext,
|
|
||||||
mozilla::RuleNodeCacheConditions& aConditions);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
|
nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
|
||||||
nsIStyleRule* aRule, mozilla::SheetType aLevel, bool aIsImportant);
|
nsIStyleRule* aRule, mozilla::SheetType aLevel, bool aIsImportant);
|
||||||
|
|
|
@ -364,4 +364,11 @@ public class AppConstants {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final boolean MOZ_ANDROID_ACTIVITY_STREAM =
|
||||||
|
//#ifdef MOZ_ANDROID_ACTIVITY_STREAM
|
||||||
|
true;
|
||||||
|
//#else
|
||||||
|
false;
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -2691,9 +2691,16 @@ public class BrowserApp extends GeckoApp
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHomeScreen == null) {
|
if (mHomeScreen == null) {
|
||||||
|
if (AppConstants.MOZ_ANDROID_ACTIVITY_STREAM) {
|
||||||
|
final ViewStub asStub = (ViewStub) findViewById(R.id.activity_stream_stub);
|
||||||
|
mHomeScreen = (HomeScreen) asStub.inflate();
|
||||||
|
} else {
|
||||||
final ViewStub homePagerStub = (ViewStub) findViewById(R.id.home_pager_stub);
|
final ViewStub homePagerStub = (ViewStub) findViewById(R.id.home_pager_stub);
|
||||||
mHomeScreen = (HomePager) homePagerStub.inflate();
|
mHomeScreen = (HomeScreen) homePagerStub.inflate();
|
||||||
|
|
||||||
|
// For now these listeners are HomePager specific. In future we might want
|
||||||
|
// to have a more abstracted data storage, with one Bundle containing all
|
||||||
|
// relevant restore data.
|
||||||
mHomeScreen.setOnPanelChangeListener(new HomeScreen.OnPanelChangeListener() {
|
mHomeScreen.setOnPanelChangeListener(new HomeScreen.OnPanelChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPanelSelected(String panelId) {
|
public void onPanelSelected(String panelId) {
|
||||||
|
@ -2714,6 +2721,7 @@ public class BrowserApp extends GeckoApp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Don't show the banner in guest mode.
|
// Don't show the banner in guest mode.
|
||||||
if (!Restrictions.isUserRestricted()) {
|
if (!Restrictions.isUserRestricted()) {
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
package org.mozilla.gecko.home.activitystream;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.LoaderManager;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.animation.PropertyAnimator;
|
||||||
|
import org.mozilla.gecko.home.HomeBanner;
|
||||||
|
import org.mozilla.gecko.home.HomeFragment;
|
||||||
|
import org.mozilla.gecko.home.HomeScreen;
|
||||||
|
|
||||||
|
public class ActivityStream extends FrameLayout implements HomeScreen {
|
||||||
|
|
||||||
|
public ActivityStream(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisible() {
|
||||||
|
// This is dependent on the loading state - currently we're a dumb panel so we're always
|
||||||
|
// "visible"
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onToolbarFocusChange(boolean hasFocus) {
|
||||||
|
// We don't care: this is HomePager specific
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showPanel(String panelId, Bundle restoreData) {
|
||||||
|
// We could use this to restore Panel data. In practice this isn't likely to be relevant for
|
||||||
|
// AS and can be ignore for now.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOnPanelChangeListener(OnPanelChangeListener listener) {
|
||||||
|
// As with showPanel: not relevant yet, could be used for persistence (scroll position?)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPanelStateChangeListener(HomeFragment.PanelStateChangeListener listener) {
|
||||||
|
// See setOnPanelChangeListener
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBanner(HomeBanner banner) {
|
||||||
|
// TODO: we should probably implement this to show snippets.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(LoaderManager lm, FragmentManager fm, String panelId, Bundle restoreData,
|
||||||
|
PropertyAnimator animator) {
|
||||||
|
// Signal to load data from storage as needed, compare with HomePager
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unload() {
|
||||||
|
// Signal to clear data that has been loaded, compare with HomePager
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,9 +78,20 @@ public class TelemetryJSONFilePingStore extends TelemetryPingStore {
|
||||||
@WorkerThread // Writes to disk
|
@WorkerThread // Writes to disk
|
||||||
public TelemetryJSONFilePingStore(final File storeDir, final String profileName) {
|
public TelemetryJSONFilePingStore(final File storeDir, final String profileName) {
|
||||||
super(profileName);
|
super(profileName);
|
||||||
|
if (storeDir.exists() && !storeDir.isDirectory()) {
|
||||||
|
// An alternative is to create a new directory, but we wouldn't
|
||||||
|
// be able to access it later so it's better to throw.
|
||||||
|
throw new IllegalStateException("Store dir unexpectedly exists & is not a directory - cannot continue");
|
||||||
|
}
|
||||||
|
|
||||||
this.storeDir = storeDir;
|
this.storeDir = storeDir;
|
||||||
this.storeDir.mkdirs();
|
this.storeDir.mkdirs();
|
||||||
uuidFilenameFilter = new FilenameRegexFilter(UUIDUtil.UUID_PATTERN);
|
uuidFilenameFilter = new FilenameRegexFilter(UUIDUtil.UUID_PATTERN);
|
||||||
|
|
||||||
|
if (!this.storeDir.canRead() || !this.storeDir.canWrite() || !this.storeDir.canExecute()) {
|
||||||
|
throw new IllegalStateException("Cannot read, write, or execute store dir: " +
|
||||||
|
this.storeDir.canRead() + " " + this.storeDir.canWrite() + " " + this.storeDir.canExecute());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting File getPingFile(final String docID) {
|
@VisibleForTesting File getPingFile(final String docID) {
|
||||||
|
@ -129,7 +140,15 @@ public class TelemetryJSONFilePingStore extends TelemetryPingStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<TelemetryPing> getAllPings() {
|
public ArrayList<TelemetryPing> getAllPings() {
|
||||||
final List<File> files = Arrays.asList(storeDir.listFiles(uuidFilenameFilter));
|
final File[] fileArray = storeDir.listFiles(uuidFilenameFilter);
|
||||||
|
if (fileArray == null) {
|
||||||
|
// Intentionally don't log all info for the store directory to prevent leaking the path.
|
||||||
|
Log.w(LOGTAG, "listFiles unexpectedly returned null - unable to retrieve pings. Debug: exists? " +
|
||||||
|
storeDir.exists() + "; directory? " + storeDir.isDirectory());
|
||||||
|
return new ArrayList<>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<File> files = Arrays.asList(fileArray);
|
||||||
Collections.sort(files, fileLastModifiedComparator); // oldest to newest
|
Collections.sort(files, fileLastModifiedComparator); // oldest to newest
|
||||||
final ArrayList<TelemetryPing> out = new ArrayList<>(files.size());
|
final ArrayList<TelemetryPing> out = new ArrayList<>(files.size());
|
||||||
for (final File file : files) {
|
for (final File file : files) {
|
||||||
|
|
|
@ -401,6 +401,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
|
||||||
'health/HealthRecorder.java',
|
'health/HealthRecorder.java',
|
||||||
'health/SessionInformation.java',
|
'health/SessionInformation.java',
|
||||||
'health/StubbedHealthRecorder.java',
|
'health/StubbedHealthRecorder.java',
|
||||||
|
'home/activitystream/ActivityStream.java',
|
||||||
'home/BookmarkFolderView.java',
|
'home/BookmarkFolderView.java',
|
||||||
'home/BookmarkScreenshotRow.java',
|
'home/BookmarkScreenshotRow.java',
|
||||||
'home/BookmarksListAdapter.java',
|
'home/BookmarksListAdapter.java',
|
||||||
|
@ -965,7 +966,8 @@ for var in ('MOZ_ANDROID_ANR_REPORTER', 'MOZ_LINKER_EXTRACT', 'MOZ_DEBUG',
|
||||||
'MOZ_ANDROID_DOWNLOADS_INTEGRATION', 'MOZ_INSTALL_TRACKING',
|
'MOZ_ANDROID_DOWNLOADS_INTEGRATION', 'MOZ_INSTALL_TRACKING',
|
||||||
'MOZ_ANDROID_GCM', 'MOZ_ANDROID_EXCLUDE_FONTS', 'MOZ_LOCALE_SWITCHER',
|
'MOZ_ANDROID_GCM', 'MOZ_ANDROID_EXCLUDE_FONTS', 'MOZ_LOCALE_SWITCHER',
|
||||||
'MOZ_ANDROID_BEAM', 'MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE',
|
'MOZ_ANDROID_BEAM', 'MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE',
|
||||||
'MOZ_SWITCHBOARD', 'MOZ_ANDROID_CUSTOM_TABS'):
|
'MOZ_SWITCHBOARD', 'MOZ_ANDROID_CUSTOM_TABS',
|
||||||
|
'MOZ_ANDROID_ACTIVITY_STREAM'):
|
||||||
if CONFIG[var]:
|
if CONFIG[var]:
|
||||||
DEFINES[var] = 1
|
DEFINES[var] = 1
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.mozilla.gecko.home.activitystream.ActivityStream xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/white">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
tools:ignore="HardcodedText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Activity Stream \\o/"
|
||||||
|
android:id="@+id/textView"
|
||||||
|
android:layout_gravity="center_horizontal"/>
|
||||||
|
</org.mozilla.gecko.home.activitystream.ActivityStream>
|
|
@ -66,6 +66,11 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
|
<ViewStub android:id="@+id/activity_stream_stub"
|
||||||
|
android:layout="@layout/activity_stream"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
<ViewStub android:id="@+id/home_banner_stub"
|
<ViewStub android:id="@+id/home_banner_stub"
|
||||||
android:layout="@layout/home_banner"
|
android:layout="@layout/home_banner"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -48,6 +48,13 @@ project_flag('MOZ_SWITCHBOARD',
|
||||||
help='Include Switchboard A/B framework on Android',
|
help='Include Switchboard A/B framework on Android',
|
||||||
default=True)
|
default=True)
|
||||||
|
|
||||||
|
option(env='MOZ_ANDROID_ACTIVITY_STREAM',
|
||||||
|
help='Enable Activity Stream on Android (replacing the default HomePager)',
|
||||||
|
default=False)
|
||||||
|
|
||||||
|
set_config('MOZ_ANDROID_ACTIVITY_STREAM',
|
||||||
|
depends_if('MOZ_ANDROID_ACTIVITY_STREAM')(lambda _: True))
|
||||||
|
|
||||||
option('--disable-android-apz', env='MOZ_ANDROID_APZ',
|
option('--disable-android-apz', env='MOZ_ANDROID_APZ',
|
||||||
help='Disable the C++ async pan/zoom code and use the Java version instead')
|
help='Disable the C++ async pan/zoom code and use the Java version instead')
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.mozilla.gecko.util.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -70,6 +71,33 @@ public class TestTelemetryJSONFilePingStore {
|
||||||
assertEquals("Temp dir contains one dir (the store dir)", 1, tempDir.getRoot().list().length);
|
assertEquals("Temp dir contains one dir (the store dir)", 1, tempDir.getRoot().list().length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void testConstructorStoreAlreadyExistsAsNonDirectory() throws Exception {
|
||||||
|
final File file = tempDir.newFile();
|
||||||
|
new TelemetryJSONFilePingStore(file, "profileName"); // expected to throw.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void testConstructorDirIsNotReadable() throws Exception {
|
||||||
|
final File dir = tempDir.newFolder();
|
||||||
|
dir.setReadable(false);
|
||||||
|
new TelemetryJSONFilePingStore(dir, "profileName"); // expected to throw.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void testConstructorDirIsNotWritable() throws Exception {
|
||||||
|
final File dir = tempDir.newFolder();
|
||||||
|
dir.setWritable(false);
|
||||||
|
new TelemetryJSONFilePingStore(dir, "profileName"); // expected to throw.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void testConstructorDirIsNotExecutable() throws Exception {
|
||||||
|
final File dir = tempDir.newFolder();
|
||||||
|
dir.setExecutable(false);
|
||||||
|
new TelemetryJSONFilePingStore(dir, "profileName"); // expected to throw.
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStorePingStoresCorrectData() throws Exception {
|
public void testStorePingStoresCorrectData() throws Exception {
|
||||||
assertStoreFileCount(0);
|
assertStoreFileCount(0);
|
||||||
|
|
|
@ -368,7 +368,8 @@ case "$target" in
|
||||||
|
|
||||||
dnl Ensure that mt.exe is 'Microsoft (R) Manifest Tool',
|
dnl Ensure that mt.exe is 'Microsoft (R) Manifest Tool',
|
||||||
dnl not something else like "magnetic tape manipulation utility".
|
dnl not something else like "magnetic tape manipulation utility".
|
||||||
MSMT_TOOL=`${MT-mt} 2>&1|grep 'Microsoft (R) Manifest Tool'`
|
MT=${MT-mt.exe}
|
||||||
|
MSMT_TOOL=`${MT} 2>&1|grep 'Microsoft (R) Manifest Tool'`
|
||||||
if test -z "$MSMT_TOOL"; then
|
if test -z "$MSMT_TOOL"; then
|
||||||
AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.])
|
AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.])
|
||||||
fi
|
fi
|
||||||
|
@ -383,6 +384,7 @@ case "$target" in
|
||||||
|
|
||||||
MSMANIFEST_TOOL=1
|
MSMANIFEST_TOOL=1
|
||||||
unset MSMT_TOOL
|
unset MSMT_TOOL
|
||||||
|
AC_SUBST(MT)
|
||||||
|
|
||||||
# Check linker version
|
# Check linker version
|
||||||
_LD_FULL_VERSION=`"${LD}" -v 2>&1 | sed -nre "$_MSVC_VER_FILTER"`
|
_LD_FULL_VERSION=`"${LD}" -v 2>&1 | sed -nre "$_MSVC_VER_FILTER"`
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import bz2
|
||||||
|
import gzip
|
||||||
|
import stat
|
||||||
|
import tarfile
|
||||||
|
|
||||||
|
|
||||||
|
# 2016-01-01T00:00:00+0000
|
||||||
|
DEFAULT_MTIME = 1451606400
|
||||||
|
|
||||||
|
|
||||||
|
def create_tar_from_files(fp, files):
|
||||||
|
"""Create a tar file deterministically.
|
||||||
|
|
||||||
|
Receives a dict mapping names of files in the archive to local filesystem
|
||||||
|
paths.
|
||||||
|
|
||||||
|
The files will be archived and written to the passed file handle opened
|
||||||
|
for writing.
|
||||||
|
|
||||||
|
Only regular files can be written.
|
||||||
|
|
||||||
|
FUTURE accept mozpack.files classes for writing
|
||||||
|
FUTURE accept a filename argument (or create APIs to write files)
|
||||||
|
"""
|
||||||
|
with tarfile.open(name='', mode='w', fileobj=fp, dereference=True) as tf:
|
||||||
|
for archive_path, fs_path in sorted(files.items()):
|
||||||
|
ti = tf.gettarinfo(fs_path, archive_path)
|
||||||
|
|
||||||
|
if not ti.isreg():
|
||||||
|
raise ValueError('not a regular file: %s' % fs_path)
|
||||||
|
|
||||||
|
# Disallow setuid and setgid bits. This is an arbitrary restriction.
|
||||||
|
# However, since we set uid/gid to root:root, setuid and setgid
|
||||||
|
# would be a glaring security hole if the archive were
|
||||||
|
# uncompressed as root.
|
||||||
|
if ti.mode & (stat.S_ISUID | stat.S_ISGID):
|
||||||
|
raise ValueError('cannot add file with setuid or setgid set: '
|
||||||
|
'%s' % fs_path)
|
||||||
|
|
||||||
|
# Set uid, gid, username, and group as deterministic values.
|
||||||
|
ti.uid = 0
|
||||||
|
ti.gid = 0
|
||||||
|
ti.uname = ''
|
||||||
|
ti.gname = ''
|
||||||
|
|
||||||
|
# Set mtime to a constant value.
|
||||||
|
ti.mtime = DEFAULT_MTIME
|
||||||
|
|
||||||
|
with open(fs_path, 'rb') as fh:
|
||||||
|
tf.addfile(ti, fh)
|
||||||
|
|
||||||
|
|
||||||
|
def create_tar_gz_from_files(fp, files, filename=None, compresslevel=9):
|
||||||
|
"""Create a tar.gz file deterministically from files.
|
||||||
|
|
||||||
|
This is a glorified wrapper around ``create_tar_from_files`` that
|
||||||
|
adds gzip compression.
|
||||||
|
|
||||||
|
The passed file handle should be opened for writing in binary mode.
|
||||||
|
When the function returns, all data has been written to the handle.
|
||||||
|
"""
|
||||||
|
# Offset 3-7 in the gzip header contains an mtime. Pin it to a known
|
||||||
|
# value so output is deterministic.
|
||||||
|
gf = gzip.GzipFile(filename=filename or '', mode='wb', fileobj=fp,
|
||||||
|
compresslevel=compresslevel, mtime=DEFAULT_MTIME)
|
||||||
|
with gf:
|
||||||
|
create_tar_from_files(gf, files)
|
||||||
|
|
||||||
|
|
||||||
|
class _BZ2Proxy(object):
|
||||||
|
"""File object that proxies writes to a bz2 compressor."""
|
||||||
|
def __init__(self, fp, compresslevel=9):
|
||||||
|
self.fp = fp
|
||||||
|
self.compressor = bz2.BZ2Compressor(compresslevel=compresslevel)
|
||||||
|
self.pos = 0
|
||||||
|
|
||||||
|
def tell(self):
|
||||||
|
return self.pos
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
data = self.compressor.compress(data)
|
||||||
|
self.pos += len(data)
|
||||||
|
self.fp.write(data)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
data = self.compressor.flush()
|
||||||
|
self.pos += len(data)
|
||||||
|
self.fp.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
def create_tar_bz2_from_files(fp, files, compresslevel=9):
|
||||||
|
"""Create a tar.bz2 file deterministically from files.
|
||||||
|
|
||||||
|
This is a glorified wrapper around ``create_tar_from_files`` that
|
||||||
|
adds bzip2 compression.
|
||||||
|
|
||||||
|
This function is similar to ``create_tar_gzip_from_files()``.
|
||||||
|
"""
|
||||||
|
proxy = _BZ2Proxy(fp, compresslevel=compresslevel)
|
||||||
|
create_tar_from_files(proxy, files)
|
||||||
|
proxy.close()
|
|
@ -0,0 +1,190 @@
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import tarfile
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from mozpack.archive import (
|
||||||
|
DEFAULT_MTIME,
|
||||||
|
create_tar_from_files,
|
||||||
|
create_tar_gz_from_files,
|
||||||
|
create_tar_bz2_from_files,
|
||||||
|
)
|
||||||
|
|
||||||
|
from mozunit import main
|
||||||
|
|
||||||
|
|
||||||
|
MODE_STANDARD = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
|
||||||
|
|
||||||
|
|
||||||
|
def file_hash(path):
|
||||||
|
h = hashlib.sha1()
|
||||||
|
with open(path, 'rb') as fh:
|
||||||
|
while True:
|
||||||
|
data = fh.read(8192)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
h.update(data)
|
||||||
|
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
class TestArchive(unittest.TestCase):
|
||||||
|
def _create_files(self, root):
|
||||||
|
files = {}
|
||||||
|
for i in range(10):
|
||||||
|
p = os.path.join(root, b'file%d' % i)
|
||||||
|
with open(p, 'wb') as fh:
|
||||||
|
fh.write(b'file%d' % i)
|
||||||
|
# Need to set permissions or umask may influence testing.
|
||||||
|
os.chmod(p, MODE_STANDARD)
|
||||||
|
files[b'file%d' % i] = p
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
|
def _verify_basic_tarfile(self, tf):
|
||||||
|
self.assertEqual(len(tf.getmembers()), 10)
|
||||||
|
|
||||||
|
names = ['file%d' % i for i in range(10)]
|
||||||
|
self.assertEqual(tf.getnames(), names)
|
||||||
|
|
||||||
|
for ti in tf.getmembers():
|
||||||
|
self.assertEqual(ti.uid, 0)
|
||||||
|
self.assertEqual(ti.gid, 0)
|
||||||
|
self.assertEqual(ti.uname, '')
|
||||||
|
self.assertEqual(ti.gname, '')
|
||||||
|
self.assertEqual(ti.mode, MODE_STANDARD)
|
||||||
|
self.assertEqual(ti.mtime, DEFAULT_MTIME)
|
||||||
|
|
||||||
|
def test_dirs_refused(self):
|
||||||
|
d = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
tp = os.path.join(d, 'test.tar')
|
||||||
|
with open(tp, 'wb') as fh:
|
||||||
|
with self.assertRaisesRegexp(ValueError, 'not a regular'):
|
||||||
|
create_tar_from_files(fh, {'test': d})
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
def test_setuid_setgid_refused(self):
|
||||||
|
d = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
uid = os.path.join(d, 'setuid')
|
||||||
|
gid = os.path.join(d, 'setgid')
|
||||||
|
with open(uid, 'a'):
|
||||||
|
pass
|
||||||
|
with open(gid, 'a'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.chmod(uid, MODE_STANDARD | stat.S_ISUID)
|
||||||
|
os.chmod(gid, MODE_STANDARD | stat.S_ISGID)
|
||||||
|
|
||||||
|
tp = os.path.join(d, 'test.tar')
|
||||||
|
with open(tp, 'wb') as fh:
|
||||||
|
with self.assertRaisesRegexp(ValueError, 'cannot add file with setuid'):
|
||||||
|
create_tar_from_files(fh, {'test': uid})
|
||||||
|
with self.assertRaisesRegexp(ValueError, 'cannot add file with setuid'):
|
||||||
|
create_tar_from_files(fh, {'test': gid})
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
def test_create_tar_basic(self):
|
||||||
|
d = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
files = self._create_files(d)
|
||||||
|
|
||||||
|
tp = os.path.join(d, 'test.tar')
|
||||||
|
with open(tp, 'wb') as fh:
|
||||||
|
create_tar_from_files(fh, files)
|
||||||
|
|
||||||
|
# Output should be deterministic.
|
||||||
|
self.assertEqual(file_hash(tp), 'cd16cee6f13391abd94dfa435d2633b61ed727f1')
|
||||||
|
|
||||||
|
with tarfile.open(tp, 'r') as tf:
|
||||||
|
self._verify_basic_tarfile(tf)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
def test_executable_preserved(self):
|
||||||
|
d = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
p = os.path.join(d, 'exec')
|
||||||
|
with open(p, 'wb') as fh:
|
||||||
|
fh.write('#!/bin/bash\n')
|
||||||
|
os.chmod(p, MODE_STANDARD | stat.S_IXUSR)
|
||||||
|
|
||||||
|
tp = os.path.join(d, 'test.tar')
|
||||||
|
with open(tp, 'wb') as fh:
|
||||||
|
create_tar_from_files(fh, {'exec': p})
|
||||||
|
|
||||||
|
self.assertEqual(file_hash(tp), '357e1b81c0b6cfdfa5d2d118d420025c3c76ee93')
|
||||||
|
|
||||||
|
with tarfile.open(tp, 'r') as tf:
|
||||||
|
m = tf.getmember('exec')
|
||||||
|
self.assertEqual(m.mode, MODE_STANDARD | stat.S_IXUSR)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
def test_create_tar_gz_basic(self):
|
||||||
|
d = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
files = self._create_files(d)
|
||||||
|
|
||||||
|
gp = os.path.join(d, 'test.tar.gz')
|
||||||
|
with open(gp, 'wb') as fh:
|
||||||
|
create_tar_gz_from_files(fh, files)
|
||||||
|
|
||||||
|
self.assertEqual(file_hash(gp), 'acb602239c1aeb625da5e69336775609516d60f5')
|
||||||
|
|
||||||
|
with tarfile.open(gp, 'r:gz') as tf:
|
||||||
|
self._verify_basic_tarfile(tf)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
def test_tar_gz_name(self):
|
||||||
|
d = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
files = self._create_files(d)
|
||||||
|
|
||||||
|
gp = os.path.join(d, 'test.tar.gz')
|
||||||
|
with open(gp, 'wb') as fh:
|
||||||
|
create_tar_gz_from_files(fh, files, filename='foobar', compresslevel=1)
|
||||||
|
|
||||||
|
self.assertEqual(file_hash(gp), 'fd099f96480cc1100f37baa8e89a6b820dbbcbd3')
|
||||||
|
|
||||||
|
with tarfile.open(gp, 'r:gz') as tf:
|
||||||
|
self._verify_basic_tarfile(tf)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
def test_create_tar_bz2_basic(self):
|
||||||
|
d = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
files = self._create_files(d)
|
||||||
|
|
||||||
|
bp = os.path.join(d, 'test.tar.bz2')
|
||||||
|
with open(bp, 'wb') as fh:
|
||||||
|
create_tar_bz2_from_files(fh, files)
|
||||||
|
|
||||||
|
self.assertEqual(file_hash(bp), '1827ad00dfe7acf857b7a1c95ce100361e3f6eea')
|
||||||
|
|
||||||
|
with tarfile.open(bp, 'r:bz2') as tf:
|
||||||
|
self._verify_basic_tarfile(tf)
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(d)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -23,16 +23,21 @@ task:
|
||||||
- 'index.gecko.v1.{{project}}.revision.linux.{{head_rev}}.{{build_name}}'
|
- 'index.gecko.v1.{{project}}.revision.linux.{{head_rev}}.{{build_name}}'
|
||||||
- 'index.gecko.v1.{{project}}.latest.linux.{{build_name}}'
|
- 'index.gecko.v1.{{project}}.latest.linux.{{build_name}}'
|
||||||
scopes:
|
scopes:
|
||||||
# Nearly all of our build tasks use tc-vcs so just include the scope across
|
- 'docker-worker:cache:level-{{level}}-hg-shared'
|
||||||
# the board.
|
- 'docker-worker:cache:level-{{level}}-workspace'
|
||||||
- 'docker-worker:cache:level-{{level}}-{{project}}-tc-vcs'
|
|
||||||
|
|
||||||
payload:
|
payload:
|
||||||
# Thirty minutes should be enough for lint checks
|
# Thirty minutes should be enough for lint checks
|
||||||
maxRunTime: 1800
|
maxRunTime: 1800
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
level-{{level}}-{{project}}-tc-vcs: '/home/worker/.tc-vcs'
|
level-{{level}}-hg-shared: '/home/worker/hg-shared'
|
||||||
|
level-{{level}}-workspace: '/home/worker/workspace'
|
||||||
|
|
||||||
|
env:
|
||||||
|
GECKO_BASE_REPOSITORY: '{{base_repository}}'
|
||||||
|
GECKO_HEAD_REPOSITORY: '{{head_repository}}'
|
||||||
|
GECKO_HEAD_REV: '{{head_rev}}'
|
||||||
|
|
||||||
extra:
|
extra:
|
||||||
build_product: '{{build_product}}'
|
build_product: '{{build_product}}'
|
||||||
|
|
|
@ -20,11 +20,12 @@ task:
|
||||||
task-reference: "<docker-image>"
|
task-reference: "<docker-image>"
|
||||||
|
|
||||||
command:
|
command:
|
||||||
|
- /home/worker/bin/checkout-gecko-and-run
|
||||||
|
- /home/worker/workspace/gecko
|
||||||
- bash
|
- bash
|
||||||
- -cx
|
- -cx
|
||||||
- >
|
- >
|
||||||
tc-vcs checkout ./gecko {{base_repository}} {{head_repository}} {{head_rev}} {{head_ref}} &&
|
cd /home/worker/workspace/gecko/tools/lint/eslint &&
|
||||||
cd gecko/tools/lint/eslint &&
|
|
||||||
/build/tooltool.py fetch -m manifest.tt &&
|
/build/tooltool.py fetch -m manifest.tt &&
|
||||||
tar xvfz eslint.tar.gz &&
|
tar xvfz eslint.tar.gz &&
|
||||||
rm eslint.tar.gz &&
|
rm eslint.tar.gz &&
|
||||||
|
|
|
@ -18,11 +18,12 @@ task:
|
||||||
taskId:
|
taskId:
|
||||||
task-reference: "<docker-image>"
|
task-reference: "<docker-image>"
|
||||||
command:
|
command:
|
||||||
|
- /home/worker/bin/checkout-gecko-and-run
|
||||||
|
- /home/worker/workspace/gecko
|
||||||
- bash
|
- bash
|
||||||
- -cx
|
- -cx
|
||||||
- >
|
- >
|
||||||
tc-vcs checkout ./gecko {{base_repository}} {{head_repository}} {{head_rev}} {{head_ref}} &&
|
cd /home/worker/workspace/gecko &&
|
||||||
cd gecko &&
|
|
||||||
./mach lint -l flake8 -f treeherder
|
./mach lint -l flake8 -f treeherder
|
||||||
extra:
|
extra:
|
||||||
locations:
|
locations:
|
||||||
|
|
|
@ -18,11 +18,12 @@ task:
|
||||||
taskId:
|
taskId:
|
||||||
task-reference: "<docker-image>"
|
task-reference: "<docker-image>"
|
||||||
command:
|
command:
|
||||||
|
- /home/worker/bin/checkout-gecko-and-run
|
||||||
|
- /home/worker/workspace/gecko
|
||||||
- bash
|
- bash
|
||||||
- -cx
|
- -cx
|
||||||
- >
|
- >
|
||||||
tc-vcs checkout ./gecko {{base_repository}} {{head_repository}} {{head_rev}} {{head_ref}} &&
|
cd /home/worker/workspace/gecko &&
|
||||||
cd gecko &&
|
|
||||||
./mach taskgraph python-tests
|
./mach taskgraph python-tests
|
||||||
extra:
|
extra:
|
||||||
locations:
|
locations:
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
.. taskcluster_dockerimages:
|
||||||
|
|
||||||
|
=============
|
||||||
|
Docker Images
|
||||||
|
=============
|
||||||
|
|
||||||
|
TaskCluster Docker images are defined in the source directory under
|
||||||
|
``testing/docker``. Each directory therein contains the name of an
|
||||||
|
image used as part of the task graph.
|
||||||
|
|
||||||
|
Adding Extra Files to Images
|
||||||
|
============================
|
||||||
|
|
||||||
|
Dockerfile syntax has been extended to allow *any* file from the
|
||||||
|
source checkout to be added to the image build *context*. (Traditionally
|
||||||
|
you can only ``ADD`` files from the same directory as the Dockerfile.)
|
||||||
|
|
||||||
|
Simply add the following syntax as a comment in a Dockerfile::
|
||||||
|
|
||||||
|
# %include <path>
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
# %include mach
|
||||||
|
# %include testing/mozharness
|
||||||
|
|
||||||
|
The argument to ``# %include`` is a relative path from the root level of
|
||||||
|
the source directory. It can be a file or a directory. If a file, only that
|
||||||
|
file will be added. If a directory, every file under that directory will be
|
||||||
|
added (even files that are untracked or ignored by version control).
|
||||||
|
|
||||||
|
Files added using ``# %include`` syntax are available inside the build
|
||||||
|
context under the ``topsrcdir/`` path.
|
||||||
|
|
||||||
|
Files are added as they exist on disk. e.g. executable flags should be
|
||||||
|
preserved. However, the file owner/group is changed to ``root`` and the
|
||||||
|
``mtime`` of the file is normalized.
|
||||||
|
|
||||||
|
Here is an example Dockerfile snippet::
|
||||||
|
|
||||||
|
# %include mach
|
||||||
|
ADD topsrcdir/mach /home/worker/mach
|
|
@ -28,3 +28,4 @@ check out the :doc:`how-to section <how-tos>`.
|
||||||
transforms
|
transforms
|
||||||
yaml-templates
|
yaml-templates
|
||||||
how-tos
|
how-tos
|
||||||
|
docker-images
|
||||||
|
|
|
@ -27,13 +27,16 @@ routes:
|
||||||
|
|
||||||
payload:
|
payload:
|
||||||
env:
|
env:
|
||||||
GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-central'
|
GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-unified'
|
||||||
GECKO_HEAD_REPOSITORY: '{{{head_repository}}}'
|
GECKO_HEAD_REPOSITORY: '{{{head_repository}}}'
|
||||||
GECKO_HEAD_REF: '{{head_ref}}'
|
GECKO_HEAD_REF: '{{head_ref}}'
|
||||||
GECKO_HEAD_REV: '{{head_rev}}'
|
GECKO_HEAD_REV: '{{head_rev}}'
|
||||||
|
ACTION_ARGS: >
|
||||||
|
--decision-id='{{decision_task_id}}'
|
||||||
|
--task-labels='{{task_labels}}'
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
level-{{level}}-{{project}}-tc-vcs-public-sources: /home/worker/.tc-vcs/
|
level-{{level}}-hg-shared: /home/worker/hg-shared
|
||||||
level-{{level}}-{{project}}-gecko-decision: /home/worker/workspace
|
level-{{level}}-{{project}}-gecko-decision: /home/worker/workspace
|
||||||
|
|
||||||
features:
|
features:
|
||||||
|
@ -41,7 +44,7 @@ payload:
|
||||||
|
|
||||||
# Note: This task is built server side without the context or tooling that
|
# Note: This task is built server side without the context or tooling that
|
||||||
# exist in tree so we must hard code the version
|
# exist in tree so we must hard code the version
|
||||||
image: 'taskcluster/decision:0.1.0'
|
image: 'taskcluster/decision:0.1.2'
|
||||||
|
|
||||||
# Virtually no network or other potentially risky operations happen as part
|
# Virtually no network or other potentially risky operations happen as part
|
||||||
# of the task timeout aside from the initial clone. We intentionally have
|
# of the task timeout aside from the initial clone. We intentionally have
|
||||||
|
@ -50,16 +53,7 @@ payload:
|
||||||
maxRunTime: 1800
|
maxRunTime: 1800
|
||||||
|
|
||||||
command:
|
command:
|
||||||
- /bin/bash
|
- /home/worker/bin/run-action
|
||||||
- -cx
|
|
||||||
- >
|
|
||||||
mkdir -p /home/worker/artifacts &&
|
|
||||||
checkout-gecko workspace &&
|
|
||||||
cd workspace/gecko &&
|
|
||||||
ln -s /home/worker/artifacts artifacts &&
|
|
||||||
./mach taskgraph action-task
|
|
||||||
--decision-id='{{decision_task_id}}'
|
|
||||||
--task-labels='{{task_labels}}'
|
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
'public':
|
'public':
|
||||||
|
|
|
@ -21,7 +21,7 @@ ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}'
|
||||||
|
|
||||||
def load_image_by_name(image_name):
|
def load_image_by_name(image_name):
|
||||||
context_path = os.path.join(GECKO, 'testing', 'docker', image_name)
|
context_path = os.path.join(GECKO, 'testing', 'docker', image_name)
|
||||||
context_hash = docker.generate_context_hash(context_path)
|
context_hash = docker.generate_context_hash(GECKO, context_path, image_name)
|
||||||
|
|
||||||
image_index_url = INDEX_URL.format('mozilla-central', image_name, context_hash)
|
image_index_url = INDEX_URL.format('mozilla-central', image_name, context_hash)
|
||||||
print("Fetching", image_index_url)
|
print("Fetching", image_index_url)
|
||||||
|
|
|
@ -9,13 +9,13 @@ import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import urllib2
|
import urllib2
|
||||||
import tarfile
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from . import base
|
from . import base
|
||||||
from taskgraph.util.docker import (
|
from taskgraph.util.docker import (
|
||||||
|
create_context_tar,
|
||||||
docker_image,
|
docker_image,
|
||||||
generate_context_hash
|
generate_context_hash,
|
||||||
)
|
)
|
||||||
from taskgraph.util.templates import Templates
|
from taskgraph.util.templates import Templates
|
||||||
|
|
||||||
|
@ -64,10 +64,8 @@ class DockerImageTask(base.Task):
|
||||||
templates = Templates(path)
|
templates = Templates(path)
|
||||||
for image_name in config['images']:
|
for image_name in config['images']:
|
||||||
context_path = os.path.join('testing', 'docker', image_name)
|
context_path = os.path.join('testing', 'docker', image_name)
|
||||||
context_hash = generate_context_hash(context_path)
|
|
||||||
|
|
||||||
image_parameters = dict(parameters)
|
image_parameters = dict(parameters)
|
||||||
image_parameters['context_hash'] = context_hash
|
|
||||||
image_parameters['context_path'] = context_path
|
image_parameters['context_path'] = context_path
|
||||||
image_parameters['artifact_path'] = 'public/image.tar'
|
image_parameters['artifact_path'] = 'public/image.tar'
|
||||||
image_parameters['image_name'] = image_name
|
image_parameters['image_name'] = image_name
|
||||||
|
@ -80,12 +78,21 @@ class DockerImageTask(base.Task):
|
||||||
"artifacts/decision_task/image_contexts/{}/context.tar.gz".format(image_name))
|
"artifacts/decision_task/image_contexts/{}/context.tar.gz".format(image_name))
|
||||||
image_parameters['context_url'] = ARTIFACT_URL.format(
|
image_parameters['context_url'] = ARTIFACT_URL.format(
|
||||||
os.environ['TASK_ID'], image_artifact_path)
|
os.environ['TASK_ID'], image_artifact_path)
|
||||||
cls.create_context_tar(context_path, destination, image_name)
|
|
||||||
|
destination = os.path.abspath(destination)
|
||||||
|
if not os.path.exists(os.path.dirname(destination)):
|
||||||
|
os.makedirs(os.path.dirname(destination))
|
||||||
|
|
||||||
|
context_hash = create_context_tar(GECKO, context_path,
|
||||||
|
destination, image_name)
|
||||||
else:
|
else:
|
||||||
# skip context generation since this isn't a decision task
|
# skip context generation since this isn't a decision task
|
||||||
# TODO: generate context tarballs using subdirectory clones in
|
# TODO: generate context tarballs using subdirectory clones in
|
||||||
# the image-building task so we don't have to worry about this.
|
# the image-building task so we don't have to worry about this.
|
||||||
image_parameters['context_url'] = 'file:///tmp/' + image_artifact_path
|
image_parameters['context_url'] = 'file:///tmp/' + image_artifact_path
|
||||||
|
context_hash = generate_context_hash(GECKO, context_path, image_name)
|
||||||
|
|
||||||
|
image_parameters['context_hash'] = context_hash
|
||||||
|
|
||||||
image_task = templates.load('image.yml', image_parameters)
|
image_task = templates.load('image.yml', image_parameters)
|
||||||
|
|
||||||
|
@ -131,16 +138,6 @@ class DockerImageTask(base.Task):
|
||||||
|
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create_context_tar(cls, context_dir, destination, image_name):
|
|
||||||
'Creates a tar file of a particular context directory.'
|
|
||||||
destination = os.path.abspath(destination)
|
|
||||||
if not os.path.exists(os.path.dirname(destination)):
|
|
||||||
os.makedirs(os.path.dirname(destination))
|
|
||||||
|
|
||||||
with tarfile.open(destination, 'w:gz') as tar:
|
|
||||||
tar.add(context_dir, arcname=image_name)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_json(cls, task_dict):
|
def from_json(cls, task_dict):
|
||||||
# Generating index_paths for optimization
|
# Generating index_paths for optimization
|
||||||
|
|
|
@ -145,12 +145,13 @@ def set_interactive_task(task, interactive):
|
||||||
|
|
||||||
|
|
||||||
def remove_caches_from_task(task):
|
def remove_caches_from_task(task):
|
||||||
r"""Remove all caches but tc-vcs from the task.
|
r"""Remove all caches but vcs from the task.
|
||||||
|
|
||||||
:param task: task definition.
|
:param task: task definition.
|
||||||
"""
|
"""
|
||||||
whitelist = [
|
whitelist = [
|
||||||
re.compile("^level-[123]-.*-tc-vcs(-public-sources)?$"),
|
re.compile("^level-[123]-.*-tc-vcs(-public-sources)?$"),
|
||||||
|
re.compile("^level-[123]-hg-shared"),
|
||||||
re.compile("^tooltool-cache$"),
|
re.compile("^tooltool-cache$"),
|
||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import tempfile
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ..task import docker_image
|
from ..task import docker_image
|
||||||
|
@ -31,12 +30,6 @@ class TestDockerImageKind(unittest.TestCase):
|
||||||
|
|
||||||
# TODO: optimize_task
|
# TODO: optimize_task
|
||||||
|
|
||||||
def test_create_context_tar(self):
|
|
||||||
image_dir = os.path.join(docker_image.GECKO, 'testing', 'docker', 'image_builder')
|
|
||||||
tarball = tempfile.mkstemp()[1]
|
|
||||||
self.task.create_context_tar(image_dir, tarball, 'image_builder')
|
|
||||||
self.failUnless(os.path.exists(tarball))
|
|
||||||
os.unlink(tarball)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -6,6 +6,8 @@ from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import stat
|
||||||
|
import tarfile
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@ -13,6 +15,9 @@ from ..util import docker
|
||||||
from mozunit import MockedOpen
|
from mozunit import MockedOpen
|
||||||
|
|
||||||
|
|
||||||
|
MODE_STANDARD = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
|
||||||
|
|
||||||
|
|
||||||
class TestDocker(unittest.TestCase):
|
class TestDocker(unittest.TestCase):
|
||||||
|
|
||||||
def test_generate_context_hash(self):
|
def test_generate_context_hash(self):
|
||||||
|
@ -26,8 +31,8 @@ class TestDocker(unittest.TestCase):
|
||||||
with open(os.path.join(tmpdir, 'docker', 'my-image', 'a-file'), "w") as f:
|
with open(os.path.join(tmpdir, 'docker', 'my-image', 'a-file'), "w") as f:
|
||||||
f.write("data\n")
|
f.write("data\n")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
docker.generate_context_hash('docker/my-image'),
|
docker.generate_context_hash(docker.GECKO, 'docker/my-image', 'my-image'),
|
||||||
'781143fcc6cc72c9024b058665265cb6bae3fb8031cad7227dd169ffbfced434'
|
'872d76a656f47ea17c043023ecc9ae6a222ba6d2a8df67b75498bba382e4fb07'
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
docker.GECKO = old_GECKO
|
docker.GECKO = old_GECKO
|
||||||
|
@ -46,3 +51,138 @@ class TestDocker(unittest.TestCase):
|
||||||
files["{}/myimage/VERSION".format(docker.DOCKER_ROOT)] = "1.2.3"
|
files["{}/myimage/VERSION".format(docker.DOCKER_ROOT)] = "1.2.3"
|
||||||
with MockedOpen(files):
|
with MockedOpen(files):
|
||||||
self.assertEqual(docker.docker_image('myimage'), "mozilla/myimage:1.2.3")
|
self.assertEqual(docker.docker_image('myimage'), "mozilla/myimage:1.2.3")
|
||||||
|
|
||||||
|
def test_create_context_tar_basic(self):
|
||||||
|
tmp = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
d = os.path.join(tmp, 'test_image')
|
||||||
|
os.mkdir(d)
|
||||||
|
with open(os.path.join(d, 'Dockerfile'), 'a'):
|
||||||
|
pass
|
||||||
|
os.chmod(os.path.join(d, 'Dockerfile'), MODE_STANDARD)
|
||||||
|
|
||||||
|
with open(os.path.join(d, 'extra'), 'a'):
|
||||||
|
pass
|
||||||
|
os.chmod(os.path.join(d, 'extra'), MODE_STANDARD)
|
||||||
|
|
||||||
|
tp = os.path.join(tmp, 'tar')
|
||||||
|
h = docker.create_context_tar(tmp, d, tp, 'my_image')
|
||||||
|
self.assertEqual(h, '2a6d7f1627eba60daf85402418e041d728827d309143c6bc1c6bb3035bde6717')
|
||||||
|
|
||||||
|
# File prefix should be "my_image"
|
||||||
|
with tarfile.open(tp, 'r:gz') as tf:
|
||||||
|
self.assertEqual(tf.getnames(), [
|
||||||
|
'my_image/Dockerfile',
|
||||||
|
'my_image/extra',
|
||||||
|
])
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp)
|
||||||
|
|
||||||
|
def test_create_context_topsrcdir_files(self):
|
||||||
|
tmp = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
d = os.path.join(tmp, 'test-image')
|
||||||
|
os.mkdir(d)
|
||||||
|
with open(os.path.join(d, 'Dockerfile'), 'wb') as fh:
|
||||||
|
fh.write(b'# %include extra/file0\n')
|
||||||
|
os.chmod(os.path.join(d, 'Dockerfile'), MODE_STANDARD)
|
||||||
|
|
||||||
|
extra = os.path.join(tmp, 'extra')
|
||||||
|
os.mkdir(extra)
|
||||||
|
with open(os.path.join(extra, 'file0'), 'a'):
|
||||||
|
pass
|
||||||
|
os.chmod(os.path.join(extra, 'file0'), MODE_STANDARD)
|
||||||
|
|
||||||
|
tp = os.path.join(tmp, 'tar')
|
||||||
|
h = docker.create_context_tar(tmp, d, tp, 'test_image')
|
||||||
|
self.assertEqual(h, '20faeb7c134f21187b142b5fadba94ae58865dc929c6c293d8cbc0a087269338')
|
||||||
|
|
||||||
|
with tarfile.open(tp, 'r:gz') as tf:
|
||||||
|
self.assertEqual(tf.getnames(), [
|
||||||
|
'test_image/Dockerfile',
|
||||||
|
'test_image/topsrcdir/extra/file0',
|
||||||
|
])
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp)
|
||||||
|
|
||||||
|
def test_create_context_absolute_path(self):
|
||||||
|
tmp = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
d = os.path.join(tmp, 'test-image')
|
||||||
|
os.mkdir(d)
|
||||||
|
|
||||||
|
# Absolute paths in %include syntax are not allowed.
|
||||||
|
with open(os.path.join(d, 'Dockerfile'), 'wb') as fh:
|
||||||
|
fh.write(b'# %include /etc/shadow\n')
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(Exception, 'cannot be absolute'):
|
||||||
|
docker.create_context_tar(tmp, d, os.path.join(tmp, 'tar'), 'test')
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp)
|
||||||
|
|
||||||
|
def test_create_context_outside_topsrcdir(self):
|
||||||
|
tmp = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
d = os.path.join(tmp, 'test-image')
|
||||||
|
os.mkdir(d)
|
||||||
|
|
||||||
|
with open(os.path.join(d, 'Dockerfile'), 'wb') as fh:
|
||||||
|
fh.write(b'# %include foo/../../../etc/shadow\n')
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(Exception, 'path outside topsrcdir'):
|
||||||
|
docker.create_context_tar(tmp, d, os.path.join(tmp, 'tar'), 'test')
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp)
|
||||||
|
|
||||||
|
def test_create_context_missing_extra(self):
|
||||||
|
tmp = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
d = os.path.join(tmp, 'test-image')
|
||||||
|
os.mkdir(d)
|
||||||
|
|
||||||
|
with open(os.path.join(d, 'Dockerfile'), 'wb') as fh:
|
||||||
|
fh.write(b'# %include does/not/exist\n')
|
||||||
|
|
||||||
|
with self.assertRaisesRegexp(Exception, 'path does not exist'):
|
||||||
|
docker.create_context_tar(tmp, d, os.path.join(tmp, 'tar'), 'test')
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp)
|
||||||
|
|
||||||
|
def test_create_context_extra_directory(self):
|
||||||
|
tmp = tempfile.mkdtemp()
|
||||||
|
try:
|
||||||
|
d = os.path.join(tmp, 'test-image')
|
||||||
|
os.mkdir(d)
|
||||||
|
|
||||||
|
with open(os.path.join(d, 'Dockerfile'), 'wb') as fh:
|
||||||
|
fh.write(b'# %include extra\n')
|
||||||
|
fh.write(b'# %include file0\n')
|
||||||
|
os.chmod(os.path.join(d, 'Dockerfile'), MODE_STANDARD)
|
||||||
|
|
||||||
|
extra = os.path.join(tmp, 'extra')
|
||||||
|
os.mkdir(extra)
|
||||||
|
for i in range(3):
|
||||||
|
p = os.path.join(extra, 'file%d' % i)
|
||||||
|
with open(p, 'wb') as fh:
|
||||||
|
fh.write(b'file%d' % i)
|
||||||
|
os.chmod(p, MODE_STANDARD)
|
||||||
|
|
||||||
|
with open(os.path.join(tmp, 'file0'), 'a'):
|
||||||
|
pass
|
||||||
|
os.chmod(os.path.join(tmp, 'file0'), MODE_STANDARD)
|
||||||
|
|
||||||
|
tp = os.path.join(tmp, 'tar')
|
||||||
|
h = docker.create_context_tar(tmp, d, tp, 'my_image')
|
||||||
|
|
||||||
|
self.assertEqual(h, 'e5440513ab46ae4c1d056269e1c6715d5da7d4bd673719d360411e35e5b87205')
|
||||||
|
|
||||||
|
with tarfile.open(tp, 'r:gz') as tf:
|
||||||
|
self.assertEqual(tf.getnames(), [
|
||||||
|
'my_image/Dockerfile',
|
||||||
|
'my_image/topsrcdir/extra/file0',
|
||||||
|
'my_image/topsrcdir/extra/file1',
|
||||||
|
'my_image/topsrcdir/extra/file2',
|
||||||
|
'my_image/topsrcdir/file0',
|
||||||
|
])
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp)
|
||||||
|
|
|
@ -6,6 +6,12 @@ from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
from mozpack.archive import (
|
||||||
|
create_tar_gz_from_files,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..'))
|
GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..'))
|
||||||
DOCKER_ROOT = os.path.join(GECKO, 'testing', 'docker')
|
DOCKER_ROOT = os.path.join(GECKO, 'testing', 'docker')
|
||||||
|
@ -28,28 +34,83 @@ def docker_image(name):
|
||||||
return '{}/{}:{}'.format(registry, name, version)
|
return '{}/{}:{}'.format(registry, name, version)
|
||||||
|
|
||||||
|
|
||||||
def generate_context_hash(image_path):
|
def generate_context_hash(topsrcdir, image_path, image_name):
|
||||||
'''Generates a sha256 hash for context directory used to build an image.
|
"""Generates a sha256 hash for context directory used to build an image."""
|
||||||
|
|
||||||
Contents of the directory are sorted alphabetically, contents of each file is hashed,
|
# It is a bit unfortunate we have to create a temp file here - it would
|
||||||
and then a hash is created for both the file hashs as well as their paths.
|
# be nicer to use an in-memory buffer.
|
||||||
|
fd, p = tempfile.mkstemp()
|
||||||
|
os.close(fd)
|
||||||
|
try:
|
||||||
|
return create_context_tar(topsrcdir, image_path, p, image_name)
|
||||||
|
finally:
|
||||||
|
os.unlink(p)
|
||||||
|
|
||||||
This ensures that hashs are consistent and also change based on if file locations
|
|
||||||
within the context directory change.
|
|
||||||
'''
|
|
||||||
context_hash = hashlib.sha256()
|
|
||||||
files = []
|
|
||||||
|
|
||||||
for dirpath, dirnames, filenames in os.walk(os.path.join(GECKO, image_path)):
|
def create_context_tar(topsrcdir, context_dir, out_path, prefix):
|
||||||
for filename in filenames:
|
"""Create a context tarball.
|
||||||
files.append(os.path.join(dirpath, filename))
|
|
||||||
|
|
||||||
for filename in sorted(files):
|
A directory ``context_dir`` containing a Dockerfile will be assembled into
|
||||||
relative_filename = filename.replace(GECKO, '')
|
a gzipped tar file at ``out_path``. Files inside the archive will be
|
||||||
with open(filename, 'rb') as f:
|
prefixed by directory ``prefix``.
|
||||||
file_hash = hashlib.sha256()
|
|
||||||
data = f.read()
|
|
||||||
file_hash.update(data)
|
|
||||||
context_hash.update(file_hash.hexdigest() + '\t' + relative_filename + '\n')
|
|
||||||
|
|
||||||
return context_hash.hexdigest()
|
We also scan the source Dockerfile for special syntax that influences
|
||||||
|
context generation.
|
||||||
|
|
||||||
|
If a line in the Dockerfile has the form ``# %include <path>``,
|
||||||
|
the relative path specified on that line will be matched against
|
||||||
|
files in the source repository and added to the context under the
|
||||||
|
path ``topsrcdir/``. If an entry is a directory, we add all files
|
||||||
|
under that directory.
|
||||||
|
|
||||||
|
Returns the SHA-256 hex digest of the created archive.
|
||||||
|
"""
|
||||||
|
archive_files = {}
|
||||||
|
|
||||||
|
for root, dirs, files in os.walk(context_dir):
|
||||||
|
for f in files:
|
||||||
|
source_path = os.path.join(root, f)
|
||||||
|
rel = source_path[len(context_dir) + 1:]
|
||||||
|
archive_path = os.path.join(prefix, rel)
|
||||||
|
archive_files[archive_path] = source_path
|
||||||
|
|
||||||
|
# Parse Dockerfile for special syntax of extra files to include.
|
||||||
|
with open(os.path.join(context_dir, 'Dockerfile'), 'rb') as fh:
|
||||||
|
for line in fh:
|
||||||
|
line = line.rstrip()
|
||||||
|
if not line.startswith('# %include'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
p = line[len('# %include '):].strip()
|
||||||
|
if os.path.isabs(p):
|
||||||
|
raise Exception('extra include path cannot be absolute: %s' % p)
|
||||||
|
|
||||||
|
fs_path = os.path.normpath(os.path.join(topsrcdir, p))
|
||||||
|
# Check for filesystem traversal exploits.
|
||||||
|
if not fs_path.startswith(topsrcdir):
|
||||||
|
raise Exception('extra include path outside topsrcdir: %s' % p)
|
||||||
|
|
||||||
|
if not os.path.exists(fs_path):
|
||||||
|
raise Exception('extra include path does not exist: %s' % p)
|
||||||
|
|
||||||
|
if os.path.isdir(fs_path):
|
||||||
|
for root, dirs, files in os.walk(fs_path):
|
||||||
|
for f in files:
|
||||||
|
source_path = os.path.join(root, f)
|
||||||
|
archive_path = os.path.join(prefix, 'topsrcdir', p, f)
|
||||||
|
archive_files[archive_path] = source_path
|
||||||
|
else:
|
||||||
|
archive_path = os.path.join(prefix, 'topsrcdir', p)
|
||||||
|
archive_files[archive_path] = fs_path
|
||||||
|
|
||||||
|
with open(out_path, 'wb') as fh:
|
||||||
|
create_tar_gz_from_files(fh, archive_files, '%s.tar.gz' % prefix)
|
||||||
|
|
||||||
|
h = hashlib.sha256()
|
||||||
|
with open(out_path, 'rb') as fh:
|
||||||
|
while True:
|
||||||
|
data = fh.read(32768)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
h.update(data)
|
||||||
|
return h.hexdigest()
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
FROM ubuntu:14.04
|
FROM ubuntu:16.04
|
||||||
MAINTAINER Greg Arndt <garndt@mozilla.com>
|
MAINTAINER Greg Arndt <garndt@mozilla.com>
|
||||||
|
|
||||||
# install non-build specific dependencies in a single layer
|
# Add worker user
|
||||||
ADD system-setup.sh /tmp/system-setup.sh
|
RUN useradd -d /home/worker -s /bin/bash -m worker
|
||||||
|
RUN mkdir /home/worker/artifacts && chown worker:worker /home/worker/artifacts
|
||||||
|
|
||||||
|
ADD system-setup.sh tooltool.py /tmp/
|
||||||
RUN bash /tmp/system-setup.sh
|
RUN bash /tmp/system-setup.sh
|
||||||
|
|
||||||
ADD bin /home/worker/bin
|
ADD bin /home/worker/bin
|
||||||
RUN chmod +x /home/worker/bin/*
|
|
||||||
|
|
||||||
ENV PATH /home/worker/bin:/usr/local/lib/python2.7.10/bin:$PATH
|
ENV PATH /home/worker/bin:$PATH
|
||||||
ENV SHELL /bin/bash
|
ENV SHELL /bin/bash
|
||||||
ENV HOME /home/worker
|
ENV HOME /home/worker
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.1.0
|
0.1.2
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
#! /bin/bash -e
|
#! /bin/bash -e
|
||||||
|
|
||||||
set -e
|
set -ex
|
||||||
|
|
||||||
# Ensure we have at least enough to check gecko out...
|
# Ensure we have at least enough to check gecko out...
|
||||||
test $GECKO_BASE_REPOSITORY
|
test $GECKO_BASE_REPOSITORY
|
||||||
|
|
||||||
# Workspace to checkout gecko into...
|
DESTDIR=$1
|
||||||
WORKSPACE=$1
|
|
||||||
mkdir -p $WORKSPACE
|
|
||||||
|
|
||||||
res=`curl --fail --retry 5 http://taskcluster/secrets/v1/secret/project/taskcluster/gecko/hgfingerprint`
|
res=`curl --fail --retry 5 http://taskcluster/secrets/v1/secret/project/taskcluster/gecko/hgfingerprint`
|
||||||
FP=`echo $res | jq -r .secret.content`
|
FP=`echo $res | jq -r .secret.content`
|
||||||
|
@ -18,16 +16,16 @@ if [[ ! "$FP" =~ ^[a-f0-9:]+$ ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir /etc/mercurial
|
if [ -n "${GECKO_HEAD_REV}" ]; then
|
||||||
cat >/etc/mercurial/hgrc <<EOF
|
args="--revision ${GECKO_HEAD_REV}"
|
||||||
[hostfingerprints]
|
else
|
||||||
hg.mozilla.org = $FP
|
args="--branch ${GECKO_HEAD_REF}"
|
||||||
EOF
|
fi
|
||||||
|
|
||||||
# Note that tc-vcs requires only the first two arguments so others are optional.
|
hg --config hostfingerprints.hg.mozilla.org=${FP} robustcheckout \
|
||||||
# This is intended to make it easier to clone local directories.
|
--sharebase /home/worker/hg-shared \
|
||||||
tc-vcs checkout $WORKSPACE/gecko \
|
--purge \
|
||||||
$GECKO_BASE_REPOSITORY \
|
${args} \
|
||||||
$GECKO_HEAD_REPOSITORY \
|
--upstream ${GECKO_BASE_REPOSITORY} \
|
||||||
$GECKO_HEAD_REV \
|
${GECKO_HEAD_REPOSITORY} \
|
||||||
$GECKO_HEAD_REF
|
${DESTDIR}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# The script starts executing as root. We need to change ownership
|
||||||
|
# of the caches because they are initially owned by root:root.
|
||||||
|
if [ $(id -u) = 0 ]; then
|
||||||
|
chown worker:worker /home/worker/hg-shared /home/worker/workspace
|
||||||
|
|
||||||
|
exec sudo -E -u worker /home/worker/bin/run-action "${@}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
/home/worker/bin/checkout-gecko /home/worker/workspace/gecko
|
||||||
|
cd /home/worker/workspace/gecko
|
||||||
|
ln -s /home/worker/artifacts artifacts &&
|
||||||
|
eval "./mach taskgraph action-task ${ACTION_ARGS}"
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# The script starts executing as root. We need to change ownership
|
||||||
|
# of the caches because they are initially owned by root:root.
|
||||||
|
if [ $(id -u) = 0 ]; then
|
||||||
|
chown worker:worker /home/worker/hg-shared /home/worker/workspace
|
||||||
|
|
||||||
|
exec sudo -E -u worker /home/worker/bin/run-decision "${@}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
/home/worker/bin/checkout-gecko /home/worker/workspace/gecko
|
||||||
|
cd /home/worker/workspace/gecko
|
||||||
|
ln -s /home/worker/artifacts artifacts
|
||||||
|
eval "./mach taskgraph decision ${DECISION_ARGS}"
|
|
@ -6,148 +6,75 @@ test `whoami` == 'root'
|
||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y --force-yes --no-install-recommends \
|
apt-get install -y --force-yes --no-install-recommends \
|
||||||
autotools-dev \
|
|
||||||
blt-dev \
|
|
||||||
bzip2 \
|
|
||||||
curl \
|
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
dpkg-dev \
|
curl \
|
||||||
gcc-multilib \
|
|
||||||
g++-multilib \
|
|
||||||
jq \
|
jq \
|
||||||
libbluetooth-dev \
|
python \
|
||||||
libbz2-dev \
|
sudo
|
||||||
libexpat1-dev \
|
|
||||||
libffi-dev \
|
|
||||||
libffi6 \
|
|
||||||
libffi6-dbg \
|
|
||||||
libgdbm-dev \
|
|
||||||
libgpm2 \
|
|
||||||
libncursesw5-dev \
|
|
||||||
libreadline-dev \
|
|
||||||
libsqlite3-dev \
|
|
||||||
libssl-dev \
|
|
||||||
libtinfo-dev \
|
|
||||||
make \
|
|
||||||
mime-support \
|
|
||||||
netbase \
|
|
||||||
net-tools \
|
|
||||||
python-dev \
|
|
||||||
python-pip \
|
|
||||||
python-crypto \
|
|
||||||
python-mox3 \
|
|
||||||
python-pil \
|
|
||||||
python-ply \
|
|
||||||
quilt \
|
|
||||||
tar \
|
|
||||||
tk-dev \
|
|
||||||
xz-utils \
|
|
||||||
zlib1g-dev
|
|
||||||
|
|
||||||
BUILD=/root/build
|
BUILD=/root/build
|
||||||
mkdir $BUILD
|
mkdir $BUILD
|
||||||
|
|
||||||
tooltool_fetch() {
|
tooltool_fetch() {
|
||||||
cat >manifest.tt
|
cat >manifest.tt
|
||||||
python $BUILD/tooltool.py fetch
|
python2.7 /tmp/tooltool.py fetch
|
||||||
rm manifest.tt
|
rm manifest.tt
|
||||||
}
|
}
|
||||||
|
|
||||||
curl https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py > ${BUILD}/tooltool.py
|
# Install Mercurial from custom debs since distro packages tend to lag behind.
|
||||||
|
|
||||||
cd $BUILD
|
cd $BUILD
|
||||||
tooltool_fetch <<'EOF'
|
tooltool_fetch <<EOF
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"size": 12250696,
|
"size": 44878,
|
||||||
"digest": "67615a6defbcda062f15a09f9dd3b9441afd01a8cc3255e5bc45b925378a0ddc38d468b7701176f6cc153ec52a4f21671b433780d9bde343aa9b9c1b2ae29feb",
|
"digest": "7b1fc1217e0dcaeea852b0af2dc559b1aafb704fbee7e29cbec75af57bacb84910a7ec92b5c33f04ee98f23b3a57f1fa451173fe7c8a96f58faefe319dc7dde1",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "Python-2.7.10.tar.xz",
|
"filename": "mercurial_3.8.4_amd64.deb"
|
||||||
"unpack": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cd Python-2.7.10
|
|
||||||
./configure --prefix /usr/local/lib/python2.7.10
|
|
||||||
make -j$(nproc)
|
|
||||||
make install
|
|
||||||
|
|
||||||
PATH=/usr/local/lib/python2.7.10/bin/:$PATH
|
|
||||||
python --version
|
|
||||||
|
|
||||||
# Enough python utilities to get "peep" working
|
|
||||||
cd $BUILD
|
|
||||||
tooltool_fetch <<'EOF'
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"size": 630700,
|
|
||||||
"digest": "1367f3a10c1fef2f8061e430585f1927f6bd7c416e764d65cea1f4255824d549efa77beef8ff784bbd62c307b4b1123502e7b3fd01a243c0cc5b433a841cc8b5",
|
|
||||||
"algorithm": "sha512",
|
|
||||||
"filename": "setuptools-18.1.tar.gz",
|
|
||||||
"unpack": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size": 1051205,
|
"size": 1818422,
|
||||||
"digest": "e7d2e003ec60fce5a75a6a23711d7f9b155e898faebcf55f3abdd912ef513f4e0cf43daca8f9da7179a7a4efe6e4a625a532d051349818847df1364eb5b326de",
|
"digest": "b476e2612e7495a1c7c5adfd84511aa7479e26cc9070289513ec705fbfc4c61806ce2dbcceca0e63f2e80669be416f3467a3cebb522dcb8a6aeb62cdd3df82f2",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "pip-6.1.1.tar.gz",
|
"filename": "mercurial-common_3.8.4_all.deb"
|
||||||
"unpack": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"size": 26912,
|
|
||||||
"digest": "9d730ed7852d4d217aaddda959cd5f871ef1b26dd6c513a3780bbb04a5a93a49d6b78e95c2274451a1311c10cc0a72755b269dc9af62640474e6e73a1abec370",
|
|
||||||
"algorithm": "sha512",
|
|
||||||
"filename": "peep-2.4.1.tar.gz",
|
|
||||||
"unpack": false
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cd $BUILD
|
dpkg -i mercurial-common_3.8.4_all.deb mercurial_3.8.4_amd64.deb
|
||||||
cd setuptools-18.1
|
|
||||||
python setup.py install
|
|
||||||
# NOTE: latest peep is not compatible with pip>=7.0
|
|
||||||
# https://github.com/erikrose/peep/pull/94
|
|
||||||
|
|
||||||
cd $BUILD
|
mkdir -p /usr/local/mercurial
|
||||||
cd pip-6.1.1
|
chown 755 /usr/local/mercurial
|
||||||
python setup.py install
|
cd /usr/local/mercurial
|
||||||
|
|
||||||
cd $BUILD
|
|
||||||
pip install peep-2.4.1.tar.gz
|
|
||||||
|
|
||||||
# Peep (latest)
|
|
||||||
cd $BUILD
|
|
||||||
pip install peep
|
|
||||||
|
|
||||||
# remaining Python utilities are installed with `peep` from upstream
|
|
||||||
# repositories; peep verifies file integrity for us
|
|
||||||
cat >requirements.txt <<'EOF'
|
|
||||||
# sha256: 90pZQ6kAXB6Je8-H9-ivfgDAb6l3e5rWkfafn6VKh9g
|
|
||||||
virtualenv==13.1.2
|
|
||||||
|
|
||||||
# sha256: wJnELXTi1SC2HdNyzZlrD6dgXAZheDT9exPHm5qaWzA
|
|
||||||
mercurial==3.7.3
|
|
||||||
EOF
|
|
||||||
peep install -r requirements.txt
|
|
||||||
|
|
||||||
# Install node
|
|
||||||
tooltool_fetch <<'EOF'
|
tooltool_fetch <<'EOF'
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"size": 5676610,
|
"size": 11849,
|
||||||
"digest": "ce27b788dfd141a5ba7674332825fc136fe2c4f49a319dd19b3a87c8fffa7a97d86cbb8535661c9a68c9122719aa969fc6a8c886458a0df9fc822eec99ed130b",
|
"digest": "c88d9b8afd6649bd28bbacfa654ebefec8087a01d1662004aae088d485edeb03a92df1193d1310c0369d7721f475b974fcd4a911428ec65936f7e40cf1609c49",
|
||||||
"algorithm": "sha512",
|
"algorithm": "sha512",
|
||||||
"filename": "node-v0.10.36-linux-x64.tar.gz"
|
"filename": "robustcheckout.py"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
tar -C /usr/local -xz --strip-components 1 < node-*.tar.gz
|
|
||||||
node -v # verify
|
|
||||||
|
|
||||||
npm install -g taskcluster-vcs@2.3.34
|
chmod 644 /usr/local/mercurial/robustcheckout.py
|
||||||
|
|
||||||
|
# Install a global hgrc file with reasonable defaults.
|
||||||
|
mkdir -p /etc/mercurial
|
||||||
|
cat >/etc/mercurial/hgrc <<EOF
|
||||||
|
# By default the progress bar starts after 3s and updates every 0.1s. We
|
||||||
|
# change this so it shows and updates every 1.0s.
|
||||||
|
[progress]
|
||||||
|
delay = 1.0
|
||||||
|
refresh = 1.0
|
||||||
|
|
||||||
|
[web]
|
||||||
|
cacerts = /etc/ssl/certs/ca-certificates.crt
|
||||||
|
|
||||||
|
[extensions]
|
||||||
|
robustcheckout = /usr/local/mercurial/robustcheckout.py
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 644 /etc/mercurial/hgrc
|
||||||
|
|
||||||
cd /
|
cd /
|
||||||
rm -rf $BUILD
|
rm -rf $BUILD
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4,15 +4,19 @@ MAINTAINER Andrew Halberstadt <ahalberstadt@mozilla.com>
|
||||||
RUN useradd -d /home/worker -s /bin/bash -m worker
|
RUN useradd -d /home/worker -s /bin/bash -m worker
|
||||||
WORKDIR /home/worker
|
WORKDIR /home/worker
|
||||||
|
|
||||||
# Install tooltool directly from github.
|
|
||||||
RUN mkdir /build
|
RUN mkdir /build
|
||||||
ADD https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py /build/tooltool.py
|
# %include testing/docker/decision/tooltool.py
|
||||||
RUN chmod +rx /build/tooltool.py
|
ADD topsrcdir/testing/docker/decision/tooltool.py /build/tooltool.py
|
||||||
|
|
||||||
# Install lint packages
|
# %include testing/docker/recipes/install-mercurial.sh
|
||||||
|
ADD topsrcdir/testing/docker/recipes/install-mercurial.sh /build/install-mercurial.sh
|
||||||
ADD system-setup.sh /tmp/system-setup.sh
|
ADD system-setup.sh /tmp/system-setup.sh
|
||||||
RUN bash /tmp/system-setup.sh
|
RUN bash /tmp/system-setup.sh
|
||||||
|
|
||||||
|
# %include testing/docker/recipes/checkout-gecko-and-run
|
||||||
|
ADD topsrcdir/testing/docker/recipes/checkout-gecko-and-run /home/worker/bin/checkout-gecko-and-run
|
||||||
|
RUN chown -R worker:worker /home/worker/bin && chmod 755 /home/worker/bin/*
|
||||||
|
|
||||||
# Set variable normally configured at login, by the shells parent process, these
|
# Set variable normally configured at login, by the shells parent process, these
|
||||||
# are taken from GNU su manual
|
# are taken from GNU su manual
|
||||||
ENV HOME /home/worker
|
ENV HOME /home/worker
|
||||||
|
|
|
@ -11,7 +11,6 @@ cd /setup
|
||||||
|
|
||||||
apt_packages=()
|
apt_packages=()
|
||||||
apt_packages+=('curl')
|
apt_packages+=('curl')
|
||||||
apt_packages+=('mercurial')
|
|
||||||
apt_packages+=('python')
|
apt_packages+=('python')
|
||||||
apt_packages+=('python-pip')
|
apt_packages+=('python-pip')
|
||||||
apt_packages+=('sudo')
|
apt_packages+=('sudo')
|
||||||
|
@ -31,6 +30,8 @@ tooltool_fetch() {
|
||||||
rm manifest.tt
|
rm manifest.tt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cd /build
|
||||||
|
. install-mercurial.sh
|
||||||
|
|
||||||
###
|
###
|
||||||
# ESLint Setup
|
# ESLint Setup
|
||||||
|
@ -40,6 +41,7 @@ tooltool_fetch() {
|
||||||
|
|
||||||
# For future reference things like this don't need to be uploaded to tooltool, as long
|
# For future reference things like this don't need to be uploaded to tooltool, as long
|
||||||
# as we verify the hash, we can download it from the external net.
|
# as we verify the hash, we can download it from the external net.
|
||||||
|
cd /setup
|
||||||
tooltool_fetch <<'EOF'
|
tooltool_fetch <<'EOF'
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -54,33 +56,24 @@ tar -C /usr/local --strip-components 1 -xJ < node-*.tar.xz
|
||||||
node -v # verify
|
node -v # verify
|
||||||
npm -v
|
npm -v
|
||||||
|
|
||||||
# install taskcluster-vcs@2.3.12
|
|
||||||
tooltool_fetch <<'EOF'
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"size": 6282161,
|
|
||||||
"visibility": "public",
|
|
||||||
"digest": "a781a96e596f6403eca6ec2300adb9c1a396659393e16993c66f98a658050e557bc681d521f70b50c1162aa4b435274e0098ffcbd37cbe969c0e4f69be19a1e0",
|
|
||||||
"algorithm": "sha512",
|
|
||||||
"filename": "taskcluster-vcs-v2.3.12.tar.gz"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
EOF
|
|
||||||
npm install -g taskcluster-vcs-v2.3.12.tar.gz
|
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# Flake8 Setup
|
# Flake8 Setup
|
||||||
###
|
###
|
||||||
|
|
||||||
|
cd /setup
|
||||||
cat >requirements.txt <<'EOF'
|
cat >requirements.txt <<'EOF'
|
||||||
mccabe==0.4.0 --hash=sha256:cbc2938f6c01061bc6d21d0c838c2489664755cb18676f0734d7617f4577d09e
|
flake8==2.5.4 \
|
||||||
pep8==1.7.0 --hash=sha256:4fc2e478addcf17016657dff30b2d8d611e8341fac19ccf2768802f6635d7b8a
|
--hash=sha256:fb5a67af4024622287a76abf6b7fe4fb3cfacf765a790976ce64f52c44c88e4a
|
||||||
pyflakes==1.2.3 --hash=sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da
|
mccabe==0.4.0 \
|
||||||
flake8==2.5.4 --hash=sha256:fb5a67af4024622287a76abf6b7fe4fb3cfacf765a790976ce64f52c44c88e4a
|
--hash=sha256:cbc2938f6c01061bc6d21d0c838c2489664755cb18676f0734d7617f4577d09e
|
||||||
|
pep8==1.7.0 \
|
||||||
|
--hash=sha256:4fc2e478addcf17016657dff30b2d8d611e8341fac19ccf2768802f6635d7b8a
|
||||||
|
pyflakes==1.2.3 \
|
||||||
|
--hash=sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
pip install --require-hashes -r requirements.txt
|
pip install --require-hashes -r requirements.txt
|
||||||
|
|
||||||
cd /
|
cd /
|
||||||
rm -rf /setup
|
rm -rf /setup
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
# The script starts executing as root. We need to change ownership
|
||||||
|
# of the caches because they are initially owned by root:root. There
|
||||||
|
# may not be a cache mount/directory on some instances. So create the
|
||||||
|
# directory if missing.
|
||||||
|
if [ $(id -u) = 0 ]; then
|
||||||
|
mkdir -p /home/worker/workspace
|
||||||
|
chown worker:worker /home/worker/hg-shared /home/worker/workspace
|
||||||
|
|
||||||
|
exec sudo -E -u worker ${0} "${@}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEST=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
# We set the base repository to mozilla-central so tc-vcs doesn't get
|
||||||
|
# confused. Switch to mozilla-unified because robustcheckout works best
|
||||||
|
# with it.
|
||||||
|
if [ "${GECKO_BASE_REPOSITORY}" = "https://hg.mozilla.org/mozilla-central" ]; then
|
||||||
|
GECKO_BASE_REPOSITORY=https://hg.mozilla.org/mozilla-unified
|
||||||
|
fi
|
||||||
|
|
||||||
|
/usr/bin/hg robustcheckout \
|
||||||
|
--sharebase /home/worker/hg-shared \
|
||||||
|
--purge \
|
||||||
|
--upstream ${GECKO_BASE_REPOSITORY} \
|
||||||
|
--revision ${GECKO_HEAD_REV} \
|
||||||
|
${GECKO_HEAD_REPOSITORY} \
|
||||||
|
${DEST}
|
||||||
|
|
||||||
|
exec "${@}"
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
# This script installs and configures Mercurial.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# ASSERTION: We are running Ubuntu 16.04.
|
||||||
|
tooltool_fetch <<EOF
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"size": 44878,
|
||||||
|
"digest": "7b1fc1217e0dcaeea852b0af2dc559b1aafb704fbee7e29cbec75af57bacb84910a7ec92b5c33f04ee98f23b3a57f1fa451173fe7c8a96f58faefe319dc7dde1",
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"filename": "mercurial_3.8.4_amd64.deb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size": 1818422,
|
||||||
|
"digest": "b476e2612e7495a1c7c5adfd84511aa7479e26cc9070289513ec705fbfc4c61806ce2dbcceca0e63f2e80669be416f3467a3cebb522dcb8a6aeb62cdd3df82f2",
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"filename": "mercurial-common_3.8.4_all.deb"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
dpkg -i mercurial-common_3.8.4_all.deb mercurial_3.8.4_amd64.deb
|
||||||
|
|
||||||
|
mkdir -p /usr/local/mercurial
|
||||||
|
cd /usr/local/mercurial
|
||||||
|
tooltool_fetch <<'EOF'
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"size": 11849,
|
||||||
|
"digest": "c88d9b8afd6649bd28bbacfa654ebefec8087a01d1662004aae088d485edeb03a92df1193d1310c0369d7721f475b974fcd4a911428ec65936f7e40cf1609c49",
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"filename": "robustcheckout.py"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
EOF
|
||||||
|
chmod 644 /usr/local/mercurial/robustcheckout.py
|
||||||
|
|
||||||
|
mkdir -p /etc/mercurial
|
||||||
|
cat >/etc/mercurial/hgrc <<EOF
|
||||||
|
# By default the progress bar starts after 3s and updates every 0.1s. We
|
||||||
|
# change this so it shows and updates every 1.0s.
|
||||||
|
[progress]
|
||||||
|
delay = 1.0
|
||||||
|
refresh = 1.0
|
||||||
|
|
||||||
|
[web]
|
||||||
|
cacerts = /etc/ssl/certs/ca-certificates.crt
|
||||||
|
|
||||||
|
[extensions]
|
||||||
|
robustcheckout = /usr/local/mercurial/robustcheckout.py
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 644 /etc/mercurial/hgrc
|
|
@ -62,18 +62,11 @@ class MarionetteHarness(object):
|
||||||
self._testcase_class.pydebugger = __import__(self.args['pydebugger'])
|
self._testcase_class.pydebugger = __import__(self.args['pydebugger'])
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
|
||||||
self.process_args()
|
self.process_args()
|
||||||
tests = self.args.pop('tests')
|
tests = self.args.pop('tests')
|
||||||
runner = self._runner_class(**self.args)
|
runner = self._runner_class(**self.args)
|
||||||
runner.run_tests(tests)
|
runner.run_tests(tests)
|
||||||
return runner.failed + runner.crashed
|
return runner.failed + runner.crashed
|
||||||
except Exception:
|
|
||||||
logger = self.args.get('logger')
|
|
||||||
if logger:
|
|
||||||
logger.error('Failure during test execution.',
|
|
||||||
exc_info=True)
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def cli(runner_class=MarionetteTestRunner, parser_class=MarionetteArguments,
|
def cli(runner_class=MarionetteTestRunner, parser_class=MarionetteArguments,
|
||||||
|
@ -88,11 +81,13 @@ def cli(runner_class=MarionetteTestRunner, parser_class=MarionetteArguments,
|
||||||
"""
|
"""
|
||||||
logger = mozlog.commandline.setup_logging('Marionette test runner', {})
|
logger = mozlog.commandline.setup_logging('Marionette test runner', {})
|
||||||
try:
|
try:
|
||||||
failed = harness_class(runner_class, parser_class, testcase_class, args=args).run()
|
harness_instance = harness_class(runner_class, parser_class, testcase_class,
|
||||||
|
args=args)
|
||||||
|
failed = harness_instance.run()
|
||||||
if failed > 0:
|
if failed > 0:
|
||||||
sys.exit(10)
|
sys.exit(10)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error('Failure during harness setup', exc_info=True)
|
logger.error('Failure during harness execution', exc_info=True)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,6 @@ skip-if = true # Bug 1265878
|
||||||
[../tests/dom/media/tests/mochitest/test_peerConnection_verifyVideoAfterRenegotiation.html]
|
[../tests/dom/media/tests/mochitest/test_peerConnection_verifyVideoAfterRenegotiation.html]
|
||||||
[../tests/dom/media/tests/mochitest/test_peerConnection_webAudio.html]
|
[../tests/dom/media/tests/mochitest/test_peerConnection_webAudio.html]
|
||||||
[../tests/dom/media/tests/mochitest/test_selftest.html]
|
[../tests/dom/media/tests/mochitest/test_selftest.html]
|
||||||
[../tests/dom/media/tests/mochitest/test_zmedia_cleanup.html]
|
|
||||||
[../tests/dom/media/tests/mochitest/identity/test_fingerprints.html]
|
[../tests/dom/media/tests/mochitest/identity/test_fingerprints.html]
|
||||||
skip-if = true # Bug 1200411
|
skip-if = true # Bug 1200411
|
||||||
[../tests/dom/media/tests/mochitest/identity/test_getIdentityAssertion.html]
|
[../tests/dom/media/tests/mochitest/identity/test_getIdentityAssertion.html]
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
config = {
|
|
||||||
'base_name': 'Android armv7 API 11+ %(branch)s',
|
|
||||||
'stage_platform': 'android-api-11',
|
|
||||||
'build_type': 'api-11-opt',
|
|
||||||
'src_mozconfig': 'mobile/android/config/mozconfigs/android-api-11/nightly',
|
|
||||||
'tooltool_manifest_src': 'mobile/android/config/tooltool-manifests/android/releng.manifest',
|
|
||||||
'multi_locale_config_platform': 'android',
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
config = {
|
|
||||||
'base_name': 'Android armv7 API 11+ %(branch)s debug',
|
|
||||||
'stage_platform': 'android-api-11-debug',
|
|
||||||
'build_type': 'api-11-debug',
|
|
||||||
'src_mozconfig': 'mobile/android/config/mozconfigs/android-api-11/debug',
|
|
||||||
'tooltool_manifest_src': 'mobile/android/config/tooltool-manifests/android/releng.manifest',
|
|
||||||
'multi_locale_config_platform': 'android',
|
|
||||||
'debug_build': True,
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
config = {
|
|
||||||
'base_name': 'Android armv7 API 9 %(branch)s',
|
|
||||||
'stage_platform': 'android-api-9',
|
|
||||||
'build_type': 'api-9-opt',
|
|
||||||
'src_mozconfig': 'mobile/android/config/mozconfigs/android-api-9-10-constrained/nightly',
|
|
||||||
'tooltool_manifest_src': 'mobile/android/config/tooltool-manifests/android/releng.manifest',
|
|
||||||
'multi_locale_config_platform': 'android',
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
config = {
|
|
||||||
'base_name': 'Android armv7 API 9 %(branch)s debug',
|
|
||||||
'stage_platform': 'android-api-9-debug',
|
|
||||||
'build_type': 'api-9-debug',
|
|
||||||
'src_mozconfig': 'mobile/android/config/mozconfigs/android-api-9-10-constrained/debug',
|
|
||||||
'tooltool_manifest_src': 'mobile/android/config/tooltool-manifests/android/releng.manifest',
|
|
||||||
'multi_locale_config_platform': 'android',
|
|
||||||
'debug_build': True,
|
|
||||||
}
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче