Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2016-07-26 11:57:38 +02:00
Родитель d3cb1d23af 574d0d452b
Коммит aa2bc77d7f
131 изменённых файлов: 2711 добавлений и 1385 удалений

Просмотреть файл

@ -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

1
config/external/nss/Makefile.in поставляемый
Просмотреть файл

@ -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

30
testing/docker/decision/bin/checkout-gecko Normal file → Executable file
Просмотреть файл

@ -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,
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше