MozReview-Commit-ID: BHxDQF6gIe3
This commit is contained in:
Wes Kocher 2016-03-08 16:00:45 -08:00
Родитель be3094d2b6 42c25b995a
Коммит 0fbf6c1476
593 изменённых файлов: 9925 добавлений и 20212 удалений

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

@ -44,7 +44,6 @@ testing/**
tools/**
uriloader/**
view/**
webapprt/**
widget/**
xpcom/**
xpfe/**

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

@ -9,7 +9,7 @@
# you are either running lldb from the top level source directory, the objdir,
# or the dist/bin directory. (.lldbinit files in the objdir and dist/bin set
# topsrcdir appropriately.)
script topsrcdir = topsrcdir if locals().has_key("topsrcdir") else "."; sys.path.append(os.path.join(topsrcdir, "python/lldbutils")); import lldbutils; lldbutils.init()
script topsrcdir = topsrcdir if locals().has_key("topsrcdir") else os.getcwd(); sys.path.append(os.path.join(topsrcdir, "python/lldbutils")); import lldbutils; lldbutils.init()
# Mozilla's use of UNIFIED_SOURCES to include multiple source files into a
# single compiled file breaks lldb breakpoint setting. This works around that.

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

@ -22,5 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Merge day clobber
Bug 1250297 - Doesn't actually need a clobber, but updating the tree to an older changeset does.

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

@ -24,7 +24,8 @@ TreeWalker::
TreeWalker(Accessible* aContext) :
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(nullptr),
mARIAOwnsIdx(0),
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(0)
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(0),
mPhase(eAtStart)
{
mChildFilter |= mContext->NoXBLKids() ?
nsIContent::eAllButXBL : nsIContent::eAllChildren;
@ -32,10 +33,6 @@ TreeWalker::
mAnchorNode = mContext->IsDoc() ?
mDoc->DocumentNode()->GetRootElement() : mContext->GetContent();
if (mAnchorNode) {
PushState(mAnchorNode);
}
MOZ_COUNT_CTOR(TreeWalker);
}
@ -43,7 +40,8 @@ TreeWalker::
TreeWalker(Accessible* aContext, nsIContent* aAnchorNode, uint32_t aFlags) :
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(aAnchorNode),
mARIAOwnsIdx(0),
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(aFlags)
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(aFlags),
mPhase(eAtStart)
{
MOZ_ASSERT(aAnchorNode, "No anchor node for the accessible tree walker");
MOZ_ASSERT(mDoc->GetAccessibleOrContainer(aAnchorNode) == mContext,
@ -52,8 +50,6 @@ TreeWalker::
mChildFilter |= mContext->NoXBLKids() ?
nsIContent::eAllButXBL : nsIContent::eAllChildren;
PushState(aAnchorNode);
MOZ_COUNT_CTOR(TreeWalker);
}
@ -62,14 +58,84 @@ TreeWalker::~TreeWalker()
MOZ_COUNT_DTOR(TreeWalker);
}
////////////////////////////////////////////////////////////////////////////////
// TreeWalker: private
bool
TreeWalker::Seek(nsIContent* aChildNode)
{
MOZ_ASSERT(aChildNode, "Child cannot be null");
mPhase = eAtStart;
mStateStack.Clear();
mARIAOwnsIdx = 0;
nsIContent* childNode = nullptr;
nsINode* parentNode = aChildNode;
do {
childNode = parentNode->AsContent();
parentNode = childNode->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) &&
(mChildFilter & nsIContent::eAllButXBL) ?
childNode->GetParentNode() : childNode->GetFlattenedTreeParent();
if (!parentNode || !parentNode->IsElement()) {
return false;
}
// If ARIA owned child.
Accessible* child = mDoc->GetAccessible(childNode);
if (child && child->IsRelocated()) {
if (child->Parent() != mContext) {
return false;
}
Accessible* ownedChild = nullptr;
while ((ownedChild = mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx++)) &&
ownedChild != child);
MOZ_ASSERT(ownedChild, "A child has to be in ARIA owned elements");
mPhase = eAtARIAOwns;
return true;
}
// Look in DOM.
dom::AllChildrenIterator* iter = PrependState(parentNode->AsElement(), true);
if (!iter->Seek(childNode)) {
return false;
}
if (parentNode == mAnchorNode) {
mPhase = eAtDOM;
return true;
}
} while (true);
return false;
}
Accessible*
TreeWalker::Next()
{
if (mStateStack.IsEmpty()) {
return mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx++);
if (mPhase == eAtEnd) {
return nullptr;
}
if (mPhase == eAtDOM || mPhase == eAtARIAOwns) {
mPhase = eAtARIAOwns;
Accessible* child = mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx);
if (child) {
mARIAOwnsIdx++;
return child;
}
mPhase = eAtEnd;
return nullptr;
}
if (!mAnchorNode) {
mPhase = eAtEnd;
return nullptr;
}
mPhase = eAtDOM;
PushState(mAnchorNode, true);
}
dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
@ -96,7 +162,7 @@ TreeWalker::Next()
// Walk down into subtree to find accessibles.
if (!skipSubtree && childNode->IsElement()) {
top = PushState(childNode);
top = PushState(childNode, true);
}
}
top = PopState();
@ -114,7 +180,7 @@ TreeWalker::Next()
return nullptr;
nsIContent* parent = parentNode->AsElement();
top = PushState(parent);
top = PushState(parent, true);
if (top->Seek(mAnchorNode)) {
mAnchorNode = parent;
return Next();
@ -130,6 +196,88 @@ TreeWalker::Next()
return Next();
}
Accessible*
TreeWalker::Prev()
{
if (mStateStack.IsEmpty()) {
if (mPhase == eAtStart || mPhase == eAtDOM) {
mPhase = eAtStart;
return nullptr;
}
if (mPhase == eAtEnd) {
mARIAOwnsIdx = mDoc->ARIAOwnedCount(mContext);
mPhase = eAtARIAOwns;
}
if (mPhase == eAtARIAOwns) {
if (mARIAOwnsIdx > 0) {
return mDoc->ARIAOwnedAt(mContext, --mARIAOwnsIdx);
}
if (!mAnchorNode) {
mPhase = eAtStart;
return nullptr;
}
mPhase = eAtDOM;
PushState(mAnchorNode, false);
}
}
dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
while (top) {
while (nsIContent* childNode = top->GetPreviousChild()) {
bool skipSubtree = false;
// No accessible creation on the way back.
Accessible* child = mDoc->GetAccessible(childNode);
// Ignore the accessible and its subtree if it was repositioned by means of
// aria-owns.
if (child) {
if (child->IsRelocated()) {
continue;
}
return child;
}
// Walk down into subtree to find accessibles.
if (!skipSubtree && childNode->IsElement()) {
top = PushState(childNode, true);
}
}
top = PopState();
}
// Move to a previous node relative the anchor node within the context
// subtree if asked.
if (mFlags != eWalkContextTree) {
mPhase = eAtStart;
return nullptr;
}
nsINode* contextNode = mContext->GetNode();
while (mAnchorNode != contextNode) {
nsINode* parentNode = mAnchorNode->GetFlattenedTreeParent();
if (!parentNode || !parentNode->IsElement()) {
return nullptr;
}
nsIContent* parent = parentNode->AsElement();
top = PushState(parent, true);
if (top->Seek(mAnchorNode)) {
mAnchorNode = parent;
return Prev();
}
mAnchorNode = parent;
}
mPhase = eAtStart;
return nullptr;
}
dom::AllChildrenIterator*
TreeWalker::PopState()
{

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

@ -50,13 +50,23 @@ public:
~TreeWalker();
/**
* Return the next accessible.
* Clears the tree walker state and resets it to the given child within
* the anchor.
*/
bool Seek(nsIContent* aChildNode);
/**
* Return the next/prev accessible.
*
* @note Returned accessible is bound to the document, if the accessible is
* rejected during tree creation then the caller should be unbind it
* from the document.
*/
Accessible* Next();
Accessible* Prev();
Accessible* Context() const { return mContext; }
DocAccessible* Document() const { return mDoc; }
private:
TreeWalker();
@ -64,15 +74,23 @@ private:
TreeWalker& operator =(const TreeWalker&);
/**
* Create new state for the given node and push it on top of stack.
* Create new state for the given node and push it on top of stack / at bottom
* of stack.
*
* @note State stack is used to navigate up/down the DOM subtree during
* accessible children search.
*/
dom::AllChildrenIterator* PushState(nsIContent* aContent)
dom::AllChildrenIterator* PushState(nsIContent* aContent,
bool aStartAtBeginning)
{
return mStateStack.AppendElement(
dom::AllChildrenIterator(aContent, mChildFilter));
dom::AllChildrenIterator(aContent, mChildFilter, aStartAtBeginning));
}
dom::AllChildrenIterator* PrependState(nsIContent* aContent,
bool aStartAtBeginning)
{
return mStateStack.InsertElementAt(0,
dom::AllChildrenIterator(aContent, mChildFilter, aStartAtBeginning));
}
/**
@ -89,6 +107,14 @@ private:
int32_t mChildFilter;
uint32_t mFlags;
enum Phase {
eAtStart,
eAtDOM,
eAtARIAOwns,
eAtEnd
};
Phase mPhase;
};
} // namespace a11y

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

@ -291,6 +291,11 @@ public:
}
return nullptr;
}
uint32_t ARIAOwnedCount(Accessible* aParent) const
{
nsTArray<RefPtr<Accessible> >* children = mARIAOwnsHash.Get(aParent);
return children ? children->Length() : 0;
}
/**
* Return true if the given ID is referred by relation attribute.

1
aclocal.m4 поставляемый
Просмотреть файл

@ -26,7 +26,6 @@ builtin(include, build/autoconf/arch.m4)dnl
builtin(include, build/autoconf/android.m4)dnl
builtin(include, build/autoconf/zlib.m4)dnl
builtin(include, build/autoconf/linux.m4)dnl
builtin(include, build/autoconf/python-virtualenv.m4)dnl
builtin(include, build/autoconf/winsdk.m4)dnl
builtin(include, build/autoconf/icu.m4)dnl
builtin(include, build/autoconf/ffi.m4)dnl

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

@ -10,9 +10,6 @@ if CONFIG['MOZ_EXTENSIONS']:
DIRS += ['/%s' % CONFIG['MOZ_BRANDING_DIRECTORY']]
if CONFIG['MOZ_WEBAPP_RUNTIME']:
DIRS += ['/webapprt']
DIRS += [
'/b2g/chrome',
'/b2g/components',

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

@ -16,8 +16,8 @@
"unpack": true
},
{
"size": 80164520,
"digest": "26fd5301aaf6174a0e4f2ac3a8d19f39573f78a051aa78e876c065d60421b2b62207c11fbf1f20f92ba61acc4b9ce58d05409bf5af886943891b04c3d22f5e04",
"size": 89319524,
"digest": "5383d843c9f28abf0a6d254e9d975d96972d2c86d627ca836fa8e272a5d53230603b387d7d1499c49df7f84b1bb946946e800a85c88d968bdbe81c755fcb02e1",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -10,9 +10,6 @@ if CONFIG['MOZ_EXTENSIONS']:
DIRS += ['/%s' % CONFIG['MOZ_BRANDING_DIRECTORY']]
if CONFIG['MOZ_WEBAPP_RUNTIME']:
DIRS += ['/webapprt']
# Never add dirs after browser because they apparently won't get
# packaged properly on Mac.
DIRS += ['/browser']

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

@ -678,8 +678,6 @@
aria-label="&urlbar.loginFillNotificationAnchor.label;"/>
<image id="password-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.passwordNotificationAnchor.label;"/>
<image id="webapps-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.webappsNotificationAnchor.label;"/>
<image id="plugins-notification-icon" class="notification-anchor-icon" role="button"
aria-label="&urlbar.pluginsNotificationAnchor.label;"/>
<image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"

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

@ -39,10 +39,6 @@
</popupnotificationcontent>
</popupnotification>
<popupnotification id="webapps-install-progress-notification" hidden="true">
<popupnotificationcontent id="webapps-install-progress-content" orient="vertical" align="start"/>
</popupnotification>
<popupnotification id="servicesInstall-notification" hidden="true">
<popupnotificationcontent orient="vertical" align="start">
<!-- XXX bug 974146, tests are looking for this, can't remove yet. -->

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

@ -278,16 +278,39 @@ Sanitizer.prototype = {
}
// Clear plugin data.
// As evidenced in bug 1253204, clearing plugin data can sometimes be
// very, very long, for mysterious reasons. Unfortunately, this is not
// something actionable by Mozilla, so crashing here serves no purpose.
//
// For this reason, instead of waiting for sanitization to always
// complete, we introduce a soft timeout. Once this timeout has
// elapsed, we proceed with the shutdown of Firefox.
let promiseClearPluginCookies;
TelemetryStopwatch.start("FX_SANITIZE_PLUGINS", refObj);
try {
yield this.promiseClearPluginCookies(range);
// We don't want to wait for this operation to complete...
promiseClearPluginCookies = this.promiseClearPluginCookies(range);
//... at least, not for more than 10 seconds.
yield Promise.race([
promiseClearPluginCookies,
new Promise(resolve => setTimeout(resolve, 10000 /* 10 seconds */))
]);
} catch (ex) {
seenException = ex;
} finally {
TelemetryStopwatch.finish("FX_SANITIZE_PLUGINS", refObj);
}
TelemetryStopwatch.finish("FX_SANITIZE_COOKIES", refObj);
// Detach waiting for plugin cookies to be cleared.
promiseClearPluginCookies.catch(() => {
// If this exception is raised before the soft timeout, it
// will appear in `seenException`. Otherwise, it's too late
// to do anything about it.
}).then(() => {
// Finally, update statistics.
TelemetryStopwatch.finish("FX_SANITIZE_PLUGINS", refObj);
TelemetryStopwatch.finish("FX_SANITIZE_COOKIES", refObj);
});
if (seenException) {
throw seenException;
}

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

@ -1,6 +1,8 @@
[DEFAULT]
skip-if = buildapp == "mulet"
support-files =
empty_file.html
file_reflect_cookie_into_title.html
[browser_usercontext.js]
[browser_windowName.js]

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

@ -0,0 +1,79 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
const USER_CONTEXTS = [
"default",
"personal",
"work",
];
const BASE_URI = "http://mochi.test:8888/browser/browser/components/"
+ "contextualidentity/test/browser/empty_file.html";
add_task(function* setup() {
// make sure userContext is enabled.
SpecialPowers.pushPrefEnv({"set": [
["privacy.userContext.enabled", true],
["browser.link.open_newwindow", 3],
]});
});
add_task(function* cleanup() {
// make sure we don't leave any prefs set for the next tests
registerCleanupFunction(function() {
SpecialPowers.popPrefEnv();
});
});
add_task(function* test() {
info("Creating first tab...");
let tab1 = gBrowser.addTab(BASE_URI + '?old', {userContextId: 1});
let browser1 = gBrowser.getBrowserForTab(tab1);
yield BrowserTestUtils.browserLoaded(browser1);
yield ContentTask.spawn(browser1, null, function(opts) {
content.window.name = 'tab-1';
});
info("Creating second tab...");
let tab2 = gBrowser.addTab(BASE_URI + '?old', {userContextId: 2});
let browser2 = gBrowser.getBrowserForTab(tab2);
yield BrowserTestUtils.browserLoaded(browser2);
yield ContentTask.spawn(browser2, null, function(opts) {
content.window.name = 'tab-2';
});
// Let's try to open a window from tab1 with a name 'tab-2'.
info("Opening a window from the first tab...");
yield ContentTask.spawn(browser1, { url: BASE_URI + '?new' }, function(opts) {
yield (new content.window.wrappedJSObject.Promise(resolve => {
let w = content.window.wrappedJSObject.open(opts.url, 'tab-2');
w.onload = function() { resolve(); }
}));
});
is(browser1.contentDocument.title, '?old', "Tab1 title must be 'old'");
is(browser1.contentDocument.nodePrincipal.userContextId, 1, "Tab1 UCI must be 1");
is(browser2.contentDocument.title, '?old', "Tab2 title must be 'old'");
is(browser2.contentDocument.nodePrincipal.userContextId, 2, "Tab2 UCI must be 2");
let found = false;
for (let i = 0; i < gBrowser.tabContainer.childNodes.length; ++i) {
let tab = gBrowser.tabContainer.childNodes[i];
let browser = gBrowser.getBrowserForTab(tab);
if (browser.contentDocument.title == '?new') {
is(browser.contentDocument.nodePrincipal.userContextId, 1, "Tab3 UCI must be 1");
isnot(browser, browser1, "Tab3 is not browser 1");
isnot(browser, browser2, "Tab3 is not browser 2");
gBrowser.removeTab(tab);
found = true;
break;
}
}
ok(found, "We have tab3");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
});

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

@ -0,0 +1,5 @@
<html><body>
<script>
document.title = window.location.search;
</script>
</body></html>

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

@ -52,9 +52,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
XPCOMUtils.defineLazyModuleGetter(this, "BookmarkJSONUtils",
"resource://gre/modules/BookmarkJSONUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebappManager",
"resource:///modules/WebappManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
"resource://gre/modules/PageThumbs.jsm");
@ -742,7 +739,6 @@ BrowserGlue.prototype = {
// handle any UI migration
this._migrateUI();
WebappManager.init();
PageThumbs.init();
webrtcUI.init();
AboutHome.init();
@ -1057,9 +1053,6 @@ BrowserGlue.prototype = {
}
SelfSupportBackend.uninit();
WebappManager.uninit();
NewTabPrefsProvider.prefs.uninit();
AboutNewTab.uninit();
webrtcUI.uninit();

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

@ -0,0 +1,22 @@
MOZ_AUTOMATION_BUILD_SYMBOLS=0
MOZ_AUTOMATION_PACKAGE_TESTS=0
MOZ_AUTOMATION_L10N_CHECK=0
. "$topsrcdir/build/mozconfig.win-common"
. "$topsrcdir/browser/config/mozconfigs/common"
ac_add_options --enable-debug
ac_add_options --enable-dmd
ac_add_options --enable-clang-plugin
. $topsrcdir/build/win32/mozconfig.vs2013-win64
# Treat warnings as errors (modulo ALLOW_COMPILER_WARNINGS).
ac_add_options --enable-warnings-as-errors
. "$topsrcdir/build/mozconfig.rust"
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"
. "$topsrcdir/build/mozconfig.clang-cl"

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

@ -15,8 +15,8 @@
"unpack": true
},
{
"size": 80164520,
"digest": "26fd5301aaf6174a0e4f2ac3a8d19f39573f78a051aa78e876c065d60421b2b62207c11fbf1f20f92ba61acc4b9ce58d05409bf5af886943891b04c3d22f5e04",
"size": 89319524,
"digest": "5383d843c9f28abf0a6d254e9d975d96972d2c86d627ca836fa8e272a5d53230603b387d7d1499c49df7f84b1bb946946e800a85c88d968bdbe81c755fcb02e1",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -6,10 +6,10 @@
"filename": "mozmake.exe"
},
{
"size": 80513610,
"digest": "a388df6ce743be521ba688132d06ba86d225673b53f71f9c7c0d3189adf16f553088d8d359f583f958e886583de9583df53873c85c34abf33b2d55ee7d807206",
"size": 78886322,
"digest": "9c2c40637de27a0852aa1166f2a08159908b23f7a55855c933087c541461bbb2a1ec9e0522df0d2b9da2b2c343b673dbb5a2fa8d30216fe8acee1eb1383336ea",
"algorithm": "sha512",
"filename": "rustc-nightly-i686-pc-windows-msvc.tar.bz2",
"filename": "rustc-beta-i686-pc-windows-msvc.tar.bz2",
"unpack": true
},
{

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

@ -6,8 +6,8 @@
"filename": "mozmake.exe"
},
{
"size": 72442063,
"digest": "899da5af9b322ba63ec04de06f92b5bb82a2700f9fe03001e75fdc6f678a435cd66a474190fd93863327456270aef5649d3788aa50d852121059ced99a6004db",
"size": 80157273,
"digest": "c4704dcc6774b9f3baaa9313192d26e36bfba2d4380d0518ee7cb89153d9adfe63f228f0ac29848f02948eb1ab7e6624ba71210f0121196d2b54ecebd640d1e6",
"algorithm": "sha512",
"visibility": "public",
"filename": "rustc.tar.bz2",

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

@ -53,7 +53,6 @@ ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-central
MAR_CHANNEL_ID=firefox-mozilla-central
MOZ_PROFILE_MIGRATOR=1
MOZ_APP_STATIC_INI=1
MOZ_WEBAPP_RUNTIME=1
MOZ_MEDIA_NAVIGATOR=1
MOZ_WEBGL_CONFORMANT=1
# Enable navigator.mozPay

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

@ -836,31 +836,6 @@ bin/libfreebl_32int64_3.so
#endif
#endif
#ifdef MOZ_WEBAPP_RUNTIME
[WebappRuntime]
#ifdef XP_WIN
@BINPATH@/webapp-uninstaller@BIN_SUFFIX@
#endif
@RESPATH@/webapprt-stub@BIN_SUFFIX@
@RESPATH@/webapprt/webapprt.ini
@RESPATH@/webapprt/chrome.manifest
@RESPATH@/webapprt/chrome/webapprt@JAREXT@
@RESPATH@/webapprt/chrome/webapprt.manifest
@RESPATH@/webapprt/chrome/@AB_CD@@JAREXT@
@RESPATH@/webapprt/chrome/@AB_CD@.manifest
@RESPATH@/webapprt/components/CommandLineHandler.js
@RESPATH@/webapprt/components/ContentPermission.js
@RESPATH@/webapprt/components/DirectoryProvider.js
@RESPATH@/webapprt/components/PaymentUIGlue.js
@RESPATH@/webapprt/components/components.manifest
@RESPATH@/webapprt/defaults/preferences/prefs.js
@RESPATH@/webapprt/modules/DownloadView.jsm
@RESPATH@/webapprt/modules/Startup.jsm
@RESPATH@/webapprt/modules/WebappRT.jsm
@RESPATH@/webapprt/modules/WebappManager.jsm
@RESPATH@/webapprt/modules/WebRTCHandler.jsm
#endif
@RESPATH@/components/DataStore.manifest
@RESPATH@/components/DataStoreImpl.js
@RESPATH@/components/dom_datastore.xpt

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

@ -100,9 +100,6 @@ libs-%:
$(NSINSTALL) -D $(DIST)/install
@$(MAKE) -C ../../toolkit/locales libs-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)'
@$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$*
ifdef MOZ_WEBAPP_RUNTIME
@$(MAKE) -C ../../webapprt/locales AB_CD=$* XPI_NAME=locale-$*
endif
@$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) -C ../extensions/pocket/locales AB_CD=$* XPI_NAME=locale-$*
@$(MAKE) -C ../extensions/loop/chrome/locale AB_CD=$* XPI_NAME=locale-$*
@ -138,14 +135,11 @@ endif
clobber-zip:
$(RM) $(STAGEDIST)/chrome/$(AB_CD).jar \
$(STAGEDIST)/chrome/$(AB_CD).manifest \
$(STAGEDIST)/webapprt/chrome/$(AB_CD).jar \
$(STAGEDIST)/webapprt/chrome/$(AB_CD).manifest \
$(STAGEDIST)/$(PREF_DIR)/firefox-l10n.js
$(RM) -rf $(STAGEDIST)/dictionaries \
$(STAGEDIST)/hyphenation \
$(STAGEDIST)/defaults/profile \
$(STAGEDIST)/chrome/$(AB_CD) \
$(STAGEDIST)/webapprt/chrome/$(AB_CD)
$(STAGEDIST)/chrome/$(AB_CD)
langpack: langpack-$(AB_CD)

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

@ -197,7 +197,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY urlbar.indexedDBNotificationAnchor.label "View the app-offline storage message">
<!ENTITY urlbar.loginFillNotificationAnchor.label "Manage your login information">
<!ENTITY urlbar.passwordNotificationAnchor.label "Check if you want to save your password">
<!ENTITY urlbar.webappsNotificationAnchor.label "View the app install message">
<!ENTITY urlbar.pluginsNotificationAnchor.label "Manage plugin usage on this page">
<!ENTITY urlbar.webNotsNotificationAnchor3.label "Change whether you can receive notifications from the site">

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

@ -473,20 +473,6 @@ processHang.button_wait.accessKey = W
processHang.button_debug.label = Debug Script
processHang.button_debug.accessKey = D
# Webapps notification popup
webapps.install = Install
webapps.install.accesskey = I
#LOCALIZATION NOTE (webapps.requestInstall2) %S is the web app name
webapps.requestInstall2 = Do you want to install “%S” from this site?
webapps.install.success = Application Installed
webapps.install.inprogress = Installation in progress
webapps.uninstall = Uninstall
webapps.uninstall.accesskey = U
webapps.doNotUninstall = Don't Uninstall
webapps.doNotUninstall.accesskey = D
#LOCALIZATION NOTE (webapps.requestUninstall) %1$S is the web app name
webapps.requestUninstall = Do you want to uninstall “%1$S”?
# LOCALIZATION NOTE (fullscreenButton.tooltip): %S is the keyboard shortcut for full screen
fullscreenButton.tooltip=Display the window in full screen (%S)

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

@ -7,7 +7,7 @@ def test(mod, path, entity = None):
# ignore anything but Firefox
if mod not in ("netwerk", "dom", "toolkit", "security/manager",
"devtools/client", "devtools/shared",
"browser", "webapprt",
"browser",
"extensions/reporter", "extensions/spellcheck",
"other-licenses/branding/firefox",
"browser/branding/official",

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

@ -19,7 +19,6 @@ dirs = browser
# RFE: that needs to be supported by compare-locales, too, though
toolkit = toolkit/locales/l10n.ini
services_sync = services/sync/locales/l10n.ini
webapprt = webapprt/locales/l10n.ini
[extras]
dirs = extensions/spellcheck

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

@ -1,335 +0,0 @@
/* 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.EXPORTED_SYMBOLS = ["WebappManager"];
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Webapps.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NativeApp",
"resource://gre/modules/NativeApp.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils",
"resource://gre/modules/WebappOSUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
this.WebappManager = {
// List of promises for in-progress installations
installations: {},
init: function() {
Services.obs.addObserver(this, "webapps-ask-install", false);
Services.obs.addObserver(this, "webapps-ask-uninstall", false);
Services.obs.addObserver(this, "webapps-launch", false);
Services.obs.addObserver(this, "webapps-uninstall", false);
cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
{ messages: ["Webapps:Install:Return:OK",
"Webapps:Install:Return:KO",
"Webapps:UpdateState"]});
cpmm.addMessageListener("Webapps:Install:Return:OK", this);
cpmm.addMessageListener("Webapps:Install:Return:KO", this);
cpmm.addMessageListener("Webapps:UpdateState", this);
},
uninit: function() {
Services.obs.removeObserver(this, "webapps-ask-install");
Services.obs.removeObserver(this, "webapps-ask-uninstall");
Services.obs.removeObserver(this, "webapps-launch");
Services.obs.removeObserver(this, "webapps-uninstall");
cpmm.sendAsyncMessage("Webapps:UnregisterForMessages",
["Webapps:Install:Return:OK",
"Webapps:Install:Return:KO",
"Webapps:UpdateState"]);
cpmm.removeMessageListener("Webapps:Install:Return:OK", this);
cpmm.removeMessageListener("Webapps:Install:Return:KO", this);
cpmm.removeMessageListener("Webapps:UpdateState", this);
},
receiveMessage: function(aMessage) {
let data = aMessage.data;
let manifestURL = data.manifestURL ||
(data.app && data.app.manifestURL) ||
data.manifest;
if (!this.installations[manifestURL]) {
return;
}
if (aMessage.name == "Webapps:UpdateState") {
if (data.error) {
this.installations[manifestURL].reject(data.error);
} else if (data.app.installState == "installed") {
this.installations[manifestURL].resolve();
}
} else if (aMessage.name == "Webapps:Install:Return:OK" &&
!data.isPackage) {
let manifest = new ManifestHelper(data.app.manifest,
data.app.origin,
data.app.manifestURL);
if (!manifest.appcache_path) {
this.installations[manifestURL].resolve();
}
} else if (aMessage.name == "Webapps:Install:Return:KO") {
this.installations[manifestURL].reject(data.error);
}
},
observe: function(aSubject, aTopic, aData) {
let data = JSON.parse(aData);
data.mm = aSubject;
let browser;
switch(aTopic) {
case "webapps-ask-install":
browser = this._getBrowserForId(data.topId);
if (browser) {
this.doInstall(data, browser);
}
break;
case "webapps-ask-uninstall":
browser = this._getBrowserForId(data.topId);
if (browser) {
this.doUninstall(data, browser);
}
break;
case "webapps-launch":
WebappOSUtils.launch(data);
break;
case "webapps-uninstall":
WebappOSUtils.uninstall(data);
break;
}
},
_getBrowserForId: function(aId) {
let windows = Services.wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
let window = windows.getNext();
let tabbrowser = window.gBrowser;
let foundBrowser = tabbrowser.getBrowserForOuterWindowID(aId);
if (foundBrowser) {
return foundBrowser;
}
}
let foundWindow = Services.wm.getOuterWindowWithId(aId);
if (foundWindow) {
return foundWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell)
.chromeEventHandler;
}
return null;
},
doInstall: function(aData, aBrowser) {
let chromeDoc = aBrowser.ownerDocument;
let chromeWin = chromeDoc.defaultView;
let popupProgressContent =
chromeDoc.getElementById("webapps-install-progress-content");
let bundle = chromeWin.gNavigatorBundle;
let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
let notification;
let mainAction = {
label: bundle.getString("webapps.install"),
accessKey: bundle.getString("webapps.install.accesskey"),
callback: () => {
notification.remove();
notification = chromeWin.PopupNotifications.
show(aBrowser,
"webapps-install-progress",
bundle.getString("webapps.install.inprogress"),
"webapps-notification-icon");
let progressMeter = chromeDoc.createElement("progressmeter");
progressMeter.setAttribute("mode", "undetermined");
popupProgressContent.appendChild(progressMeter);
let manifestURL = aData.app.manifestURL;
let nativeApp = new NativeApp(aData.app, jsonManifest,
aData.app.categories);
this.installations[manifestURL] = Promise.defer();
this.installations[manifestURL].promise.then(() => {
notifyInstallSuccess(aData.app, nativeApp, bundle,
PrivateBrowsingUtils.isBrowserPrivate(aBrowser));
}, (error) => {
Cu.reportError("Error installing webapp: " + error);
}).then(() => {
popupProgressContent.removeChild(progressMeter);
delete this.installations[manifestURL];
if (Object.getOwnPropertyNames(this.installations).length == 0) {
notification.remove();
}
});
let localDir;
try {
localDir = nativeApp.createProfile();
} catch (ex) {
DOMApplicationRegistry.denyInstall(aData);
return;
}
DOMApplicationRegistry.confirmInstall(aData, localDir,
Task.async(function*(aApp, aManifest, aZipPath) {
try {
yield nativeApp.install(aApp, aManifest, aZipPath);
} catch (ex) {
Cu.reportError("Error installing webapp: " + ex);
throw ex;
}
})
);
}
};
let requestingURI = chromeWin.makeURI(aData.from);
let app = aData.app;
let manifest = new ManifestHelper(jsonManifest, app.origin, app.manifestURL);
let options = {
displayURI: requestingURI,
};
let message = bundle.getFormattedString("webapps.requestInstall2",
[manifest.name]);
let gBrowser = chromeWin.gBrowser;
if (gBrowser) {
let windowID = aData.oid;
let listener = {
onLocationChange(webProgress) {
if (webProgress.DOMWindowID == windowID) {
notification.remove();
}
}
};
gBrowser.addProgressListener(listener);
options.eventCallback = event => {
if (event != "removed") {
return;
}
// The notification was removed, so we should
// remove our listener.
gBrowser.removeProgressListener(listener);
};
}
notification = chromeWin.PopupNotifications.show(aBrowser,
"webapps-install",
message,
"webapps-notification-icon",
mainAction, [],
options);
},
doUninstall: function(aData, aBrowser) {
let chromeDoc = aBrowser.ownerDocument;
let chromeWin = chromeDoc.defaultView;
let bundle = chromeWin.gNavigatorBundle;
let jsonManifest = aData.app.manifest;
let notification;
let mainAction = {
label: bundle.getString("webapps.uninstall"),
accessKey: bundle.getString("webapps.uninstall.accesskey"),
callback: () => {
notification.remove();
DOMApplicationRegistry.confirmUninstall(aData);
}
};
let secondaryAction = {
label: bundle.getString("webapps.doNotUninstall"),
accessKey: bundle.getString("webapps.doNotUninstall.accesskey"),
callback: () => {
notification.remove();
DOMApplicationRegistry.denyUninstall(aData, "USER_DECLINED");
}
};
let manifest = new ManifestHelper(jsonManifest, aData.app.origin,
aData.app.manifestURL);
let message = bundle.getFormattedString("webapps.requestUninstall",
[manifest.name]);
let options = {};
let gBrowser = chromeWin.gBrowser;
if (gBrowser) {
let windowID = aData.oid;
let listener = {
onLocationChange(webProgress) {
if (webProgress.DOMWindowID == windowID) {
notification.remove();
}
}
};
gBrowser.addProgressListener(listener);
options.eventCallback = event => {
if (event != "removed") {
return;
}
// The notification was removed, so we should
// remove our listener.
gBrowser.removeProgressListener(listener);
};
}
notification = chromeWin.PopupNotifications.show(
aBrowser, "webapps-uninstall", message,
"webapps-notification-icon",
mainAction, [secondaryAction],
options);
}
}
function notifyInstallSuccess(aApp, aNativeApp, aBundle, aInPrivateBrowsing) {
let launcher = {
observe: function(aSubject, aTopic) {
if (aTopic == "alertclickcallback") {
WebappOSUtils.launch(aApp);
}
}
};
try {
let notifier = Cc["@mozilla.org/alerts-service;1"].
getService(Ci.nsIAlertsService);
notifier.showAlertNotification(aNativeApp.iconURI.spec,
aBundle.getString("webapps.install.success"),
aNativeApp.appNameAsFilename,
true, null, launcher, "", "", "", "", null,
aInPrivateBrowsing);
} catch (ex) {}
}

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

@ -44,7 +44,6 @@ EXTRA_JS_MODULES += [
'TabGroupsMigrator.jsm',
'TransientPrefs.jsm',
'UserContextUI.jsm',
'WebappManager.jsm',
'webrtcUI.jsm',
]

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

@ -62,11 +62,6 @@
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install-progress"],
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://global/skin/icons/webapps-64.png);
}
.popup-notification-icon[popupid="webRTC-sharingDevices"],
.popup-notification-icon[popupid="webRTC-shareDevices"] {
list-style-image: url(chrome://browser/skin/webRTC-shareDevice-64.png);
@ -159,11 +154,6 @@
transform: scaleX(-1);
}
.webapps-notification-icon,
#webapps-notification-icon {
list-style-image: url(chrome://global/skin/icons/webapps-16.png);
}
#plugins-notification-icon {
list-style-image: url(chrome://browser/skin/notification-pluginNormal.png);
}

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

@ -20,6 +20,15 @@ dnl MOZ_ARG_WITH_STRING( NAME, HELP, IF-SET [, ELSE])
dnl MOZ_ARG_HEADER(Comment)
dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
define([MOZ_DIVERSION_ARGS], 12)
AC_DEFUN([MOZ_ARG],[dnl
AC_DIVERT_PUSH(MOZ_DIVERSION_ARGS)dnl
'$1',
AC_DIVERT_POP()dnl
])
AC_DEFUN([MOZ_AC_ARG_ENABLE],[MOZ_ARG([--enable-]translit([$1],[_],[-]))AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
AC_DEFUN([MOZ_AC_ARG_WITH],[MOZ_ARG([--with-]translit([$1],[_],[-]))AC_ARG_WITH([$1], [$2], [$3], [$4])])
dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE])
AC_DEFUN([MOZ_TWO_STRING_TEST],
@ -35,19 +44,19 @@ AC_DEFUN([MOZ_TWO_STRING_TEST],
dnl MOZ_ARG_ENABLE_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]])
AC_DEFUN([MOZ_ARG_ENABLE_BOOL],
[AC_ARG_ENABLE([$1], [$2],
[MOZ_AC_ARG_ENABLE([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4])],
[$5])])
dnl MOZ_ARG_DISABLE_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]])
AC_DEFUN([MOZ_ARG_DISABLE_BOOL],
[AC_ARG_ENABLE([$1], [$2],
[MOZ_AC_ARG_ENABLE([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$enableval], no, [$3], yes, [$4])],
[$5])])
dnl MOZ_ARG_ENABLE_STRING(NAME, HELP, IF-SET [, ELSE])
AC_DEFUN([MOZ_ARG_ENABLE_STRING],
[AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
[MOZ_AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
dnl MOZ_ARG_ENABLE_BOOL_OR_STRING(NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING],
@ -55,25 +64,25 @@ AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING],
[errprint([Option, $1, needs an "IF-SET" argument.
])
m4exit(1)],
[AC_ARG_ENABLE([$1], [$2],
[MOZ_AC_ARG_ENABLE([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4], [$5])],
[$6])])])
dnl MOZ_ARG_WITH_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE])
AC_DEFUN([MOZ_ARG_WITH_BOOL],
[AC_ARG_WITH([$1], [$2],
[MOZ_AC_ARG_WITH([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$withval], yes, [$3], no, [$4])],
[$5])])
dnl MOZ_ARG_WITHOUT_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE])
AC_DEFUN([MOZ_ARG_WITHOUT_BOOL],
[AC_ARG_WITH([$1], [$2],
[MOZ_AC_ARG_WITH([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$withval], no, [$3], yes, [$4])],
[$5])])
dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE])
AC_DEFUN([MOZ_ARG_WITH_STRING],
[AC_ARG_WITH([$1], [$2], [$3], [$4])])
[MOZ_AC_ARG_WITH([$1], [$2], [$3], [$4])])
dnl MOZ_ARG_HEADER(Comment)
dnl This is used by webconfig to group options
@ -82,42 +91,5 @@ define(MOZ_ARG_HEADER, [# $1])
dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
AC_DEFUN([MOZ_READ_MOZCONFIG],
[AC_REQUIRE([AC_INIT_BINSH])dnl
inserted=
dnl Shell is hard, so here is what the following does:
dnl - Reset $@ (command line arguments)
dnl - Add the configure options from mozconfig to $@ one by one
dnl - Add the original command line arguments after that, one by one
dnl
dnl There are several tricks involved:
dnl - It is not possible to preserve the whitespaces in $@ by assigning to
dnl another variable, so the two first steps above need to happen in the first
dnl iteration of the third step.
dnl - We always want the configure options to be added, so the loop must be
dnl iterated at least once, so we add a dummy argument first, and discard it.
dnl - something | while read line ... makes the while run in a subshell, meaning
dnl that anything it does is not propagated to the main shell, so we can't do
dnl set -- foo there. As a consequence, what the while loop reading mach
dnl environment output does is output a set of shell commands for the main shell
dnl to eval.
dnl - Extra care is due when lines from mach environment output contain special
dnl shell characters, so we use ' for quoting and ensure no ' end up in between
dnl the quoting mark unescaped.
dnl Some of the above is directly done in mach environment --format=configure.
failed_eval() {
echo "Failed eval'ing the following:"
$(dirname [$]0)/[$1]/mach environment --format=configure
exit 1
}
set -- dummy "[$]@"
for ac_option
do
if test -z "$inserted"; then
set --
eval "$($(dirname [$]0)/[$1]/mach environment --format=configure)" || failed_eval
inserted=1
else
set -- "[$]@" "$ac_option"
fi
done
. ./old-configure.vars
])

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

@ -510,6 +510,7 @@ AC_DEFUN([MOZ_SET_WARNINGS_CXXFLAGS],
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wwrite-strings"
# -Wclass-varargs - catches objects passed by value to variadic functions.
# -Wimplicit-fallthrough - catches unintentional switch case fallthroughs
# -Wloop-analysis - catches issues around loops
# -Wnon-literal-null-conversion - catches expressions used as a null pointer constant
# -Wthread-safety - catches inconsistent use of mutexes
@ -528,6 +529,7 @@ AC_DEFUN([MOZ_SET_WARNINGS_CXXFLAGS],
MOZ_CXX_SUPPORTS_WARNING(-W, c++14-compat-pedantic, ac_cxx_has_wcxx14_compat_pedantic)
MOZ_CXX_SUPPORTS_WARNING(-W, c++1z-compat, ac_cxx_has_wcxx1z_compat)
MOZ_CXX_SUPPORTS_WARNING(-W, class-varargs, ac_cxx_has_wclass_varargs)
MOZ_CXX_SUPPORTS_WARNING(-W, implicit-fallthrough, ac_cxx_has_wimplicit_fallthrough)
MOZ_CXX_SUPPORTS_WARNING(-W, loop-analysis, ac_cxx_has_wloop_analysis)
if test "$MOZ_ENABLE_WARNINGS_AS_ERRORS"; then

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

@ -83,11 +83,9 @@ dnl Replace AC_OUTPUT to create and call a python config.status
define([MOZ_CREATE_CONFIG_STATUS],
[dnl Top source directory in Windows format (as opposed to msys format).
WIN_TOP_SRC=
encoding=utf-8
case "$host_os" in
mingw*)
WIN_TOP_SRC=`cd $srcdir; pwd -W`
encoding=mbcs
;;
esac
AC_SUBST(WIN_TOP_SRC)
@ -101,30 +99,13 @@ trap '' 1 2 15
AC_CACHE_SAVE
trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
: ${CONFIG_STATUS=./config.status}
: ${CONFIG_STATUS=./config.data}
dnl We're going to need [ ] for python syntax.
changequote(<<<, >>>)dnl
echo creating $CONFIG_STATUS
extra_python_path=${COMM_BUILD:+"'mozilla', "}
cat > $CONFIG_STATUS <<EOF
#!${PYTHON}
# coding=$encoding
import os
import types
dnl topsrcdir is the top source directory in native form, as opposed to a
dnl form suitable for make.
topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
if not os.path.isabs(topsrcdir):
rel = os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir)
topsrcdir = os.path.abspath(rel)
topsrcdir = os.path.normpath(topsrcdir)
topobjdir = os.path.abspath(os.path.dirname(<<<__file__>>>))
def unique_list(l):
result = []
for i in l:
@ -135,7 +116,7 @@ def unique_list(l):
dnl All defines and substs are stored with an additional space at the beginning
dnl and at the end of the string, to avoid any problem with values starting or
dnl ending with quotes.
defines = [(name[1:-1], value[1:-1]) for name, value in [
defines = [
EOF
dnl confdefs.pytmp contains AC_DEFINEs, in the expected format, but
@ -144,9 +125,9 @@ sed 's/$/,/' confdefs.pytmp >> $CONFIG_STATUS
rm confdefs.pytmp confdefs.h
cat >> $CONFIG_STATUS <<\EOF
] ]
]
substs = [(name[1:-1], value[1:-1] if isinstance(value, types.StringTypes) else value) for name, value in [
substs = [
EOF
dnl The MOZ_DIVERSION_SUBST output diversion contains AC_SUBSTs, in the
@ -162,7 +143,7 @@ for ac_subst_arg in $_subconfigure_ac_subst_args; do
done
cat >> $CONFIG_STATUS <<\EOF
] ]
]
dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
non_global_defines = [
@ -177,38 +158,12 @@ fi
cat >> $CONFIG_STATUS <<EOF
]
__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs']
flags = [
undivert(MOZ_DIVERSION_ARGS)dnl
]
EOF
# We don't want js/src/config.status to do anything in gecko builds.
if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
cat >> $CONFIG_STATUS <<EOF
dnl Do the actual work
if __name__ == '__main__':
args = dict([(name, globals()[name]) for name in __all__])
from mozbuild.config_status import config_status
config_status(**args)
EOF
fi
changequote([, ])
chmod +x $CONFIG_STATUS
])
define([MOZ_RUN_CONFIG_STATUS],
[
MOZ_RUN_ALL_SUBCONFIGURES()
rm -fr confdefs* $ac_clean_files
dnl Execute config.status, unless --no-create was passed to configure.
if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
trap '' EXIT
exit 1
fi
])
define([m4_fatal],[
@ -225,21 +180,3 @@ MOZ_RUN_CONFIG_STATUS()],
define([AC_CONFIG_HEADER],
[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
])
define([MOZ_BUILD_BACKEND],
[
dnl For now, only enable the unified hybrid build system on artifact builds,
dnl otherwise default to RecursiveMake /and/ FasterMake.
if test -n "$MOZ_ARTIFACT_BUILDS"; then
BUILD_BACKENDS="FasterMake+RecursiveMake"
else
BUILD_BACKENDS="RecursiveMake FasterMake"
fi
MOZ_ARG_ENABLE_STRING(build-backend,
[ --enable-build-backend={$($(dirname ]$[0)/$1/mach python -c "from mozbuild.backend import backends; print ','.join(sorted(backends))")}
Enable additional build backends],
[ BUILD_BACKENDS="$BUILD_BACKENDS `echo $enableval | sed 's/,/ /g'`"])
AC_SUBST_SET([BUILD_BACKENDS])
])

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

@ -1,85 +0,0 @@
dnl This Source Code Form is subject to the terms of the Mozilla Public
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
AC_DEFUN([MOZ_PYTHON],
[
dnl We honor the Python path defined in an environment variable. This is used
dnl to pass the virtualenv's Python from the main configure to SpiderMonkey's
dnl configure, for example.
if test -z "$PYTHON"; then
MOZ_PATH_PROGS(PYTHON, $PYTHON python2.7 python)
if test -z "$PYTHON"; then
AC_MSG_ERROR([python was not found in \$PATH])
fi
else
AC_MSG_RESULT([Using Python from environment variable \$PYTHON])
fi
_virtualenv_topsrcdir=
_virtualenv_populate_path=
dnl If this is a mozilla-central, we'll find the virtualenv in the top
dnl source directory. If this is a SpiderMonkey build, we assume we're at
dnl js/src and try to find the virtualenv from the mozilla-central root.
for base in $MOZILLA_CENTRAL_PATH $_topsrcdir $_topsrcdir/../..; do
possible=$base/python/mozbuild/mozbuild/virtualenv.py
if test -e $possible; then
_virtualenv_topsrcdir=$base
_virtualenv_populate_path=$possible
break
fi
done
if test -z $_virtualenv_populate_path; then
AC_MSG_ERROR([Unable to find Virtualenv population script. In order
to build, you will need mozilla-central's virtualenv.
If you are building from a mozilla-central checkout, you should never see this
message. If you are building from a source archive, the source archive was
likely not created properly (it is missing the virtualenv files).
If you have a copy of mozilla-central available, define the
MOZILLA_CENTRAL_PATH environment variable to the top source directory of
mozilla-central and relaunch configure.])
fi
if test -z $DONT_POPULATE_VIRTUALENV; then
AC_MSG_RESULT([Creating Python environment])
dnl This verifies our Python version is sane and ensures the Python
dnl virtualenv is present and up to date. It sanitizes the environment
dnl for us, so we don't need to clean anything out.
$PYTHON $_virtualenv_populate_path \
$_virtualenv_topsrcdir $MOZ_BUILD_ROOT $MOZ_BUILD_ROOT/_virtualenv \
$_virtualenv_topsrcdir/build/virtualenv_packages.txt || exit 1
case "$host_os" in
mingw*)
PYTHON=`cd $MOZ_BUILD_ROOT && pwd -W`/_virtualenv/Scripts/python.exe
;;
*)
PYTHON=$MOZ_BUILD_ROOT/_virtualenv/bin/python
;;
esac
fi
AC_SUBST(PYTHON)
AC_MSG_CHECKING([Python environment is Mozilla virtualenv])
$PYTHON -c "import mozbuild.base"
if test "$?" != 0; then
AC_MSG_ERROR([Python environment does not appear to be sane.])
fi
AC_MSG_RESULT([yes])
PYTHON_SITE_PACKAGES=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib()"`
if test -z "$PYTHON_SITE_PACKAGES"; then
AC_MSG_ERROR([Could not determine python site packages directory.])
fi
AC_SUBST([PYTHON_SITE_PACKAGES])
])

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

@ -31,9 +31,6 @@ a11y.ini
xpcshell.ini
For *xpcshell* tests.
webapprt.ini
For the *chrome* flavor of webapp runtime mochitests.
.. _manifestparser_manifests:
ManifestParser Manifests

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

@ -12,7 +12,6 @@ ALL_HARNESSES = [
'common', # Harnesses without a specific package will look here.
'mochitest',
'reftest',
'webapprt',
'xpcshell',
'cppunittest',
'jittest',

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

@ -0,0 +1,200 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
include('util.configure')
option(env='DIST', nargs=1, help='DIST directory')
# Do not allow objdir == srcdir builds.
# ==============================================================
@depends('--help', 'DIST')
def check_build_environment(help, dist):
topobjdir = os.path.realpath(os.path.abspath('.'))
topsrcdir = os.path.realpath(os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', '..')))
set_config('TOPSRCDIR', topsrcdir)
set_config('TOPOBJDIR', topobjdir)
set_config('MOZ_BUILD_ROOT', topobjdir)
if dist:
set_config('DIST', normsep(dist[0]))
else:
set_config('DIST', os.path.join(topobjdir, 'dist'))
if help:
return
if topsrcdir == topobjdir:
error(
' ***\n'
' * Building directly in the main source directory is not allowed.\n'
' *\n'
' * To build, you must run configure from a separate directory\n'
' * (referred to as an object directory).\n'
' *\n'
' * If you are building with a mozconfig, you will need to change your\n'
' * mozconfig to point to a different object directory.\n'
' ***'
)
# Check for a couple representative files in the source tree
conflict_files = [
'* %s' % f for f in ('Makefile', 'config/autoconf.mk')
if os.path.exists(os.path.join(topsrcdir, f))
]
if conflict_files:
error(
' ***\n'
' * Your source tree contains these files:\n'
' %s\n'
' * This indicates that you previously built in the source tree.\n'
' * A source tree build can confuse the separate objdir build.\n'
' *\n'
' * To clean up the source tree:\n'
' * 1. cd %s\n'
' * 2. gmake distclean\n'
' ***'
% ('\n '.join(conflict_files), topsrcdir)
)
option(env='MOZ_CURRENT_PROJECT', nargs=1, help='Current build project')
option(env='MOZCONFIG', nargs=1, help='Mozconfig location')
# Read user mozconfig
# ==============================================================
# Note: the dependency on --help is only there to always read the mozconfig,
# even when --help is passed. Without this dependency, the function wouldn't
# be called when --help is passed, and the mozconfig wouldn't be read.
@depends('MOZ_CURRENT_PROJECT', 'MOZCONFIG', check_build_environment, '--help')
@advanced
def mozconfig(current_project, mozconfig, build_env, help):
from mozbuild.mozconfig import MozconfigLoader
# Don't read the mozconfig for the js configure (yay backwards
# compatibility)
if build_env['TOPOBJDIR'].endswith('/js/src'):
return {'path': None}
loader = MozconfigLoader(build_env['TOPSRCDIR'])
current_project = current_project[0] if current_project else None
mozconfig = mozconfig[0] if mozconfig else None
mozconfig = loader.find_mozconfig(env={'MOZCONFIG': mozconfig})
mozconfig = loader.read_mozconfig(mozconfig, moz_build_app=current_project)
return mozconfig
option(env='PYTHON', nargs=1, help='Python interpreter')
# Setup python virtualenv
# ==============================================================
@depends('PYTHON', check_build_environment, mozconfig)
@advanced
def virtualenv_python(env_python, build_env, mozconfig):
import os
import sys
import subprocess
from mozbuild.virtualenv import (
VirtualenvManager,
verify_python_version,
)
python = env_python[0] if env_python else None
# Ideally we'd rely on the mozconfig injection from mozconfig_options,
# but we'd rather avoid the verbosity when we need to reexecute with
# a different python.
if mozconfig['path']:
if 'PYTHON' in mozconfig['env']['added']:
python = mozconfig['env']['added']['PYTHON']
elif 'PYTHON' in mozconfig['env']['modified']:
python = mozconfig['env']['modified']['PYTHON'][1]
elif 'PYTHON' in mozconfig['vars']['added']:
python = mozconfig['vars']['added']['PYTHON']
elif 'PYTHON' in mozconfig['vars']['modified']:
python = mozconfig['vars']['modified']['PYTHON'][1]
verify_python_version(sys.stderr)
topsrcdir, topobjdir = build_env['TOPSRCDIR'], build_env['TOPOBJDIR']
if topobjdir.endswith('/js/src'):
topobjdir = topobjdir[:-7]
manager = VirtualenvManager(
topsrcdir, topobjdir,
os.path.join(topobjdir, '_virtualenv'), sys.stdout,
os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt'))
if python:
# If we're not in the virtualenv, we need the which module for
# find_program.
if normsep(sys.executable) != normsep(manager.python_path):
sys.path.append(os.path.join(topsrcdir, 'python', 'which'))
found_python = find_program(python)
if not found_python:
error('The PYTHON environment variable does not contain '
'a valid path. Cannot find %s' % python)
python = found_python
else:
python = sys.executable
if not manager.up_to_date(python):
warn('Creating Python environment')
manager.build(python)
python = normsep(manager.python_path)
if python != normsep(sys.executable):
warn('Reexecuting in the virtualenv')
if env_python:
del os.environ['PYTHON']
# One would prefer to use os.execl, but that's completely borked on
# Windows.
sys.exit(subprocess.call([python] + sys.argv))
# We are now in the virtualenv
import distutils.sysconfig
if not distutils.sysconfig.get_python_lib():
error('Could not determine python site packages directory')
set_config('PYTHON', python)
return python
# Inject mozconfig options
# ==============================================================
@template
@advanced
def command_line_helper():
# This escapes the sandbox. Don't copy this. This is only here because
# it is a one off and because the required functionality doesn't need
# to be exposed for other usecases.
return depends.__self__._helper
@depends(mozconfig)
def mozconfig_options(mozconfig):
if mozconfig['path']:
helper = command_line_helper()
warn('Adding configure options from %s' % mozconfig['path'])
for arg in mozconfig['configure_args']:
warn(' %s' % arg)
# We could be using imply_option() here, but it has other
# contraints that don't really apply to the command-line
# emulation that mozconfig provides.
helper.add(arg, origin='mozconfig', args=helper._args)
# Ideally we'd handle mozconfig['env'] and mozconfig['vars'] here,
# but at the moment, moz.configure has no knowledge of the options
# that may appear there. We'll opt-in when we move things from
# old-configure.in, which will be tedious but necessary until we
# can discriminate what old-configure.in supports.
del command_line_helper
option(env='MOZILLABUILD', nargs=1,
help='Path to Mozilla Build (Windows-only)')

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

@ -0,0 +1,402 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# It feels dirty replicating this from python/mozbuild/mozbuild/mozconfig.py,
# but the end goal being that the configure script would go away...
@depends('MOZILLABUILD')
@advanced
def shell(mozillabuild):
import sys
shell = 'sh'
if mozillabuild:
shell = mozillabuild[0] + '/msys/bin/sh'
if sys.platform == 'win32':
shell = shell + '.exe'
return shell
option(env='AUTOCONF', nargs=1, help='Path to autoconf 2.13')
@depends(mozconfig, 'AUTOCONF')
@advanced
def autoconf(mozconfig, autoconf):
import re
mozconfig_autoconf = None
if mozconfig['path']:
make_extra = mozconfig['make_extra']
if make_extra:
for assignment in make_extra:
m = re.match('(?:export\s+)?AUTOCONF\s*:?=\s*(.+)$',
assignment)
if m:
mozconfig_autoconf = m.group(1)
autoconf = autoconf[0] if autoconf else None
for ac in (mozconfig_autoconf, autoconf, 'autoconf-2.13', 'autoconf2.13',
'autoconf213'):
if ac:
autoconf = find_program(ac)
if autoconf:
break
else:
fink = find_program('fink')
if find:
autoconf = os.path.normpath(os.path.join(
fink, '..', '..', 'lib', 'autoconf2.13', 'bin', 'autoconf'))
if not autoconf:
error('Could not find autoconf 2.13')
set_config('AUTOCONF', autoconf)
return autoconf
option(env='OLD_CONFIGURE', nargs=1, help='Path to the old configure script')
@depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell,
virtualenv_python, compile_environment)
@advanced
def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
python, compile_env):
import glob
import itertools
import subprocess
import sys
# Import getmtime without overwriting the sandbox os.path.
from os.path import getmtime
from mozbuild.shellutil import quote
if not old_configure:
error('The OLD_CONFIGURE environment variable must be set')
# os.path.abspath in the sandbox will ensure forward slashes on Windows,
# which is actually necessary because this path actually ends up literally
# as $0, and backslashes there breaks autoconf's detection of the source
# directory.
old_configure = os.path.abspath(old_configure[0])
refresh = True
if os.path.exists(old_configure):
mtime = getmtime(old_configure)
aclocal = os.path.join(build_env['TOPSRCDIR'], 'build', 'autoconf',
'*.m4')
for input in itertools.chain(
(old_configure + '.in',
os.path.join(os.path.dirname(old_configure), 'aclocal.m4')),
glob.iglob(aclocal),
):
if getmtime(input) > mtime:
break
else:
refresh = False
if refresh:
warn('Refreshing %s with %s' % (old_configure, autoconf))
with open(old_configure, 'wb') as fh:
subprocess.check_call([
shell, autoconf,
'--localdir=%s' % os.path.dirname(old_configure),
old_configure + '.in'], stdout=fh)
cmd = [shell, old_configure] + sys.argv[1:]
with open('old-configure.vars', 'w') as out:
if mozconfig['path']:
if mozconfig['configure_args']:
cmd += mozconfig['configure_args']
for key, value in mozconfig['env']['added'].items():
print("export %s=%s" % (key, quote(value)), file=out)
for key, (old, value) in mozconfig['env']['modified'].items():
print("export %s=%s" % (key, quote(value)), file=out)
for key, value in mozconfig['vars']['added'].items():
print("%s=%s" % (key, quote(value)), file=out)
for key, (old, value) in mozconfig['vars']['modified'].items():
print("%s=%s" % (key, quote(value)), file=out)
for t in ('env', 'vars'):
for key in mozconfig[t]['removed'].keys():
print("unset %s" % key, file=out)
print('PYTHON=%s' % quote(python), file=out)
if compile_env:
print('COMPILE_ENVIRONMENT=1', file=out)
return cmd
@template
def old_configure_options(*options):
for opt in options:
option(opt, nargs='*', help='Help missing for old configure options')
@depends('--help')
def all_options(help):
return set(options)
return depends(prepare_configure, all_options, *options)
@old_configure_options(
'--cache-file',
'--enable-accessibility',
'--enable-address-sanitizer',
'--enable-alsa',
'--enable-android-apz',
'--enable-android-omx',
'--enable-android-resource-constrained',
'--enable-application',
'--enable-approximate-location',
'--enable-b2g-bt',
'--enable-b2g-camera',
'--enable-b2g-ril',
'--enable-bundled-fonts',
'--enable-callgrind',
'--enable-chrome-format',
'--enable-clang-plugin',
'--enable-content-sandbox',
'--enable-cookies',
'--enable-cpp-rtti',
'--enable-crashreporter',
'--enable-ctypes',
'--enable-dbm',
'--enable-dbus',
'--enable-debug',
'--enable-debug-js-modules',
'--enable-debug-symbols',
'--enable-default-toolkit',
'--enable-directshow',
'--enable-dmd',
'--enable-dtrace',
'--enable-dump-painting',
'--enable-elf-hack',
'--enable-eme',
'--enable-export-js',
'--enable-extensions',
'--enable-faststripe',
'--enable-feeds',
'--enable-ffmpeg',
'--enable-fmp4',
'--enable-gamepad',
'--enable-gc-trace',
'--enable-gconf',
'--enable-gczeal',
'--enable-gio',
'--enable-gnomeui',
'--enable-gold',
'--enable-gps-debug',
'--enable-hardware-aec-ns',
'--enable-icf',
'--enable-install-strip',
'--enable-instruments',
'--enable-ion',
'--enable-ios-target',
'--enable-ipdl-tests',
'--enable-jemalloc',
'--enable-jitspew',
'--enable-jprof',
'--enable-libjpeg-turbo',
'--enable-libproxy',
'--enable-llvm-hacks',
'--enable-logrefcnt',
'--enable-macos-target',
'--enable-maintenance-service',
'--enable-media-navigator',
'--enable-memory-sanitizer',
'--enable-mobile-optimize',
'--enable-more-deterministic',
'--enable-mozril-geoloc',
'--enable-necko-protocols',
'--enable-necko-wifi',
'--enable-negotiateauth',
'--enable-nfc',
'--enable-nspr-build',
'--enable-official-branding',
'--enable-omx-plugin',
'--enable-oom-breakpoint',
'--enable-optimize',
'--enable-parental-controls',
'--enable-perf',
'--enable-permissions',
'--enable-pie',
'--enable-png-arm-neon-support',
'--enable-posix-nspr-emulation',
'--enable-pref-extensions',
'--enable-printing',
'--enable-profilelocking',
'--enable-profiling',
'--enable-pulseaudio',
'--enable-raw',
'--enable-readline',
'--enable-reflow-perf',
'--enable-release',
'--enable-replace-malloc',
'--enable-require-all-d3dc-versions',
'--enable-rust',
'--enable-safe-browsing',
'--enable-sandbox',
'--enable-shared-js',
'--enable-signmar',
'--enable-simulator',
'--enable-skia',
'--enable-skia-gpu',
'--enable-small-chunk-size',
'--enable-startup-notification',
'--enable-startupcache',
'--enable-stdcxx-compat',
'--enable-strip',
'--enable-synth-pico',
'--enable-synth-speechd',
'--enable-system-cairo',
'--enable-system-extension-dirs',
'--enable-system-ffi',
'--enable-system-hunspell',
'--enable-system-pixman',
'--enable-system-sqlite',
'--enable-systrace',
'--enable-tasktracer',
'--enable-tests',
'--enable-thread-sanitizer',
'--enable-trace-logging',
'--enable-tree-freetype',
'--enable-ui-locale',
'--enable-universalchardet',
'--enable-update-channel',
'--enable-update-packaging',
'--enable-updater',
'--enable-url-classifier',
'--enable-valgrind',
'--enable-verify-mar',
'--enable-vtune',
'--enable-warnings-as-errors',
'--enable-webapp-runtime',
'--enable-webrtc',
'--enable-websms-backend',
'--enable-webspeech',
'--enable-webspeechtestbackend',
'--enable-wmf',
'--enable-xterm-updates',
'--enable-xul',
'--enable-zipwriter',
'--host',
'--no-create',
'--prefix',
'--target',
'--with-adjust-sdk-keyfile',
'--with-android-cxx-stl',
'--with-android-distribution-directory',
'--with-android-gnu-compiler-version',
'--with-android-max-sdk',
'--with-android-min-sdk',
'--with-android-ndk',
'--with-android-sdk',
'--with-android-toolchain',
'--with-android-version',
'--with-app-basename',
'--with-app-name',
'--with-arch',
'--with-arm-kuser',
'--with-bing-api-keyfile',
'--with-branding',
'--with-ccache',
'--with-compiler-wrapper',
'--with-crashreporter-enable-percent',
'--with-cross-lib',
'--with-debug-label',
'--with-default-mozilla-five-home',
'--with-distribution-id',
'--with-doc-include-dirs',
'--with-doc-input-dirs',
'--with-doc-output-dir',
'--with-external-source-dir',
'--with-float-abi',
'--with-fpu',
'--with-gl-provider',
'--with-gonk',
'--with-gonk-toolchain-prefix',
'--with-google-api-keyfile',
'--with-google-oauth-api-keyfile',
'--with-gradle',
'--with-intl-api',
'--with-ios-sdk',
'--with-java-bin-path',
'--with-jitreport-granularity',
'--with-l10n-base',
'--with-libxul-sdk',
'--with-linux-headers',
'--with-macbundlename-prefix',
'--with-macos-private-frameworks',
'--with-macos-sdk',
'--with-mozilla-api-keyfile',
'--with-nspr-cflags',
'--with-nspr-libs',
'--with-pthreads',
'--with-qemu-exe',
'--with-qtdir',
'--with-servo',
'--with-sixgill',
'--with-soft-float',
'--with-system-bz2',
'--with-system-icu',
'--with-system-jpeg',
'--with-system-libevent',
'--with-system-libvpx',
'--with-system-nspr',
'--with-system-nss',
'--with-system-png',
'--with-system-zlib',
'--with-thumb',
'--with-thumb-interwork',
'--with-unify-dist',
'--with-user-appdir',
'--with-windows-version',
'--with-x',
'--with-xulrunner-stub-name',
'--x-includes',
'--x-libraries',
)
@advanced
def old_configure(prepare_configure, all_options, *options):
import codecs
import os
import subprocess
import sys
import types
ret = subprocess.call(prepare_configure)
if ret:
sys.exit(ret)
raw_config = {}
encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
with codecs.open('config.data', 'r', encoding) as fh:
code = compile(fh.read(), 'config.data', 'exec')
# Every variation of the exec() function I tried led to:
# SyntaxError: unqualified exec is not allowed in function 'main' it
# contains a nested function with free variables
exec code in raw_config
# Ensure all the flags known to old-configure appear in the
# @old_configure_options above.
for flag in raw_config['flags']:
if flag not in all_options:
error('Missing option in `@old_configure_options` in %s: %s'
% (__file__, flag))
# If the code execution above fails, we want to keep the file around for
# debugging.
os.remove('config.data')
config = {}
for k, v in raw_config['substs']:
set_config(k[1:-1], v[1:-1] if isinstance(v, types.StringTypes) else v)
for k, v in dict(raw_config['defines']).iteritems():
set_define(k[1:-1], v[1:-1])
set_config('non_global_defines', raw_config['non_global_defines'])

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

@ -0,0 +1,78 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@template
@advanced
def warn(*args):
import sys
print(*args, file=sys.stderr)
sys.stderr.flush()
@template
@advanced
def error(*args):
import sys
print(*args, file=sys.stderr)
sys.stderr.flush()
sys.exit(1)
@template
@advanced
def is_absolute_or_relative(path):
import os
if os.altsep and os.altsep in path:
return True
return os.sep in path
@template
@advanced
def normsep(path):
import mozpack.path as mozpath
return mozpath.normsep(path)
@template
@advanced
def find_program(file):
if is_absolute_or_relative(file):
return os.path.abspath(file) if os.path.isfile(file) else None
from which import which, WhichError
try:
return normsep(which(file))
except WhichError:
return None
@depends('--help')
def _defines(help):
ret = {}
set_config('DEFINES', ret)
return ret
@template
def set_define(name, value):
@depends(_defines)
@advanced
def _add_define(defines):
from mozbuild.configure import ConfigureError
if name in defines:
raise ConfigureError("'%s' is already defined" % name)
defines[name] = value
del _defines
@template
def unique_list(l):
result = []
for i in l:
if l not in result:
result.append(i)
return result

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

@ -1550,9 +1550,6 @@ libs export::
$(CHECK_FROZEN_VARIABLES)
PURGECACHES_DIRS ?= $(DIST)/bin
ifdef MOZ_WEBAPP_RUNTIME
PURGECACHES_DIRS += $(DIST)/bin/webapprt
endif
PURGECACHES_FILES = $(addsuffix /.purgecaches,$(PURGECACHES_DIRS))

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

@ -4,120 +4,70 @@
from __future__ import print_function, unicode_literals
import glob
import itertools
import codecs
import json
import os
import subprocess
import sys
import re
base_dir = os.path.dirname(__file__)
sys.path.append(os.path.join(base_dir, 'python', 'which'))
base_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.join(base_dir, 'python', 'mozbuild'))
from which import which, WhichError
from mozbuild.mozconfig import MozconfigLoader
from mozbuild.configure import ConfigureSandbox
# If feel dirty replicating this from python/mozbuild/mozbuild/mozconfig.py,
# but the end goal being that the configure script would go away...
shell = 'sh'
if 'MOZILLABUILD' in os.environ:
shell = os.environ['MOZILLABUILD'] + '/msys/bin/sh'
if sys.platform == 'win32':
shell = shell + '.exe'
def main(argv):
config = {}
sandbox = ConfigureSandbox(config, os.environ, argv)
sandbox.run(os.path.join(os.path.dirname(__file__), 'moz.configure'))
if sandbox._help:
return 0
def is_absolute_or_relative(path):
if os.altsep and os.altsep in path:
return True
return os.sep in path
# Sanitize config data to feed config.status
sanitized_config = {}
sanitized_config['substs'] = {
k: v for k, v in config.iteritems()
if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR')
}
sanitized_config['defines'] = config['DEFINES']
sanitized_config['non_global_defines'] = config['non_global_defines']
sanitized_config['topsrcdir'] = config['TOPSRCDIR']
sanitized_config['topobjdir'] = config['TOPOBJDIR']
# Create config.status. Eventually, we'll want to just do the work it does
# here, when we're able to skip configure tests/use cached results/not rely
# on autoconf.
print("Creating config.status", file=sys.stderr)
encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
with codecs.open('config.status', 'w', encoding) as fh:
fh.write('#!%s\n' % config['PYTHON'])
fh.write('# coding=%s\n' % encoding)
for k, v in sanitized_config.iteritems():
fh.write('%s = ' % k)
json.dump(v, fh, sort_keys=True, indent=4, ensure_ascii=False)
fh.write('\n')
fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', "
"'non_global_defines', 'substs']")
def find_program(file):
if is_absolute_or_relative(file):
return os.path.abspath(file) if os.path.isfile(file) else None
try:
return which(file)
except WhichError:
return None
def autoconf_refresh(configure):
if os.path.exists(configure):
mtime = os.path.getmtime(configure)
aclocal = os.path.join(base_dir, 'build', 'autoconf', '*.m4')
for input in itertools.chain(
(configure + '.in',
os.path.join(os.path.dirname(configure), 'aclocal.m4')),
glob.iglob(aclocal),
):
if os.path.getmtime(input) > mtime:
break
else:
return
mozconfig_autoconf = None
configure_dir = os.path.dirname(configure)
# Don't read the mozconfig for the js configure (yay backwards
# compatibility)
if not configure_dir.replace(os.sep, '/').endswith('/js/src'):
loader = MozconfigLoader(os.path.dirname(configure))
project = os.environ.get('MOZ_CURRENT_PROJECT')
mozconfig = loader.find_mozconfig(env=os.environ)
mozconfig = loader.read_mozconfig(mozconfig, moz_build_app=project)
make_extra = mozconfig['make_extra']
if make_extra:
for assignment in make_extra:
m = re.match('(?:export\s+)?AUTOCONF\s*:?=\s*(.+)$',
assignment)
if m:
mozconfig_autoconf = m.group(1)
for ac in (mozconfig_autoconf, os.environ.get('AUTOCONF'), 'autoconf-2.13',
'autoconf2.13', 'autoconf213'):
if ac:
autoconf = find_program(ac)
if autoconf:
break
else:
fink = find_program('fink')
if fink:
autoconf = os.path.normpath(os.path.join(
fink, '..', '..', 'lib', 'autoconf2.13', 'bin', 'autoconf'))
if not autoconf:
raise RuntimeError('Could not find autoconf 2.13')
# Add or adjust AUTOCONF for subprocesses, especially the js/src configure
os.environ['AUTOCONF'] = autoconf
print('Refreshing %s with %s' % (configure, autoconf), file=sys.stderr)
with open(configure, 'wb') as fh:
subprocess.check_call([
shell, autoconf, '--localdir=%s' % os.path.dirname(configure),
configure + '.in'], stdout=fh)
def main(args):
old_configure = os.environ.get('OLD_CONFIGURE')
if not old_configure:
raise Exception('The OLD_CONFIGURE environment variable must be set')
# We need to replace backslashes with forward slashes on Windows because
# this path actually ends up literally as $0, which breaks autoconf's
# detection of the source directory.
old_configure = os.path.abspath(old_configure).replace(os.sep, '/')
try:
autoconf_refresh(old_configure)
except RuntimeError as e:
print(e.message, file=sys.stderr)
return 1
return subprocess.call([shell, old_configure] + args)
if not config.get('BUILDING_JS') or config.get('JS_STANDALONE'):
fh.write('''
if __name__ == '__main__':
args = dict([(name, globals()[name]) for name in __all__])
from mozbuild.config_status import config_status
config_status(**args)
''')
# Other things than us are going to run this file, so we need to give it
# executable permissions.
os.chmod('config.status', 0755)
if not config.get('BUILDING_JS') or config.get('JS_STANDALONE'):
if not config.get('JS_STANDALONE'):
os.environ['WRITE_MOZINFO'] = '1'
# Until we have access to the virtualenv from this script, execute
# config.status externally, with the virtualenv python.
return subprocess.call([config['PYTHON'], 'config.status'])
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
sys.exit(main(sys.argv))

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

@ -888,7 +888,7 @@ WebConsoleActor.prototype =
error.unsafeDereference();
errorMessage = unsafeDereference && unsafeDereference.toString
? unsafeDereference.toString()
: "" + error;
: String(error);
}
}

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

@ -85,12 +85,6 @@ function setup() {
Components.utils.import('resource://gre/modules/Webapps.jsm');
DOMApplicationRegistry.allAppsLaunchable = true;
// Mock WebappOSUtils
Cu.import("resource://gre/modules/WebappOSUtils.jsm");
WebappOSUtils.getPackagePath = function(aApp) {
return aApp.basePath + "/" + aApp.id;
}
// Enable launch/close method of the webapps actor
let {WebappsActor} = require("devtools/server/actors/webapps");
WebappsActor.prototype.supportsLaunch = true;

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

@ -62,6 +62,21 @@ function onAttach(aState, aResponse)
});
});
let symbolTestValues = [
["Symbol.iterator", "Symbol(Symbol.iterator)"],
["Symbol('foo')", "Symbol(foo)"],
["Symbol()", "Symbol()"],
];
symbolTestValues.forEach(function([expr, message]) {
tests.push(function() {
aState.client.evaluateJS("throw " + expr + ";", function(aResponse) {
is(aResponse.exceptionMessage, message,
"response.exception for throw " + expr);
nextTest();
});
});
});
runTests(tests, endTest.bind(null, aState));
}

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

@ -3498,6 +3498,11 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
return false;
}
if (static_cast<nsDocShell*>(targetDS.get())->GetOriginAttributes().mUserContextId !=
static_cast<nsDocShell*>(accessingDS.get())->GetOriginAttributes().mUserContextId) {
return false;
}
// A private document can't access a non-private one, and vice versa.
if (static_cast<nsDocShell*>(targetDS.get())->UsePrivateBrowsing() !=
static_cast<nsDocShell*>(accessingDS.get())->UsePrivateBrowsing()) {
@ -14191,7 +14196,9 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceReques
if (aIsNonSubresourceRequest) {
PrincipalOriginAttributes attrs;
attrs.InheritFromDocShellToDoc(mOriginAttributes, aURI);
*aShouldIntercept = swm->IsAvailable(attrs, aURI);
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
*aShouldIntercept = swm->IsAvailable(principal, aURI);
return NS_OK;
}

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

@ -68,9 +68,9 @@ CSSPseudoElement::Animate(
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
ErrorResult& aError)
{
// Bug 1241784: Implement this API.
NS_NOTREACHED("CSSPseudoElement::Animate() is not implemented yet.");
return nullptr;
Nullable<ElementOrCSSPseudoElement> target;
target.SetValue().SetAsCSSPseudoElement() = this;
return Element::Animate(target, aContext, aFrames, aOptions, aError);
}
/* static */ already_AddRefed<CSSPseudoElement>

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

@ -34,8 +34,8 @@ public:
EffectSet()
: mCascadeNeedsUpdate(false)
, mAnimationGeneration(0)
, mActiveIterators(0)
#ifdef DEBUG
, mActiveIterators(0)
, mCalledPropertyDtor(false)
#endif
{
@ -87,7 +87,9 @@ public:
, mHashIterator(mozilla::Move(aEffectSet.mEffects.Iter()))
, mIsEndIterator(false)
{
#ifdef DEBUG
mEffectSet.mActiveIterators++;
#endif
}
Iterator(Iterator&& aOther)
@ -95,7 +97,9 @@ public:
, mHashIterator(mozilla::Move(aOther.mHashIterator))
, mIsEndIterator(aOther.mIsEndIterator)
{
#ifdef DEBUG
mEffectSet.mActiveIterators++;
#endif
}
static Iterator EndIterator(EffectSet& aEffectSet)
@ -107,8 +111,10 @@ public:
~Iterator()
{
#ifdef DEBUG
MOZ_ASSERT(mEffectSet.mActiveIterators > 0);
mEffectSet.mActiveIterators--;
#endif
}
bool operator!=(const Iterator& aOther) const {
@ -221,11 +227,11 @@ private:
// the animation manager.
uint64_t mAnimationGeneration;
#ifdef DEBUG
// Track how many iterators are referencing this effect set when we are
// destroyed, we can assert that nothing is still pointing to us.
DebugOnly<uint64_t> mActiveIterators;
uint64_t mActiveIterators;
#ifdef DEBUG
bool mCalledPropertyDtor;
#endif
};

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

@ -16,9 +16,6 @@ Cu.import("resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils",
"resource://gre/modules/WebappOSUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
@ -385,7 +382,7 @@ this.AppsUtils = {
"isCoreApp": isCoreApp };
}
return { "path": WebappOSUtils.getPackagePath(app),
return { "path": app.basePath + "/" + app.id,
"isCoreApp": isCoreApp };
},

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

@ -73,9 +73,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "OfflineCacheInstaller",
XPCOMUtils.defineLazyModuleGetter(this, "SystemMessagePermissionsChecker",
"resource://gre/modules/SystemMessagePermissionsChecker.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebappOSUtils",
"resource://gre/modules/WebappOSUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
@ -135,9 +132,7 @@ function supportSystemMessages() {
// Minimum delay between two progress events while downloading, in ms.
const MIN_PROGRESS_EVENT_DELAY = 1500;
const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
const chromeWindowType = WEBAPP_RUNTIME ? "webapprt:webapp" : "navigator:browser";
const chromeWindowType = "navigator:browser";
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
"@mozilla.org/parentprocessmessagemanager;1",
@ -180,10 +175,8 @@ XPCOMUtils.defineLazyGetter(this, "permMgr", function() {
#elifdef ANDROID
const DIRECTORY_NAME = "webappsDir";
#else
// If we're executing in the context of the webapp runtime, the data files
// are in a different directory (currently the Firefox profile that installed
// the webapp); otherwise, they're in the current profile.
const DIRECTORY_NAME = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
// Mulet, B2G Desktop, etc.
const DIRECTORY_NAME = "ProfD";
#endif
// We'll use this to identify privileged apps that have been preinstalled
@ -2998,7 +2991,7 @@ this.DOMApplicationRegistry = {
app.manifestHash = AppsUtils.computeHash(JSON.stringify(aUpdateManifest ||
aManifest));
let zipFile = WebappOSUtils.getPackagePath(app);
let zipFile = app.basePath + "/" + app.id;
app.packageHash = yield this._computeFileHash(zipFile);
app.role = aManifest.role || "";
@ -4811,10 +4804,7 @@ this.DOMApplicationRegistry = {
},
_isLaunchable: function(aApp) {
if (this.allAppsLaunchable)
return true;
return WebappOSUtils.isLaunchable(aApp);
return true;
},
_notifyCategoryAndObservers: function(subject, topic, data, msg) {

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

@ -19,19 +19,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=945152
const gSJS = gBaseURL + 'file_bug_945152.sjs';
var gGenerator = runTest();
// When using SpecialPowers.autoConfirmAppInstall, it skips the local
// installation, and we need this mock to get correct package path.
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/WebappOSUtils.jsm");
var oldWebappOSUtils = WebappOSUtils;
WebappOSUtils.getPackagePath = function(aApp) {
return aApp.basePath + "/" + aApp.id;
}
SimpleTest.registerCleanupFunction(() => {
WebappOSUtils = oldWebappOSUtils;
});
function go() {
gGenerator.next();
}

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

@ -23,20 +23,12 @@ const gSJS = gBaseURL + 'asmjs_app.sjs';
const gManifestURL = gSJS + '?getManifest=true';
let gGenerator = runTest();
// Mock WebappOSUtils
Cu.import("resource://gre/modules/WebappOSUtils.jsm");
let oldWebappOSUtils = WebappOSUtils;
WebappOSUtils.getPackagePath = function(aApp) {
return aApp.basePath + "/" + aApp.id;
}
// Enable the ScriptPreloader module
Cu.import("resource://gre/modules/ScriptPreloader.jsm");
let oldScriptPreloaderEnabled = ScriptPreloader._enabled;
ScriptPreloader._enabled = true;
SimpleTest.registerCleanupFunction(() => {
WebappOSUtils = oldWebappOSUtils;
ScriptPreloader._enabled = oldScriptPreloaderEnabled;
});

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

@ -137,13 +137,15 @@
#include "nsITextControlElement.h"
#include "nsITextControlFrame.h"
#include "nsISupportsImpl.h"
#include "mozilla/dom/CSSPseudoElement.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/dom/KeyframeEffectBinding.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/VRDevice.h"
#include "nsComputedDOMStyle.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Preferences.h"
#include "nsComputedDOMStyle.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -3307,7 +3309,31 @@ Element::Animate(JSContext* aContext,
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
ErrorResult& aError)
{
nsCOMPtr<nsIGlobalObject> ownerGlobal = GetOwnerGlobal();
Nullable<ElementOrCSSPseudoElement> target;
target.SetValue().SetAsElement() = this;
return Animate(target, aContext, aFrames, aOptions, aError);
}
/* static */ already_AddRefed<Animation>
Element::Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
JSContext* aContext,
JS::Handle<JSObject*> aFrames,
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
ErrorResult& aError)
{
MOZ_ASSERT(!aTarget.IsNull() &&
(aTarget.Value().IsElement() ||
aTarget.Value().IsCSSPseudoElement()),
"aTarget should be initialized");
RefPtr<Element> referenceElement;
if (aTarget.Value().IsElement()) {
referenceElement = &aTarget.Value().GetAsElement();
} else {
referenceElement = aTarget.Value().GetAsCSSPseudoElement().ParentElement();
}
nsCOMPtr<nsIGlobalObject> ownerGlobal = referenceElement->GetOwnerGlobal();
if (!ownerGlobal) {
aError.Throw(NS_ERROR_FAILURE);
return nullptr;
@ -3327,17 +3353,16 @@ Element::Animate(JSContext* aContext,
}
}
Nullable<ElementOrCSSPseudoElement> target;
target.SetValue().SetAsElement() = this;
RefPtr<KeyframeEffect> effect =
KeyframeEffect::Constructor(global, target, frames,
TimingParams::FromOptionsUnion(aOptions, target), aError);
KeyframeEffect::Constructor(global, aTarget, frames,
TimingParams::FromOptionsUnion(aOptions, aTarget), aError);
if (aError.Failed()) {
return nullptr;
}
RefPtr<Animation> animation =
Animation::Constructor(global, effect, OwnerDoc()->Timeline(), aError);
Animation::Constructor(global, effect,
referenceElement->OwnerDoc()->Timeline(), aError);
if (aError.Failed()) {
return nullptr;
}

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

@ -36,6 +36,7 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/Nullable.h"
#include "Units.h"
class nsIFrame;
@ -56,6 +57,7 @@ namespace mozilla {
namespace dom {
struct ScrollIntoViewOptions;
struct ScrollToOptions;
class ElementOrCSSPseudoElement;
class UnrestrictedDoubleOrKeyframeAnimationOptions;
} // namespace dom
} // namespace mozilla
@ -826,11 +828,20 @@ public:
{
}
already_AddRefed<Animation> Animate(
JSContext* aContext,
JS::Handle<JSObject*> aFrames,
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
ErrorResult& aError);
already_AddRefed<Animation>
Animate(JSContext* aContext,
JS::Handle<JSObject*> aFrames,
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
ErrorResult& aError);
// A helper method that factors out the common functionality needed by
// Element::Animate and CSSPseudoElement::Animate
static already_AddRefed<Animation>
Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
JSContext* aContext,
JS::Handle<JSObject*> aFrames,
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
ErrorResult& aError);
// Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
void GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations);

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

@ -104,8 +104,8 @@ SubtleCrypto::ImportKey(JSContext* cx,
const Sequence<nsString>& keyUsages,
ErrorResult& aRv)
{
SUBTLECRYPTO_METHOD_BODY(ImportKey, aRv, cx, format, keyData, algorithm,
extractable, keyUsages)
SUBTLECRYPTO_METHOD_BODY(ImportKey, aRv, mParent, cx, format, keyData,
algorithm, extractable, keyUsages)
}
already_AddRefed<Promise>
@ -121,7 +121,8 @@ SubtleCrypto::GenerateKey(JSContext* cx, const ObjectOrString& algorithm,
bool extractable, const Sequence<nsString>& keyUsages,
ErrorResult& aRv)
{
SUBTLECRYPTO_METHOD_BODY(GenerateKey, aRv, cx, algorithm, extractable, keyUsages)
SUBTLECRYPTO_METHOD_BODY(GenerateKey, aRv, mParent, cx, algorithm,
extractable, keyUsages)
}
already_AddRefed<Promise>
@ -132,7 +133,7 @@ SubtleCrypto::DeriveKey(JSContext* cx,
bool extractable, const Sequence<nsString>& keyUsages,
ErrorResult& aRv)
{
SUBTLECRYPTO_METHOD_BODY(DeriveKey, aRv, cx, algorithm, baseKey,
SUBTLECRYPTO_METHOD_BODY(DeriveKey, aRv, mParent, cx, algorithm, baseKey,
derivedKeyType, extractable, keyUsages)
}
@ -168,9 +169,9 @@ SubtleCrypto::UnwrapKey(JSContext* cx,
const Sequence<nsString>& keyUsages,
ErrorResult& aRv)
{
SUBTLECRYPTO_METHOD_BODY(UnwrapKey, aRv, cx, format, wrappedKey, unwrappingKey,
unwrapAlgorithm, unwrappedKeyAlgorithm,
extractable, keyUsages)
SUBTLECRYPTO_METHOD_BODY(UnwrapKey, aRv, mParent, cx, format, wrappedKey,
unwrappingKey, unwrapAlgorithm,
unwrappedKeyAlgorithm, extractable, keyUsages)
}
} // namespace dom

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

@ -486,7 +486,7 @@ public:
*
* https://dom.spec.whatwg.org/#dom-node-ownerdocument
*
* For all other cases GetOwnerDoc and GetOwnerDocument behave identically.
* For all other cases OwnerDoc and GetOwnerDocument behave identically.
*/
nsIDocument *OwnerDoc() const
{

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

@ -261,6 +261,7 @@ support-files =
file_bug1250148.sjs
mozbrowser_api_utils.js
websocket_helpers.js
websocket_tests.js
[test_anonymousContent_api.html]
[test_anonymousContent_append_after_reflow.html]

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

@ -5,242 +5,12 @@
<title>WebSocket test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="websocket_helpers.js"></script>
<script type="text/javascript" src="websocket_tests.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="testWebSocket()">
<script class="testbody" type="text/javascript">
function test1() {
return new Promise(function(resolve, reject) {
try {
var ws = CreateTestWS("http://mochi.test:8888/tests/dom/base/test/file_websocket");
ok(false, "test1 failed");
} catch (e) {
ok(true, "test1 failed");
}
resolve();
});
}
// this test expects that the serialization list to connect to the proxy
// is empty.
function test2() {
return new Promise(function(resolve, reject) {
var waitTest2Part1 = true;
var waitTest2Part2 = true;
var ws1 = CreateTestWS("ws://sub2.test2.example.com/tests/dom/base/test/file_websocket", "test-2.1");
var ws2 = CreateTestWS("ws://sub2.test2.example.com/tests/dom/base/test/file_websocket", "test-2.2");
var ws2CanConnect = false;
function maybeFinished() {
if (!waitTest2Part1 && !waitTest2Part2) {
resolve();
}
}
ws1.onopen = function() {
ok(true, "ws1 open in test 2");
ws2CanConnect = true;
ws1.close();
}
ws1.onclose = function(e) {
waitTest2Part1 = false;
maybeFinished();
}
ws2.onopen = function() {
ok(ws2CanConnect, "shouldn't connect yet in test-2!");
ws2.close();
}
ws2.onclose = function(e) {
waitTest2Part2 = false;
maybeFinished();
}
});
}
function test3() {
return new Promise(function(resolve, reject) {
var hasError = false;
var ws = CreateTestWS("ws://this.websocket.server.probably.does.not.exist");
ws.onopen = shouldNotOpen;
ws.onerror = function (e) {
hasError = true;
}
ws.onclose = function(e) {
shouldCloseNotCleanly(e);
ok(hasError, "rcvd onerror event");
is(e.code, 1006, "test-3 close code should be 1006 but is:" + e.code);
resolve();
}
});
}
function test4() {
return new Promise(function(resolve, reject) {
try {
var ws = CreateTestWS("file_websocket");
ok(false, "test-4 failed");
} catch (e) {
ok(true, "test-4 failed");
}
resolve();
});
}
function test5() {
return new Promise(function(resolve, reject) {
try {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "");
ok(false, "couldn't accept an empty string in the protocol parameter");
} catch (e) {
ok(true, "couldn't accept an empty string in the protocol parameter");
}
try {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "\n");
ok(false, "couldn't accept any not printable ASCII character in the protocol parameter");
} catch (e) {
ok(true, "couldn't accept any not printable ASCII character in the protocol parameter");
}
try {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test 5");
ok(false, "U+0020 not acceptable in protocol parameter");
} catch (e) {
ok(true, "U+0020 not acceptable in protocol parameter");
}
resolve();
});
}
function test6() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-6");
var counter = 1;
ws.onopen = function() {
ws.send(counter);
}
ws.onmessage = function(e) {
if (counter == 5) {
is(e.data, "あいうえお", "test-6 counter 5 data ok");
ws.close();
} else {
is(parseInt(e.data), counter+1, "bad counter");
counter += 2;
ws.send(counter);
}
}
ws.onclose = function(e) {
shouldCloseCleanly(e);
resolve();
}
});
}
function test7() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://sub2.test2.example.org/tests/dom/base/test/file_websocket", "test-7");
var gotmsg = false;
ws.onopen = function() {
ok(true, "test 7 open");
}
ws.onmessage = function(e) {
ok(true, "test 7 message");
is(e.origin, "ws://sub2.test2.example.org", "onmessage origin set to ws:// host");
gotmsg = true;
ws.close();
}
ws.onclose = function(e) {
ok(gotmsg, "recvd message in test 7 before close");
shouldCloseCleanly(e);
resolve();
}
});
}
function test8() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-8");
ws.onopen = function() {
is(ws.protocol, "test-8", "test-8 subprotocol selection");
ws.close();
}
ws.onclose = function(e) {
shouldCloseCleanly(e);
// We called close() with no close code: so pywebsocket will also send no
// close code, which translates to code 1005
is(e.code, 1005, "test-8 close code has wrong value:" + e.code);
is(e.reason, "", "test-8 close reason has wrong value:" + e.reason);
resolve();
}
});
}
function test9() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://test2.example.org/tests/dom/base/test/file_websocket", "test-9");
ws._receivedErrorEvent = false;
ws.onopen = shouldNotOpen;
ws.onerror = function(e) {
ws._receivedErrorEvent = true;
}
ws.onclose = function(e) {
ok(ws._receivedErrorEvent, "Didn't received the error event in test 9.");
shouldCloseNotCleanly(e);
resolve();
}
ws.close();
});
}
function test10() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://sub1.test1.example.com/tests/dom/base/test/file_websocket", "test-10");
ws.onclose = function(e) {
shouldCloseCleanly(e);
resolve();
}
try {
ws.send("client data");
ok(false, "Couldn't send data before connecting!");
} catch (e) {
ok(true, "Couldn't send data before connecting!");
}
ws.onopen = function()
{
ok(true, "test 10 opened");
ws.close();
}
});
}
var tests = [
test1, // client tries to connect to a http scheme location;
test2, // assure serialization of the connections;
@ -259,6 +29,10 @@ function testWebSocket() {
doTest();
}
SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
"Expect all sorts of flakiness in this test...");
SimpleTest.waitForExplicitFinish();
</script>
<div id="feedback">

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

@ -5,244 +5,12 @@
<title>WebSocket test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="websocket_helpers.js"></script>
<script type="text/javascript" src="websocket_tests.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="testWebSocket()">
<script class="testbody" type="text/javascript">
function test11() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-11");
is(ws.readyState, 0, "create bad readyState in test-11!");
ws.onopen = function() {
is(ws.readyState, 1, "open bad readyState in test-11!");
ws.send("client data");
}
ws.onmessage = function(e) {
is(e.data, "server data", "bad received message in test-11!");
ws.close(1000, "Have a nice day");
// this ok() is disabled due to a race condition - it state may have
// advanced through 2 (closing) and into 3 (closed) before it is evald
// ok(ws.readyState == 2, "onmessage bad readyState in test-11!");
}
ws.onclose = function(e) {
is(ws.readyState, 3, "onclose bad readyState in test-11!");
shouldCloseCleanly(e);
is(e.code, 1000, "test 11 got wrong close code: " + e.code);
is(e.reason, "Have a nice day", "test 11 got wrong close reason: " + e.reason);
resolve();
}
});
}
function test12() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-12");
ws.onopen = function() {
try {
// send an unpaired surrogate
ws._gotMessage = false;
ws.send("a\ud800b");
ok(true, "ok to send an unpaired surrogate");
} catch (e) {
ok(false, "shouldn't fail any more when sending an unpaired surrogate!");
}
}
ws.onmessage = function(msg) {
is(msg.data, "SUCCESS", "Unpaired surrogate in UTF-16 not converted in test-12");
ws._gotMessage = true;
// Must support unpaired surrogates in close reason, too
ws.close(1000, "a\ud800b");
}
ws.onclose = function(e) {
is(ws.readyState, 3, "onclose bad readyState in test-12!");
ok(ws._gotMessage, "didn't receive message!");
shouldCloseCleanly(e);
is(e.code, 1000, "test 12 got wrong close code: " + e.code);
is(e.reason, "a\ufffdb", "test 11 didn't get replacement char in close reason: " + e.reason);
resolve();
}
});
}
function test13() {
return new Promise(function(resolve, reject) {
// previous versions of this test counted the number of protocol errors
// returned, but the protocol stack typically closes down after reporting a
// protocol level error - trying to resync is too dangerous
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-13");
ws._timesCalledOnError = 0;
ws.onerror = function() {
ws._timesCalledOnError++;
}
ws.onclose = function(e) {
ok(ws._timesCalledOnError > 0, "no error events");
resolve();
}
});
}
function test14() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-14");
ws.onmessage = function() {
ok(false, "shouldn't received message after the server sent the close frame");
}
ws.onclose = function(e) {
shouldCloseCleanly(e);
resolve();
};
});
}
function test15() {
return new Promise(function(resolve, reject) {
/*
* DISABLED: see comments for test-15 case in file_websocket_wsh.py
*/
resolve();
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-15");
ws.onclose = function(e) {
shouldCloseNotCleanly(e);
resolve();
}
// termination of the connection might cause an error event if it happens in OPEN
ws.onerror = function() {
}
});
}
function test16() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-16");
ws.onopen = function() {
ws.close();
ok(!ws.send("client data"), "shouldn't send message after calling close()");
}
ws.onmessage = function() {
ok(false, "shouldn't send message after calling close()");
}
ws.onerror = function() {
}
ws.onclose = function() {
resolve();
}
});
}
function test17() {
return new Promise(function(resolve, reject) {
var status_test17 = "not started";
var test17func = function() {
var local_ws = new WebSocket("ws://sub1.test2.example.org/tests/dom/base/test/file_websocket", "test-17");
status_test17 = "started";
local_ws.onopen = function(e) {
status_test17 = "opened";
e.target.send("client data");
forcegc();
};
local_ws.onerror = function() {
ok(false, "onerror called on test " + current_test + "!");
};
local_ws.onmessage = function(e) {
ok(e.data == "server data", "Bad message in test-17");
status_test17 = "got message";
forcegc();
};
local_ws.onclose = function(e) {
ok(status_test17 == "got message", "Didn't got message in test-17!");
shouldCloseCleanly(e);
status_test17 = "closed";
forcegc();
resolve();
};
window._test17 = null;
forcegc();
}
window._test17 = test17func;
window._test17();
});
}
// The tests that expects that their websockets neither open nor close MUST
// be in the end of the tests, i.e. HERE, in order to prevent blocking the other
// tests.
function test18() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket_http_resource.txt");
ws.onopen = shouldNotOpen;
ws.onerror = ignoreError;
ws.onclose = function(e)
{
shouldCloseNotCleanly(e);
resolve();
}
});
}
function test19() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-19");
ws.onopen = shouldNotOpen;
ws.onerror = ignoreError;
ws.onclose = function(e)
{
shouldCloseNotCleanly(e);
resolve();
}
});
}
function test20() {
return new Promise(function(resolve, reject) {
var test20func = function() {
var local_ws = new WebSocket("ws://sub1.test1.example.org/tests/dom/base/test/file_websocket", "test-20");
local_ws.onerror = function() {
ok(false, "onerror called on test " + current_test + "!");
}
local_ws.onclose = function(e) {
ok(true, "test 20 closed despite gc");
resolve();
}
local_ws = null;
window._test20 = null;
forcegc();
}
window._test20 = test20func;
window._test20();
});
}
var tests = [
test11, // a simple hello echo;
test12, // client sends a message containing unpaired surrogates
@ -263,6 +31,10 @@ function testWebSocket() {
doTest();
}
SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
"Expect all sorts of flakiness in this test...");
SimpleTest.waitForExplicitFinish();
</script>
<div id="feedback">

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

@ -5,197 +5,12 @@
<title>WebSocket test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="websocket_helpers.js"></script>
<script type="text/javascript" src="websocket_tests.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="testWebSocket()">
<script class="testbody" type="text/javascript">
function test21() {
return new Promise(function(resolve, reject) {
var test21func = function() {
var local_ws = new WebSocket("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-21");
var received_message = false;
local_ws.onopen = function(e) {
e.target.send("client data");
forcegc();
e.target.onopen = null;
forcegc();
}
local_ws.onerror = function() {
ok(false, "onerror called on test " + current_test + "!");
}
local_ws.onmessage = function(e) {
is(e.data, "server data", "Bad message in test-21");
received_message = true;
forcegc();
e.target.onmessage = null;
forcegc();
}
local_ws.onclose = function(e) {
shouldCloseCleanly(e);
ok(received_message, "close transitioned through onmessage");
resolve();
}
local_ws = null;
window._test21 = null;
forcegc();
}
window._test21 = test21func;
window._test21();
});
}
function test22() {
return new Promise(function(resolve, reject) {
const pref_open = "network.websocket.timeout.open";
SpecialPowers.setIntPref(pref_open, 5);
var ws = CreateTestWS("ws://sub2.test2.example.org/tests/dom/base/test/file_websocket", "test-22");
ws.onopen = shouldNotOpen;
ws.onerror = ignoreError;
ws.onclose = function(e) {
shouldCloseNotCleanly(e);
resolve();
}
SpecialPowers.clearUserPref(pref_open);
});
}
function test23() {
return new Promise(function(resolve, reject) {
ok("WebSocket" in window, "WebSocket should be available on window object");
resolve();
});
}
function test24() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-does-not-exist");
ws.onopen = shouldNotOpen;
ws.onclose = function(e) {
shouldCloseNotCleanly(e);
resolve();
}
ws.onerror = function() {
}
});
}
function test25() {
return new Promise(function(resolve, reject) {
var prots=[];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
// This test errors because the server requires a sub-protocol, but
// the test just wants to ensure that the ctor doesn't generate an
// exception
ws.onerror = ignoreError;
ws.onopen = shouldNotOpen;
ws.onclose = function(e) {
is(ws.protocol, "", "test25 subprotocol selection");
ok(true, "test 25 protocol array close");
resolve();
}
});
}
function test26() {
return new Promise(function(resolve, reject) {
var prots=[""];
try {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ok(false, "testing empty element sub protocol array");
} catch (e) {
ok(true, "testing empty sub element protocol array");
}
resolve();
});
}
function test27() {
return new Promise(function(resolve, reject) {
var prots=["test27", ""];
try {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ok(false, "testing empty element mixed sub protocol array");
} catch (e) {
ok(true, "testing empty element mixed sub protocol array");
}
resolve();
});
}
function test28() {
return new Promise(function(resolve, reject) {
var prots=["test28"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 28 protocol array open");
ws.close();
}
ws.onclose = function(e) {
is(ws.protocol, "test28", "test28 subprotocol selection");
ok(true, "test 28 protocol array close");
resolve();
}
});
}
function test29() {
return new Promise(function(resolve, reject) {
var prots=["test29a", "test29b"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 29 protocol array open");
ws.close();
}
ws.onclose = function(e) {
ok(true, "test 29 protocol array close");
resolve();
}
});
}
function test30() {
return new Promise(function(resolve, reject) {
var prots=["test-does-not-exist"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = shouldNotOpen;
ws.onclose = function(e) {
shouldCloseNotCleanly(e);
resolve();
}
ws.onerror = function() {
}
});
}
var tests = [
test21, // see bug 572975 - same as test 17, but delete strong event listeners
// when receiving the message event;
@ -216,6 +31,10 @@ function testWebSocket() {
doTest();
}
SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
"Expect all sorts of flakiness in this test...");
SimpleTest.waitForExplicitFinish();
</script>
<div id="feedback">

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

@ -5,264 +5,12 @@
<title>WebSocket test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="websocket_helpers.js"></script>
<script type="text/javascript" src="websocket_tests.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="testWebSocket()">
<script class="testbody" type="text/javascript">
function test31() {
return new Promise(function(resolve, reject) {
var prots=["test-does-not-exist", "test31"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 31 protocol array open");
ws.close();
}
ws.onclose = function(e) {
is(ws.protocol, "test31", "test31 subprotocol selection");
ok(true, "test 31 protocol array close");
resolve();
}
});
}
function test32() {
return new Promise(function(resolve, reject) {
var prots=["test32","test32"];
try {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ok(false, "testing duplicated element sub protocol array");
} catch (e) {
ok(true, "testing duplicated sub element protocol array");
}
resolve();
});
}
function test33() {
return new Promise(function(resolve, reject) {
var prots=["test33"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 33 open");
ws.close(3131); // pass code but not reason
}
ws.onclose = function(e) {
ok(true, "test 33 close");
shouldCloseCleanly(e);
is(e.code, 3131, "test 33 got wrong close code: " + e.code);
is(e.reason, "", "test 33 got wrong close reason: " + e.reason);
resolve();
}
});
}
function test34() {
return new Promise(function(resolve, reject) {
var prots=["test-34"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 34 open");
ws.close();
}
ws.onclose = function(e)
{
ok(true, "test 34 close");
ok(e.wasClean, "test 34 closed cleanly");
is(e.code, 1001, "test 34 custom server code");
is(e.reason, "going away now", "test 34 custom server reason");
resolve();
}
});
}
function test35() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-35a");
ws.onopen = function(e) {
ok(true, "test 35a open");
ws.close(3500, "my code");
}
ws.onclose = function(e) {
ok(true, "test 35a close");
ok(e.wasClean, "test 35a closed cleanly");
var wsb = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-35b");
wsb.onopen = function(e) {
ok(true, "test 35b open");
wsb.close();
}
wsb.onclose = function(e) {
ok(true, "test 35b close");
ok(e.wasClean, "test 35b closed cleanly");
is(e.code, 3501, "test 35 custom server code");
is(e.reason, "my code", "test 35 custom server reason");
resolve();
}
}
});
}
function test36() {
return new Promise(function(resolve, reject) {
var prots=["test-36"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 36 open");
try {
ws.close(13200);
ok(false, "testing custom close code out of range");
} catch (e) {
ok(true, "testing custom close code out of range");
ws.close(3200);
}
}
ws.onclose = function(e) {
ok(true, "test 36 close");
ok(e.wasClean, "test 36 closed cleanly");
resolve();
}
});
}
function test37() {
return new Promise(function(resolve, reject) {
var prots=["test-37"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 37 open");
try {
ws.close(3100,"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123");
ok(false, "testing custom close reason out of range");
} catch (e) {
ok(true, "testing custom close reason out of range");
ws.close(3100,"012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012");
}
}
ws.onclose = function(e) {
ok(true, "test 37 close");
ok(e.wasClean, "test 37 closed cleanly");
var wsb = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-37b");
wsb.onopen = function(e) {
// now test that a rejected close code and reason dont persist
ok(true, "test 37b open");
try {
wsb.close(3101,"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123");
ok(false, "testing custom close reason out of range 37b");
} catch (e) {
ok(true, "testing custom close reason out of range 37b");
wsb.close();
}
}
wsb.onclose = function(e) {
ok(true, "test 37b close");
ok(e.wasClean, "test 37b closed cleanly");
var wsc = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-37c");
wsc.onopen = function(e) {
ok(true, "test 37c open");
wsc.close();
}
wsc.onclose = function(e) {
isnot(e.code, 3101, "test 37c custom server code not present");
is(e.reason, "", "test 37c custom server reason not present");
resolve();
}
}
}
});
}
function test38() {
return new Promise(function(resolve, reject) {
var prots=["test-38"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 38 open");
isnot(ws.extensions, undefined, "extensions attribute defined");
// is(ws.extensions, "deflate-stream", "extensions attribute deflate-stream");
ws.close();
}
ws.onclose = function(e) {
ok(true, "test 38 close");
resolve();
}
});
}
function test39() {
return new Promise(function(resolve, reject) {
var prots=["test-39"];
var ws = CreateTestWS("wss://example.com/tests/dom/base/test/file_websocket", prots);
status_test39 = "started";
ws.onopen = function(e) {
status_test39 = "opened";
ok(true, "test 39 open");
ws.close();
}
ws.onclose = function(e) {
ok(true, "test 39 close");
is(status_test39, "opened", "test 39 did open");
resolve();
}
});
}
function test40() {
return new Promise(function(resolve, reject) {
var prots=["test-40"];
var ws = CreateTestWS("wss://nocert.example.com/tests/dom/base/test/file_websocket", prots);
status_test40 = "started";
ws.onerror = ignoreError;
ws.onopen = function(e) {
status_test40 = "opened";
ok(false, "test 40 open");
ws.close();
}
ws.onclose = function(e) {
ok(true, "test 40 close");
is(status_test40, "started", "test 40 did not open");
resolve();
}
});
}
var tests = [
test31, // ctor using valid 2 element sub-protocol array with 1 element server
// will reject and one server will accept
@ -281,6 +29,10 @@ function testWebSocket() {
doTest();
}
SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
"Expect all sorts of flakiness in this test...");
SimpleTest.waitForExplicitFinish();
</script>
<div id="feedback">

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

@ -5,271 +5,12 @@
<title>WebSocket test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="websocket_helpers.js"></script>
<script type="text/javascript" src="websocket_tests.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body onload="testWebSocket()">
<script class="testbody" type="text/javascript">
function test41() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://example.com/tests/dom/base/test/file_websocket", "test-41a", 1);
ws.onopen = function(e) {
ok(true, "test 41a open");
is(ws.url, "ws://example.com/tests/dom/base/test/file_websocket",
"test 41a initial ws should not be redirected");
ws.close();
}
ws.onclose = function(e) {
ok(true, "test 41a close");
// establish a hsts policy for example.com
var wsb = CreateTestWS("wss://example.com/tests/dom/base/test/file_websocket", "test-41b", 1);
wsb.onopen = function(e) {
ok(true, "test 41b open");
wsb.close();
}
wsb.onclose = function(e) {
ok(true, "test 41b close");
// try ws:// again, it should be done over wss:// now due to hsts
var wsc = CreateTestWS("ws://example.com/tests/dom/base/test/file_websocket", "test-41c");
wsc.onopen = function(e) {
ok(true, "test 41c open");
is(wsc.url, "wss://example.com/tests/dom/base/test/file_websocket",
"test 41c ws should be redirected by hsts to wss");
wsc.close();
}
wsc.onclose = function(e) {
ok(true, "test 41c close");
// clean up the STS state
const Ci = SpecialPowers.Ci;
var loadContext = SpecialPowers.wrap(window)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsILoadContext);
var flags = 0;
if (loadContext.usePrivateBrowsing)
flags |= Ci.nsISocketProvider.NO_PERMANENT_STORAGE;
SpecialPowers.cleanUpSTSData("http://example.com", flags);
resolve();
}
}
}
});
}
function test42() {
return new Promise(function(resolve, reject) {
// test some utf-8 non-characters. They should be allowed in the
// websockets context. Test via round trip echo.
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-42");
var data = ["U+FFFE \ufffe",
"U+FFFF \uffff",
"U+10FFFF \udbff\udfff"];
var index = 0;
ws.onopen = function() {
ws.send(data[0]);
ws.send(data[1]);
ws.send(data[2]);
}
ws.onmessage = function(e) {
is(e.data, data[index], "bad received message in test-42! index="+index);
index++;
if (index == 3) {
ws.close();
}
}
ws.onclose = function(e) {
resolve();
}
});
}
function test43() {
return new Promise(function(resolve, reject) {
var prots=["test-43"];
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", prots);
ws.onopen = function(e) {
ok(true, "test 43 open");
// Test binaryType setting
ws.binaryType = "arraybuffer";
ws.binaryType = "blob";
ws.binaryType = ""; // illegal
is(ws.binaryType, "blob");
ws.binaryType = "ArrayBuffer"; // illegal
is(ws.binaryType, "blob");
ws.binaryType = "Blob"; // illegal
is(ws.binaryType, "blob");
ws.binaryType = "mcfoofluu"; // illegal
is(ws.binaryType, "blob");
ws.close();
}
ws.onclose = function(e) {
ok(true, "test 43 close");
resolve();
}
});
}
function test44() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-44");
is(ws.readyState, 0, "bad readyState in test-44!");
ws.binaryType = "arraybuffer";
ws.onopen = function() {
is(ws.readyState, 1, "open bad readyState in test-44!");
var buf = new ArrayBuffer(3);
// create byte view
var view = new Uint8Array(buf);
view[0] = 5;
view[1] = 0; // null byte
view[2] = 7;
ws.send(buf);
}
ws.onmessage = function(e) {
ok(e.data instanceof ArrayBuffer, "Should receive an arraybuffer!");
var view = new Uint8Array(e.data);
ok(view.length == 2 && view[0] == 0 && view[1] ==4, "testing Reply arraybuffer" );
ws.close();
}
ws.onclose = function(e) {
is(ws.readyState, 3, "onclose bad readyState in test-44!");
shouldCloseCleanly(e);
resolve();
}
});
}
function test45()
{
return new Promise(function(resolve, reject) {
function test45Real(blobFile) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-45");
is(ws.readyState, 0, "bad readyState in test-45!");
// ws.binaryType = "blob"; // Don't need to specify: blob is the default
ws.onopen = function() {
is(ws.readyState, 1, "open bad readyState in test-45!");
ws.send(blobFile);
}
var test45blob;
ws.onmessage = function(e) {
test45blob = e.data;
ok(test45blob instanceof Blob, "We should be receiving a Blob");
ws.close();
}
ws.onclose = function(e) {
is(ws.readyState, 3, "onclose bad readyState in test-45!");
shouldCloseCleanly(e);
// check blob contents
var reader = new FileReader();
reader.onload = function(event) {
is(reader.result, "flob", "response should be 'flob': got '"
+ reader.result + "'");
}
reader.onerror = function(event) {
testFailed("Failed to read blob: error code = " + reader.error.code);
}
reader.onloadend = function(event) {
resolve();
}
reader.readAsBinaryString(test45blob);
}
}
SpecialPowers.createFiles([{name: "testBlobFile", data: "flob"}],
function(files) {
test45Real(files[0]);
},
function(msg) {
testFailed("Failed to create file for test45: " + msg);
resolve();
});
});
}
function test46() {
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-46");
is(ws.readyState, 0, "create bad readyState in test-46!");
ws.onopen = function() {
is(ws.readyState, 1, "open bad readyState in test-46!");
ws.close()
is(ws.readyState, 2, "close must set readyState to 2 in test-46!");
}
ws.onmessage = function(e) {
ok(false, "received message after calling close in test-46!");
}
ws.onclose = function(e) {
is(ws.readyState, 3, "onclose bad readyState in test-46!");
shouldCloseCleanly(e);
resolve();
}
});
}
function test47() {
return new Promise(function(resolve, reject) {
var hasError = false;
var ws = CreateTestWS("ws://another.websocket.server.that.probably.does.not.exist");
ws.onopen = shouldNotOpen;
ws.onerror = function (e) {
is(ws.readyState, 3, "test-47: readyState should be CLOSED(3) in onerror: got "
+ ws.readyState);
ok(!ws._withinClose, "onerror() called during close()!");
hasError = true;
}
ws.onclose = function(e) {
shouldCloseNotCleanly(e);
ok(hasError, "test-47: should have called onerror before onclose");
is(ws.readyState, 3, "test-47: readyState should be CLOSED(3) in onclose: got "
+ ws.readyState);
ok(!ws._withinClose, "onclose() called during close()!");
is(e.code, 1006, "test-47 close code should be 1006 but is:" + e.code);
resolve();
}
// Call close before we're connected: throws error
// Make sure we call onerror/onclose asynchronously
ws._withinClose = 1;
ws.close(3333, "Closed before we were open: error");
ws._withinClose = 0;
is(ws.readyState, 2, "test-47: readyState should be CLOSING(2) after close(): got "
+ ws.readyState);
});
}
var tests = [
test41, // HSTS
test42, // non-char utf-8 sequences
@ -284,6 +25,10 @@ function testWebSocket() {
doTest();
}
SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
"Expect all sorts of flakiness in this test...");
SimpleTest.waitForExplicitFinish();
</script>
<div id="feedback">

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

@ -47,16 +47,20 @@ function forcegc() {
SpecialPowers.gc();
}
function feedback() {
$("feedback").innerHTML = "executing test: " + (current_test+1) + " of " + tests.length + " tests.";
}
function finish() {
SimpleTest.finish();
}
function doTest() {
if (current_test >= tests.length) {
SimpleTest.finish();
finish();
return;
}
$("feedback").innerHTML = "executing test: " + (current_test+1) + " of " + tests.length + " tests.";
feedback();
tests[current_test++]().then(doTest);
}
SimpleTest.requestFlakyTimeout("The web socket tests are really fragile, but avoiding timeouts might be hard, since it's testing stuff on the network. " +
"Expect all sorts of flakiness in this test...");
SimpleTest.waitForExplicitFinish();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -140,15 +140,18 @@ BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInf
doc->NodePrincipal()->GetAppStatus(&status);
}
mCharging = aBatteryInfo.charging();
mRemainingTime = aBatteryInfo.remainingTime();
if (!nsContentUtils::IsChromeDoc(doc) &&
status != nsIPrincipal::APP_STATUS_CERTIFIED)
{
mLevel = lround(mLevel * 10.0) / 10.0;
if (mLevel == 1.0) {
mRemainingTime = mCharging ? kDefaultRemainingTime : kUnknownRemainingTime;
}
}
mCharging = aBatteryInfo.charging();
mRemainingTime = aBatteryInfo.remainingTime();
// Add some guards to make sure the values are coherent.
if (mLevel == 1.0 && mCharging == true &&
mRemainingTime != kDefaultRemainingTime) {

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

@ -3499,13 +3499,9 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
virtual nscoord GetWidth()
{
gfxTextRun::Metrics textRunMetrics = mTextRun->MeasureText(0,
mTextRun->GetLength(),
mDoMeasureBoundingBox ?
gfxFont::TIGHT_INK_EXTENTS :
gfxFont::LOOSE_INK_EXTENTS,
mDrawTarget,
nullptr);
gfxTextRun::Metrics textRunMetrics = mTextRun->MeasureText(
mDoMeasureBoundingBox ? gfxFont::TIGHT_INK_EXTENTS
: gfxFont::LOOSE_INK_EXTENTS, mDrawTarget);
// this only measures the height; the total width is gotten from the
// the return value of ProcessText.
@ -3535,13 +3531,10 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
// glyph string on OS X and DWrite where textrun widths may
// involve fractional pixels.
gfxTextRun::Metrics textRunMetrics =
mTextRun->MeasureText(0,
mTextRun->GetLength(),
mDoMeasureBoundingBox ?
gfxFont::TIGHT_INK_EXTENTS :
gfxFont::LOOSE_INK_EXTENTS,
mDrawTarget,
nullptr);
mTextRun->MeasureText(mDoMeasureBoundingBox ?
gfxFont::TIGHT_INK_EXTENTS :
gfxFont::LOOSE_INK_EXTENTS,
mDrawTarget);
inlineCoord += textRunMetrics.mAdvanceWidth;
// old code was:
// point.x += width * mAppUnitsPerDevPixel;

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

@ -26,7 +26,9 @@ class WebGLContextLossHandler : public dom::workers::WorkerFeature
bool mShouldRunTimerAgain;
bool mIsDisabled;
bool mFeatureAdded;
DebugOnly<nsIThread*> mThread;
#ifdef DEBUG
nsIThread* mThread;
#endif
public:
NS_INLINE_DECL_REFCOUNTING(WebGLContextLossHandler)

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

@ -1332,24 +1332,16 @@ private:
class ImportKeyTask : public WebCryptoTask
{
public:
void Init(JSContext* aCx,
const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
void Init(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat, const ObjectOrString& aAlgorithm,
bool aExtractable, const Sequence<nsString>& aKeyUsages)
{
mFormat = aFormat;
mDataIsSet = false;
mDataIsJwk = false;
// Get the current global object from the context
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
if (!global) {
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
return;
}
// This stuff pretty much always happens, so we'll do it here
mKey = new CryptoKey(global);
mKey = new CryptoKey(aGlobal);
mKey->SetExtractable(aExtractable);
mKey->ClearUsages();
for (uint32_t i = 0; i < aKeyUsages.Length(); ++i) {
@ -1472,20 +1464,20 @@ private:
class ImportSymmetricKeyTask : public ImportKeyTask
{
public:
ImportSymmetricKeyTask(JSContext* aCx,
ImportSymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
}
ImportSymmetricKeyTask(JSContext* aCx,
ImportSymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat, const JS::Handle<JSObject*> aKeyData,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
@ -1498,12 +1490,11 @@ public:
}
}
void Init(JSContext* aCx,
const nsAString& aFormat,
void Init(nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
@ -1630,20 +1621,20 @@ private:
class ImportRsaKeyTask : public ImportKeyTask
{
public:
ImportRsaKeyTask(JSContext* aCx,
ImportRsaKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
}
ImportRsaKeyTask(JSContext* aCx,
ImportRsaKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat, JS::Handle<JSObject*> aKeyData,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
@ -1656,12 +1647,12 @@ public:
}
}
void Init(JSContext* aCx,
void Init(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
@ -1798,19 +1789,19 @@ private:
class ImportEcKeyTask : public ImportKeyTask
{
public:
ImportEcKeyTask(JSContext* aCx, const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
ImportEcKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat, const ObjectOrString& aAlgorithm,
bool aExtractable, const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
}
ImportEcKeyTask(JSContext* aCx, const nsAString& aFormat,
JS::Handle<JSObject*> aKeyData,
ImportEcKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat, JS::Handle<JSObject*> aKeyData,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
@ -1819,11 +1810,11 @@ public:
NS_ENSURE_SUCCESS_VOID(mEarlyRv);
}
void Init(JSContext* aCx, const nsAString& aFormat,
void Init(nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
@ -1951,30 +1942,30 @@ private:
class ImportDhKeyTask : public ImportKeyTask
{
public:
ImportDhKeyTask(JSContext* aCx, const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
ImportDhKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat, const ObjectOrString& aAlgorithm,
bool aExtractable, const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
}
ImportDhKeyTask(JSContext* aCx, const nsAString& aFormat,
JS::Handle<JSObject*> aKeyData,
ImportDhKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const nsAString& aFormat, JS::Handle<JSObject*> aKeyData,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_SUCCEEDED(mEarlyRv)) {
SetKeyData(aCx, aKeyData);
NS_ENSURE_SUCCESS_VOID(mEarlyRv);
}
}
void Init(JSContext* aCx, const nsAString& aFormat,
void Init(nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
if (NS_FAILED(mEarlyRv)) {
return;
}
@ -2197,18 +2188,12 @@ private:
class GenerateSymmetricKeyTask : public WebCryptoTask
{
public:
GenerateSymmetricKeyTask(JSContext* aCx,
GenerateSymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
{
nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
if (!global) {
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
return;
}
// Create an empty key and set easy attributes
mKey = new CryptoKey(global);
mKey = new CryptoKey(aGlobal);
mKey->SetExtractable(aExtractable);
mKey->SetType(CryptoKey::SECRET);
@ -2326,16 +2311,10 @@ private:
};
GenerateAsymmetricKeyTask::GenerateAsymmetricKeyTask(
JSContext* aCx, const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
nsIGlobalObject* aGlobal, JSContext* aCx, const ObjectOrString& aAlgorithm,
bool aExtractable, const Sequence<nsString>& aKeyUsages)
: mKeyPair(new CryptoKeyPair())
{
nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
if (!global) {
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
return;
}
mArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!mArena) {
mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
@ -2343,8 +2322,8 @@ GenerateAsymmetricKeyTask::GenerateAsymmetricKeyTask(
}
// Create an empty key pair and set easy attributes
mKeyPair->mPrivateKey = new CryptoKey(global);
mKeyPair->mPublicKey = new CryptoKey(global);
mKeyPair->mPrivateKey = new CryptoKey(aGlobal);
mKeyPair->mPublicKey = new CryptoKey(aGlobal);
// Extract algorithm name
mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, mAlgName);
@ -2853,7 +2832,7 @@ template<class DeriveBitsTask>
class DeriveKeyTask : public DeriveBitsTask
{
public:
DeriveKeyTask(JSContext* aCx,
DeriveKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
const ObjectOrString& aDerivedKeyType, bool aExtractable,
const Sequence<nsString>& aKeyUsages)
@ -2865,7 +2844,7 @@ public:
}
NS_NAMED_LITERAL_STRING(format, WEBCRYPTO_KEY_FORMAT_RAW);
mTask = new ImportSymmetricKeyTask(aCx, format, aDerivedKeyType,
mTask = new ImportSymmetricKeyTask(aGlobal, aCx, format, aDerivedKeyType,
aExtractable, aKeyUsages);
}
@ -3295,7 +3274,8 @@ WebCryptoTask::CreateDigestTask(JSContext* aCx,
}
WebCryptoTask*
WebCryptoTask::CreateImportKeyTask(JSContext* aCx,
WebCryptoTask::CreateImportKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const nsAString& aFormat,
JS::Handle<JSObject*> aKeyData,
const ObjectOrString& aAlgorithm,
@ -3333,19 +3313,19 @@ WebCryptoTask::CreateImportKeyTask(JSContext* aCx,
algName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_HKDF) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
return new ImportSymmetricKeyTask(aGlobal, aCx, aFormat, aKeyData,
aAlgorithm, aExtractable, aKeyUsages);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
return new ImportRsaKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
return new ImportRsaKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
return new ImportEcKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
return new ImportEcKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else if (algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
return new ImportDhKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
return new ImportDhKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm,
aExtractable, aKeyUsages);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@ -3394,7 +3374,8 @@ WebCryptoTask::CreateExportKeyTask(const nsAString& aFormat,
}
WebCryptoTask*
WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
WebCryptoTask::CreateGenerateKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const ObjectOrString& aAlgorithm,
bool aExtractable,
const Sequence<nsString>& aKeyUsages)
@ -3420,21 +3401,24 @@ WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
algName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
algName.EqualsASCII(WEBCRYPTO_ALG_AES_KW) ||
algName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
return new GenerateSymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
return new GenerateSymmetricKeyTask(aGlobal, aCx, aAlgorithm, aExtractable,
aKeyUsages);
} else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
algName.EqualsASCII(WEBCRYPTO_ALG_RSA_PSS) ||
algName.EqualsASCII(WEBCRYPTO_ALG_ECDH) ||
algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA) ||
algName.EqualsASCII(WEBCRYPTO_ALG_DH)) {
return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
return new GenerateAsymmetricKeyTask(aGlobal, aCx, aAlgorithm, aExtractable,
aKeyUsages);
} else {
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
}
WebCryptoTask*
WebCryptoTask::CreateDeriveKeyTask(JSContext* aCx,
WebCryptoTask::CreateDeriveKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const ObjectOrString& aAlgorithm,
CryptoKey& aBaseKey,
const ObjectOrString& aDerivedKeyType,
@ -3460,21 +3444,21 @@ WebCryptoTask::CreateDeriveKeyTask(JSContext* aCx,
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_HKDF)) {
return new DeriveKeyTask<DeriveHkdfBitsTask>(aCx, aAlgorithm, aBaseKey,
aDerivedKeyType, aExtractable,
aKeyUsages);
return new DeriveKeyTask<DeriveHkdfBitsTask>(aGlobal, aCx, aAlgorithm,
aBaseKey, aDerivedKeyType,
aExtractable, aKeyUsages);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
return new DeriveKeyTask<DerivePbkdfBitsTask>(aCx, aAlgorithm, aBaseKey,
aDerivedKeyType, aExtractable,
aKeyUsages);
return new DeriveKeyTask<DerivePbkdfBitsTask>(aGlobal, aCx, aAlgorithm,
aBaseKey, aDerivedKeyType,
aExtractable, aKeyUsages);
}
if (algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
return new DeriveKeyTask<DeriveEcdhBitsTask>(aCx, aAlgorithm, aBaseKey,
aDerivedKeyType, aExtractable,
aKeyUsages);
return new DeriveKeyTask<DeriveEcdhBitsTask>(aGlobal, aCx, aAlgorithm,
aBaseKey, aDerivedKeyType,
aExtractable, aKeyUsages);
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
@ -3568,7 +3552,8 @@ WebCryptoTask::CreateWrapKeyTask(JSContext* aCx,
}
WebCryptoTask*
WebCryptoTask::CreateUnwrapKeyTask(JSContext* aCx,
WebCryptoTask::CreateUnwrapKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const nsAString& aFormat,
const ArrayBufferViewOrArrayBuffer& aWrappedKey,
CryptoKey& aUnwrappingKey,
@ -3602,13 +3587,13 @@ WebCryptoTask::CreateUnwrapKeyTask(JSContext* aCx,
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_HKDF) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
importTask = new ImportSymmetricKeyTask(aCx, aFormat,
importTask = new ImportSymmetricKeyTask(aGlobal, aCx, aFormat,
aUnwrappedKeyAlgorithm,
aExtractable, aKeyUsages);
} else if (keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_PSS)) {
importTask = new ImportRsaKeyTask(aCx, aFormat,
importTask = new ImportRsaKeyTask(aGlobal, aCx, aFormat,
aUnwrappedKeyAlgorithm,
aExtractable, aKeyUsages);
} else {

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

@ -122,7 +122,8 @@ public:
const ObjectOrString& aAlgorithm,
const CryptoOperationData& aData);
static WebCryptoTask* CreateImportKeyTask(JSContext* aCx,
static WebCryptoTask* CreateImportKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const nsAString& aFormat,
JS::Handle<JSObject*> aKeyData,
const ObjectOrString& aAlgorithm,
@ -130,12 +131,14 @@ public:
const Sequence<nsString>& aKeyUsages);
static WebCryptoTask* CreateExportKeyTask(const nsAString& aFormat,
CryptoKey& aKey);
static WebCryptoTask* CreateGenerateKeyTask(JSContext* aCx,
static WebCryptoTask* CreateGenerateKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const ObjectOrString& aAlgorithm,
bool aExtractable,
const Sequence<nsString>& aKeyUsages);
static WebCryptoTask* CreateDeriveKeyTask(JSContext* aCx,
static WebCryptoTask* CreateDeriveKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const ObjectOrString& aAlgorithm,
CryptoKey& aBaseKey,
const ObjectOrString& aDerivedKeyType,
@ -151,7 +154,8 @@ public:
CryptoKey& aKey,
CryptoKey& aWrappingKey,
const ObjectOrString& aWrapAlgorithm);
static WebCryptoTask* CreateUnwrapKeyTask(JSContext* aCx,
static WebCryptoTask* CreateUnwrapKeyTask(nsIGlobalObject* aGlobal,
JSContext* aCx,
const nsAString& aFormat,
const ArrayBufferViewOrArrayBuffer& aWrappedKey,
CryptoKey& aUnwrappingKey,
@ -228,7 +232,7 @@ private:
class GenerateAsymmetricKeyTask : public WebCryptoTask
{
public:
GenerateAsymmetricKeyTask(JSContext* aCx,
GenerateAsymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
const ObjectOrString& aAlgorithm, bool aExtractable,
const Sequence<nsString>& aKeyUsages);
protected:

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

@ -987,6 +987,52 @@ TestArray.addTest(
doCheckRSASSA().then(error(that), complete(that));
}
);
// -----------------------------------------------------------------------------
TestArray.addTest(
"Test that we're using the right globals when creating objects",
function() {
var that = this;
var data = crypto.getRandomValues(new Uint8Array(10));
var hmacAlg = {name: "HMAC", length: 256, hash: "SHA-1"};
var rsaAlg = {
name: "RSA-PSS",
hash: "SHA-1",
modulusLength: 1024,
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
function checkPrototypes(obj, type) {
return obj.__proto__ != window[type].prototype &&
obj.__proto__ == frames[0][type].prototype
}
var p1 = crypto.subtle.importKey.call(
frames[0].crypto.subtle, "raw", data, hmacAlg, false, ["sign", "verify"]);
var p2 = crypto.subtle.generateKey.call(
frames[0].crypto.subtle, hmacAlg, false, ["sign", "verify"]);
var p3 = crypto.subtle.generateKey.call(
frames[0].crypto.subtle, rsaAlg, false, ["sign", "verify"]);
if (!checkPrototypes(p1, "Promise") ||
!checkPrototypes(p2, "Promise") ||
!checkPrototypes(p3, "Promise")) {
error(that)();
}
Promise.all([p1, p2, p3]).then(complete(that, keys => {
return keys.every(key => {
if (key instanceof CryptoKey) {
return checkPrototypes(key, "CryptoKey");
}
return checkPrototypes(key.publicKey, "CryptoKey") &&
checkPrototypes(key.privateKey, "CryptoKey");
});
}), error(that));
}
);
/*]]>*/</script>
</head>
@ -997,6 +1043,7 @@ TestArray.addTest(
<b>Web</b>Crypto<br>
</div>
<iframe style="display: none;"></iframe>
<div id="start" onclick="start();">RUN ALL</div>
<div id="resultDiv" class="content">

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

@ -658,10 +658,9 @@ ContentEventHandler::AppendFontRanges(FontRangeArray& aFontRanges,
}
}
uint32_t skipStart = iter.ConvertOriginalToSkipped(frameXPStart);
uint32_t skipEnd = iter.ConvertOriginalToSkipped(frameXPEnd);
gfxTextRun::GlyphRunIterator runIter(
textRun, skipStart, skipEnd - skipStart);
gfxTextRun::Range skipRange(iter.ConvertOriginalToSkipped(frameXPStart),
iter.ConvertOriginalToSkipped(frameXPEnd));
gfxTextRun::GlyphRunIterator runIter(textRun, skipRange);
int32_t lastXPEndOffset = frameXPStart;
while (runIter.NextRun()) {
gfxFont* font = runIter.GetGlyphRun()->mFont.get();

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

@ -39,13 +39,13 @@
</div>
</div>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(runTests, window);
SimpleTest.waitForFocus(runTest, window);
var gScrollableElement = document.getElementById("scrollable");
var gScrolledElement = document.getElementById("scrolled");
@ -55,42 +55,43 @@ var gHorizontalLine = 0;
var gPageHeight = 0;
var gPageWidth = 0;
function prepareScrollUnits()
function* prepareScrollUnits()
{
var result = -1;
function handler(aEvent)
{
result = aEvent.detail;
aEvent.preventDefault();
setTimeout(continueTest, 0);
}
window.addEventListener("MozMousePixelScroll", handler, true);
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaY: 1.0, lineOrPageDeltaY: 1 });
yield synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaY: 1.0, lineOrPageDeltaY: 1 });
gLineHeight = result;
ok(gLineHeight > 10 && gLineHeight < 25, "prepareScrollUnits: gLineHeight may be illegal value, got " + gLineHeight);
result = -1;
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, lineOrPageDeltaX: 1 });
yield synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, lineOrPageDeltaX: 1 });
gHorizontalLine = result;
ok(gHorizontalLine > 5 && gHorizontalLine < 16, "prepareScrollUnits: gHorizontalLine may be illegal value, got " + gHorizontalLine);
result = -1;
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaY: 1.0, lineOrPageDeltaY: 1 });
yield synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaY: 1.0, lineOrPageDeltaY: 1 });
gPageHeight = result;
// XXX Cannot we know the actual scroll port size?
ok(gPageHeight >= 150 && gPageHeight <= 200,
"prepareScrollUnits: gPageHeight is strange value, got " + gPageHeight);
result = -1;
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 1.0, lineOrPageDeltaX: 1 });
yield synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_PAGE,
deltaX: 1.0, lineOrPageDeltaX: 1 });
gPageWidth = result;
ok(gPageWidth >= 150 && gPageWidth <= 200,
"prepareScrollUnits: gPageWidth is strange value, got " + gPageWidth);
@ -123,7 +124,7 @@ function testMakingUntrustedEvent()
// delta_multiplier prefs should cause changing delta values of trusted events only.
// And also legacy events' detail value should be changed too.
function testDeltaMultiplierPrefs()
function* testDeltaMultiplierPrefs()
{
const kModifierAlt = 0x01;
const kModifierControl = 0x02;
@ -190,6 +191,7 @@ function testDeltaMultiplierPrefs()
];
var currentTest, currentModifiers, currentEvent, currentPref, currentMultiplier, testingExpected;
var expectedHandlerCalls;
var description;
var calledHandlers = { wheel: false,
DOMMouseScroll: { horizontal: false, vertical: false },
@ -215,9 +217,13 @@ function testDeltaMultiplierPrefs()
break;
}
}
is(aEvent.deltaX, expectedDeltaX, description + "deltaX (" + currentEvent.deltaX + ") was invaild");
is(aEvent.deltaY, expectedDeltaY, description + "deltaY (" + currentEvent.deltaY + ") was invaild");
is(aEvent.deltaZ, expectedDeltaZ, description + "deltaZ (" + currentEvent.deltaZ + ") was invaild");
is(aEvent.deltaX, expectedDeltaX, description + "deltaX (" + currentEvent.deltaX + ") was invalid");
is(aEvent.deltaY, expectedDeltaY, description + "deltaY (" + currentEvent.deltaY + ") was invalid");
is(aEvent.deltaZ, expectedDeltaZ, description + "deltaZ (" + currentEvent.deltaZ + ") was invalid");
if (--expectedHandlerCalls == 0) {
setTimeout(continueTest, 0);
}
}
function legacyEventHandler(aEvent) {
@ -276,13 +282,17 @@ function testDeltaMultiplierPrefs()
is(aEvent.detail, expectedDetail, description + eventName + "detail was invalid");
aEvent.preventDefault();
if (--expectedHandlerCalls == 0) {
setTimeout(continueTest, 0);
}
}
window.addEventListener("wheel", wheelEventHandler, true);
window.addEventListener("DOMMouseScroll", legacyEventHandler, true);
window.addEventListener("MozMousePixelScroll", legacyEventHandler, true);
function dispatchEvent(aIsExpected) {
function* dispatchEvent(aIsExpected) {
for (var i = 0; i < kEvents.length; i++) {
currentEvent = kEvents[i];
currentEvent.shiftKey = (currentModifiers & kModifierShift) != 0;
@ -312,17 +322,13 @@ function testDeltaMultiplierPrefs()
for (var k = 0; k < kDeltaMultiplierPrefs.length; k++) {
currentPref = "mousewheel." + currentTest.name + "." + kDeltaMultiplierPrefs[k];
SpecialPowers.setIntPref(currentPref, kPrefValues[j]);
yield SpecialPowers.pushPrefEnv({"set": [[currentPref, kPrefValues[j]]]}, continueTest);
gScrollableElement.scrollTop = gScrollableElement.scrollBottom = 1000;
// trusted event's delta valuses should be reverted by the pref.
testingExpected = aIsExpected;
description = "testDeltaMultiplierPrefs, pref: " + currentPref + "=" + kPrefValues[j] +
", deltaMode: " + currentEvent.deltaMode + ", modifiers: \"" + modifierList + "\", (trusted event): ";
synthesizeWheel(gScrollableElement, 10, 10, currentEvent);
var expectedProps = {
deltaX: currentEvent.deltaX * currentMultiplier,
deltaY: currentEvent.deltaY * currentMultiplier,
@ -331,20 +337,37 @@ function testDeltaMultiplierPrefs()
lineOrPageDeltaY: currentEvent.lineOrPageDeltaY * currentMultiplier,
};
var expectedWheel = expectedProps.deltaX != 0 || expectedProps.deltaY != 0 || expectedProps.deltaZ != 0;
var expectedDOMMouseX = expectedProps.lineOrPageDeltaX >= 1 || expectedProps.lineOrPageDeltaX <= -1;
var expectedDOMMouseY = expectedProps.lineOrPageDeltaY >= 1 || expectedProps.lineOrPageDeltaY <= -1;
var expectedMozMouseX = expectedProps.deltaX >= 1 || expectedProps.deltaX <= -1;
var expectedMozMouseY = expectedProps.deltaY >= 1 || expectedProps.deltaY <= -1;
expectedHandlerCalls = 0;
if (expectedWheel) ++expectedHandlerCalls;
if (expectedDOMMouseX) ++expectedHandlerCalls;
if (expectedDOMMouseY) ++expectedHandlerCalls;
if (expectedMozMouseX) ++expectedHandlerCalls;
if (expectedMozMouseY) ++expectedHandlerCalls;
description = "testDeltaMultiplierPrefs, pref: " + currentPref + "=" + kPrefValues[j] +
", deltaMode: " + currentEvent.deltaMode + ", modifiers: \"" + modifierList + "\", (trusted event): ";
yield synthesizeWheel(gScrollableElement, 10, 10, currentEvent);
is(calledHandlers.wheel,
expectedProps.deltaX != 0 || expectedProps.deltaY != 0 || expectedProps.deltaZ != 0,
expectedWheel,
description + "wheel event was (not) fired");
is(calledHandlers.DOMMouseScroll.horizontal,
expectedProps.lineOrPageDeltaX >= 1 || expectedProps.lineOrPageDeltaX <= -1,
expectedDOMMouseX,
description + "Horizontal DOMMouseScroll event was (not) fired");
is(calledHandlers.DOMMouseScroll.vertical,
expectedProps.lineOrPageDeltaY >= 1 || expectedProps.lineOrPageDeltaY <= -1,
expectedDOMMouseY,
description + "Vertical DOMMouseScroll event was (not) fired");
is(calledHandlers.MozMousePixelScroll.horizontal,
expectedProps.deltaY >= 1 || expectedProps.deltaY <= -1,
expectedMozMouseX,
description + "Horizontal MozMousePixelScroll event was (not) fired");
is(calledHandlers.MozMousePixelScroll.vertical,
expectedProps.deltaY >= 1 || expectedProps.deltaY <= -1,
expectedMozMouseY,
description + "Vertical MozMousePixelScroll event was (not) fired");
calledHandlers = { wheel: false,
@ -381,7 +404,7 @@ function testDeltaMultiplierPrefs()
ok(!calledHandlers.MozMousePixelScroll.vertical,
description + "Vertical MozMousePixelScroll event was fired for untrusted event");
SpecialPowers.setIntPref(currentPref, 100);
yield SpecialPowers.pushPrefEnv({"set": [[currentPref, 100]]}, continueTest);
calledHandlers = { wheel: false,
DOMMouseScroll: { horizontal: false, vertical: false },
@ -401,11 +424,11 @@ function testDeltaMultiplierPrefs()
currentTest = kTests[i];
for (var j = 0; j < currentTest.expected.length; j++) {
currentModifiers = currentTest.expected[j];
dispatchEvent(true);
yield* dispatchEvent(true);
}
for (var k = 0; k < currentTest.unexpected.length; k++) {
currentModifiers = currentTest.unexpected[k];
dispatchEvent(false);
yield* dispatchEvent(false);
}
}
@ -468,7 +491,7 @@ function testDispatchingUntrustEvent()
window.removeEventListener("MozMousePixelScroll", legacyEventHandler, true);
}
function testEventOrder()
function* testEventOrder()
{
const kWheelEvent = 0x0001;
const kDOMMouseScrollEvent = 0x0002;
@ -615,21 +638,24 @@ function testEventOrder()
event |= kDefaultPrevented;
}
currentTest.resultEvents.push(event);
return event;
if (event == currentTest.doPreventDefaultAt) {
aEvent.preventDefault();
}
if (currentTest.resultEvents.length == currentTest.expectedEvents.length) {
setTimeout(continueTest, 0);
}
}
function handler(aEvent)
{
if (pushEvent(aEvent, false) == currentTest.doPreventDefaultAt) {
aEvent.preventDefault();
}
pushEvent(aEvent, false);
}
function systemHandler(aEvent)
{
if (pushEvent(aEvent, true) == currentTest.doPreventDefaultAt) {
aEvent.preventDefault();
}
pushEvent(aEvent, true);
}
window.addEventListener("wheel", handler, true);
@ -642,8 +668,8 @@ function testEventOrder()
for (var i = 0; i < kTests.length; i++) {
currentTest = kTests[i];
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE, deltaX: 1.0, deltaY: 1.0 });
yield synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE, deltaX: 1.0, deltaY: 1.0 });
for (var j = 0; j < currentTest.expectedEvents.length; j++) {
if (currentTest.resultEvents.length == j) {
@ -672,34 +698,54 @@ function testEventOrder()
}
var gOnWheelAttrHandled = new Array;
var gOnWheelAttrCount = 0;
function testOnWheelAttr()
function* testOnWheelAttr()
{
document.documentElement.setAttribute("onwheel", "gOnWheelAttrHandled['html'] = true;");
document.body.setAttribute("onwheel", "gOnWheelAttrHandled['body'] = true;");
gScrollableElement.setAttribute("onwheel", "gOnWheelAttrHandled['div'] = true;");
function onWheelHandledString(attr) {
return `gOnWheelAttrHandled['${attr}'] = true;
++gOnWheelAttrCount;
if (gOnWheelAttrCount == 3) {
setTimeout(continueTest, 0);
};`;
}
document.documentElement.setAttribute("onwheel", onWheelHandledString("html"));
document.body.setAttribute("onwheel", onWheelHandledString("body"));
gScrollableElement.setAttribute("onwheel", onWheelHandledString("div"));
var target = document.getElementById("onwheel");
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 2.0 });
yield synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 2.0 });
ok(gOnWheelAttrHandled['html'], "html element's onwheel attribute isn't performed");
ok(gOnWheelAttrHandled['body'], "body element's onwheel attribute isn't performed");
ok(gOnWheelAttrHandled['div'], "div element's onwheel attribute isn't performed");
}
var gOnWheelPropHandled = new Array;
var gOnWheelPropCount = 0;
function testOnWheelProperty()
function* testOnWheelProperty()
{
window.onwheel = function (e) { gOnWheelPropHandled["window"] = true; }
document.onwheel = function (e) { gOnWheelPropHandled["document"] = true; }
document.documentElement.onwheel = function (e) { gOnWheelPropHandled["html"] = true; };
document.body.onwheel = function (e) { gOnWheelPropHandled["body"] = true; };
gScrollableElement.onwheel = function (e) { gOnWheelPropHandled["div"] = true; };
const handleOnWheelProp = prop => e => {
gOnWheelPropHandled[prop] = true;
++gOnWheelPropCount;
if (gOnWheelPropCount == 5) {
setTimeout(continueTest, 0);
}
}
window.onwheel = handleOnWheelProp('window');
document.onwheel = handleOnWheelProp('document');
document.documentElement.onwheel = handleOnWheelProp('html');
document.body.onwheel = handleOnWheelProp('body');
gScrollableElement.onwheel = handleOnWheelProp('div');
var target = document.getElementById("onwheel");
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 2.0 });
yield synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 2.0 });
ok(gOnWheelPropHandled['window'], "window's onwheel property isn't performed");
ok(gOnWheelPropHandled['document'], "document's onwheel property isn't performed");
ok(gOnWheelPropHandled['html'], "html element's onwheel property isn't performed");
@ -707,57 +753,53 @@ function testOnWheelProperty()
ok(gOnWheelPropHandled['div'], "div element's onwheel property isn't performed");
}
function runTests()
function* testBody()
{
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_x", 100);
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_y", 100);
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_z", 100);
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_x", 100);
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_y", 100);
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_z", 100);
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_x", 100);
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_y", 100);
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_z", 100);
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_x", 100);
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_y", 100);
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_z", 100);
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_x", 100);
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_y", 100);
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_z", 100);
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_x", 100);
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_y", 100);
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_z", 100);
prepareScrollUnits();
yield* prepareScrollUnits();
testMakingUntrustedEvent();
testDeltaMultiplierPrefs();
yield* testDeltaMultiplierPrefs();
testDispatchingUntrustEvent();
testEventOrder();
testOnWheelAttr();
testOnWheelProperty();
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_x");
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_y");
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_z");
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_x");
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_y");
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_z");
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_x");
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_y");
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_z");
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_x");
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_y");
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_z");
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_x");
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_y");
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_z");
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_x");
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_y");
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_z");
SimpleTest.finish();
yield* testEventOrder();
yield* testOnWheelAttr();
yield* testOnWheelProperty();
}
var gTestContinuation = null;
function continueTest()
{
if (!gTestContinuation) {
gTestContinuation = testBody();
}
var ret = gTestContinuation.next();
if (ret.done) {
SimpleTest.finish();
}
}
function runTest()
{
SpecialPowers.pushPrefEnv({"set": [
["mousewheel.default.delta_multiplier_x", 100],
["mousewheel.default.delta_multiplier_y", 100],
["mousewheel.default.delta_multiplier_z", 100],
["mousewheel.with_alt.delta_multiplier_x", 100],
["mousewheel.with_alt.delta_multiplier_y", 100],
["mousewheel.with_alt.delta_multiplier_z", 100],
["mousewheel.with_control.delta_multiplier_x", 100],
["mousewheel.with_control.delta_multiplier_y", 100],
["mousewheel.with_control.delta_multiplier_z", 100],
["mousewheel.with_meta.delta_multiplier_x", 100],
["mousewheel.with_meta.delta_multiplier_y", 100],
["mousewheel.with_meta.delta_multiplier_z", 100],
["mousewheel.with_shift.delta_multiplier_x", 100],
["mousewheel.with_shift.delta_multiplier_y", 100],
["mousewheel.with_shift.delta_multiplier_z", 100],
["mousewheel.with_win.delta_multiplier_x", 100],
["mousewheel.with_win.delta_multiplier_y", 100],
["mousewheel.with_win.delta_multiplier_z", 100]]},
continueTest);
}
</script>
</pre>
</body>

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

@ -755,7 +755,9 @@ template <class Derived>
FetchBody<Derived>::FetchBody()
: mFeature(nullptr)
, mBodyUsed(false)
#ifdef DEBUG
, mReadDone(false)
#endif
{
if (!NS_IsMainThread()) {
mWorkerPrivate = GetCurrentThreadWorkerPrivate();
@ -940,7 +942,9 @@ FetchBody<Derived>::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength
MOZ_ASSERT(mBodyUsed);
MOZ_ASSERT(!mReadDone);
MOZ_ASSERT_IF(mWorkerPrivate, mFeature);
#ifdef DEBUG
mReadDone = true;
#endif
AutoFreeBuffer autoFree(aResult);

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

@ -214,7 +214,9 @@ private:
// Only touched on target thread.
ConsumeType mConsumeType;
RefPtr<Promise> mConsumePromise;
DebugOnly<bool> mReadDone;
#ifdef DEBUG
bool mReadDone;
#endif
nsMainThreadPtrHandle<nsIInputStreamPump> mConsumeBodyPump;
};

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

@ -50,8 +50,10 @@ FetchDriver::FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
: mPrincipal(aPrincipal)
, mLoadGroup(aLoadGroup)
, mRequest(aRequest)
#ifdef DEBUG
, mResponseAvailableCalled(false)
, mFetchCalled(false)
#endif
{
}
@ -66,8 +68,10 @@ nsresult
FetchDriver::Fetch(FetchDriverObserver* aObserver)
{
workers::AssertIsOnMainThread();
#ifdef DEBUG
MOZ_ASSERT(!mFetchCalled);
mFetchCalled = true;
#endif
mObserver = aObserver;
@ -412,7 +416,9 @@ FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse,
MOZ_ASSERT(filteredResponse);
MOZ_ASSERT(mObserver);
mObserver->OnResponseAvailable(filteredResponse);
#ifdef DEBUG
mResponseAvailableCalled = true;
#endif
return filteredResponse.forget();
}
@ -423,7 +429,9 @@ FetchDriver::FailWithNetworkError()
RefPtr<InternalResponse> error = InternalResponse::NetworkError();
if (mObserver) {
mObserver->OnResponseAvailable(error);
#ifdef DEBUG
mResponseAvailableCalled = true;
#endif
mObserver->OnResponseEnd();
mObserver = nullptr;
}

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

@ -83,8 +83,10 @@ private:
RefPtr<FetchDriverObserver> mObserver;
nsCOMPtr<nsIDocument> mDocument;
DebugOnly<bool> mResponseAvailableCalled;
DebugOnly<bool> mFetchCalled;
#ifdef DEBUG
bool mResponseAvailableCalled;
bool mFetchCalled;
#endif
FetchDriver() = delete;
FetchDriver(const FetchDriver&) = delete;

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

@ -5653,7 +5653,9 @@ struct ConnectionPool::TransactionInfo final
const bool mIsWriteTransaction;
bool mRunning;
DebugOnly<bool> mFinished;
#ifdef DEBUG
bool mFinished;
#endif
TransactionInfo(DatabaseInfo* aDatabaseInfo,
const nsID& aBackgroundChildLoggingId,
@ -5913,7 +5915,9 @@ private:
class MOZ_STACK_CLASS DatabaseOperationBase::AutoSetProgressHandler final
{
mozIStorageConnection* mConnection;
DebugOnly<DatabaseOperationBase*> mDEBUGDatabaseOp;
#ifdef DEBUG
DatabaseOperationBase* mDEBUGDatabaseOp;
#endif
public:
AutoSetProgressHandler();
@ -6014,7 +6018,9 @@ class Factory final
RefPtr<DatabaseLoggingInfo> mLoggingInfo;
DebugOnly<bool> mActorDestroyed;
#ifdef DEBUG
bool mActorDestroyed;
#endif
public:
static already_AddRefed<Factory>
@ -7924,7 +7930,9 @@ class NormalTransactionOp
: public TransactionDatabaseOperationBase
, public PBackgroundIDBRequestParent
{
DebugOnly<bool> mResponseSent;
#ifdef DEBUG
bool mResponseSent;
#endif
public:
virtual void
@ -7933,7 +7941,9 @@ public:
protected:
explicit NormalTransactionOp(TransactionBase* aTransaction)
: TransactionDatabaseOperationBase(aTransaction)
#ifdef DEBUG
, mResponseSent(false)
#endif
{ }
virtual
@ -8392,13 +8402,17 @@ protected:
CursorResponse mResponse;
DebugOnly<bool> mResponseSent;
#ifdef DEBUG
bool mResponseSent;
#endif
protected:
explicit CursorOpBase(Cursor* aCursor)
: TransactionDatabaseOperationBase(aCursor->mTransaction)
, mCursor(aCursor)
#ifdef DEBUG
, mResponseSent(false)
#endif
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aCursor);
@ -9245,16 +9259,20 @@ class MOZ_STACK_CLASS DatabaseMaintenance::AutoProgressHandler final
NS_DECL_OWNINGTHREAD
#ifdef DEBUG
// This class is stack-based so we never actually allow AddRef/Release to do
// anything. But we need to know if any consumer *thinks* that they have a
// reference to this object so we track the reference countin DEBUG builds.
DebugOnly<nsrefcnt> mDEBUGRefCnt;
nsrefcnt mDEBUGRefCnt;
#endif
public:
explicit AutoProgressHandler(Maintenance* aMaintenance)
: mMaintenance(aMaintenance)
, mConnection(nullptr)
#ifdef DEBUG
, mDEBUGRefCnt(0)
#endif
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsOnBackgroundThread());
@ -12642,7 +12660,9 @@ TransactionInfo::TransactionInfo(
, mObjectStoreNames(aObjectStoreNames)
, mIsWriteTransaction(aIsWriteTransaction)
, mRunning(false)
#ifdef DEBUG
, mFinished(false)
#endif
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aDatabaseInfo);
@ -12793,7 +12813,9 @@ uint64_t Factory::sFactoryInstanceCount = 0;
Factory::Factory(already_AddRefed<DatabaseLoggingInfo> aLoggingInfo)
: mLoggingInfo(Move(aLoggingInfo))
#ifdef DEBUG
, mActorDestroyed(false)
#endif
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread());
@ -12882,7 +12904,9 @@ Factory::ActorDestroy(ActorDestroyReason aWhy)
AssertIsOnBackgroundThread();
MOZ_ASSERT(!mActorDestroyed);
#ifdef DEBUG
mActorDestroyed = true;
#endif
// Clean up if there are no more instances.
if (!(--sFactoryInstanceCount)) {
@ -18205,7 +18229,9 @@ AutoProgressHandler::AddRef()
{
NS_ASSERT_OWNINGTHREAD(DatabaseMaintenance::AutoProgressHandler);
#ifdef DEBUG
mDEBUGRefCnt++;
#endif
return 2;
}
@ -18215,7 +18241,9 @@ AutoProgressHandler::Release()
{
NS_ASSERT_OWNINGTHREAD(DatabaseMaintenance::AutoProgressHandler);
#ifdef DEBUG
mDEBUGRefCnt--;
#endif
return 1;
}
@ -19203,7 +19231,9 @@ DatabaseOperationBase::OnProgress(mozIStorageConnection* aConnection,
DatabaseOperationBase::
AutoSetProgressHandler::AutoSetProgressHandler()
: mConnection(nullptr)
#ifdef DEBUG
, mDEBUGDatabaseOp(nullptr)
#endif
{
MOZ_ASSERT(!IsOnBackgroundThread());
}
@ -19244,7 +19274,9 @@ AutoSetProgressHandler::Register(mozIStorageConnection* aConnection,
MOZ_ASSERT(!oldProgressHandler);
mConnection = aConnection;
#ifdef DEBUG
mDEBUGDatabaseOp = aDatabaseOp;
#endif
return NS_OK;
}
@ -24352,7 +24384,9 @@ NormalTransactionOp::SendSuccessResult()
}
}
#ifdef DEBUG
mResponseSent = true;
#endif
return NS_OK;
}
@ -24371,7 +24405,9 @@ NormalTransactionOp::SendFailureResult(nsresult aResultCode)
ClampResultCode(aResultCode));
}
#ifdef DEBUG
mResponseSent = true;
#endif
return result;
}
@ -26062,7 +26098,9 @@ CursorOpBase::SendFailureResult(nsresult aResultCode)
mCursor->SendResponseInternal(mResponse, mFiles);
}
#ifdef DEBUG
mResponseSent = true;
#endif
return false;
}
@ -27072,7 +27110,9 @@ OpenOp::SendSuccessResult()
mCursor->SendResponseInternal(mResponse, mFiles);
#ifdef DEBUG
mResponseSent = true;
#endif
return NS_OK;
}
@ -27248,7 +27288,9 @@ ContinueOp::SendSuccessResult()
mCursor->SendResponseInternal(mResponse, mFiles);
#ifdef DEBUG
mResponseSent = true;
#endif
return NS_OK;
}

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

@ -297,7 +297,9 @@ TabParent::TabParent(nsIContentParent* aManager,
, mCursor(nsCursor(-1))
, mTabSetsCursor(false)
, mHasContentOpener(false)
#ifdef DEBUG
, mActiveSupressDisplayportCount(0)
#endif
{
MOZ_ASSERT(aManager);
}
@ -2835,13 +2837,14 @@ TabParent::SuppressDisplayport(bool aEnabled)
return NS_OK;
}
#ifdef DEBUG
if (aEnabled) {
mActiveSupressDisplayportCount++;
} else {
mActiveSupressDisplayportCount--;
}
MOZ_ASSERT(mActiveSupressDisplayportCount >= 0);
#endif
Unused << SendSuppressDisplayport(aEnabled);
return NS_OK;

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

@ -720,7 +720,9 @@ private:
bool mHasContentOpener;
DebugOnly<int32_t> mActiveSupressDisplayportCount;
#ifdef DEBUG
int32_t mActiveSupressDisplayportCount;
#endif
ShowInfo GetShowInfo();

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

@ -9,6 +9,8 @@
#include "mozilla/ClearOnShutdown.h"
#include "CubebUtils.h"
#include "webrtc/MediaEngineWebRTC.h"
#ifdef XP_MACOSX
#include <sys/sysctl.h>
#endif
@ -606,15 +608,22 @@ AudioCallbackDriver::Init()
input = output;
input.channels = mInputChannels; // change to support optional stereo capture
cubeb_stream* stream;
// XXX Only pass input input if we have an input listener. Always
// set up output because it's easier, and it will just get silence.
// XXX Add support for adding/removing an input listener later.
if (cubeb_stream_init(CubebUtils::GetCubebContext(), &stream,
cubeb_stream* stream = nullptr;
CubebUtils::AudioDeviceID input_id = nullptr, output_id = nullptr;
// We have to translate the deviceID values to cubeb devid's since those can be
// freed whenever enumerate is called.
if ((!mGraphImpl->mInputWanted ||
AudioInputCubeb::GetDeviceID(mGraphImpl->mInputDeviceID, input_id)) &&
(mGraphImpl->mOutputDeviceID == -1 || // pass nullptr for ID for default output
AudioInputCubeb::GetDeviceID(mGraphImpl->mOutputDeviceID, output_id)) &&
// XXX Only pass input input if we have an input listener. Always
// set up output because it's easier, and it will just get silence.
// XXX Add support for adding/removing an input listener later.
cubeb_stream_init(CubebUtils::GetCubebContext(), &stream,
"AudioCallbackDriver",
mGraphImpl->mInputDeviceID,
input_id,
mGraphImpl->mInputWanted ? &input : nullptr,
mGraphImpl->mOutputDeviceID,
output_id,
mGraphImpl->mOutputWanted ? &output : nullptr, latency,
DataCallback_s, StateCallback_s, this) == CUBEB_OK) {
mAudioStream.own(stream);

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

@ -695,22 +695,6 @@ MediaDecoderStateMachine::Push(MediaData* aSample, MediaData::Type aSampleType)
DispatchDecodeTasksIfNeeded();
}
void
MediaDecoderStateMachine::PushFront(MediaData* aSample, MediaData::Type aSampleType)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aSample);
if (aSample->mType == MediaData::AUDIO_DATA) {
AudioQueue().PushFront(aSample);
} else if (aSample->mType == MediaData::VIDEO_DATA) {
aSample->As<VideoData>()->mFrameID = ++mCurrentFrameID;
VideoQueue().PushFront(aSample);
} else {
// TODO: Handle MediaRawData, determine which queue should be pushed.
}
UpdateNextFrameStatus();
}
void
MediaDecoderStateMachine::CheckIsAudible(const MediaData* aSample)
{
@ -885,7 +869,8 @@ MediaDecoderStateMachine::MaybeFinishDecodeFirstFrame()
}
void
MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample)
MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample,
TimeStamp aDecodeStartTime)
{
MOZ_ASSERT(OnTaskQueue());
RefPtr<MediaData> video(aVideoSample);
@ -931,7 +916,7 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample)
if (mReader->IsAsync()) {
return;
}
TimeDuration decodeTime = TimeStamp::Now() - mVideoDecodeStartTime;
TimeDuration decodeTime = TimeStamp::Now() - aDecodeStartTime;
if (!IsDecodingFirstFrame() &&
THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
!HasLowUndecodedData())
@ -1768,24 +1753,32 @@ MediaDecoderStateMachine::RequestVideoData()
// Time the video decode, so that if it's slow, we can increase our low
// audio threshold to reduce the chance of an audio underrun while we're
// waiting for a video decode to complete.
mVideoDecodeStartTime = TimeStamp::Now();
TimeStamp videoDecodeStartTime = TimeStamp::Now();
bool skipToNextKeyFrame = mSentFirstFrameLoadedEvent &&
NeedToSkipToNextKeyframe();
int64_t currentTime = mState == DECODER_STATE_SEEKING ? 0 : GetMediaTime();
int64_t currentTime =
mState == DECODER_STATE_SEEKING || !mSentFirstFrameLoadedEvent
? 0 : GetMediaTime() + StartTime();
SAMPLE_LOG("Queueing video task - queued=%i, decoder-queued=%o, skip=%i, time=%lld",
VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
currentTime);
RefPtr<MediaDecoderStateMachine> self = this;
if (mSentFirstFrameLoadedEvent) {
mVideoDataRequest.Begin(
InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::RequestVideoData,
skipToNextKeyFrame, currentTime)
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded));
->Then(OwnerThread(), __func__,
[self, videoDecodeStartTime] (MediaData* aVideoSample) {
self->OnVideoDecoded(aVideoSample, videoDecodeStartTime);
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
self->OnVideoNotDecoded(aReason);
}));
} else {
mVideoDataRequest.Begin(
InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
@ -1795,9 +1788,13 @@ MediaDecoderStateMachine::RequestVideoData()
&StartTimeRendezvous::ProcessFirstSample<VideoDataPromise, MediaData::VIDEO_DATA>,
&StartTimeRendezvous::FirstSampleRejected<MediaData::VIDEO_DATA>)
->CompletionPromise()
->Then(OwnerThread(), __func__, this,
&MediaDecoderStateMachine::OnVideoDecoded,
&MediaDecoderStateMachine::OnVideoNotDecoded));
->Then(OwnerThread(), __func__,
[self, videoDecodeStartTime] (MediaData* aVideoSample) {
self->OnVideoDecoded(aVideoSample, videoDecodeStartTime);
},
[self] (MediaDecoderReader::NotDecodedReason aReason) {
self->OnVideoNotDecoded(aReason);
}));
}
}
@ -2524,7 +2521,8 @@ MediaDecoderStateMachine::DropVideoUpToSeekTarget(MediaData* aSample)
DECODER_LOG("DropVideoUpToSeekTarget() found video frame [%lld, %lld] containing target=%lld",
video->mTime, video->GetEndTime(), target);
PushFront(video, MediaData::VIDEO_DATA);
MOZ_ASSERT(VideoQueue().GetSize() == 0, "Should be the 1st sample after seeking");
Push(video, MediaData::VIDEO_DATA);
}
return NS_OK;
@ -2600,7 +2598,8 @@ MediaDecoderStateMachine::DropAudioUpToSeekTarget(MediaData* aSample)
Move(audioData),
channels,
audio->mRate));
PushFront(data, MediaData::AUDIO_DATA);
MOZ_ASSERT(AudioQueue().GetSize() == 0, "Should be the 1st sample after seeking");
Push(data, MediaData::AUDIO_DATA);
return NS_OK;
}

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

@ -364,7 +364,7 @@ private:
// TODO: Those callback function may receive demuxed-only data.
// Need to figure out a suitable API name for this case.
void OnAudioDecoded(MediaData* aAudioSample);
void OnVideoDecoded(MediaData* aVideoSample);
void OnVideoDecoded(MediaData* aVideoSample, TimeStamp aDecodeStartTime);
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
void OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
{
@ -392,7 +392,6 @@ protected:
// aSample must not be null.
void Push(MediaData* aSample, MediaData::Type aSampleType);
void PushFront(MediaData* aSample, MediaData::Type aSampleType);
void OnAudioPopped(const RefPtr<MediaData>& aSample);
void OnVideoPopped(const RefPtr<MediaData>& aSample);
@ -789,11 +788,6 @@ private:
bool HaveStartTime() { return mStartTimeRendezvous && mStartTimeRendezvous->HaveStartTime(); }
int64_t StartTime() { return mStartTimeRendezvous->StartTime(); }
// Time at which the last video sample was requested. If it takes too long
// before the sample arrives, we will increase the amount of audio we buffer.
// This is necessary for legacy synchronous decoders to prevent underruns.
TimeStamp mVideoDecodeStartTime;
// Queue of audio frames. This queue is threadsafe, and is accessed from
// the audio, decoder, state machine, and main threads.
MediaQueue<MediaData> mAudioQueue;

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

@ -23,7 +23,6 @@ class CDMProxy;
class MediaFormatReader final : public MediaDecoderReader
{
typedef TrackInfo::TrackType TrackType;
typedef media::Interval<int64_t> ByteInterval;
public:
MediaFormatReader(AbstractMediaDecoder* aDecoder,

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

@ -1510,11 +1510,11 @@ MediaManager::IsInMediaThread()
MediaManager::Get() {
if (!sSingleton) {
MOZ_ASSERT(NS_IsMainThread());
#ifdef DEBUG
static int timesCreated = 0;
timesCreated++;
MOZ_ASSERT(timesCreated == 1);
#endif
MOZ_RELEASE_ASSERT(timesCreated == 1);
sSingleton = new MediaManager();
sSingleton->mMediaThread = new base::Thread("MediaManager");
@ -3291,8 +3291,12 @@ GetUserMediaCallbackMediaStreamListener::NotifyFinished()
mFinished = true;
Stop(); // we know it's been activated
RefPtr<MediaManager> manager(MediaManager::GetInstance());
manager->RemoveFromWindowList(mWindowID, this);
RefPtr<MediaManager> manager(MediaManager::GetIfExists());
if (manager) {
manager->RemoveFromWindowList(mWindowID, this);
} else {
NS_WARNING("Late NotifyFinished after MediaManager shutdown");
}
}
// Called from the MediaStreamGraph thread

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

@ -104,7 +104,8 @@ MediaStreamGraphImpl::AddStreamGraphThread(MediaStream* aStream)
STREAM_LOG(LogLevel::Debug, ("Adding media stream %p to the graph, in the suspended stream array", aStream));
} else {
mStreams.AppendElement(aStream);
STREAM_LOG(LogLevel::Debug, ("Adding media stream %p to the graph", aStream));
STREAM_LOG(LogLevel::Debug, ("Adding media stream %p to graph %p, count %lu", aStream, this, mStreams.Length()));
LIFECYCLE_LOG("Adding media stream %p to graph %p, count %lu", aStream, this, mStreams.Length());
}
SetStreamOrderDirty();
@ -134,9 +135,12 @@ MediaStreamGraphImpl::RemoveStreamGraphThread(MediaStream* aStream)
mStreams.RemoveElement(aStream);
}
NS_RELEASE(aStream); // probably destroying it
STREAM_LOG(LogLevel::Debug, ("Removed media stream %p from graph %p, count %lu",
aStream, this, mStreams.Length()))
LIFECYCLE_LOG("Removed media stream %p from graph %p, count %lu",
aStream, this, mStreams.Length());
STREAM_LOG(LogLevel::Debug, ("Removing media stream %p from the graph", aStream));
NS_RELEASE(aStream); // probably destroying it
}
void
@ -336,19 +340,19 @@ namespace {
const uint32_t IN_MUTED_CYCLE = 1;
} // namespace
void
MediaStreamGraphImpl::UpdateStreamOrder()
bool
MediaStreamGraphImpl::AudioTrackPresent(bool& aNeedsAEC)
{
#ifdef MOZ_WEBRTC
bool shouldAEC = false;
#endif
bool audioTrackPresent = false;
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
for (uint32_t i = 0; i < mStreams.Length() && audioTrackPresent == false; ++i) {
MediaStream* stream = mStreams[i];
SourceMediaStream* source = stream->AsSourceStream();
#ifdef MOZ_WEBRTC
if (stream->AsSourceStream() &&
stream->AsSourceStream()->NeedsMixing()) {
shouldAEC = true;
if (source && source->NeedsMixing()) {
aNeedsAEC = true;
}
#endif
// If this is a AudioNodeStream, force a AudioCallbackDriver.
@ -360,14 +364,46 @@ MediaStreamGraphImpl::UpdateStreamOrder()
audioTrackPresent = true;
}
}
if (source) {
for (auto& data : source->mPendingTracks) {
if (data.mData->GetType() == MediaSegment::AUDIO) {
audioTrackPresent = true;
break;
}
}
}
}
// XXX For some reason, there are race conditions when starting an audio input where
// we find no active audio tracks. In any case, if we have an active audio input we
// should not allow a switch back to a SystemClockDriver
if (!audioTrackPresent && mInputDeviceUsers.Count() != 0) {
NS_WARNING("No audio tracks, but full-duplex audio is enabled!!!!!");
audioTrackPresent = true;
shouldAEC = true;
}
#ifdef MOZ_WEBRTC
aNeedsAEC = shouldAEC;
#endif
return audioTrackPresent;
}
void
MediaStreamGraphImpl::UpdateStreamOrder()
{
bool shouldAEC = false;
bool audioTrackPresent = AudioTrackPresent(shouldAEC);
// Note that this looks for any audio streams, input or output, and switches to a
// SystemClockDriver if there are none
// SystemClockDriver if there are none. However, if another is already pending, let that
// switch happen.
if (!audioTrackPresent && mRealtime &&
CurrentDriver()->AsAudioCallbackDriver()) {
MonitorAutoLock mon(mMonitor);
if (CurrentDriver()->AsAudioCallbackDriver()->IsStarted()) {
if (CurrentDriver()->AsAudioCallbackDriver()->IsStarted() &&
!(CurrentDriver()->Switching())) {
if (mLifecycleState == LIFECYCLE_RUNNING) {
SystemClockDriver* driver = new SystemClockDriver(this);
CurrentDriver()->SwitchAtNextIteration(driver);
@ -935,7 +971,7 @@ MediaStreamGraphImpl::PlayVideo(MediaStream* aStream)
}
void
MediaStreamGraphImpl::OpenAudioInputImpl(CubebUtils::AudioDeviceID aID,
MediaStreamGraphImpl::OpenAudioInputImpl(int aID,
AudioDataListener *aListener)
{
// Bug 1238038 Need support for multiple mics at once
@ -957,24 +993,30 @@ MediaStreamGraphImpl::OpenAudioInputImpl(CubebUtils::AudioDeviceID aID,
count++;
mInputDeviceUsers.Put(aListener, count); // creates a new entry in the hash if needed
// aID is a cubeb_devid, and we assume that opaque ptr is valid until
// we close cubeb.
mInputDeviceID = aID;
if (count == 1) { // first open for this listener
// aID is a cubeb_devid, and we assume that opaque ptr is valid until
// we close cubeb.
mInputDeviceID = aID;
mAudioInputs.AppendElement(aListener); // always monitor speaker data
}
// Switch Drivers since we're adding input (to input-only or full-duplex)
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
driver->SetInputListener(aListener);
CurrentDriver()->SwitchAtNextIteration(driver);
// Switch Drivers since we're adding input (to input-only or full-duplex)
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
AudioCallbackDriver* driver = new AudioCallbackDriver(this);
STREAM_LOG(LogLevel::Debug, ("OpenAudioInput: starting new AudioCallbackDriver(input) %p", driver));
LIFECYCLE_LOG("OpenAudioInput: starting new AudioCallbackDriver(input) %p", driver);
driver->SetInputListener(aListener);
CurrentDriver()->SwitchAtNextIteration(driver);
} else {
STREAM_LOG(LogLevel::Error, ("OpenAudioInput in shutdown!"));
LIFECYCLE_LOG("OpenAudioInput in shutdown!");
NS_ASSERTION(false, "Can't open cubeb inputs in shutdown");
}
}
}
nsresult
MediaStreamGraphImpl::OpenAudioInput(CubebUtils::AudioDeviceID aID,
MediaStreamGraphImpl::OpenAudioInput(int aID,
AudioDataListener *aListener)
{
// So, so, so annoying. Can't AppendMessage except on Mainthread
@ -986,7 +1028,7 @@ MediaStreamGraphImpl::OpenAudioInput(CubebUtils::AudioDeviceID aID,
}
class Message : public ControlMessage {
public:
Message(MediaStreamGraphImpl *aGraph, CubebUtils::AudioDeviceID aID,
Message(MediaStreamGraphImpl *aGraph, int aID,
AudioDataListener *aListener) :
ControlMessage(nullptr), mGraph(aGraph), mID(aID), mListener(aListener) {}
virtual void Run()
@ -994,9 +1036,7 @@ MediaStreamGraphImpl::OpenAudioInput(CubebUtils::AudioDeviceID aID,
mGraph->OpenAudioInputImpl(mID, mListener);
}
MediaStreamGraphImpl *mGraph;
// aID is a cubeb_devid, and we assume that opaque ptr is valid until
// we close cubeb.
CubebUtils::AudioDeviceID mID;
int mID;
RefPtr<AudioDataListener> mListener;
};
// XXX Check not destroyed!
@ -1015,7 +1055,7 @@ MediaStreamGraphImpl::CloseAudioInputImpl(AudioDataListener *aListener)
return; // still in use
}
mInputDeviceUsers.Remove(aListener);
mInputDeviceID = nullptr;
mInputDeviceID = -1;
mInputWanted = false;
AudioCallbackDriver *driver = CurrentDriver()->AsAudioCallbackDriver();
if (driver) {
@ -1024,20 +1064,8 @@ MediaStreamGraphImpl::CloseAudioInputImpl(AudioDataListener *aListener)
mAudioInputs.RemoveElement(aListener);
// Switch Drivers since we're adding or removing an input (to nothing/system or output only)
bool audioTrackPresent = false;
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
MediaStream* stream = mStreams[i];
// If this is a AudioNodeStream, force a AudioCallbackDriver.
if (stream->AsAudioNodeStream()) {
audioTrackPresent = true;
} else if (CurrentDriver()->AsAudioCallbackDriver()) {
// only if there's a real switch!
for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer(), MediaSegment::AUDIO);
!tracks.IsEnded(); tracks.Next()) {
audioTrackPresent = true;
}
}
}
bool shouldAEC = false;
bool audioTrackPresent = AudioTrackPresent(shouldAEC);
MonitorAutoLock mon(mMonitor);
if (mLifecycleState == LIFECYCLE_RUNNING) {
@ -2322,7 +2350,7 @@ MediaStream::AddMainThreadListener(MainThreadMediaStreamListener* aListener)
}
nsresult
SourceMediaStream::OpenAudioInput(CubebUtils::AudioDeviceID aID,
SourceMediaStream::OpenAudioInput(int aID,
AudioDataListener *aListener)
{
if (GraphImpl()) {
@ -2371,6 +2399,7 @@ SourceMediaStream::AddTrackInternal(TrackID aID, TrackRate aRate, StreamTime aSt
nsTArray<TrackData> *track_data = (aFlags & ADDTRACK_QUEUED) ?
&mPendingTracks : &mUpdateTracks;
TrackData* data = track_data->AppendElement();
LIFECYCLE_LOG("AddTrackInternal: %lu/%lu", mPendingTracks.Length(), mUpdateTracks.Length());
data->mID = aID;
data->mInputRate = aRate;
data->mResamplerChannelCount = 0;
@ -2388,6 +2417,7 @@ SourceMediaStream::FinishAddTracks()
{
MutexAutoLock lock(mMutex);
mUpdateTracks.AppendElements(Move(mPendingTracks));
LIFECYCLE_LOG("FinishAddTracks: %lu/%lu", mPendingTracks.Length(), mUpdateTracks.Length());
if (GraphImpl()) {
GraphImpl()->EnsureNextIteration();
}
@ -2808,9 +2838,9 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
: MediaStreamGraph(aSampleRate)
, mPortCount(0)
, mInputWanted(false)
, mInputDeviceID(nullptr)
, mInputDeviceID(-1)
, mOutputWanted(true)
, mOutputDeviceID(nullptr)
, mOutputDeviceID(-1)
, mNeedAnotherIteration(false)
, mGraphDriverAsleep(false)
, mMonitor("MediaStreamGraphImpl")
@ -3271,17 +3301,9 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(
// This is the same logic as in UpdateStreamOrder, but it's simpler to have it
// here as well so we don't have to store the Promise(s) on the Graph.
if (aOperation != AudioContextOperation::Resume) {
bool audioTrackPresent = false;
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
MediaStream* stream = mStreams[i];
if (stream->AsAudioNodeStream()) {
audioTrackPresent = true;
}
for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer(), MediaSegment::AUDIO);
!tracks.IsEnded(); tracks.Next()) {
audioTrackPresent = true;
}
}
bool shouldAEC = false;
bool audioTrackPresent = AudioTrackPresent(shouldAEC);
if (!audioTrackPresent && CurrentDriver()->AsAudioCallbackDriver()) {
CurrentDriver()->AsAudioCallbackDriver()->
EnqueueStreamAndPromiseForOperation(aDestinationStream, aPromise,

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

@ -739,7 +739,7 @@ public:
// last stream referencing an input goes away, so it can close the cubeb
// input. Also note: callable on any thread (though it bounces through
// MainThread to set the command if needed).
nsresult OpenAudioInput(CubebUtils::AudioDeviceID aID,
nsresult OpenAudioInput(int aID,
AudioDataListener *aListener);
// Note: also implied when Destroy() happens
void CloseAudioInput();
@ -1224,7 +1224,7 @@ public:
// Idempotent
static void DestroyNonRealtimeInstance(MediaStreamGraph* aGraph);
virtual nsresult OpenAudioInput(CubebUtils::AudioDeviceID aID,
virtual nsresult OpenAudioInput(int aID,
AudioDataListener *aListener) {
return NS_ERROR_FAILURE;
}

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

@ -185,10 +185,6 @@ public:
* This is called during application shutdown.
*/
void ForceShutDown(ShutdownTicket* aShutdownTicket);
/**
* Shutdown() this MediaStreamGraph's threads and return when they've shut down.
*/
void ShutdownThreads();
/**
* Called before the thread runs.
@ -333,6 +329,12 @@ public:
void SuspendOrResumeStreams(dom::AudioContextOperation aAudioContextOperation,
const nsTArray<MediaStream*>& aStreamSet);
/**
* Determine if we have any audio tracks, or are about to add any audiotracks.
* Also checks if we'll need the AEC running (i.e. microphone input tracks)
*/
bool AudioTrackPresent(bool& aNeedsAEC);
/**
* Sort mStreams so that every stream not in a cycle is after any streams
* it depends on, and every stream in a cycle is marked as being in a cycle.
@ -389,9 +391,9 @@ public:
* at the current buffer end point. The StreamBuffer's tracks must be
* explicitly set to finished by the caller.
*/
void OpenAudioInputImpl(CubebUtils::AudioDeviceID aID,
void OpenAudioInputImpl(int aID,
AudioDataListener *aListener);
virtual nsresult OpenAudioInput(CubebUtils::AudioDeviceID aID,
virtual nsresult OpenAudioInput(int aID,
AudioDataListener *aListener) override;
void CloseAudioInputImpl(AudioDataListener *aListener);
virtual void CloseAudioInput(AudioDataListener *aListener) override;
@ -628,9 +630,9 @@ public:
* and boolean to control if we want input/output
*/
bool mInputWanted;
CubebUtils::AudioDeviceID mInputDeviceID;
int mInputDeviceID;
bool mOutputWanted;
CubebUtils::AudioDeviceID mOutputDeviceID;
int mOutputDeviceID;
// Maps AudioDataListeners to a usecount of streams using the listener
// so we can know when it's no longer in use.
nsDataHashtable<nsPtrHashKey<AudioDataListener>, uint32_t> mInputDeviceUsers;

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

@ -366,6 +366,8 @@ RTCPeerConnection.prototype = {
Services.prefs.getBoolPref("media.peerconnection.ice.relay_only")) {
rtcConfig.iceTransportPolicy = "relay";
}
this._config = Object.assign({}, rtcConfig);
if (!rtcConfig.iceServers ||
!Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) {
try {
@ -452,6 +454,10 @@ RTCPeerConnection.prototype = {
return this._pc;
},
getConfiguration: function() {
return this._config;
},
_initCertificate: function(certificates) {
let certPromise;
if (certificates && certificates.length > 0) {

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

@ -28,7 +28,7 @@ GetDirectShowLog() {
DirectShowReader::DirectShowReader(AbstractMediaDecoder* aDecoder)
: MediaDecoderReader(aDecoder),
mMP3FrameParser(aDecoder->GetResource()->GetLength()),
#ifdef DEBUG
#ifdef DIRECTSHOW_REGISTER_GRAPH
mRotRegister(0),
#endif
mNumChannels(0),
@ -44,7 +44,7 @@ DirectShowReader::~DirectShowReader()
{
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
MOZ_COUNT_DTOR(DirectShowReader);
#ifdef DEBUG
#ifdef DIRECTSHOW_REGISTER_GRAPH
if (mRotRegister) {
RemoveGraphFromRunningObjectTable(mRotRegister);
}
@ -104,11 +104,7 @@ DirectShowReader::ReadMetadata(MediaInfo* aInfo,
rv = ParseMP3Headers(&mMP3FrameParser, mDecoder->GetResource());
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
// Add the graph to the Running Object Table so that we can connect
// to this graph with GraphEdit/GraphStudio. Note: on Vista and up you must
// also regsvr32 proppage.dll from the Windows SDK.
// See: http://msdn.microsoft.com/en-us/library/ms787252(VS.85).aspx
#ifdef DIRECTSHOW_REGISTER_GRAPH
hr = AddGraphToRunningObjectTable(mGraph, &mRotRegister);
NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
#endif

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

@ -13,6 +13,12 @@
#include "mozilla/RefPtr.h"
#include "MP3FrameParser.h"
// Add the graph to the Running Object Table so that we can connect
// to this graph with GraphEdit/GraphStudio. Note: on Vista and up you must
// also regsvr32 proppage.dll from the Windows SDK.
// See: http://msdn.microsoft.com/en-us/library/ms787252(VS.85).aspx
// #define DIRECTSHOW_REGISTER_GRAPH
struct IGraphBuilder;
struct IMediaControl;
struct IMediaSeeking;
@ -83,7 +89,7 @@ private:
// the MP3 frames to get a more accuate estimate of the duration.
MP3FrameParser mMP3FrameParser;
#ifdef DEBUG
#ifdef DIRECTSHOW_REGISTER_GRAPH
// Used to add/remove the filter graph to the Running Object Table. You can
// connect GraphEdit/GraphStudio to the graph to observe and/or debug its
// topology and state.

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

@ -167,7 +167,7 @@ CanCreateWMFDecoder()
static bool
IsH264DecoderBlacklisted()
{
#ifdef _WIN64
#ifdef BLACKLIST_CRASHY_H264_DECODERS
WCHAR systemPath[MAX_PATH + 1];
if (!ConstructSystem32Path(L"msmpeg2vdec.dll", systemPath, MAX_PATH + 1)) {
// Cannot build path -> Assume it's not the blacklisted DLL.
@ -193,7 +193,7 @@ IsH264DecoderBlacklisted()
return true;
}
}
#endif // _WIN64
#endif // BLACKLIST_CRASHY_H264_DECODERS
return false;
}

193
dom/media/test/external/README.md поставляемый
Просмотреть файл

@ -1,196 +1,5 @@
external-media-tests
===================
[Marionette Python tests][marionette-python-tests] for media playback in Mozilla Firefox. MediaTestCase uses [Firefox Puppeteer][ff-puppeteer-docs] library.
Documentation for this library has moved to https://developer.mozilla.org/en-US/docs/Mozilla/QA/external-media-tests.
Setup
-----
Normally, you get this source by cloning a firefox repo such as mozilla-central. The path to these tests would be in <mozilla-central>/dom/media/test/external, and these instructions refer to this path as '$PROJECT_HOME'.
Running from a build
--------------------
If you have built Firefox using ./mach build from a source tree such as mozilla-central, you can run the following command:
'''sh
$ ./mach external-media-tests
'''
You can pass any of the test options on this command line. They are listed below.
Running with an installer and a tests payload
---------------------------------------------
If you are testing a version of Firefox that you have not built, you must setup a virtualenv to run tests from. You will need a path to the installer or binary of Firefox.
* Create a virtualenv called `foo`.
```sh
$ virtualenv foo
$ source foo/bin/activate #or `foo\Scripts\activate` on Windows
```
* Install `external-media-tests` in development mode. (To get an environment that is closer to what is actually used in Mozilla's automation jobs, run `pip install -r requirements.txt` first.)
```sh
$ python setup.py develop
```
Now `external-media-tests` should be a recognized command. Try `external-media-tests --help` to see if it works.
Running the Tests
-----------------
In the examples below, `$FF_PATH` is a path to a recent Firefox binary. If you are running from a source build, the commands below should be invoked with:
'''sh
./mach external-media-tests
'''
If you are running with a virtualenv, you will need to run like this:
'''sh
external-media-tests --binary $FF_PATH
'''
or
'''sh
external-media-tests --installer $FF_INSTALLER_PATH
'''
or
'''sh
external-media-tests --installer-url <url to installer package>
'''
The following examples assume that you will use of these command lines instead of $EXTERNAL-MEDIA-TESTS.
This runs all the tests listed in `$PROJECT_HOME/external_media_tests/manifest.ini`:
```sh
$ $EXTERNAL-MEDIA-TESTS
```
You can also run all the tests at a particular path:
```sh
$ $EXTERNAL-MEDIA-TESTS some/path/foo
```
Or you can run the tests that are listed in a manifest file of your choice.
```sh
$ $EXTERNAL-MEDIA-TESTS some/other/path/manifest.ini
```
By default, the urls listed in `external_media_tests/urls/default.ini` are used for the tests, but you can also supply your own ini file of urls:
```sh
$ $EXTERNAL-MEDIA-TESTS --urls some/other/path/my_urls.ini
```
### Running EME tests
In order to run EME tests, you must use a Firefox profile that has a signed plugin-container.exe and voucher.bin. With Netflix, this will be created when you log in and save the credentials. You must also use a custom .ini file for urls to the provider's content and indicate which test to run, like above. Ex:
```sh
$ $EXTERNAL-MEDIA-TESTS some/path/tests.ini --profile custom_profile --urls some/path/provider-urls.ini
```
### Running tests in a way that provides information about a crash
What if Firefox crashes during a test run? You want to know why! To report useful crash data, the test runner needs access to a "minidump_stackwalk" binary and a "symbols.zip" file.
1. Download a `minidump_stackwalk` binary for your platform (save it wherever). Get it from http://hg.mozilla.org/build/tools/file/tip/breakpad/.
2. Make `minidump_stackwalk` executable
```sh
$ chmod +x path/to/minidump_stackwalk
```
3. Create an environment variable called `MINIDUMP_STACKWALK` that points to that local path
```sh
$ export MINIDUMP_STACKWALK=path/to/minidump_stackwalk
```
4. Download the `crashreporter-symbols.zip` file for the Firefox build you are testing and extract it. Example: ftp://ftp.mozilla.org/pub/firefox/tinderbox-builds/mozilla-aurora-win32/1427442016/firefox-38.0a2.en-US.win32.crashreporter-symbols.zip
5. Run the tests with a `--symbols-path` flag
```sh
$ $EXTERNAL-MEDIA-TESTS --symbols-path path/to/example/firefox-38.0a2.en-US.win32.crashreporter-symbols
```
To check whether the above setup is working for you, trigger a (silly) Firefox crash while the tests are running. One way to do this is with the [crashme add-on](https://github.com/luser/crashme) -- you can add it to Firefox even while the tests are running. Another way on Linux and Mac OS systems:
1. Find the process id (PID) of the Firefox process being used by the tests.
```sh
$ ps x | grep 'Firefox'
```
2. Kill the Firefox process with SIGABRT.
```sh
# 1234 is an example of a PID
$ kill -6 1234
```
Somewhere in the output produced by `external-media-tests`, you should see something like:
```
0:12.68 CRASH: MainThread pid:1234. Test:test_basic_playback.py TestVideoPlayback.test_playback_starts.
Minidump anaylsed:False.
Signature:[@ XUL + 0x2a65900]
Crash dump filename:
/var/folders/5k/xmn_fndx0qs2jcpcwhzl86wm0000gn/T/tmpB4Bolj.mozrunner/minidumps/DA3BB025-8302-4F96-8DF3-A97E424C877A.dmp
Operating system: Mac OS X
10.10.2 14C1514
CPU: amd64
family 6 model 69 stepping 1
4 CPUs
Crash reason: EXC_SOFTWARE / SIGABRT
Crash address: 0x104616900
...
```
### Setting up for network shaping tests (browsermobproxy)
1. Download the browsermob proxy zip file from http://bmp.lightbody.net/. The most current version as of this writing is browsermob-proxy-2.1.0-beta-2-bin.zip.
2. Unpack the .zip file.
3. Verify that you can launch browsermobproxy on your machine by running \<browsermob\>/bin/browsermob-proxy (or browsermob-proxy.bat on Windows) on your machine. I had to do a lot of work to install and use a java that browsermobproxy would like.
4. Import the certificate into your Firefox profile. Select Preferences->Advanced->Certificates->View Certificates->Import... Navigate to <browsermob>/ssl-support and select cybervilliansCA.cer. Select all of the checkboxes.
5. Tell marionette where browsermobproxy is and what port to start it on. Add the following command-line parameters to your external-media-tests command line:
<pre><code>
--browsermob-script <browsermob>/bin/browsermob-proxy --browsermob-port 999 --profile <your saved profile>
</code></pre>
You can then call browsermob to shape the network. You can find an example in external_media_tests/playback/test_playback_limiting_bandwidth.py. Another example can be found at https://dxr.mozilla.org/mozilla-central/source/testing/marionette/harness/marionette/tests/unit/test_browsermobproxy.py.
### A warning about video URLs
The ini files in `external_media_tests/urls` may contain URLs pulled from Firefox crash or bug data. Automated tests don't care about video content, but you might: visit these at your own risk and be aware that they may be NSFW. We do not intend to ever moderate or filter these URLs.
Writing a test
--------------
Write your test in a new or existing `test_*.py` file under `$PROJECT_HOME/external_media_tests`. Add it to the appropriate `manifest.ini` file(s) as well. Look in `media_utils` for useful video-playback functions.
* [Marionette docs][marionette-docs]
- [Marionette Command Line Options](https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options)
* [Firefox Puppeteer docs][ff-puppeteer-docs]
License
-------
This software is licensed under the [Mozilla Public License v. 2.0](http://mozilla.org/MPL/2.0/).
[marionette-python-tests]: https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/Marionette_Python_Tests
[ff-puppeteer-docs]: http://firefox-puppeteer.readthedocs.org/en/latest/
[marionette-docs]: http://marionette-client.readthedocs.org/en/latest/reference.html
[ff-nightly]:https://nightly.mozilla.org/

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

@ -690,7 +690,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
skip-if = os == 'win' && !debug # bug 1228605
tags=msg
[test_mediarecorder_bitrate.html]
skip-if = (toolkit == 'gonk' || android_version == '10') # B2G emulator is too slow to run this without timing out and Android doesn't like the seek.webm
skip-if = (toolkit == 'gonk' || toolkit == 'android') # B2G emulator is too slow to run this without timing out and Fennec does not support video recording
tags=msg
[test_mediarecorder_creation.html]
tags=msg capturestream
@ -707,7 +707,7 @@ tags=msg
[test_mediarecorder_record_audionode.html]
tags=msg
[test_mediarecorder_record_canvas_captureStream.html]
skip-if = android_version < '17' # Android/Gonk before SDK version 17 does not have the OMX Encoder API.
skip-if = (android_version < '17' || toolkit == 'android') # Android/Gonk before SDK version 17 does not have the OMX Encoder API and Fennec does not support video recording
tags=msg
[test_mediarecorder_record_changing_video_resolution.html]
skip-if = android_version < '17' # Android/Gonk before SDK version 17 does not have the OMX Encoder API.

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

@ -9,12 +9,14 @@ var Ci = SpecialPowers.Ci;
// Specifies whether we are using fake streams to run this automation
var FAKE_ENABLED = true;
var TEST_AUDIO_FREQ = 1000;
try {
var audioDevice = SpecialPowers.getCharPref('media.audio_loopback_dev');
var videoDevice = SpecialPowers.getCharPref('media.video_loopback_dev');
dump('TEST DEVICES: Using media devices:\n');
dump('audio: ' + audioDevice + '\nvideo: ' + videoDevice + '\n');
FAKE_ENABLED = false;
TEST_AUDIO_FREQ = 440;
} catch (e) {
dump('TEST DEVICES: No test devices found (in media.{audio,video}_loopback_dev, using fake streams.\n');
FAKE_ENABLED = true;

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

@ -22,6 +22,16 @@ var makePC = (config, expected_error) => {
"RTCPeerConnection(" + JSON.stringify(config) + ")");
};
// The order of properties in objects is not guaranteed in JavaScript, so this
// transform produces json-comparable dictionaries. The resulting copy is only
// meant to be used in comparisons (e.g. array-ness is not preserved).
var toComparable = o =>
(typeof o != 'object' || !o)? o : Object.keys(o).sort().reduce((co, key) => {
co[key] = toComparable(o[key]);
return co;
}, {});
// This is a test of the iceServers parsing code + readable errors
runNetworkTest(() => {
var exception = null;
@ -72,6 +82,21 @@ runNetworkTest(() => {
"RTCPeerConnection() constructor has readable exceptions");
}
// Test getConfiguration
var config = {
bundlePolicy: "max-bundle",
iceTransportPolicy: "relay",
peerIdentity: null,
iceServers: [
{ urls: ["stun:127.0.0.1", "stun:localhost"], credentialType:"password" },
{ urls: ["turn:[::1]:3478"], username:"p", credential:"p", credentialType:"token" },
],
};
var pc = new RTCPeerConnection(config);
is(JSON.stringify(toComparable(pc.getConfiguration())),
JSON.stringify(toComparable(config)), "getConfiguration");
pc.close();
// Below tests are setting the about:config User preferences for default
// ice servers and checking the outputs when RTCPeerConnection() is
// invoked. See Bug 1167922 for more information.

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

@ -17,7 +17,7 @@ runNetworkTest(() => {
var test = new PeerConnectionTest();
// Always use fake tracks since we depend on video to be somewhat green and
// audio to have a large 1000Hz component.
// audio to have a large 1000Hz component (or 440Hz if using fake devices).
test.setMediaConstraints([{audio: true, video: true, fake: true}], []);
test.chain.append([
function CHECK_ASSUMPTIONS() {

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

@ -44,20 +44,20 @@
local1Analyser = new AudioStreamAnalyser(ac, test.pcLocal.streams[0]);
remote1Analyser = new AudioStreamAnalyser(ac, test.pcRemote.streams[0]);
freq1k = local1Analyser.binIndexForFrequency(1000);
freq = local1Analyser.binIndexForFrequency(TEST_AUDIO_FREQ);
return Promise.resolve()
.then(() => info("Checking local audio enabled"))
.then(() => checkAudioEnabled(local1Analyser, freq1k))
.then(() => checkAudioEnabled(local1Analyser, freq))
.then(() => info("Checking remote audio enabled"))
.then(() => checkAudioEnabled(remote1Analyser, freq1k))
.then(() => checkAudioEnabled(remote1Analyser, freq))
.then(() => test.pcLocal.streams[0].getAudioTracks()[0].enabled = false)
.then(() => info("Checking local audio disabled"))
.then(() => checkAudioDisabled(local1Analyser, freq1k))
.then(() => checkAudioDisabled(local1Analyser, freq))
.then(() => info("Checking remote audio disabled"))
.then(() => checkAudioDisabled(remote1Analyser, freq1k))
.then(() => checkAudioDisabled(remote1Analyser, freq))
}
]);
@ -86,31 +86,31 @@
local2Analyser = new AudioStreamAnalyser(ac, test.pcLocal.streams[1]);
remote2Analyser = new AudioStreamAnalyser(ac, test.pcRemote.streams[1]);
freq1k = local2Analyser.binIndexForFrequency(1000);
freq = local2Analyser.binIndexForFrequency(TEST_AUDIO_FREQ);
return Promise.resolve()
.then(() => info("Checking local audio disabled"))
.then(() => checkAudioDisabled(local1Analyser, freq1k))
.then(() => checkAudioDisabled(local1Analyser, freq))
.then(() => info("Checking remote audio disabled"))
.then(() => checkAudioDisabled(remote1Analyser, freq1k))
.then(() => checkAudioDisabled(remote1Analyser, freq))
.then(() => info("Checking local2 audio enabled"))
.then(() => checkAudioEnabled(local2Analyser, freq1k))
.then(() => checkAudioEnabled(local2Analyser, freq))
.then(() => info("Checking remote2 audio enabled"))
.then(() => checkAudioEnabled(remote2Analyser, freq1k))
.then(() => checkAudioEnabled(remote2Analyser, freq))
.then(() => test.pcLocal.streams[1].getAudioTracks()[0].enabled = false)
.then(() => test.pcLocal.streams[0].getAudioTracks()[0].enabled = true)
.then(() => info("Checking local2 audio disabled"))
.then(() => checkAudioDisabled(local2Analyser, freq1k))
.then(() => checkAudioDisabled(local2Analyser, freq))
.then(() => info("Checking remote2 audio disabled"))
.then(() => checkAudioDisabled(remote2Analyser, freq1k))
.then(() => checkAudioDisabled(remote2Analyser, freq))
.then(() => info("Checking local audio enabled"))
.then(() => checkAudioEnabled(local1Analyser, freq1k))
.then(() => checkAudioEnabled(local1Analyser, freq))
.then(() => info("Checking remote audio enabled"))
.then(() => checkAudioEnabled(remote1Analyser, freq1k))
.then(() => checkAudioEnabled(remote1Analyser, freq))
}
]);

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

@ -67,7 +67,9 @@ protected:
android::MediaBuffer* mMediaBuffer;
// Check if current thread is the same one which called SetMediaBuffer().
// It doesn't need to hold reference count.
DebugOnly<nsIThread*> mThread;
#ifdef DEBUG
nsIThread* mThread;
#endif
};
} // namespace mozilla

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

@ -50,6 +50,54 @@ nsTArray<nsCString>* AudioInputCubeb::mDeviceNames;
cubeb_device_collection* AudioInputCubeb::mDevices = nullptr;
bool AudioInputCubeb::mAnyInUse = false;
// AudioDeviceID is an annoying opaque value that's really a string
// pointer, and is freed when the cubeb_device_collection is destroyed
void AudioInputCubeb::UpdateDeviceList()
{
cubeb_device_collection *devices = nullptr;
if (CUBEB_OK != cubeb_enumerate_devices(CubebUtils::GetCubebContext(),
CUBEB_DEVICE_TYPE_INPUT,
&devices)) {
return;
}
for (auto& device_index : (*mDeviceIndexes)) {
device_index = -1; // unmapped
}
// We keep all the device names, but wipe the mappings and rebuild them
// Calculate translation from existing mDevices to new devices. Note we
// never end up with less devices than before, since people have
// stashed indexes.
// For some reason the "fake" device for automation is marked as DISABLED,
// so white-list it.
for (uint32_t i = 0; i < devices->count; i++) {
if (devices->device[i]->type == CUBEB_DEVICE_TYPE_INPUT && // paranoia
(devices->device[i]->state == CUBEB_DEVICE_STATE_ENABLED ||
devices->device[i]->state == CUBEB_DEVICE_STATE_UNPLUGGED ||
(devices->device[i]->state == CUBEB_DEVICE_STATE_DISABLED &&
strcmp(devices->device[i]->friendly_name, "Sine source at 440 Hz") == 0)))
{
auto j = mDeviceNames->IndexOf(devices->device[i]->device_id);
if (j != nsTArray<nsCString>::NoIndex) {
// match! update the mapping
(*mDeviceIndexes)[j] = i;
} else {
// new device, add to the array
mDeviceIndexes->AppendElement(i);
mDeviceNames->AppendElement(devices->device[i]->device_id);
}
}
}
// swap state
if (mDevices) {
cubeb_device_collection_destroy(mDevices);
}
mDevices = devices;
}
MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
: mMutex("mozilla::MediaEngineWebRTC"),
mVoiceEngine(nullptr),

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

@ -183,7 +183,7 @@ public:
return 0;
}
int32_t DeviceIndex(int aIndex)
static int32_t DeviceIndex(int aIndex)
{
if (aIndex == -1) {
aIndex = 0; // -1 = system default
@ -195,6 +195,16 @@ public:
return (*mDeviceIndexes)[aIndex]; // translate to mDevices index
}
static bool GetDeviceID(int aDeviceIndex, CubebUtils::AudioDeviceID &aID)
{
int dev_index = DeviceIndex(aDeviceIndex);
if (dev_index != -1) {
aID = mDevices->device[dev_index]->device_id;
return true;
}
return false;
}
int GetRecordingDeviceName(int aIndex, char aStrNameUTF8[128],
char aStrGuidUTF8[128])
{
@ -230,7 +240,7 @@ public:
}
mInUseCount++;
// Always tell the stream we're using it for input
aStream->OpenAudioInput(mDevices->device[mSelectedDevice]->devid, aListener);
aStream->OpenAudioInput(mSelectedDevice, aListener);
}
void StopRecording(SourceMediaStream *aStream)
@ -243,11 +253,7 @@ public:
int SetRecordingDevice(int aIndex)
{
int32_t devindex = DeviceIndex(aIndex);
if (!mDevices || devindex < 0) {
return 1;
}
mSelectedDevice = devindex;
mSelectedDevice = aIndex;
return 0;
}
@ -258,50 +264,7 @@ protected:
private:
// It would be better to watch for device-change notifications
void UpdateDeviceList()
{
cubeb_device_collection *devices = nullptr;
if (CUBEB_OK != cubeb_enumerate_devices(CubebUtils::GetCubebContext(),
CUBEB_DEVICE_TYPE_INPUT,
&devices)) {
return;
}
for (auto& device_index : (*mDeviceIndexes)) {
device_index = -1; // unmapped
}
// We keep all the device names, but wipe the mappings and rebuild them
// Calculate translation from existing mDevices to new devices. Note we
// never end up with less devices than before, since people have
// stashed indexes.
// For some reason the "fake" device for automation is marked as DISABLED,
// so white-list it.
for (uint32_t i = 0; i < devices->count; i++) {
if (devices->device[i]->type == CUBEB_DEVICE_TYPE_INPUT && // paranoia
(devices->device[i]->state == CUBEB_DEVICE_STATE_ENABLED ||
devices->device[i]->state == CUBEB_DEVICE_STATE_UNPLUGGED ||
(devices->device[i]->state == CUBEB_DEVICE_STATE_DISABLED &&
strcmp(devices->device[i]->friendly_name, "Sine source at 440 Hz") == 0)))
{
auto j = mDeviceNames->IndexOf(devices->device[i]->device_id);
if (j != nsTArray<nsCString>::NoIndex) {
// match! update the mapping
(*mDeviceIndexes)[j] = i;
} else {
// new device, add to the array
mDeviceIndexes->AppendElement(i);
mDeviceNames->AppendElement(devices->device[i]->device_id);
}
}
}
// swap state
if (mDevices) {
cubeb_device_collection_destroy(mDevices);
}
mDevices = devices;
}
void UpdateDeviceList();
// We have an array, which consists of indexes to the current mDevices
// list. This is updated on mDevices updates. Many devices in mDevices
@ -382,8 +345,9 @@ protected:
virtual ~WebRTCAudioDataListener() {}
public:
explicit WebRTCAudioDataListener(MediaEngineAudioSource* aAudioSource) :
mAudioSource(aAudioSource)
explicit WebRTCAudioDataListener(MediaEngineAudioSource* aAudioSource)
: mMutex("WebRTCAudioDataListener")
, mAudioSource(aAudioSource)
{}
// AudioDataListenerInterface methods
@ -391,16 +355,29 @@ public:
AudioDataValue* aBuffer, size_t aFrames,
TrackRate aRate, uint32_t aChannels) override
{
mAudioSource->NotifyOutputData(aGraph, aBuffer, aFrames, aRate, aChannels);
MutexAutoLock lock(mMutex);
if (mAudioSource) {
mAudioSource->NotifyOutputData(aGraph, aBuffer, aFrames, aRate, aChannels);
}
}
virtual void NotifyInputData(MediaStreamGraph* aGraph,
const AudioDataValue* aBuffer, size_t aFrames,
TrackRate aRate, uint32_t aChannels) override
{
mAudioSource->NotifyInputData(aGraph, aBuffer, aFrames, aRate, aChannels);
MutexAutoLock lock(mMutex);
if (mAudioSource) {
mAudioSource->NotifyInputData(aGraph, aBuffer, aFrames, aRate, aChannels);
}
}
void Shutdown()
{
MutexAutoLock lock(mMutex);
mAudioSource = nullptr;
}
private:
Mutex mMutex;
RefPtr<MediaEngineAudioSource> mAudioSource;
};
@ -496,7 +473,9 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
protected:
~MediaEngineWebRTCMicrophoneSource() { Shutdown(); }
~MediaEngineWebRTCMicrophoneSource() {
Shutdown();
}
private:
void Init();
@ -510,7 +489,9 @@ private:
ScopedCustomReleasePtr<webrtc::VoENetwork> mVoENetwork;
ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mVoEProcessing;
// accessed from the GraphDriver thread except for deletion
nsAutoPtr<AudioPacketizer<AudioDataValue, int16_t>> mPacketizer;
ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERenderListener;
// mMonitor protects mSources[] access/changes, and transitions of mState
// from kStarted to kStopped (which are combined with EndTrack()).

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