зеркало из 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:
|
||||
# checkout-gecko uses these to check out the source; the inputs
|
||||
# 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_REF: '{{revision}}'
|
||||
GECKO_HEAD_REV: '{{revision}}'
|
||||
|
||||
cache:
|
||||
level-{{level}}-{{project}}-tc-vcs-public-sources: /home/worker/.tc-vcs/
|
||||
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.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
|
||||
# Arguments passed into `mach taskgraph decision`
|
||||
# TODO use mozilla-unified for the base repository once the tc-vcs
|
||||
# tar.gz archives are created or tc-vcs isn't being used.
|
||||
DECISION_ARGS: >
|
||||
--pushlog-id='{{pushlog_id}}'
|
||||
--project='{{project}}'
|
||||
--message='{{comment}}'
|
||||
|
@ -104,6 +85,22 @@ tasks:
|
|||
--head-rev='{{revision}}'
|
||||
--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:
|
||||
'public':
|
||||
type: 'directory'
|
||||
|
|
|
@ -7452,7 +7452,7 @@ var gRemoteTabsUI = {
|
|||
* passed via this object.
|
||||
* This object also allows:
|
||||
* - '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
|
||||
* matching when comparing URIs.
|
||||
* - 'replaceQueryString' property to be set to true to exclude query string
|
||||
|
@ -7488,32 +7488,42 @@ function switchToTabHavingURI(aURI, aOpenNew, aOpenParams={}) {
|
|||
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;
|
||||
for (let i = 0; i < browsers.length; i++) {
|
||||
let browser = browsers[i];
|
||||
if (ignoreFragment ? browser.currentURI.equalsExceptRef(aURI) :
|
||||
browser.currentURI.equals(aURI)) {
|
||||
// Focus the matching window & tab
|
||||
let browserCompare = cleanURL(
|
||||
browser.currentURI.spec, ignoreQueryString || replaceQueryString, ignoreFragment);
|
||||
if (requestedCompare == browserCompare) {
|
||||
aWindow.focus();
|
||||
if (ignoreFragment) {
|
||||
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) {
|
||||
if (ignoreFragment || replaceQueryString) {
|
||||
browser.loadURI(aURI.spec);
|
||||
}
|
||||
aWindow.gBrowser.tabContainer.selectedIndex = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
add_task(function test_ignoreFragment() {
|
||||
add_task(function *test_ignoreFragment() {
|
||||
let tabRefAboutHome = gBrowser.addTab("about:home#1");
|
||||
yield promiseTabLoaded(tabRefAboutHome);
|
||||
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
||||
|
@ -35,7 +35,7 @@ add_task(function test_ignoreFragment() {
|
|||
cleanupTestTabs();
|
||||
});
|
||||
|
||||
add_task(function test_ignoreQueryString() {
|
||||
add_task(function* test_ignoreQueryString() {
|
||||
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
|
||||
yield promiseTabLoaded(tabRefAboutHome);
|
||||
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
||||
|
@ -52,7 +52,7 @@ add_task(function test_ignoreQueryString() {
|
|||
cleanupTestTabs();
|
||||
});
|
||||
|
||||
add_task(function test_replaceQueryString() {
|
||||
add_task(function* test_replaceQueryString() {
|
||||
let tabRefAboutHome = gBrowser.addTab("about:home?hello=firefox");
|
||||
yield promiseTabLoaded(tabRefAboutHome);
|
||||
let tabRefAboutMozilla = gBrowser.addTab("about:mozilla");
|
||||
|
@ -72,6 +72,38 @@ add_task(function test_replaceQueryString() {
|
|||
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
|
||||
|
||||
function cleanupTestTabs() {
|
||||
|
|
|
@ -627,7 +627,7 @@ function openPreferences(paneID, extraArgs)
|
|||
win = Services.ww.openWindow(null, Services.prefs.getCharPref("browser.chromeURL"),
|
||||
"_blank", "chrome,dialog=no,all", windowArguments);
|
||||
} else {
|
||||
newLoad = !win.switchToTabHavingURI(preferencesURL, true, {ignoreFragment: true});
|
||||
newLoad = !win.switchToTabHavingURI(preferencesURL, true, { ignoreFragment: true, replaceQueryString: true });
|
||||
browser = win.gBrowser.selectedBrowser;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,12 +140,24 @@ toolbarbutton.bookmark-item:not(.subviewbutton):not(:hover):not(:active):not([op
|
|||
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[open="true"] {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 1px;
|
||||
padding-inline-start: 4px;
|
||||
padding-inline-end: 2px;
|
||||
background: var(--toolbarbutton-active-background);
|
||||
box-shadow: var(--toolbarbutton-active-boxshadow);
|
||||
border-color: var(--toolbarbutton-active-bordercolor);
|
||||
}
|
||||
|
||||
.bookmark-item > .toolbarbutton-icon,
|
||||
|
@ -1670,7 +1682,7 @@ toolbarbutton.chevron {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -464,14 +464,20 @@ toolbarbutton.bookmark-item:not(.subviewbutton),
|
|||
#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder {
|
||||
margin: 0;
|
||||
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"] {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 1px;
|
||||
padding-inline-start: 4px;
|
||||
padding-inline-end: 2px;
|
||||
border-color: var(--toolbarbutton-active-bordercolor);
|
||||
box-shadow: var(--toolbarbutton-active-boxshadow);
|
||||
background: var(--toolbarbutton-active-background);
|
||||
}
|
||||
|
||||
.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"
|
||||
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
|
||||
MOZ_FORCE_GOLD=1
|
||||
fi
|
||||
|
|
|
@ -117,6 +117,7 @@ export MOZ_DEBUG_SYMBOLS
|
|||
|
||||
DEFAULT_GMAKE_FLAGS =
|
||||
DEFAULT_GMAKE_FLAGS += CC='$(CC)'
|
||||
DEFAULT_GMAKE_FLAGS += MT='$(MT)'
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST)
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR)
|
||||
DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST)
|
||||
|
|
|
@ -662,14 +662,14 @@ ifdef MSMANIFEST_TOOL
|
|||
@if test -f $@.manifest; then \
|
||||
if test -f '$(srcdir)/$@.manifest'; then \
|
||||
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 \
|
||||
echo 'Embedding manifest from $@.manifest'; \
|
||||
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||
$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||
fi; \
|
||||
elif test -f '$(srcdir)/$@.manifest'; then \
|
||||
echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
|
||||
mt.exe -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
||||
$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
||||
fi
|
||||
endif # MSVC with manifest tool
|
||||
ifdef MOZ_PROFILE_GENERATE
|
||||
|
@ -697,14 +697,14 @@ ifdef MSMANIFEST_TOOL
|
|||
@if test -f $@.manifest; then \
|
||||
if test -f '$(srcdir)/$@.manifest'; then \
|
||||
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 \
|
||||
echo 'Embedding manifest from $@.manifest'; \
|
||||
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||
$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||
fi; \
|
||||
elif test -f '$(srcdir)/$@.manifest'; then \
|
||||
echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
|
||||
mt.exe -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
||||
$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
|
||||
fi
|
||||
endif # MSVC with manifest tool
|
||||
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)
|
||||
ifdef MSMANIFEST_TOOL
|
||||
@if test -f $@.manifest; then \
|
||||
mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||
$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
|
||||
rm -f $@.manifest; \
|
||||
fi
|
||||
endif # MSVC with manifest tool
|
||||
|
@ -833,7 +833,7 @@ ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
|
|||
ifdef MSMANIFEST_TOOL
|
||||
ifdef EMBED_MANIFEST_AT
|
||||
@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; \
|
||||
fi
|
||||
endif # EMBED_MANIFEST_AT
|
||||
|
|
|
@ -11,5 +11,10 @@
|
|||
"synthesizeKeyFromKeyTag": true,
|
||||
"TargetFactory": true,
|
||||
"waitForTick": true,
|
||||
}
|
||||
},
|
||||
|
||||
"rules": {
|
||||
// Tests can always import anything.
|
||||
"mozilla/reject-some-requires": 0,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -15,5 +15,7 @@
|
|||
"block-scoped-var": 0,
|
||||
// Allow run_test to be unused in xpcshell
|
||||
"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";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const Services = require("Services");
|
||||
const promise = require("promise");
|
||||
const FocusManager = Services.focus;
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Cc, Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
|
||||
const ToolDefinitions = require("devtools/client/definitions").Tools;
|
||||
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 {createChild} = require("devtools/client/inspector/shared/utils");
|
||||
const {gDevTools} = require("devtools/client/framework/devtools");
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||
|
||||
loader.lazyRequireGetter(this, "overlays",
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
const l10n = require("gcli/l10n");
|
||||
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {EyeDropper, HighlighterEnvironment} = require("devtools/server/actors/highlighters");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
|
||||
exports.items = [{
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Cc, Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
|
||||
var Services = require("Services");
|
||||
var promise = require("promise");
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const promise = require("promise");
|
||||
const {Task} = require("devtools/shared/task");
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Cc, Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const {Task} = require("devtools/shared/task");
|
||||
const {InplaceEditor, editableItem} =
|
||||
require("devtools/client/shared/inplace-editor");
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Cc, Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
|
||||
// Page size for pageup/pagedown
|
||||
const PAGE_SIZE = 10;
|
||||
|
@ -54,7 +56,9 @@ const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
|
|||
const {template} = require("devtools/shared/gcli/templater");
|
||||
const nodeConstants = require("devtools/shared/dom-node-constants");
|
||||
const nodeFilterConstants = require("devtools/shared/dom-node-filter-constants");
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
|
||||
loader.lazyRequireGetter(this, "CSS", "CSS");
|
||||
loader.lazyGetter(this, "AutocompletePopup", () => {
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const promise = require("promise");
|
||||
const CssLogic = require("devtools/shared/inspector/css-logic");
|
||||
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Cc, Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const {escapeCSSComment} = require("devtools/shared/css-parsing-utils");
|
||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "domUtils", function () {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
|
|
|
@ -7,11 +7,15 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Cc, Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const promise = require("promise");
|
||||
const defer = require("devtools/shared/defer");
|
||||
const Services = require("Services");
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const {Task} = require("devtools/shared/task");
|
||||
const {Tools} = require("devtools/client/definitions");
|
||||
const {l10n} = require("devtools/shared/inspector/css-logic");
|
||||
|
|
|
@ -4,8 +4,12 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const {l10n} = require("devtools/shared/inspector/css-logic");
|
||||
const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
|
||||
const {PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const {l10n} = require("devtools/shared/inspector/css-logic");
|
||||
const {getCssProperties} = require("devtools/shared/fronts/css-properties");
|
||||
const {InplaceEditor, editableField} =
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const {Ci} = require("chrome");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
const {parseDeclarations} = require("devtools/shared/css-parsing-utils");
|
||||
const promise = require("promise");
|
||||
const {getCSSLexer} = require("devtools/shared/css-lexer");
|
||||
|
|
|
@ -10,7 +10,9 @@ var Services = require("Services");
|
|||
var EventEmitter = require("devtools/shared/event-emitter");
|
||||
var Telemetry = require("devtools/client/shared/telemetry");
|
||||
var { Task } = require("devtools/shared/task");
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
var { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
/* eslint-enable mozilla/reject-some-requires */
|
||||
|
||||
/**
|
||||
* This object represents replacement for ToolSidebar
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<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 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>
|
||||
|
|
До Ширина: | Высота: | Размер: 568 B После Ширина: | Высота: | Размер: 785 B |
|
@ -364,7 +364,7 @@
|
|||
}
|
||||
|
||||
.devtools-filterinput {
|
||||
background-image: var(--filter-image);
|
||||
background-image: url(images/filter.svg#filterinput);
|
||||
}
|
||||
|
||||
.devtools-searchinput:-moz-locale-dir(rtl),
|
||||
|
|
|
@ -5,24 +5,46 @@
|
|||
"use strict";
|
||||
|
||||
(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) {
|
||||
// require
|
||||
factory.call(this, require, exports, module);
|
||||
let console;
|
||||
if (isWorker) {
|
||||
console = {
|
||||
error: () => {}
|
||||
};
|
||||
} 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;
|
||||
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,
|
||||
// but it doesn't depends on any real module. We can save a few cycles
|
||||
// and bytes by not loading Loader.jsm.
|
||||
let require = function (module) {
|
||||
const Cu = Components.utils;
|
||||
switch (module) {
|
||||
case "devtools/shared/defer":
|
||||
return Cu.import("resource://gre/modules/Promise.jsm", {}).Promise.defer;
|
||||
case "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":
|
||||
return {
|
||||
Cu,
|
||||
|
@ -31,10 +53,13 @@
|
|||
}
|
||||
return null;
|
||||
};
|
||||
factory.call(this, require, this, { exports: this });
|
||||
factory.call(this, require, this, { exports: this }, console);
|
||||
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 () {};
|
||||
module.exports = EventEmitter;
|
||||
|
||||
|
@ -44,18 +69,13 @@
|
|||
const defer = require("devtools/shared/defer");
|
||||
let loggingEnabled = true;
|
||||
|
||||
let console = {};
|
||||
if (!isWorker) {
|
||||
console = require("resource://gre/modules/Console.jsm").console;
|
||||
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
|
||||
Services.prefs.addObserver("devtools.dump.emit", {
|
||||
observe: () => {
|
||||
loggingEnabled = Services.prefs.getBoolPref("devtools.dump.emit");
|
||||
}
|
||||
}, 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;
|
||||
}
|
||||
|
||||
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
|
||||
bool
|
||||
SpecifiedKeyframeArraysAreEqual(const nsTArray<Keyframe>& aA,
|
||||
|
|
|
@ -294,8 +294,6 @@ public:
|
|||
bool HasAnimationOfProperty(nsCSSProperty aProperty) const {
|
||||
return GetAnimationOfProperty(aProperty) != nullptr;
|
||||
}
|
||||
bool HasAnimationOfProperties(const nsCSSProperty* aProperties,
|
||||
size_t aPropertyCount) const;
|
||||
const InfallibleTArray<AnimationProperty>& Properties() const {
|
||||
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-5.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 1277272-1.html
|
||||
|
|
|
@ -41,6 +41,7 @@ support-files =
|
|||
mozilla/file_document-timeline-origin-time-range.html
|
||||
mozilla/file_hide_and_show.html
|
||||
mozilla/file_partial_keyframes.html
|
||||
mozilla/file_transform_limits.html
|
||||
style/file_animation-seeking-with-current-time.html
|
||||
style/file_animation-seeking-with-start-time.html
|
||||
testcommon.js
|
||||
|
@ -89,5 +90,6 @@ skip-if = (toolkit == 'gonk' && debug)
|
|||
[mozilla/test_hide_and_show.html]
|
||||
[mozilla/test_partial_keyframes.html]
|
||||
[mozilla/test_set-easing.html]
|
||||
[mozilla/test_transform_limits.html]
|
||||
[style/test_animation-seeking-with-current-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());
|
||||
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -323,9 +323,8 @@ MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown ||
|
||||
if (IsShutdown() ||
|
||||
!mDecoderStateMachine ||
|
||||
mPlayState == PLAY_STATE_SHUTDOWN ||
|
||||
!mOwner->GetVideoFrameContainer() ||
|
||||
(mOwner->GetMediaElement() && mOwner->GetMediaElement()->IsBeingDestroyed()) ||
|
||||
!mDormantSupported)
|
||||
|
@ -372,20 +371,8 @@ MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity)
|
|||
return;
|
||||
}
|
||||
|
||||
if (mIsDormant) {
|
||||
DECODER_LOG("UpdateDormantState() entering DORMANT state");
|
||||
// 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);
|
||||
}
|
||||
DECODER_LOG("UpdateDormantState() %s DORMANT state", mIsDormant ? "entering" : "exiting");
|
||||
mDecoderStateMachine->DispatchSetDormant(mIsDormant);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -407,7 +394,7 @@ MediaDecoder::StartDormantTimer()
|
|||
}
|
||||
|
||||
if (mIsHeuristicDormant ||
|
||||
mShuttingDown ||
|
||||
IsShutdown() ||
|
||||
mIsVisible ||
|
||||
(mPlayState != PLAY_STATE_PAUSED &&
|
||||
!IsEnded()))
|
||||
|
@ -437,12 +424,13 @@ void
|
|||
MediaDecoder::Pause()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mPlayState == PLAY_STATE_LOADING ||
|
||||
IsEnded()) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
if (mPlayState == PLAY_STATE_LOADING || IsEnded()) {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeState(PLAY_STATE_PAUSED);
|
||||
}
|
||||
|
||||
|
@ -488,13 +476,13 @@ void
|
|||
MediaDecoder::SetInfinite(bool aInfinite)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
mInfiniteStream = aInfinite;
|
||||
DurationChanged();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoder::IsInfinite()
|
||||
MediaDecoder::IsInfinite() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mInfiniteStream;
|
||||
|
@ -516,13 +504,11 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
|||
, mVideoFrameContainer(aOwner->GetVideoFrameContainer())
|
||||
, mPlaybackStatistics(new MediaChannelStatistics())
|
||||
, mPinnedForSeek(false)
|
||||
, mShuttingDown(false)
|
||||
, mPausedForPlaybackRateNull(false)
|
||||
, mMinimizePreroll(false)
|
||||
, mMediaTracksConstructed(false)
|
||||
, mFiredMetadataLoaded(false)
|
||||
, mIsDormant(false)
|
||||
, mWasEndedWhenEnteredDormant(false)
|
||||
, mIsHeuristicDormantSupported(
|
||||
Preferences::GetBool("media.decoder.heuristic.dormant.enabled", false))
|
||||
, mHeuristicDormantTimeout(
|
||||
|
@ -620,12 +606,10 @@ MediaDecoder::Shutdown()
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mShuttingDown = true;
|
||||
|
||||
// Unwatch all watch targets to prevent further notifications.
|
||||
mWatchManager.Shutdown();
|
||||
|
||||
|
@ -820,7 +804,7 @@ nsresult
|
|||
MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType, dom::Promise* aPromise /*=nullptr*/)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_TRUE(!mShuttingDown, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(!IsShutdown(), NS_ERROR_FAILURE);
|
||||
|
||||
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();
|
||||
|
||||
mLogicalPosition = aTime;
|
||||
mWasEndedWhenEnteredDormant = false;
|
||||
|
||||
mLogicallySeeking = true;
|
||||
SeekTarget target = SeekTarget(timeUsecs, aSeekType);
|
||||
|
@ -924,7 +907,7 @@ MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
|
|||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
|
||||
DECODER_LOG("MetadataLoaded, channels=%u rate=%u hasAudio=%d hasVideo=%d",
|
||||
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
||||
|
@ -997,7 +980,7 @@ MediaDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
|||
MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
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",
|
||||
aInfo->mAudio.mChannels, aInfo->mAudio.mRate,
|
||||
|
@ -1030,7 +1013,7 @@ nsresult
|
|||
MediaDecoder::FinishDecoderSetup(MediaResource* aResource)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
HTMLMediaElement* element = mOwner->GetMediaElement();
|
||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||
element->FinishDecoderSetup(this, aResource);
|
||||
|
@ -1041,7 +1024,7 @@ void
|
|||
MediaDecoder::ResetConnectionState()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
|
||||
// Notify the media element that connection gets lost.
|
||||
mOwner->ResetConnectionState();
|
||||
|
@ -1056,7 +1039,7 @@ void
|
|||
MediaDecoder::NetworkError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown)
|
||||
if (IsShutdown())
|
||||
return;
|
||||
|
||||
mOwner->NetworkError();
|
||||
|
@ -1067,7 +1050,7 @@ void
|
|||
MediaDecoder::DecodeError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown)
|
||||
if (IsShutdown())
|
||||
return;
|
||||
|
||||
mOwner->DecodeError();
|
||||
|
@ -1092,14 +1075,14 @@ bool
|
|||
MediaDecoder::IsEndedOrShutdown() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return IsEnded() || mPlayState == PLAY_STATE_SHUTDOWN;
|
||||
return IsEnded() || IsShutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoder::OwnerHasError() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mShuttingDown || mOwner->HasError();
|
||||
return IsShutdown() || mOwner->HasError();
|
||||
}
|
||||
|
||||
class MediaElementGMPCrashHelper : public GMPCrashHelper
|
||||
|
@ -1134,8 +1117,14 @@ bool
|
|||
MediaDecoder::IsEnded() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mPlayState == PLAY_STATE_ENDED ||
|
||||
(mWasEndedWhenEnteredDormant && (mPlayState != PLAY_STATE_SHUTDOWN));
|
||||
return mPlayState == PLAY_STATE_ENDED;
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoder::IsShutdown() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mPlayState == PLAY_STATE_SHUTDOWN;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1143,7 +1132,7 @@ MediaDecoder::PlaybackEnded()
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown ||
|
||||
if (IsShutdown() ||
|
||||
mLogicallySeeking ||
|
||||
mPlayState == PLAY_STATE_LOADING) {
|
||||
return;
|
||||
|
@ -1220,7 +1209,7 @@ void
|
|||
MediaDecoder::NotifySuspendedStatusChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
if (mResource) {
|
||||
bool suspended = mResource->IsSuspendedByCache();
|
||||
mOwner->NotifySuspendedByCache(suspended);
|
||||
|
@ -1231,7 +1220,7 @@ void
|
|||
MediaDecoder::NotifyBytesDownloaded()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
UpdatePlaybackRate();
|
||||
|
@ -1242,7 +1231,7 @@ void
|
|||
MediaDecoder::NotifyDownloadEnded(nsresult aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
|
||||
DECODER_LOG("NotifyDownloadEnded, status=%x", aStatus);
|
||||
|
||||
|
@ -1268,7 +1257,7 @@ void
|
|||
MediaDecoder::NotifyPrincipalChanged()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
nsCOMPtr<nsIPrincipal> newPrincipal = GetCurrentPrincipal();
|
||||
mMediaPrincipalHandle = MakePrincipalHandle(newPrincipal);
|
||||
mOwner->NotifyDecoderPrincipalChanged();
|
||||
|
@ -1278,7 +1267,7 @@ void
|
|||
MediaDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
|
||||
if (mIgnoreProgressData) {
|
||||
return;
|
||||
|
@ -1297,7 +1286,7 @@ MediaDecoder::OnSeekResolved(SeekResolveValue aVal)
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mSeekRequest.Complete();
|
||||
|
||||
if (mShuttingDown)
|
||||
if (IsShutdown())
|
||||
return;
|
||||
|
||||
bool fireEnded = false;
|
||||
|
@ -1337,7 +1326,7 @@ void
|
|||
MediaDecoder::SeekingStarted(MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown)
|
||||
if (IsShutdown())
|
||||
return;
|
||||
|
||||
if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
|
||||
|
@ -1349,15 +1338,12 @@ void
|
|||
MediaDecoder::ChangeState(PlayState aState)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsShutdown(), "SHUTDOWN is the final state.");
|
||||
|
||||
if (mNextState == aState) {
|
||||
mNextState = PLAY_STATE_PAUSED;
|
||||
}
|
||||
|
||||
if (mPlayState == PLAY_STATE_SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
DECODER_LOG("ChangeState %s => %s", PlayStateStr(), ToPlayStateStr(aState));
|
||||
mPlayState = aState;
|
||||
|
||||
|
@ -1376,7 +1362,7 @@ void
|
|||
MediaDecoder::UpdateLogicalPositionInternal(MediaDecoderEventVisibility aEventVisibility)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1401,7 +1387,7 @@ MediaDecoder::DurationChanged()
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1681,7 +1667,7 @@ MediaDecoder::NotifyDataArrived() {
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Don't publish events since task queues might be shutting down.
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1699,7 +1685,7 @@ void
|
|||
MediaDecoder::FireTimeUpdate()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
mOwner->FireTimeUpdate(true);
|
||||
|
@ -1879,7 +1865,7 @@ MediaDecoder::GetOwner()
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// mOwner is valid until shutdown.
|
||||
return !mShuttingDown ? mOwner : nullptr;
|
||||
return !IsShutdown() ? mOwner : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1887,7 +1873,7 @@ MediaDecoder::ConstructMediaTracks()
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown || mMediaTracksConstructed || !mInfo) {
|
||||
if (IsShutdown() || mMediaTracksConstructed || !mInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1923,7 +1909,7 @@ MediaDecoder::RemoveMediaTracks()
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1964,16 +1950,16 @@ void
|
|||
MediaDecoder::DumpDebugInfo()
|
||||
{
|
||||
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->HasAudio() : 0, mInfo ? mInfo->HasVideo() : 0,
|
||||
PlayStateStr(), mIsDormant, mShuttingDown);
|
||||
PlayStateStr(), mIsDormant, IsShutdown());
|
||||
|
||||
nsString str;
|
||||
GetMozDebugReaderData(str);
|
||||
DUMP_LOG("reader data:\n%s", NS_ConvertUTF16toUTF8(str).get());
|
||||
|
||||
if (!mShuttingDown && GetStateMachine()) {
|
||||
if (!IsShutdown() && GetStateMachine()) {
|
||||
GetStateMachine()->DumpDebugInfo();
|
||||
}
|
||||
}
|
||||
|
@ -1981,7 +1967,7 @@ MediaDecoder::DumpDebugInfo()
|
|||
void
|
||||
MediaDecoder::NotifyAudibleStateChanged()
|
||||
{
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
MOZ_ASSERT(!IsShutdown());
|
||||
mOwner->SetAudibleState(mIsAudioDataAudible);
|
||||
}
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ public:
|
|||
virtual double GetDuration();
|
||||
|
||||
// Return true if the stream is infinite (see SetInfinite).
|
||||
virtual bool IsInfinite();
|
||||
bool IsInfinite() const;
|
||||
|
||||
// Called by MediaResource when some data has been received.
|
||||
// Call on the main thread only.
|
||||
|
@ -232,12 +232,12 @@ public:
|
|||
|
||||
// Return true if we are currently seeking in the media resource.
|
||||
// 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
|
||||
// has shutdown.
|
||||
// Call on the main thread only.
|
||||
virtual bool IsEndedOrShutdown() const;
|
||||
bool IsEndedOrShutdown() const;
|
||||
|
||||
// Return true if the MediaDecoderOwner's error attribute is not null.
|
||||
// If the MediaDecoder is shutting down, OwnerHasError will return true.
|
||||
|
@ -493,7 +493,7 @@ private:
|
|||
void UpdateReadyState()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mShuttingDown) {
|
||||
if (!IsShutdown()) {
|
||||
mOwner->UpdateReadyState();
|
||||
}
|
||||
}
|
||||
|
@ -528,6 +528,8 @@ protected:
|
|||
// Return true if the decoder has reached the end of playback
|
||||
bool IsEnded() const;
|
||||
|
||||
bool IsShutdown() const;
|
||||
|
||||
// Called by the state machine to notify the decoder that the duration
|
||||
// has changed.
|
||||
void DurationChanged();
|
||||
|
@ -682,12 +684,6 @@ protected:
|
|||
// while seeking.
|
||||
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.
|
||||
bool mPausedForPlaybackRateNull;
|
||||
|
||||
|
@ -715,12 +711,6 @@ protected:
|
|||
// True if MediaDecoder is in dormant state.
|
||||
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.
|
||||
const bool mIsHeuristicDormantSupported;
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ MediaOmxCommonDecoder::ResumeStateMachine()
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DECODER_LOG(LogLevel::Debug, ("%s current time %f", __PRETTY_FUNCTION__, mLogicalPosition));
|
||||
|
||||
if (mShuttingDown) {
|
||||
if (IsShutdown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -156,8 +156,6 @@ MediaOmxCommonDecoder::ResumeStateMachine()
|
|||
// Call Seek of MediaDecoderStateMachine to suppress seek events.
|
||||
GetStateMachine()->InvokeSeek(target);
|
||||
|
||||
mNextState = mPlayState;
|
||||
ChangeState(PLAY_STATE_LOADING);
|
||||
// exit dormant state
|
||||
GetStateMachine()->DispatchSetDormant(false);
|
||||
UpdateLogicalPosition();
|
||||
|
|
|
@ -795,6 +795,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
|||
'IccChangeEvent.webidl',
|
||||
'ImageCaptureErrorEvent.webidl',
|
||||
'MediaStreamEvent.webidl',
|
||||
'MediaStreamTrackEvent.webidl',
|
||||
'MozCellBroadcastEvent.webidl',
|
||||
'MozClirModeEvent.webidl',
|
||||
'MozContactChangeEvent.webidl',
|
||||
|
@ -836,7 +837,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
|||
|
||||
if CONFIG['MOZ_WEBRTC']:
|
||||
GENERATED_EVENTS_WEBIDL_FILES += [
|
||||
'MediaStreamTrackEvent.webidl',
|
||||
'RTCDataChannelEvent.webidl',
|
||||
'RTCPeerConnectionIceEvent.webidl',
|
||||
'RTCTrackEvent.webidl',
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#define MOZ_GL_DEBUG 1
|
||||
#endif
|
||||
|
||||
#include "../../mfbt/Maybe.h"
|
||||
#include "../../mfbt/RefPtr.h"
|
||||
#include "../../mfbt/UniquePtr.h"
|
||||
|
||||
|
@ -3303,13 +3302,6 @@ public:
|
|||
|
||||
GLuint GetFB();
|
||||
|
||||
/*
|
||||
* Retrieves the size of the native windowing system drawable.
|
||||
*/
|
||||
virtual Maybe<gfx::IntSize> GetTargetSize() {
|
||||
return Maybe<gfx::IntSize>();
|
||||
};
|
||||
|
||||
private:
|
||||
void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
|
||||
switch (precisiontype) {
|
||||
|
|
|
@ -66,8 +66,6 @@ public:
|
|||
// Undoes the effect of a drawable override.
|
||||
bool RestoreDrawable();
|
||||
|
||||
virtual Maybe<gfx::IntSize> GetTargetSize() override;
|
||||
|
||||
private:
|
||||
friend class GLContextProviderGLX;
|
||||
|
||||
|
|
|
@ -987,20 +987,6 @@ GLContextGLX::SwapBuffers()
|
|||
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
|
||||
GLContextGLX::OverrideDrawable(GLXDrawable drawable)
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "CompositingRenderTargetOGL.h"
|
||||
#include "GLContext.h"
|
||||
#include "GLReadTexImageHelper.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -69,7 +70,9 @@ CompositingRenderTargetOGL::BindRenderTarget()
|
|||
}
|
||||
|
||||
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->fClearDepth(0.0);
|
||||
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);
|
||||
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 =
|
||||
CompositingRenderTargetOGL::RenderTargetForWindow(this, viewportSize);
|
||||
CompositingRenderTargetOGL::RenderTargetForWindow(this,
|
||||
IntSize(width, height));
|
||||
SetRenderTarget(rt);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -1060,7 +1050,8 @@ CompositorOGL::DrawQuad(const Rect& aRect,
|
|||
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);
|
||||
|
||||
MaskType maskType;
|
||||
|
@ -1501,21 +1492,13 @@ CompositorOGL::EndFrame()
|
|||
return;
|
||||
}
|
||||
|
||||
mCurrentRenderTarget = nullptr;
|
||||
|
||||
if (mTexturePool) {
|
||||
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();
|
||||
}
|
||||
|
||||
mCurrentRenderTarget = nullptr;
|
||||
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// Unbind all textures
|
||||
|
|
|
@ -241,7 +241,8 @@ case "$target" in
|
|||
|
||||
dnl Ensure that mt.exe is 'Microsoft (R) Manifest Tool',
|
||||
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
|
||||
AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.])
|
||||
fi
|
||||
|
@ -256,6 +257,7 @@ case "$target" in
|
|||
|
||||
MSMANIFEST_TOOL=1
|
||||
unset MSMT_TOOL
|
||||
AC_SUBST(MT)
|
||||
|
||||
# Check linker version
|
||||
_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.
|
||||
AutoMarkingNativeInterfacePtr iface(cx);
|
||||
if (iid) {
|
||||
if (Interface)
|
||||
iface = *Interface;
|
||||
|
||||
|
@ -835,7 +834,6 @@ XPCConvert::NativeInterface2JSObject(MutableHandleValue d,
|
|||
if (Interface)
|
||||
*Interface = iface;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<XPCWrappedNative> wrapper;
|
||||
nsresult rv = XPCWrappedNative::GetNewOrUsed(aHelper, xpcscope, iface,
|
||||
|
|
|
@ -446,7 +446,7 @@ ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
|
|||
if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) {
|
||||
return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
|
||||
}
|
||||
return nsLayoutUtils::HasCurrentAnimationsForProperties(aFrame, &aProperty, 1);
|
||||
return nsLayoutUtils::HasCurrentAnimationOfProperty(aFrame, aProperty);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
|
|
|
@ -2050,6 +2050,15 @@ FrameLayerBuilder::GetDebugSingleOldPaintedLayerForFrame(nsIFrame* aFrame)
|
|||
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>
|
||||
ContainerState::CreateOrRecycleColorLayer(PaintedLayer *aPainted)
|
||||
{
|
||||
|
@ -2057,7 +2066,7 @@ ContainerState::CreateOrRecycleColorLayer(PaintedLayer *aPainted)
|
|||
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
|
||||
RefPtr<ColorLayer> layer = data->mColorLayer;
|
||||
if (layer) {
|
||||
layer->SetMaskLayer(nullptr);
|
||||
ResetLayerStateForRecycling(layer);
|
||||
layer->ClearExtraDumpInfo();
|
||||
} else {
|
||||
// Create a new layer
|
||||
|
@ -2081,7 +2090,7 @@ ContainerState::CreateOrRecycleImageLayer(PaintedLayer *aPainted)
|
|||
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
|
||||
RefPtr<ImageLayer> layer = data->mImageLayer;
|
||||
if (layer) {
|
||||
layer->SetMaskLayer(nullptr);
|
||||
ResetLayerStateForRecycling(layer);
|
||||
layer->ClearExtraDumpInfo();
|
||||
} else {
|
||||
// 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.
|
||||
// We will reapply any necessary clipping.
|
||||
aLayer->SetMaskLayer(nullptr);
|
||||
aLayer->SetAncestorMaskLayers({});
|
||||
ResetLayerStateForRecycling(aLayer);
|
||||
aLayer->ClearExtraDumpInfo();
|
||||
|
||||
PaintedDisplayItemLayerUserData* data =
|
||||
|
@ -5230,8 +5238,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
|||
NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER,
|
||||
"Wrong layer type");
|
||||
containerLayer = static_cast<ContainerLayer*>(oldLayer);
|
||||
containerLayer->SetMaskLayer(nullptr);
|
||||
containerLayer->SetAncestorMaskLayers({});
|
||||
ResetLayerStateForRecycling(containerLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5417,7 +5424,7 @@ FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
|
|||
// layer rendering.
|
||||
return nullptr;
|
||||
}
|
||||
layer->SetMaskLayer(nullptr);
|
||||
ResetLayerStateForRecycling(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
|
||||
nsLayoutUtils::HasRelevantAnimationOfProperty(const nsIFrame* aFrame,
|
||||
nsCSSProperty aProperty)
|
||||
|
|
|
@ -2245,14 +2245,6 @@ public:
|
|||
*/
|
||||
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,
|
||||
* running or filling) animations or transitions for the
|
||||
|
|
|
@ -1082,12 +1082,14 @@ AddCSSValueAngle(double aCoeff1, const nsCSSValue &aValue1,
|
|||
{
|
||||
if (aValue1.GetUnit() == aValue2.GetUnit()) {
|
||||
// To avoid floating point error, if the units match, maintain the unit.
|
||||
aResult.SetFloatValue(aCoeff1 * aValue1.GetFloatValue() +
|
||||
aCoeff2 * aValue2.GetFloatValue(),
|
||||
aResult.SetFloatValue(
|
||||
EnsureNotNan(aCoeff1 * aValue1.GetFloatValue() +
|
||||
aCoeff2 * aValue2.GetFloatValue()),
|
||||
aValue1.GetUnit());
|
||||
} else {
|
||||
aResult.SetFloatValue(aCoeff1 * aValue1.GetAngleValueInRadians() +
|
||||
aCoeff2 * aValue2.GetAngleValueInRadians(),
|
||||
aResult.SetFloatValue(
|
||||
EnsureNotNan(aCoeff1 * aValue1.GetAngleValueInRadians() +
|
||||
aCoeff2 * aValue2.GetAngleValueInRadians()),
|
||||
eCSSUnit_Radian);
|
||||
}
|
||||
}
|
||||
|
@ -1254,7 +1256,7 @@ AddTransformScale(double aCoeff1, const nsCSSValue &aValue1,
|
|||
float v1 = aValue1.GetFloatValue() - 1.0f,
|
||||
v2 = aValue2.GetFloatValue() - 1.0f;
|
||||
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>
|
||||
|
|
|
@ -15417,6 +15417,16 @@ CSSParserImpl::ParseFunctionInternals(const uint32_t aVariantMask[],
|
|||
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);
|
||||
|
||||
if (ExpectSymbol(',', true)) {
|
||||
|
|
|
@ -413,9 +413,9 @@ void nsCSSValue::SetPercentValue(float aValue)
|
|||
|
||||
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();
|
||||
if (eCSSUnit_Number <= aUnit) {
|
||||
if (IsFloatUnit(aUnit)) {
|
||||
mUnit = aUnit;
|
||||
mValue.mFloat = aValue;
|
||||
MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
|
||||
|
|
|
@ -516,6 +516,8 @@ public:
|
|||
{ return eCSSUnit_Point <= aUnit && aUnit <= eCSSUnit_Pixel; }
|
||||
bool IsPixelLengthUnit() const
|
||||
{ return IsPixelLengthUnit(mUnit); }
|
||||
static bool IsFloatUnit(nsCSSUnit aUnit)
|
||||
{ return eCSSUnit_Number <= aUnit; }
|
||||
bool IsAngularUnit() const
|
||||
{ return eCSSUnit_Degree <= mUnit && mUnit <= eCSSUnit_Turn; }
|
||||
bool IsFrequencyUnit() const
|
||||
|
|
|
@ -4184,12 +4184,11 @@ inline uint32_t ListLength(const T* aList)
|
|||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
already_AddRefed<nsCSSShadowArray>
|
||||
nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
||||
static already_AddRefed<nsCSSShadowArray>
|
||||
GetShadowData(const nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
bool aIsBoxShadow,
|
||||
nsPresContext* aPresContext,
|
||||
RuleNodeCacheConditions& aConditions)
|
||||
{
|
||||
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
|
||||
unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(),
|
||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
||||
aContext, mPresContext, aConditions);
|
||||
aContext, aPresContext, aConditions);
|
||||
NS_ASSERTION(unitOK, "unexpected unit");
|
||||
item->mXOffset = tempCoord.GetCoordValue();
|
||||
|
||||
unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(),
|
||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
||||
aContext, mPresContext, aConditions);
|
||||
aContext, aPresContext, aConditions);
|
||||
NS_ASSERTION(unitOK, "unexpected unit");
|
||||
item->mYOffset = tempCoord.GetCoordValue();
|
||||
|
||||
|
@ -4228,7 +4227,7 @@ nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
|||
unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(),
|
||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY |
|
||||
SETCOORD_CALC_CLAMP_NONNEGATIVE,
|
||||
aContext, mPresContext, aConditions);
|
||||
aContext, aPresContext, aConditions);
|
||||
NS_ASSERTION(unitOK, "unexpected unit");
|
||||
item->mRadius = tempCoord.GetCoordValue();
|
||||
} else {
|
||||
|
@ -4239,7 +4238,7 @@ nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
|||
if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) {
|
||||
unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(),
|
||||
SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
|
||||
aContext, mPresContext, aConditions);
|
||||
aContext, aPresContext, aConditions);
|
||||
NS_ASSERTION(unitOK, "unexpected unit");
|
||||
item->mSpread = tempCoord.GetCoordValue();
|
||||
} else {
|
||||
|
@ -4249,7 +4248,7 @@ nsRuleNode::GetShadowData(const nsCSSValueList* aList,
|
|||
if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
|
||||
item->mHasColor = true;
|
||||
// 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);
|
||||
NS_ASSERTION(unitOK, "unexpected unit");
|
||||
}
|
||||
|
@ -4452,7 +4451,7 @@ nsRuleNode::ComputeTextData(void* aStartStruct,
|
|||
textShadowValue->GetUnit() == eCSSUnit_ListDep) {
|
||||
// List of arrays
|
||||
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)
|
||||
}
|
||||
|
||||
already_AddRefed<nsStyleBasicShape>
|
||||
nsRuleNode::GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
|
||||
static already_AddRefed<nsStyleBasicShape>
|
||||
GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
|
||||
nsStyleContext* aStyleContext,
|
||||
nsPresContext* aPresContext,
|
||||
RuleNodeCacheConditions& aConditions)
|
||||
|
@ -9698,8 +9697,8 @@ nsRuleNode::GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
|
|||
return basicShape.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||
static void
|
||||
SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
||||
const nsCSSValue* aValue,
|
||||
nsStyleContext* aStyleContext,
|
||||
nsPresContext* aPresContext,
|
||||
|
@ -9740,8 +9739,8 @@ nsRuleNode::SetStyleClipPathToCSSValue(nsStyleClipPath* aStyleClipPath,
|
|||
}
|
||||
|
||||
// Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
|
||||
bool
|
||||
nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
||||
static bool
|
||||
SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
||||
const nsCSSValue& aValue,
|
||||
nsStyleContext* aStyleContext,
|
||||
nsPresContext* aPresContext,
|
||||
|
@ -9773,6 +9772,7 @@ nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
|
|||
filterFunction->Item(1).GetListValue(),
|
||||
aStyleContext,
|
||||
false,
|
||||
aPresContext,
|
||||
aConditions);
|
||||
aStyleFilter->SetDropShadow(shadowArray);
|
||||
return true;
|
||||
|
@ -10161,7 +10161,7 @@ nsRuleNode::ComputeEffectsData(void* aStartStruct,
|
|||
case eCSSUnit_List:
|
||||
case eCSSUnit_ListDep:
|
||||
effects->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(),
|
||||
aContext, true, conditions);
|
||||
aContext, true, mPresContext, conditions);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -783,27 +783,6 @@ protected:
|
|||
inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID,
|
||||
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:
|
||||
nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
|
||||
nsIStyleRule* aRule, mozilla::SheetType aLevel, bool aIsImportant);
|
||||
|
|
|
@ -364,4 +364,11 @@ public class AppConstants {
|
|||
// Do nothing.
|
||||
//#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 (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);
|
||||
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() {
|
||||
@Override
|
||||
public void onPanelSelected(String panelId) {
|
||||
|
@ -2714,6 +2721,7 @@ public class BrowserApp extends GeckoApp
|
|||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Don't show the banner in guest mode.
|
||||
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
|
||||
public TelemetryJSONFilePingStore(final File storeDir, final String 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.mkdirs();
|
||||
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) {
|
||||
|
@ -129,7 +140,15 @@ public class TelemetryJSONFilePingStore extends TelemetryPingStore {
|
|||
|
||||
@Override
|
||||
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
|
||||
final ArrayList<TelemetryPing> out = new ArrayList<>(files.size());
|
||||
for (final File file : files) {
|
||||
|
|
|
@ -401,6 +401,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
|
|||
'health/HealthRecorder.java',
|
||||
'health/SessionInformation.java',
|
||||
'health/StubbedHealthRecorder.java',
|
||||
'home/activitystream/ActivityStream.java',
|
||||
'home/BookmarkFolderView.java',
|
||||
'home/BookmarkScreenshotRow.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_GCM', 'MOZ_ANDROID_EXCLUDE_FONTS', 'MOZ_LOCALE_SWITCHER',
|
||||
'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]:
|
||||
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_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"
|
||||
android:layout="@layout/home_banner"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -48,6 +48,13 @@ project_flag('MOZ_SWITCHBOARD',
|
|||
help='Include Switchboard A/B framework on Android',
|
||||
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',
|
||||
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.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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);
|
||||
}
|
||||
|
||||
@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
|
||||
public void testStorePingStoresCorrectData() throws Exception {
|
||||
assertStoreFileCount(0);
|
||||
|
|
|
@ -368,7 +368,8 @@ case "$target" in
|
|||
|
||||
dnl Ensure that mt.exe is 'Microsoft (R) Manifest Tool',
|
||||
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
|
||||
AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.])
|
||||
fi
|
||||
|
@ -383,6 +384,7 @@ case "$target" in
|
|||
|
||||
MSMANIFEST_TOOL=1
|
||||
unset MSMT_TOOL
|
||||
AC_SUBST(MT)
|
||||
|
||||
# Check linker version
|
||||
_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}}.latest.linux.{{build_name}}'
|
||||
scopes:
|
||||
# Nearly all of our build tasks use tc-vcs so just include the scope across
|
||||
# the board.
|
||||
- 'docker-worker:cache:level-{{level}}-{{project}}-tc-vcs'
|
||||
- 'docker-worker:cache:level-{{level}}-hg-shared'
|
||||
- 'docker-worker:cache:level-{{level}}-workspace'
|
||||
|
||||
payload:
|
||||
# Thirty minutes should be enough for lint checks
|
||||
maxRunTime: 1800
|
||||
|
||||
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:
|
||||
build_product: '{{build_product}}'
|
||||
|
|
|
@ -20,11 +20,12 @@ task:
|
|||
task-reference: "<docker-image>"
|
||||
|
||||
command:
|
||||
- /home/worker/bin/checkout-gecko-and-run
|
||||
- /home/worker/workspace/gecko
|
||||
- bash
|
||||
- -cx
|
||||
- >
|
||||
tc-vcs checkout ./gecko {{base_repository}} {{head_repository}} {{head_rev}} {{head_ref}} &&
|
||||
cd gecko/tools/lint/eslint &&
|
||||
cd /home/worker/workspace/gecko/tools/lint/eslint &&
|
||||
/build/tooltool.py fetch -m manifest.tt &&
|
||||
tar xvfz eslint.tar.gz &&
|
||||
rm eslint.tar.gz &&
|
||||
|
|
|
@ -18,11 +18,12 @@ task:
|
|||
taskId:
|
||||
task-reference: "<docker-image>"
|
||||
command:
|
||||
- /home/worker/bin/checkout-gecko-and-run
|
||||
- /home/worker/workspace/gecko
|
||||
- bash
|
||||
- -cx
|
||||
- >
|
||||
tc-vcs checkout ./gecko {{base_repository}} {{head_repository}} {{head_rev}} {{head_ref}} &&
|
||||
cd gecko &&
|
||||
cd /home/worker/workspace/gecko &&
|
||||
./mach lint -l flake8 -f treeherder
|
||||
extra:
|
||||
locations:
|
||||
|
|
|
@ -18,11 +18,12 @@ task:
|
|||
taskId:
|
||||
task-reference: "<docker-image>"
|
||||
command:
|
||||
- /home/worker/bin/checkout-gecko-and-run
|
||||
- /home/worker/workspace/gecko
|
||||
- bash
|
||||
- -cx
|
||||
- >
|
||||
tc-vcs checkout ./gecko {{base_repository}} {{head_repository}} {{head_rev}} {{head_ref}} &&
|
||||
cd gecko &&
|
||||
cd /home/worker/workspace/gecko &&
|
||||
./mach taskgraph python-tests
|
||||
extra:
|
||||
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
|
||||
yaml-templates
|
||||
how-tos
|
||||
docker-images
|
||||
|
|
|
@ -27,13 +27,16 @@ routes:
|
|||
|
||||
payload:
|
||||
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_REF: '{{head_ref}}'
|
||||
GECKO_HEAD_REV: '{{head_rev}}'
|
||||
ACTION_ARGS: >
|
||||
--decision-id='{{decision_task_id}}'
|
||||
--task-labels='{{task_labels}}'
|
||||
|
||||
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
|
||||
|
||||
features:
|
||||
|
@ -41,7 +44,7 @@ payload:
|
|||
|
||||
# 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'
|
||||
image: 'taskcluster/decision:0.1.2'
|
||||
|
||||
# Virtually no network or other potentially risky operations happen as part
|
||||
# of the task timeout aside from the initial clone. We intentionally have
|
||||
|
@ -50,16 +53,7 @@ payload:
|
|||
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 action-task
|
||||
--decision-id='{{decision_task_id}}'
|
||||
--task-labels='{{task_labels}}'
|
||||
- /home/worker/bin/run-action
|
||||
|
||||
artifacts:
|
||||
'public':
|
||||
|
|
|
@ -21,7 +21,7 @@ ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}'
|
|||
|
||||
def load_image_by_name(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)
|
||||
print("Fetching", image_index_url)
|
||||
|
|
|
@ -9,13 +9,13 @@ import json
|
|||
import os
|
||||
import re
|
||||
import urllib2
|
||||
import tarfile
|
||||
import time
|
||||
|
||||
from . import base
|
||||
from taskgraph.util.docker import (
|
||||
create_context_tar,
|
||||
docker_image,
|
||||
generate_context_hash
|
||||
generate_context_hash,
|
||||
)
|
||||
from taskgraph.util.templates import Templates
|
||||
|
||||
|
@ -64,10 +64,8 @@ class DockerImageTask(base.Task):
|
|||
templates = Templates(path)
|
||||
for image_name in config['images']:
|
||||
context_path = os.path.join('testing', 'docker', image_name)
|
||||
context_hash = generate_context_hash(context_path)
|
||||
|
||||
image_parameters = dict(parameters)
|
||||
image_parameters['context_hash'] = context_hash
|
||||
image_parameters['context_path'] = context_path
|
||||
image_parameters['artifact_path'] = 'public/image.tar'
|
||||
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))
|
||||
image_parameters['context_url'] = ARTIFACT_URL.format(
|
||||
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:
|
||||
# skip context generation since this isn't a decision task
|
||||
# TODO: generate context tarballs using subdirectory clones in
|
||||
# the image-building task so we don't have to worry about this.
|
||||
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)
|
||||
|
||||
|
@ -131,16 +138,6 @@ class DockerImageTask(base.Task):
|
|||
|
||||
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
|
||||
def from_json(cls, task_dict):
|
||||
# Generating index_paths for optimization
|
||||
|
|
|
@ -145,12 +145,13 @@ def set_interactive_task(task, interactive):
|
|||
|
||||
|
||||
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.
|
||||
"""
|
||||
whitelist = [
|
||||
re.compile("^level-[123]-.*-tc-vcs(-public-sources)?$"),
|
||||
re.compile("^level-[123]-hg-shared"),
|
||||
re.compile("^tooltool-cache$"),
|
||||
]
|
||||
try:
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import unittest
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
from ..task import docker_image
|
||||
|
@ -31,12 +30,6 @@ class TestDockerImageKind(unittest.TestCase):
|
|||
|
||||
# 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__':
|
||||
main()
|
||||
|
|
|
@ -6,6 +6,8 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
import tarfile
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
@ -13,6 +15,9 @@ from ..util import docker
|
|||
from mozunit import MockedOpen
|
||||
|
||||
|
||||
MODE_STANDARD = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
|
||||
|
||||
|
||||
class TestDocker(unittest.TestCase):
|
||||
|
||||
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:
|
||||
f.write("data\n")
|
||||
self.assertEqual(
|
||||
docker.generate_context_hash('docker/my-image'),
|
||||
'781143fcc6cc72c9024b058665265cb6bae3fb8031cad7227dd169ffbfced434'
|
||||
docker.generate_context_hash(docker.GECKO, 'docker/my-image', 'my-image'),
|
||||
'872d76a656f47ea17c043023ecc9ae6a222ba6d2a8df67b75498bba382e4fb07'
|
||||
)
|
||||
finally:
|
||||
docker.GECKO = old_GECKO
|
||||
|
@ -46,3 +51,138 @@ class TestDocker(unittest.TestCase):
|
|||
files["{}/myimage/VERSION".format(docker.DOCKER_ROOT)] = "1.2.3"
|
||||
with MockedOpen(files):
|
||||
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 os
|
||||
import tempfile
|
||||
|
||||
from mozpack.archive import (
|
||||
create_tar_gz_from_files,
|
||||
)
|
||||
|
||||
|
||||
GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..'))
|
||||
DOCKER_ROOT = os.path.join(GECKO, 'testing', 'docker')
|
||||
|
@ -28,28 +34,83 @@ def docker_image(name):
|
|||
return '{}/{}:{}'.format(registry, name, version)
|
||||
|
||||
|
||||
def generate_context_hash(image_path):
|
||||
'''Generates a sha256 hash for context directory used to build an image.
|
||||
def generate_context_hash(topsrcdir, image_path, image_name):
|
||||
"""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,
|
||||
and then a hash is created for both the file hashs as well as their paths.
|
||||
# It is a bit unfortunate we have to create a temp file here - it would
|
||||
# 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)):
|
||||
for filename in filenames:
|
||||
files.append(os.path.join(dirpath, filename))
|
||||
def create_context_tar(topsrcdir, context_dir, out_path, prefix):
|
||||
"""Create a context tarball.
|
||||
|
||||
for filename in sorted(files):
|
||||
relative_filename = filename.replace(GECKO, '')
|
||||
with open(filename, 'rb') as f:
|
||||
file_hash = hashlib.sha256()
|
||||
data = f.read()
|
||||
file_hash.update(data)
|
||||
context_hash.update(file_hash.hexdigest() + '\t' + relative_filename + '\n')
|
||||
A directory ``context_dir`` containing a Dockerfile will be assembled into
|
||||
a gzipped tar file at ``out_path``. Files inside the archive will be
|
||||
prefixed by directory ``prefix``.
|
||||
|
||||
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>
|
||||
|
||||
# install non-build specific dependencies in a single layer
|
||||
ADD system-setup.sh /tmp/system-setup.sh
|
||||
# Add worker user
|
||||
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
|
||||
|
||||
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 HOME /home/worker
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.1.0
|
||||
0.1.2
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
#! /bin/bash -e
|
||||
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
# Ensure we have at least enough to check gecko out...
|
||||
test $GECKO_BASE_REPOSITORY
|
||||
|
||||
# Workspace to checkout gecko into...
|
||||
WORKSPACE=$1
|
||||
mkdir -p $WORKSPACE
|
||||
DESTDIR=$1
|
||||
|
||||
res=`curl --fail --retry 5 http://taskcluster/secrets/v1/secret/project/taskcluster/gecko/hgfingerprint`
|
||||
FP=`echo $res | jq -r .secret.content`
|
||||
|
@ -18,16 +16,16 @@ if [[ ! "$FP" =~ ^[a-f0-9:]+$ ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
mkdir /etc/mercurial
|
||||
cat >/etc/mercurial/hgrc <<EOF
|
||||
[hostfingerprints]
|
||||
hg.mozilla.org = $FP
|
||||
EOF
|
||||
if [ -n "${GECKO_HEAD_REV}" ]; then
|
||||
args="--revision ${GECKO_HEAD_REV}"
|
||||
else
|
||||
args="--branch ${GECKO_HEAD_REF}"
|
||||
fi
|
||||
|
||||
# Note that tc-vcs requires only the first two arguments so others are optional.
|
||||
# This is intended to make it easier to clone local directories.
|
||||
tc-vcs checkout $WORKSPACE/gecko \
|
||||
$GECKO_BASE_REPOSITORY \
|
||||
$GECKO_HEAD_REPOSITORY \
|
||||
$GECKO_HEAD_REV \
|
||||
$GECKO_HEAD_REF
|
||||
hg --config hostfingerprints.hg.mozilla.org=${FP} robustcheckout \
|
||||
--sharebase /home/worker/hg-shared \
|
||||
--purge \
|
||||
${args} \
|
||||
--upstream ${GECKO_BASE_REPOSITORY} \
|
||||
${GECKO_HEAD_REPOSITORY} \
|
||||
${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 install -y --force-yes --no-install-recommends \
|
||||
autotools-dev \
|
||||
blt-dev \
|
||||
bzip2 \
|
||||
curl \
|
||||
ca-certificates \
|
||||
dpkg-dev \
|
||||
gcc-multilib \
|
||||
g++-multilib \
|
||||
curl \
|
||||
jq \
|
||||
libbluetooth-dev \
|
||||
libbz2-dev \
|
||||
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
|
||||
python \
|
||||
sudo
|
||||
|
||||
BUILD=/root/build
|
||||
mkdir $BUILD
|
||||
|
||||
tooltool_fetch() {
|
||||
cat >manifest.tt
|
||||
python $BUILD/tooltool.py fetch
|
||||
python2.7 /tmp/tooltool.py fetch
|
||||
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
|
||||
tooltool_fetch <<'EOF'
|
||||
tooltool_fetch <<EOF
|
||||
[
|
||||
{
|
||||
"size": 12250696,
|
||||
"digest": "67615a6defbcda062f15a09f9dd3b9441afd01a8cc3255e5bc45b925378a0ddc38d468b7701176f6cc153ec52a4f21671b433780d9bde343aa9b9c1b2ae29feb",
|
||||
"size": 44878,
|
||||
"digest": "7b1fc1217e0dcaeea852b0af2dc559b1aafb704fbee7e29cbec75af57bacb84910a7ec92b5c33f04ee98f23b3a57f1fa451173fe7c8a96f58faefe319dc7dde1",
|
||||
"algorithm": "sha512",
|
||||
"filename": "Python-2.7.10.tar.xz",
|
||||
"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
|
||||
"filename": "mercurial_3.8.4_amd64.deb"
|
||||
},
|
||||
{
|
||||
"size": 1051205,
|
||||
"digest": "e7d2e003ec60fce5a75a6a23711d7f9b155e898faebcf55f3abdd912ef513f4e0cf43daca8f9da7179a7a4efe6e4a625a532d051349818847df1364eb5b326de",
|
||||
"size": 1818422,
|
||||
"digest": "b476e2612e7495a1c7c5adfd84511aa7479e26cc9070289513ec705fbfc4c61806ce2dbcceca0e63f2e80669be416f3467a3cebb522dcb8a6aeb62cdd3df82f2",
|
||||
"algorithm": "sha512",
|
||||
"filename": "pip-6.1.1.tar.gz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 26912,
|
||||
"digest": "9d730ed7852d4d217aaddda959cd5f871ef1b26dd6c513a3780bbb04a5a93a49d6b78e95c2274451a1311c10cc0a72755b269dc9af62640474e6e73a1abec370",
|
||||
"algorithm": "sha512",
|
||||
"filename": "peep-2.4.1.tar.gz",
|
||||
"unpack": false
|
||||
"filename": "mercurial-common_3.8.4_all.deb"
|
||||
}
|
||||
]
|
||||
EOF
|
||||
|
||||
cd $BUILD
|
||||
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
|
||||
dpkg -i mercurial-common_3.8.4_all.deb mercurial_3.8.4_amd64.deb
|
||||
|
||||
cd $BUILD
|
||||
cd pip-6.1.1
|
||||
python setup.py install
|
||||
|
||||
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
|
||||
mkdir -p /usr/local/mercurial
|
||||
chown 755 /usr/local/mercurial
|
||||
cd /usr/local/mercurial
|
||||
tooltool_fetch <<'EOF'
|
||||
[
|
||||
{
|
||||
"size": 5676610,
|
||||
"digest": "ce27b788dfd141a5ba7674332825fc136fe2c4f49a319dd19b3a87c8fffa7a97d86cbb8535661c9a68c9122719aa969fc6a8c886458a0df9fc822eec99ed130b",
|
||||
"size": 11849,
|
||||
"digest": "c88d9b8afd6649bd28bbacfa654ebefec8087a01d1662004aae088d485edeb03a92df1193d1310c0369d7721f475b974fcd4a911428ec65936f7e40cf1609c49",
|
||||
"algorithm": "sha512",
|
||||
"filename": "node-v0.10.36-linux-x64.tar.gz"
|
||||
"filename": "robustcheckout.py"
|
||||
}
|
||||
]
|
||||
|
||||
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 /
|
||||
rm -rf $BUILD
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4,15 +4,19 @@ MAINTAINER Andrew Halberstadt <ahalberstadt@mozilla.com>
|
|||
RUN useradd -d /home/worker -s /bin/bash -m worker
|
||||
WORKDIR /home/worker
|
||||
|
||||
# Install tooltool directly from github.
|
||||
RUN mkdir /build
|
||||
ADD https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py /build/tooltool.py
|
||||
RUN chmod +rx /build/tooltool.py
|
||||
# %include testing/docker/decision/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
|
||||
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
|
||||
# are taken from GNU su manual
|
||||
ENV HOME /home/worker
|
||||
|
|
|
@ -11,7 +11,6 @@ cd /setup
|
|||
|
||||
apt_packages=()
|
||||
apt_packages+=('curl')
|
||||
apt_packages+=('mercurial')
|
||||
apt_packages+=('python')
|
||||
apt_packages+=('python-pip')
|
||||
apt_packages+=('sudo')
|
||||
|
@ -31,6 +30,8 @@ tooltool_fetch() {
|
|||
rm manifest.tt
|
||||
}
|
||||
|
||||
cd /build
|
||||
. install-mercurial.sh
|
||||
|
||||
###
|
||||
# ESLint Setup
|
||||
|
@ -40,6 +41,7 @@ tooltool_fetch() {
|
|||
|
||||
# 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.
|
||||
cd /setup
|
||||
tooltool_fetch <<'EOF'
|
||||
[
|
||||
{
|
||||
|
@ -54,33 +56,24 @@ tar -C /usr/local --strip-components 1 -xJ < node-*.tar.xz
|
|||
node -v # verify
|
||||
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
|
||||
###
|
||||
|
||||
cd /setup
|
||||
cat >requirements.txt <<'EOF'
|
||||
mccabe==0.4.0 --hash=sha256:cbc2938f6c01061bc6d21d0c838c2489664755cb18676f0734d7617f4577d09e
|
||||
pep8==1.7.0 --hash=sha256:4fc2e478addcf17016657dff30b2d8d611e8341fac19ccf2768802f6635d7b8a
|
||||
pyflakes==1.2.3 --hash=sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da
|
||||
flake8==2.5.4 --hash=sha256:fb5a67af4024622287a76abf6b7fe4fb3cfacf765a790976ce64f52c44c88e4a
|
||||
flake8==2.5.4 \
|
||||
--hash=sha256:fb5a67af4024622287a76abf6b7fe4fb3cfacf765a790976ce64f52c44c88e4a
|
||||
mccabe==0.4.0 \
|
||||
--hash=sha256:cbc2938f6c01061bc6d21d0c838c2489664755cb18676f0734d7617f4577d09e
|
||||
pep8==1.7.0 \
|
||||
--hash=sha256:4fc2e478addcf17016657dff30b2d8d611e8341fac19ccf2768802f6635d7b8a
|
||||
pyflakes==1.2.3 \
|
||||
--hash=sha256:e87bac26c62ea5b45067cc89e4a12f56e1483f1f2cda17e7c9b375b9fd2f40da
|
||||
EOF
|
||||
|
||||
pip install --require-hashes -r requirements.txt
|
||||
|
||||
cd /
|
||||
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'])
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.process_args()
|
||||
tests = self.args.pop('tests')
|
||||
runner = self._runner_class(**self.args)
|
||||
runner.run_tests(tests)
|
||||
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,
|
||||
|
@ -88,11 +81,13 @@ def cli(runner_class=MarionetteTestRunner, parser_class=MarionetteArguments,
|
|||
"""
|
||||
logger = mozlog.commandline.setup_logging('Marionette test runner', {})
|
||||
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:
|
||||
sys.exit(10)
|
||||
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(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_webAudio.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]
|
||||
skip-if = true # Bug 1200411
|
||||
[../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,
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче