This commit is contained in:
Ryan VanderMeulen 2015-07-02 16:00:46 -04:00
Родитель 159cd7e187 be503875d7
Коммит ffdc1661d7
146 изменённых файлов: 2369 добавлений и 1220 удалений

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

@ -25,6 +25,7 @@
#include "nsCoord.h"
#include "nsObjCExceptions.h"
#include "nsWhitespaceTokenizer.h"
#include <prdtoa.h>
using namespace mozilla;
using namespace mozilla::a11y;
@ -38,11 +39,11 @@ using namespace mozilla::a11y;
#define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
#define NSAccessibilityMathUnderAttribute @"AXMathUnder"
#define NSAccessibilityMathOverAttribute @"AXMathOver"
#define NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
// XXX WebKit also defines the following attributes.
// See bugs 1176970, 1176973 and 1176983.
// See bugs 1176970 and 1176983.
// - NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
// - NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
// - NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
// - NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
// - NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
@ -172,8 +173,7 @@ ConvertToNSArray(nsTArray<Accessible*>& aArray)
case roles::MATHML_FRACTION:
[additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
[additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
// XXX bug 1176973
// WebKit also defines NSAccessibilityMathLineThicknessAttribute
[additional addObject:NSAccessibilityMathLineThicknessAttribute];
break;
case roles::MATHML_SUB:
case roles::MATHML_SUP:
@ -422,8 +422,24 @@ ConvertToNSArray(nsTArray<Accessible*>& aArray)
return [self childAt:0];
if ([attribute isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
return [self childAt:1];
// XXX bug 1176973
// WebKit also defines NSAccessibilityMathLineThicknessAttribute
if ([attribute isEqualToString:NSAccessibilityMathLineThicknessAttribute]) {
// WebKit sets line thickness to some logical value parsed in the
// renderer object of the <mfrac> element. It's not clear whether the
// exact value is relevant to assistive technologies. From a semantic
// point of view, the only important point is to distinguish between
// <mfrac> elements that have a fraction bar and those that do not.
// Per the MathML 3 spec, the latter happens iff the linethickness
// attribute is of the form [zero-float][optional-unit]. In that case we
// set line thickness to zero and in the other cases we set it to one.
nsCOMPtr<nsIPersistentProperties> attributes = accWrap->Attributes();
nsAutoString thickness;
nsAccUtils::GetAccAttr(attributes, nsGkAtoms::linethickness_, thickness);
double value = 1.0;
if (!thickness.IsEmpty())
value = PR_strtod(NS_LossyConvertUTF16toASCII(thickness).get(),
nullptr);
return [NSNumber numberWithInteger:(value ? 1 : 0)];
}
break;
case roles::MATHML_SUB:
if ([attribute isEqualToString:NSAccessibilityMathBaseAttribute])

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

@ -31,6 +31,15 @@ XPCOMUtils.defineLazyGetter(this, 'MemoryFront', function() {
Cu.import('resource://gre/modules/Frames.jsm');
let _telemetryDebug = true;
function telemetryDebug(...args) {
if (_telemetryDebug) {
args.unshift('[AdvancedTelemetry]');
console.log(...args);
}
}
/**
* The Developer HUD is an on-device developer tool that displays widgets,
* showing visual debug information about apps. Each widget corresponds to a
@ -43,6 +52,7 @@ let developerHUD = {
_conn: null,
_watchers: [],
_logging: true,
_telemetry: false,
/**
* This method registers a metric watcher that will watch one or more metrics
@ -90,6 +100,10 @@ let developerHUD = {
SettingsListener.observe('hud.logging', this._logging, enabled => {
this._logging = enabled;
});
SettingsListener.observe('debug.performance_data.advanced_telemetry', this._telemetry, enabled => {
this._telemetry = enabled;
});
},
uninit: function dwp_uninit() {
@ -169,13 +183,24 @@ let developerHUD = {
* metrics, and how to notify the front-end when metrics have changed.
*/
function Target(frame, actor) {
this.frame = frame;
this._frame = frame;
this.actor = actor;
this.metrics = new Map();
}
Target.prototype = {
get frame() {
let frame = this._frame;
let systemapp = document.querySelector('#systemapp');
return (frame === systemapp ? getContentWindow() : frame);
},
get manifest() {
return this._frame.appManifestURL;
},
/**
* Register a metric that can later be updated. Does not update the front-end.
*/
@ -203,7 +228,7 @@ Target.prototype = {
let data = {
metrics: [], // FIXME(Bug 982066) Remove this field.
manifest: this.frame.appManifestURL,
manifest: this.manifest,
metric: metric,
message: message
};
@ -218,6 +243,7 @@ Target.prototype = {
if (message) {
developerHUD.log('[' + data.manifest + '] ' + data.message);
}
this._send(data);
},
@ -251,14 +277,33 @@ Target.prototype = {
_send: function target_send(data) {
let frame = this.frame;
let systemapp = document.querySelector('#systemapp');
if (this.frame === systemapp) {
frame = getContentWindow();
shell.sendEvent(frame, 'developer-hud-update', Cu.cloneInto(data, frame));
this._sendTelemetryEvent(data.metric);
},
_sendTelemetryEvent: function target_sendTelemetryEvent(metric) {
if (!developerHUD._telemetry || !metric || metric.skipTelemetry) {
return;
}
shell.sendEvent(frame, 'developer-hud-update', Cu.cloneInto(data, frame));
}
if (!this.appName) {
let manifest = this.manifest;
if (!manifest) {
return;
}
let start = manifest.indexOf('/') + 2;
let end = manifest.indexOf('.', start);
this.appName = manifest.substring(start, end).toLowerCase();
}
metric.appName = this.appName;
let data = { metric: metric };
let frame = this.frame;
telemetryDebug('sending advanced-telemetry-update with this data: ' + JSON.stringify(data));
shell.sendEvent(frame, 'advanced-telemetry-update', Cu.cloneInto(data, frame));
}
};
@ -359,6 +404,18 @@ let consoleWatcher = {
if (this._security.indexOf(pageError.category) > -1) {
metric.name = 'security';
// Telemetry sends the security error category not the
// count of security errors.
target._sendTelemetryEvent({
name: 'security',
value: pageError.category,
});
// Indicate that the 'hud' security metric (the count of security
// errors) should not be sent as a telemetry metric since the
// security error category is being sent instead.
metric.skipTelemetry = true;
}
let {errorMessage, sourceName, category, lineNumber, columnNumber} = pageError;
@ -379,6 +436,16 @@ let consoleWatcher = {
output += 'Warning (console)';
break;
case 'info':
this.handleTelemetryMessage(target, packet);
// Currently, informational log entries are tracked only by
// advanced telemetry. Nonetheless, for consistency, we
// continue here and let the function return normally, when it
// concludes 'info' entries are not being watched.
metric.name = 'info';
break;
default:
return;
}
@ -394,6 +461,9 @@ let consoleWatcher = {
if (sourceURL) {
output += ' ' + this.formatSourceURL(packet);
}
// Telemetry also records reflow duration.
target._sendTelemetryEvent({name: 'reflow-duration', value: Math.round(duration)});
break;
default:
@ -417,6 +487,49 @@ let consoleWatcher = {
', ' + source + ':' + sourceLine;
return source;
},
handleTelemetryMessage:
function cw_handleTelemetryMessage(target, packet) {
if (!developerHUD._telemetry) {
return;
}
// If this is a 'telemetry' log entry, create a telemetry metric from
// the log content.
let separator = '|';
let logContent = packet.message.arguments.toString();
if (logContent.indexOf('telemetry') < 0) {
return;
}
let telemetryData = logContent.split(separator);
// Positions of the components of a telemetry log entry.
let TELEMETRY_IDENTIFIER_IDX = 0;
let NAME_IDX = 1;
let VALUE_IDX = 2;
let CONTEXT_IDX = 3;
if (telemetryData[TELEMETRY_IDENTIFIER_IDX] != 'telemetry' ||
telemetryData.length < 3 || telemetryData.length > 4) {
return;
}
let metric = {
name: telemetryData[NAME_IDX],
value: telemetryData[VALUE_IDX]
};
// The metric's app name, if a 'context' was provided, is the
// specified context appended to the specified app name.
if (telemetryData.length === 4) {
metric.context = telemetryData[CONTEXT_IDX];
}
target._sendTelemetryEvent(metric);
}
};
developerHUD.registerWatcher(consoleWatcher);

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

@ -149,7 +149,7 @@ this.AboutServiceWorkers = {
!message.principal.origin ||
!message.principal.originAttributes ||
!message.principal.originAttributes.appId ||
!message.principal.originAttributes.isInBrowser) {
(message.principal.originAttributes.inBrowser == null)) {
self.sendError(message.id, "MissingPrincipal");
return;
}
@ -157,7 +157,7 @@ this.AboutServiceWorkers = {
let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(
Services.io.newURI(message.principal.origin, null, null),
message.principal.originAttributes.appId,
message.principal.originAttributes.isInBrowser
message.principal.originAttributes.inBrowser
);
if (!message.scope) {

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "4b7ad0dde990bdc44e166818c0bb09a35cd1207f",
"git_revision": "722028715a56a03f327e2e70f2c32dcb6d819d4c",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "4dd94426a71c70db03184cb1e2d9c4c2ad065461",
"revision": "547f049d7e7510b628b5b1074f73b204ab6627df",
"repo_path": "integration/gaia-central"
}

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -126,12 +126,14 @@ var FullScreen = {
} else {
let topWin = event.target.ownerDocument.defaultView.top;
browser = gBrowser.getBrowserForContentWindow(topWin);
if (!browser) {
document.mozCancelFullScreen();
break;
}
}
if (!this.enterDomFullscreen(browser)) {
if (!browser || !this.enterDomFullscreen(browser)) {
if (document.mozFullScreen) {
// MozDOMFullscreen:Entered is dispatched synchronously in
// fullscreen change, hence we have to avoid calling this
// method synchronously here.
setTimeout(() => document.mozCancelFullScreen(), 0);
}
break;
}
// If it is a remote browser, send a message to ask the content
@ -176,7 +178,6 @@ var FullScreen = {
// active. If not, we exit fullscreen since the "full-screen document" isn't
// actually visible now.
if (gBrowser.selectedBrowser != aBrowser) {
document.mozCancelFullScreen();
return false;
}
@ -184,7 +185,6 @@ var FullScreen = {
if (focusManager.activeWindow != window) {
// The top-level window has lost focus since the request to enter
// full-screen was made. Cancel full-screen.
document.mozCancelFullScreen();
return false;
}

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

@ -18,6 +18,7 @@
#include "nsPIDOMWindow.h"
class nsIConsoleAPIStorage;
class nsIPrincipal;
class nsIProfiler;
class nsIXPConnectJSObjectHolder;

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

@ -5,8 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PerformanceEntry.h"
#include "nsIURI.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/PerformanceEntryBinding.h"
#include "nsIURI.h"
using namespace mozilla::dom;

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

@ -8,6 +8,8 @@
#define mozilla_dom_PerformanceEntry_h___
#include "nsDOMNavigationTiming.h"
#include "nsString.h"
#include "nsWrapperCache.h"
class nsISupports;

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PerformanceMark.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/PerformanceMarkBinding.h"
using namespace mozilla::dom;

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

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PerformanceMeasure.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/PerformanceMeasureBinding.h"
using namespace mozilla::dom;

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

@ -16,6 +16,7 @@
#include "nsGlobalWindow.h"
#include "nsIPresShell.h"
#include "nsIPrincipal.h"
#include "nsPresContext.h"
namespace mozilla {
namespace dom {

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

@ -11,9 +11,11 @@
#include "nsCOMPtr.h"
#include "nsRefPtr.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
class nsGlobalWindow;
class nsIPrincipal;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {

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

@ -8,6 +8,7 @@
#include "nsContentCID.h"
#include "nsDOMClassInfoID.h"
#include "mozilla/HoldDropJSObjects.h"
using namespace mozilla;
using namespace mozilla::dom;

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

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SameProcessMessageQueue.h"
#include "nsThreadUtils.h"
using namespace mozilla;
using namespace mozilla::dom;

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

@ -33,6 +33,7 @@
#include "xpcpublic.h"
#include "nsObserverService.h"
#include "nsFocusManager.h"
#include "nsIInterfaceRequestorUtils.h"
using namespace mozilla;
using namespace mozilla::dom;

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

@ -16,11 +16,13 @@
#include "nsContentPolicy.h"
#include "nsIURI.h"
#include "nsIDocShell.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIDOMWindow.h"
#include "nsIContent.h"
#include "nsILoadContext.h"
#include "nsCOMArray.h"
#include "nsContentUtils.h"
using mozilla::LogLevel;

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

@ -17,6 +17,8 @@
#include "mozilla/dom/Animation.h"
#include "mozilla/dom/KeyframeEffect.h"
using mozilla::dom::Animation;
nsAutoTArray<nsRefPtr<nsDOMMutationObserver>, 4>*
nsDOMMutationObserver::sScheduledMutationObservers = nullptr;
@ -345,12 +347,12 @@ void
nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation,
AnimationMutation aMutationType)
{
KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
mozilla::dom::KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
if (!effect) {
return;
}
Element* animationTarget = effect->GetTarget();
mozilla::dom::Element* animationTarget = effect->GetTarget();
if (!animationTarget) {
return;
}

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

@ -3536,6 +3536,7 @@ nsDOMWindowUtils::RequestCompositorProperty(const nsAString& property,
NS_IMETHODIMP
nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
const nsAString& aProperty,
const nsAString& aPseudoElement,
nsAString& aResult)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
@ -3547,6 +3548,15 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
nsRefPtr<nsROCSSPrimitiveValue> cssValue = nullptr;
nsIFrame* frame = element->GetPrimaryFrame();
if (frame && !aPseudoElement.IsEmpty()) {
if (aPseudoElement.EqualsLiteral("::before")) {
frame = nsLayoutUtils::GetBeforeFrame(frame);
} else if (aPseudoElement.EqualsLiteral("::after")) {
frame = nsLayoutUtils::GetAfterFrame(frame);
} else {
return NS_ERROR_INVALID_ARG;
}
}
if (frame && nsLayoutUtils::AreAsyncAnimationsEnabled()) {
if (aProperty.EqualsLiteral("opacity")) {
Layer* layer =

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

@ -3904,6 +3904,9 @@ nsDocument::DeleteShell()
if (IsEventHandlingEnabled()) {
RevokeAnimationFrameNotifications();
}
if (nsPresContext* presContext = mPresShell->GetPresContext()) {
presContext->RefreshDriver()->CancelPendingEvents(this);
}
// When our shell goes away, request that all our images be immediately
// discarded, so we don't carry around decoded image data for a document we
@ -9213,15 +9216,32 @@ NotifyPageHide(nsIDocument* aDocument, void* aData)
return true;
}
static void
DispatchCustomEventWithFlush(nsINode* aTarget, const nsAString& aEventType,
bool aBubbles, bool aOnlyChromeDispatch)
{
nsCOMPtr<nsIDOMEvent> event;
NS_NewDOMEvent(getter_AddRefs(event), aTarget, nullptr, nullptr);
nsresult rv = event->InitEvent(aEventType, aBubbles, false);
if (NS_FAILED(rv)) {
return;
}
event->SetTrusted(true);
if (aOnlyChromeDispatch) {
event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
}
if (nsIPresShell* shell = aTarget->OwnerDoc()->GetShell()) {
shell->GetPresContext()->
RefreshDriver()->ScheduleEventDispatch(aTarget, event);
}
}
static void
DispatchFullScreenChange(nsIDocument* aTarget)
{
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(aTarget,
NS_LITERAL_STRING("mozfullscreenchange"),
true,
false);
asyncDispatcher->PostDOMEvent();
DispatchCustomEventWithFlush(
aTarget, NS_LITERAL_STRING("mozfullscreenchange"),
/* Bubbles */ true, /* OnlyChrome */ false);
}
void
@ -11167,11 +11187,10 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
// Dispatch MozDOMFullscreen:Exited to the last document in
// the list since we want this event to follow the same path
// MozDOMFullscreen:Entered dispatched.
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(changed.LastElement(),
NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
true, true);
asyncDispatcher->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
changed.LastElement(), ToSupports(changed.LastElement()),
NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
// Move the top-level window out of fullscreen mode.
FullscreenRoots::Remove(root);
SetWindowFullScreen(root, false);
@ -11250,9 +11269,10 @@ nsDocument::RestorePreviousFullScreenState()
// If we are fully exiting fullscreen, don't touch anything here,
// just wait for the window to get out from fullscreen first.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
(new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
/* Bubbles */ true, /* ChromeOnly */ true))->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
/* Bubbles */ true, /* Cancelable */ false,
/* DefaultAction */ nullptr);
} else {
SetWindowFullScreen(this, false);
}
@ -11295,11 +11315,9 @@ nsDocument::RestorePreviousFullScreenState()
if (!nsContentUtils::HaveEqualPrincipals(fullScreenDoc, doc) ||
(!nsContentUtils::IsSitePermAllow(doc->NodePrincipal(), "fullscreen") &&
!static_cast<nsDocument*>(doc)->mIsApprovedForFullscreen)) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(
doc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
DispatchCustomEventWithFlush(
doc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
}
}
break;
@ -11691,9 +11709,9 @@ nsDocument::RequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
if (XRE_GetProcessType() == GeckoProcessType_Content) {
// If we are not the top level process, dispatch an event to make
// our parent process go fullscreen first.
(new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:Request"),
/* Bubbles */ true, /* ChromeOnly */ true))->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Request"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
} else {
// Make the window fullscreen.
FullscreenRequest* lastRequest = sPendingFullscreenRequests.getLast();
@ -11820,13 +11838,6 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
}
}
// Dispatch "mozfullscreenchange" events. Note this loop is in reverse
// order so that the events for the root document arrives before the leaf
// document, as required by the spec.
for (uint32_t i = 0; i < changed.Length(); ++i) {
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
}
// If this document hasn't already been approved in this session,
// check to see if the user has granted the fullscreen access
// to the document's principal's host, if it has one. Note that documents
@ -11839,17 +11850,17 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
}
FullscreenRoots::Add(this);
// If it is the first entry of the fullscreen, trigger an event so
// that the UI can response to this change, e.g. hide chrome, or
// notifying parent process to enter fullscreen. Note that chrome
// code may also want to listen to MozDOMFullscreen:NewOrigin event
// to pop up warning/approval UI.
if (!previousFullscreenDoc) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(
elem, NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(elem), NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
/* Bubbles */ true, /* Cancelable */ false, /* DefaultAction */ nullptr);
}
// The origin which is fullscreen gets changed. Trigger an event so
@ -11861,14 +11872,17 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
// shouldn't rely on this event itself.
if (aRequest.mShouldNotifyNewOrigin &&
!nsContentUtils::HaveEqualPrincipals(previousFullscreenDoc, this)) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
DispatchCustomEventWithFlush(
this, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
}
FullscreenRoots::Add(this);
// Dispatch "mozfullscreenchange" events. Note this loop is in reverse
// order so that the events for the root document arrives before the leaf
// document, as required by the spec.
for (uint32_t i = 0; i < changed.Length(); ++i) {
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
}
}
NS_IMETHODIMP

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

@ -206,7 +206,7 @@ class BlobURLsReporter final : public nsIMemoryReporter
{
EnumArg* envp = static_cast<EnumArg*>(aUserArg);
nsCOMPtr<nsIDOMBlob> tmp = do_QueryInterface(aInfo->mObject);
nsRefPtr<Blob> blob = static_cast<Blob*>(tmp.get());
nsRefPtr<mozilla::dom::Blob> blob = static_cast<mozilla::dom::Blob*>(tmp.get());
if (blob) {
NS_NAMED_LITERAL_CSTRING

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

@ -106,7 +106,7 @@ nsHostObjectURI::Serialize(mozilla::ipc::URIParams& aParams)
hostParams.principal() = info;
} else {
hostParams.principal() = void_t();
hostParams.principal() = mozilla::void_t();
}
aParams = hostParams;

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

@ -6,6 +6,8 @@
#include "nsIGlobalObject.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#include "nsHostObjectProtocolHandler.h"
nsIGlobalObject::~nsIGlobalObject()
{

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

@ -17,6 +17,7 @@
#include "nsIIOService.h"
#include "nsIExternalProtocolHandler.h"
#include "nsNetUtil.h"
#include "nsContentUtils.h"
NS_IMPL_ISUPPORTS(nsNoDataProtocolContentPolicy, nsIContentPolicy)

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

@ -77,12 +77,6 @@ extern bool gBluetoothDebugFlag;
#define BT_WARNING(msg, ...) printf("%s: " msg, __FUNCTION__, ##__VA_ARGS__)
#endif
/**
* Prints 'R'ELEASE build logs for WebBluetooth API v2.
*/
#define BT_API2_LOGR(msg, ...) \
BT_LOGR("[WEBBT-API2] " msg, ##__VA_ARGS__)
/**
* Wrap literal name and value into a BluetoothNamedValue
* and append it to the array.
@ -141,7 +135,7 @@ extern bool gBluetoothDebugFlag;
#define BT_ENSURE_TRUE_RESOLVE(x, promise, ret) \
do { \
if (MOZ_UNLIKELY(!(x))) { \
BT_API2_LOGR("BT_ENSURE_TRUE_RESOLVE(" #x ") failed"); \
BT_LOGR("BT_ENSURE_TRUE_RESOLVE(" #x ") failed"); \
(promise)->MaybeResolve(ret); \
return (promise).forget(); \
} \
@ -153,7 +147,7 @@ extern bool gBluetoothDebugFlag;
#define BT_ENSURE_TRUE_REJECT(x, promise, ret) \
do { \
if (MOZ_UNLIKELY(!(x))) { \
BT_API2_LOGR("BT_ENSURE_TRUE_REJECT(" #x ") failed"); \
BT_LOGR("BT_ENSURE_TRUE_REJECT(" #x ") failed"); \
(promise)->MaybeReject(ret); \
return (promise).forget(); \
} \

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

@ -680,7 +680,7 @@ public:
virtual void DeregisterNotification() { }
virtual void ReadRemoteRssi() { }
virtual void GetDeviceType() { }
virtual void GetDeviceType(BluetoothTypeOfDevice type) { }
virtual void SetAdvData() { }
virtual void TestCommand() { }

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

@ -875,14 +875,37 @@ BluetoothDaemonGattModule::ClientReadRemoteRssiRsp(
UnpackPDUInitOp(aPDU));
}
// Init operator class for ClientGetDeviceTypeRsp
class BluetoothDaemonGattModule::ClientGetDeviceTypeInitOp final
: private PDUInitOp
{
public:
ClientGetDeviceTypeInitOp(DaemonSocketPDU& aPDU)
: PDUInitOp(aPDU)
{ }
nsresult
operator () (BluetoothTypeOfDevice& aArg1) const
{
/* Read device type */
nsresult rv = UnpackPDU(
GetPDU(), UnpackConversion<uint8_t, BluetoothTypeOfDevice>(aArg1));
if (NS_FAILED(rv)) {
return rv;
}
WarnAboutTrailingData();
return NS_OK;
}
};
void
BluetoothDaemonGattModule::ClientGetDeviceTypeRsp(
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
BluetoothGattClientResultHandler* aRes)
{
ClientResultRunnable::Dispatch(
ClientGetDeviceTypeResultRunnable::Dispatch(
aRes, &BluetoothGattClientResultHandler::GetDeviceType,
UnpackPDUInitOp(aPDU));
ClientGetDeviceTypeInitOp(aPDU));
}
void

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

@ -227,6 +227,10 @@ protected:
typedef BluetoothResultRunnable0<BluetoothGattClientResultHandler, void>
ClientResultRunnable;
typedef BluetoothResultRunnable1<BluetoothGattClientResultHandler, void,
BluetoothTypeOfDevice, BluetoothTypeOfDevice>
ClientGetDeviceTypeResultRunnable;
typedef BluetoothResultRunnable0<BluetoothGattResultHandler, void>
ResultRunnable;
@ -455,6 +459,7 @@ protected:
class ClientScanResultInitOp;
class ClientConnectDisconnectInitOp;
class ClientReadRemoteRssiInitOp;
class ClientGetDeviceTypeInitOp;
void ClientRegisterNtf(const DaemonSocketPDUHeader& aHeader,
DaemonSocketPDU& aPDU);

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

@ -402,6 +402,12 @@ Convert(uint8_t aIn, BluetoothHandsfreeWbsConfig& aOut)
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothTypeOfDevice& aOut)
{
return Convert((int32_t)aIn, aOut);
}
nsresult
Convert(uint8_t aIn, BluetoothPropertyType& aOut)
{

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

@ -13,6 +13,11 @@ typedef
BluetoothHALInterfaceRunnable0<BluetoothGattClientResultHandler, void>
BluetoothGattClientHALResultRunnable;
typedef
BluetoothHALInterfaceRunnable1<BluetoothGattClientResultHandler, void,
BluetoothTypeOfDevice, BluetoothTypeOfDevice>
BluetoothGattClientGetDeviceTypeHALResultRunnable;
typedef
BluetoothHALInterfaceRunnable1<BluetoothGattClientResultHandler, void,
BluetoothStatus, BluetoothStatus>
@ -50,6 +55,35 @@ DispatchBluetoothGattClientHALResult(
return rv;
}
template <typename ResultRunnable, typename Tin1, typename Arg1>
static nsresult
DispatchBluetoothGattClientHALResult(
BluetoothGattClientResultHandler* aRes,
void (BluetoothGattClientResultHandler::*aMethod)(Arg1),
Tin1 aArg1,
BluetoothStatus aStatus)
{
MOZ_ASSERT(aRes);
nsRunnable* runnable;
Arg1 arg1;
if (aStatus != STATUS_SUCCESS) {
runnable = new BluetoothGattClientHALErrorRunnable(aRes,
&BluetoothGattClientResultHandler::OnError, aStatus);
} else if (NS_FAILED(Convert(aArg1, arg1))) {
runnable = new BluetoothGattClientHALErrorRunnable(aRes,
&BluetoothGattClientResultHandler::OnError, STATUS_PARM_INVALID);
} else {
runnable = new ResultRunnable(aRes, aMethod, arg1);
}
nsresult rv = NS_DispatchToMainThread(runnable);
if (NS_FAILED(rv)) {
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
}
return rv;
}
static nsresult
DispatchBluetoothGattHALResult(
BluetoothGattResultHandler* aRes,
@ -1007,22 +1041,23 @@ void
BluetoothGattClientHALInterface::GetDeviceType(
const nsAString& aBdAddr, BluetoothGattClientResultHandler* aRes)
{
int status;
int status = BT_STATUS_FAIL;
bt_device_type_t type = BT_DEVICE_DEVTYPE_BLE;
#if ANDROID_VERSION >= 19
bt_bdaddr_t bdAddr;
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
status = mInterface->get_device_type(&bdAddr);
} else {
status = BT_STATUS_PARM_INVALID;
status = BT_STATUS_SUCCESS;
type = static_cast<bt_device_type_t>(mInterface->get_device_type(&bdAddr));
}
#else
status = BT_STATUS_UNSUPPORTED;
#endif
if (aRes) {
DispatchBluetoothGattClientHALResult(
aRes, &BluetoothGattClientResultHandler::GetDeviceType,
DispatchBluetoothGattClientHALResult<
BluetoothGattClientGetDeviceTypeHALResultRunnable>(
aRes, &BluetoothGattClientResultHandler::GetDeviceType, type,
ConvertDefault(status, STATUS_FAIL));
}
}

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

@ -1355,7 +1355,6 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
int aClientIf,
const BluetoothUuid& aAppUuid)
{
BT_API2_LOGR("Client Registered, clientIf = %d", aClientIf);
MOZ_ASSERT(NS_IsMainThread());
nsString uuid;
@ -1370,9 +1369,8 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
NS_ENSURE_TRUE_VOID(bs);
if (aStatus != GATT_STATUS_SUCCESS) {
BT_API2_LOGR(
"RegisterClient failed, clientIf = %d, status = %d, appUuid = %s",
aClientIf, aStatus, NS_ConvertUTF16toUTF8(uuid).get());
BT_LOGD("RegisterClient failed: clientIf = %d, status = %d, appUuid = %s",
aClientIf, aStatus, NS_ConvertUTF16toUTF8(uuid).get());
// Notify BluetoothGatt for client disconnected
bs->DistributeSignal(
@ -1418,6 +1416,53 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
}
}
class BluetoothGattManager::ScanDeviceTypeResultHandler final
: public BluetoothGattClientResultHandler
{
public:
ScanDeviceTypeResultHandler(const nsAString& aBdAddr, int aRssi,
const BluetoothGattAdvData& aAdvData)
: mBdAddr(aBdAddr)
, mRssi(static_cast<int32_t>(aRssi))
{
mAdvData.AppendElements(aAdvData.mAdvData, sizeof(aAdvData.mAdvData));
}
void GetDeviceType(BluetoothTypeOfDevice type)
{
DistributeSignalDeviceFound(type);
}
void OnError(BluetoothStatus aStatus) override
{
DistributeSignalDeviceFound(TYPE_OF_DEVICE_BLE);
}
private:
void DistributeSignalDeviceFound(BluetoothTypeOfDevice type)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> properties;
BT_APPEND_NAMED_VALUE(properties, "Address", mBdAddr);
BT_APPEND_NAMED_VALUE(properties, "Rssi", mRssi);
BT_APPEND_NAMED_VALUE(properties, "GattAdv", mAdvData);
BT_APPEND_NAMED_VALUE(properties, "Type", static_cast<uint32_t>(type));
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
bs->DistributeSignal(NS_LITERAL_STRING("LeDeviceFound"),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(properties));
}
nsString mBdAddr;
int32_t mRssi;
nsTArray<uint8_t> mAdvData;
};
void
BluetoothGattManager::ScanResultNotification(
const nsAString& aBdAddr, int aRssi,
@ -1425,23 +1470,13 @@ BluetoothGattManager::ScanResultNotification(
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> properties;
NS_ENSURE_TRUE_VOID(sBluetoothGattClientInterface);
nsTArray<uint8_t> advData;
advData.AppendElements(aAdvData.mAdvData, sizeof(aAdvData.mAdvData));
BT_APPEND_NAMED_VALUE(properties, "Address", nsString(aBdAddr));
BT_APPEND_NAMED_VALUE(properties, "Rssi", static_cast<int32_t>(aRssi));
BT_APPEND_NAMED_VALUE(properties, "GattAdv", advData);
BT_APPEND_NAMED_VALUE(properties, "Type",
static_cast<uint32_t>(TYPE_OF_DEVICE_BLE));
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
bs->DistributeSignal(NS_LITERAL_STRING("LeDeviceFound"),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(properties));
// Distribute "LeDeviceFound" signal after we know the corresponding
// BluetoothTypeOfDevice of the device
sBluetoothGattClientInterface->GetDeviceType(
aBdAddr,
new ScanDeviceTypeResultHandler(aBdAddr, aRssi, aAdvData));
}
void
@ -1450,7 +1485,6 @@ BluetoothGattManager::ConnectNotification(int aConnId,
int aClientIf,
const nsAString& aDeviceAddr)
{
BT_API2_LOGR();
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
@ -1463,8 +1497,8 @@ BluetoothGattManager::ConnectNotification(int aConnId,
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
if (aStatus != GATT_STATUS_SUCCESS) {
BT_API2_LOGR("Connect failed, clientIf = %d, connId = %d, status = %d",
aClientIf, aConnId, aStatus);
BT_LOGD("Connect failed: clientIf = %d, connId = %d, status = %d",
aClientIf, aConnId, aStatus);
// Notify BluetoothGatt that the client remains disconnected
bs->DistributeSignal(
@ -1503,7 +1537,6 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
int aClientIf,
const nsAString& aDeviceAddr)
{
BT_API2_LOGR();
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
@ -2030,7 +2063,6 @@ BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf,
int aRssi,
BluetoothGattStatus aStatus)
{
BT_API2_LOGR();
MOZ_ASSERT(NS_IsMainThread());
BluetoothService* bs = BluetoothService::Get();
@ -2043,9 +2075,9 @@ BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf,
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
if (aStatus != GATT_STATUS_SUCCESS) { // operation failed
BT_API2_LOGR("ReadRemoteRssi failed, clientIf = %d, bdAddr = %s, " \
"rssi = %d, status = %d", aClientIf,
NS_ConvertUTF16toUTF8(aBdAddr).get(), aRssi, (int)aStatus);
BT_LOGD("ReadRemoteRssi failed: clientIf = %d, bdAddr = %s, rssi = %d, " \
"status = %d", aClientIf, NS_ConvertUTF16toUTF8(aBdAddr).get(),
aRssi, (int)aStatus);
// Reject the read remote rssi request
if (client->mReadRemoteRssiRunnable) {

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

@ -110,6 +110,7 @@ private:
class WriteCharacteristicValueResultHandler;
class ReadDescriptorValueResultHandler;
class WriteDescriptorValueResultHandler;
class ScanDeviceTypeResultHandler;
BluetoothGattManager();

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

@ -566,8 +566,6 @@ BluetoothAdapter::StartDiscovery(ErrorResult& aRv)
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
BT_API2_LOGR();
// Clear unpaired devices before start discovery
for (int32_t i = mDevices.Length() - 1; i >= 0; i--) {
if (!mDevices[i]->Paired()) {
@ -608,8 +606,6 @@ BluetoothAdapter::StopDiscovery(ErrorResult& aRv)
BluetoothService* bs = BluetoothService::Get();
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
BT_API2_LOGR();
nsRefPtr<BluetoothReplyRunnable> result =
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
promise,
@ -1193,8 +1189,6 @@ void
BluetoothAdapter::DispatchDeviceEvent(const nsAString& aType,
const BluetoothDeviceEventInit& aInit)
{
BT_API2_LOGR("aType (%s)", NS_ConvertUTF16toUTF8(aType).get());
nsRefPtr<BluetoothDeviceEvent> event =
BluetoothDeviceEvent::Constructor(this, aType, aInit);
DispatchTrustedEvent(event);

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

@ -248,7 +248,7 @@ BluetoothGatt::DiscoverServices(ErrorResult& aRv)
void
BluetoothGatt::UpdateConnectionState(BluetoothConnectionState aState)
{
BT_API2_LOGR("GATT connection state changes to: %d", int(aState));
BT_LOGR("GATT connection state changes to: %d", int(aState));
mConnectionState = aState;
// Dispatch connectionstatechanged event to application

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

@ -81,7 +81,6 @@ class GetAdaptersTask : public BluetoothReplyRunnable
const InfallibleTArray<BluetoothNamedValue>& adaptersPropertiesArray =
adaptersProperties.get_ArrayOfBluetoothNamedValue();
BT_API2_LOGR("GetAdaptersTask: len[%d]", adaptersPropertiesArray.Length());
// Append a BluetoothAdapter into adapters array for each properties array
uint32_t numAdapters = adaptersPropertiesArray.Length();
@ -114,7 +113,6 @@ BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow)
MOZ_ASSERT(aWindow);
RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
BT_API2_LOGR("aWindow %p", aWindow);
// Query adapters list from bluetooth backend
BluetoothService* bs = BluetoothService::Get();
@ -139,8 +137,6 @@ BluetoothManager::DisconnectFromOwner()
BluetoothAdapter*
BluetoothManager::GetDefaultAdapter()
{
BT_API2_LOGR("mDefaultAdapterIndex: %d", mDefaultAdapterIndex);
return DefaultAdapterExists() ? mAdapters[mDefaultAdapterIndex] : nullptr;
}
@ -185,7 +181,6 @@ void
BluetoothManager::HandleAdapterAdded(const BluetoothValue& aValue)
{
MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
BT_API2_LOGR();
AppendAdapter(aValue);
@ -230,8 +225,6 @@ BluetoothManager::ReselectDefaultAdapter()
{
// Select the first of existing/remaining adapters as default adapter
mDefaultAdapterIndex = mAdapters.IsEmpty() ? -1 : 0;
BT_API2_LOGR("mAdapters length: %d => NEW mDefaultAdapterIndex: %d",
mAdapters.Length(), mDefaultAdapterIndex);
// Notify application of default adapter change
DispatchAttributeEvent();
@ -241,8 +234,6 @@ void
BluetoothManager::DispatchAdapterEvent(const nsAString& aType,
const BluetoothAdapterEventInit& aInit)
{
BT_API2_LOGR("aType (%s)", NS_ConvertUTF16toUTF8(aType).get());
nsRefPtr<BluetoothAdapterEvent> event =
BluetoothAdapterEvent::Constructor(this, aType, aInit);
DispatchTrustedEvent(event);
@ -252,7 +243,6 @@ void
BluetoothManager::DispatchAttributeEvent()
{
MOZ_ASSERT(NS_IsMainThread());
BT_API2_LOGR();
Sequence<nsString> types;
BT_APPEND_ENUM_STRING_FALLIBLE(types,

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

@ -23,11 +23,7 @@ BluetoothReplyRunnable::BluetoothReplyRunnable(nsIDOMDOMRequest* aReq,
, mPromise(aPromise)
, mErrorStatus(STATUS_FAIL)
, mName(aName)
{
if (aPromise) {
BT_API2_LOGR("<%s>", NS_ConvertUTF16toUTF8(mName).get());
}
}
{}
void
BluetoothReplyRunnable::SetReply(BluetoothReply* aReply)
@ -61,7 +57,6 @@ BluetoothReplyRunnable::FireReplySuccess(JS::Handle<JS::Value> aVal)
// Promise
if (mPromise) {
BT_API2_LOGR("<%s>", NS_ConvertUTF16toUTF8(mName).get());
mPromise->MaybeResolve(aVal);
}
@ -82,8 +77,6 @@ BluetoothReplyRunnable::FireErrorString()
// Promise
if (mPromise) {
BT_API2_LOGR("<%s>", NS_ConvertUTF16toUTF8(mName).get());
nsresult rv =
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_BLUETOOTH, mErrorStatus);
mPromise->MaybeReject(rv);

29
dom/cache/test/mochitest/app/after_clear.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Test app for bug 1172562</title>
<script src='test.js'></script>
<script type='application/javascript;version=1.7'>
function runTests() {
return Promise.resolve()
.then(() => { return navigator.serviceWorker.ready })
.then((registration) => {
return new Promise((resolve) => {
var worker = registration.waiting || registration.active;
worker.postMessage('read');
navigator.serviceWorker.onmessage = (message) => {
if (message.data.type == 'done') {
ok(!message.data.cached, 'No cached data');
resolve();
}
};
});
})
.then(done);
}
</script>
</head>
<body onload='runTests()'>
</body>
</html>

31
dom/cache/test/mochitest/app/before_clear.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Test app for bug 1172562</title>
<script src='test.js'></script>
<script type='application/javascript;version=1.7'>
function runTests() {
return Promise.resolve()
.then(() => { return navigator.serviceWorker.ready })
.then((registration) => {
return new Promise((resolve) => {
var worker = registration.waiting || registration.active;
worker.postMessage('write');
navigator.serviceWorker.onmessage = (message) => {
if (message.data.type == 'written') {
worker.postMessage('read');
} else if (message.data.type == 'done') {
ok(message.data.cached, 'Write success');
resolve();
}
};
});
})
.then(done);
}
</script>
</head>
<body onload='runTests()'>
</body>
</html>

41
dom/cache/test/mochitest/app/index.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Test app for bug 1172562</title>
<script type='application/javascript;version=1.7'>
function ok(aCondition, aMessage) {
if (aCondition) {
alert('OK: ' + aMessage);
} else {
alert('KO: ' + aMessage);
}
}
function ready() {
alert('READY');
}
function registerServiceWorker() {
return new Promise((resolve, reject) => {
navigator.serviceWorker.ready.then(() => {
ready();
resolve();
});
navigator.serviceWorker.register('sw.js', {scope: '.'})
.then(registration => {
ok(true, 'service worker registered');
})
.catch(reject);
});
}
function runTests() {
return Promise.resolve()
.then(registerServiceWorker)
.then(ready)
}
</script>
</head>
<body onload='runTests()'>
</body>
</html>

5
dom/cache/test/mochitest/app/manifest.webapp поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
{
"name": "App",
"launch_path": "/index.html",
"description": "Test app for bug 1172562"
}

1
dom/cache/test/mochitest/app/manifest.webapp^headers^ поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
Content-Type: application/manifest+json

18
dom/cache/test/mochitest/app/sw.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,18 @@
self.addEventListener('message', (message) => {
caches.open('acache').then((cache) => {
if(message.data == 'write') {
cache.add('aurl').then(() => {
message.source.postMessage({
type: 'written'
});
});
} else if (message.data == 'read') {
cache.match('aurl').then((result) => {
message.source.postMessage({
type: 'done',
cached: !!result
});
});
}
});
});

15
dom/cache/test/mochitest/app/test.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
function ok(aCondition, aMessage) {
if (aCondition) {
alert('OK: ' + aMessage);
} else {
alert('KO: ' + aMessage);
}
}
function ready() {
alert('READY');
}
function done() {
alert('DONE');
}

3
dom/cache/test/mochitest/mochitest.ini поставляемый
Просмотреть файл

@ -23,6 +23,7 @@ support-files =
test_cache_https.js
large_url_list.js
empty.html
app/*
[test_cache.html]
[test_cache_add.html]
@ -40,6 +41,8 @@ support-files =
skip-if = buildapp == 'b2g' # bug 1162353
[test_cache_restart.html]
[test_cache_shrink.html]
[test_cache_clear_on_app_uninstall.html]
skip-if = e10s || buildapp == 'b2g' # bug 1178685
[test_cache_orphaned_cache.html]
[test_cache_orphaned_body.html]
[test_cache_untrusted.html]

163
dom/cache/test/mochitest/test_cache_clear_on_app_uninstall.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,163 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1172562 - Clear QuotaManager storage when uninstalling an app</title>
<script type='text/javascript' src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css' />
</head>
<body onload='runTests()'>
<p id='display'></p>
<div id='content' style='display: none'></div>
<pre id='test'></pre>
<script class='testbody' type='application/javascript;version=1.7'>
SimpleTest.waitForExplicitFinish();
const gOrigin = 'http://mochi.test:8888/tests/dom/cache/test/mochitest/app';
const appManifestURL = gOrigin + '/manifest.webapp';
let gApp;
function setup() {
return new Promise((resolve, reject) => {
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.pushPrefEnv({'set': [
['dom.mozBrowserFramesEnabled', true],
['dom.serviceWorkers.exemptFromPerDomainMax', true],
['dom.serviceWorkers.enabled', true],
['dom.serviceWorkers.testing.enabled', true],
['dom.caches.enabled', true],
]}, () => {
SpecialPowers.pushPermissions([
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
{ 'type': 'browser', 'allow': 1, 'context': document },
{ 'type': 'embed-apps', 'allow': 1, 'context': document }
], () => {
SpecialPowers.autoConfirmAppInstall(() => {
SpecialPowers.autoConfirmAppUninstall(resolve);
});
});
});
});
}
function installApp() {
return new Promise((resolve, reject) => {
let req = navigator.mozApps.install(appManifestURL);
req.onsuccess = function() {
gApp = req.result;
is(req.result.manifestURL, appManifestURL, 'app installed');
if (req.result.installState == 'installed') {
is(req.result.installState, 'installed', 'app downloaded');
resolve()
} else {
req.result.ondownloadapplied = function() {
is(req.result.installState, 'installed', 'app downloaded');
resolve();
}
}
}
req.onerror = reject;
});
}
function launchApp() {
if (!gApp) {
ok(false, 'No test application to launch');
return Promise.reject();
}
return new Promise((resolve, reject) => {
let iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.setAttribute('mozapp', gApp.manifestURL);
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
let message = e.detail.message;
if (/OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/READY/.exec(message)) {
ok(true, "Message from app: " + message);
resolve();
} else {
ok(false, "Unexpected message received: " + message);
}
}, false);
let domParent = document.getElementById('container');
domParent.appendChild(iframe);
SpecialPowers.wrap(iframe.contentWindow).location =
gOrigin + gApp.manifest.launch_path;
});
}
function loadControlled(aUrl) {
return new Promise((resolve, reject) => {
let iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.setAttribute('mozapp', gApp.manifestURL);
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
let message = e.detail.message;
if (/OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/DONE/.exec(message)) {
ok(true, "Messaging from app complete");
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
let domParent = document.getElementById('container');
domParent.removeChild(iframe);
resolve();
} else {
ok(false, "Unexpected message received: " + message);
}
}, false);
let domParent = document.getElementById('container');
domParent.appendChild(iframe);
SpecialPowers.wrap(iframe.contentWindow).location =
gOrigin + aUrl;
});
}
function loadBeforeClear() {
return loadControlled('/before_clear.html');
}
function loadAfterClear() {
return loadControlled('/after_clear.html');
}
function uninstallApp() {
return new Promise((resolve, reject) => {
if (!gApp) {
return reject();
}
let req = navigator.mozApps.mgmt.uninstall(gApp);
req.onsuccess = resolve;
req.onerror = reject;
});
}
function runTests() {
setup()
.then(installApp)
.then(launchApp)
.then(loadBeforeClear)
.then(uninstallApp)
.then(installApp)
.then(launchApp)
.then(loadAfterClear)
.then(uninstallApp)
.then(SimpleTest.finish)
.catch((e) => {
ok(false, 'Unexpected error ' + e.target.error.name);
SimpleTest.finish();
});
}
</script>
<div id='container'></div>
</body>
</html>

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

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(e7b44320-8255-4ad1-bbe9-d78a8a1867c9)]
[scriptable, uuid(336a8683-5626-4512-a3d5-ec280c13e5c2)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1746,7 +1746,8 @@ interface nsIDOMWindowUtils : nsISupports {
* If the property is NOT currently being animated on the compositor thread,
* returns an empty string.
*/
AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty);
AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty,
[optional] in AString aPseudoElement);
/**
* Special function that gets a property syncronously from the last composite

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

@ -10,6 +10,7 @@
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIInputStreamPump.h"
#include "nsIIOService.h"
#include "nsIProtocolHandler.h"
@ -870,6 +871,16 @@ private:
return rv;
}
// If we are loading a script for a ServiceWorker then we must not
// try to intercept it. If the interception matches the current
// ServiceWorker's scope then we could deadlock the load.
if (mWorkerPrivate->IsServiceWorker()) {
nsCOMPtr<nsIHttpChannelInternal> internal = do_QueryInterface(channel);
if (internal) {
internal->ForceNoIntercept();
}
}
if (loadInfo.mCacheStatus != ScriptLoadInfo::ToBeCached) {
rv = channel->AsyncOpen(loader, indexSupports);
if (NS_WARN_IF(NS_FAILED(rv))) {

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

@ -51,6 +51,11 @@ ServiceWorker::ServiceWorker(nsPIDOMWindow* aWindow,
MOZ_ASSERT(aInfo);
MOZ_ASSERT(mSharedWorker);
if (aWindow) {
mDocument = aWindow->GetExtantDoc();
mWindow = aWindow->GetOuterWindow();
}
// This will update our state too.
mInfo->AppendWorker(this);
}
@ -68,7 +73,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorker)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorker, DOMEventTargetHelper,
mSharedWorker)
mSharedWorker, mDocument, mWindow)
JSObject*
ServiceWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
@ -97,9 +102,12 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
return;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetParentObject());
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(new ServiceWorkerClientInfo(doc));
MOZ_ASSERT(mDocument && mWindow,
"Cannot call PostMessage on a ServiceWorker object that doesn't "
"have a window");
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(
new ServiceWorkerClientInfo(mDocument, mWindow));
workerPrivate->PostMessageToServiceWorker(aCx, aMessage, aTransferable,
clientInfo, aRv);

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

@ -11,6 +11,7 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ServiceWorkerBinding.h" // For ServiceWorkerState.
class nsIDocument;
class nsPIDOMWindow;
namespace mozilla {
@ -91,6 +92,10 @@ private:
// can be released and recreated as required rather than re-implement some of
// the SharedWorker logic.
nsRefPtr<SharedWorker> mSharedWorker;
// We need to keep the document and window alive for PostMessage to be able
// to access them.
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsPIDOMWindow> mWindow;
};
} // namespace workers

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

@ -28,7 +28,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc,
nsPIDOMWindow* aWindow)
: mWindowId(0)
{
MOZ_ASSERT(aDoc);
@ -53,7 +54,7 @@ ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
NS_WARNING("Failed to get focus information.");
}
nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aDoc->GetWindow());
nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aWindow);
MOZ_ASSERT(outerWindow);
if (!outerWindow->IsTopLevelWindow()) {
mFrameType = FrameType::Nested;

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

@ -14,6 +14,9 @@
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/ClientBinding.h"
class nsIDocument;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
namespace workers {
@ -29,7 +32,7 @@ class ServiceWorkerClientInfo final
friend class ServiceWorkerWindowClient;
public:
explicit ServiceWorkerClientInfo(nsIDocument* aDoc);
ServiceWorkerClientInfo(nsIDocument* aDoc, nsPIDOMWindow* aWindow);
private:
nsString mClientId;

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

@ -3551,7 +3551,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut
if (!isNavigation) {
MOZ_ASSERT(aDoc);
aRv = GetDocumentController(aDoc->GetInnerWindow(), getter_AddRefs(serviceWorker));
clientInfo = new ServiceWorkerClientInfo(aDoc);
clientInfo = new ServiceWorkerClientInfo(aDoc, aDoc->GetWindow());
} else {
nsCOMPtr<nsIChannel> internalChannel;
aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
@ -3924,7 +3924,7 @@ EnumControlledDocuments(nsISupports* aKey,
return PL_DHASH_NEXT;
}
ServiceWorkerClientInfo clientInfo(document);
ServiceWorkerClientInfo clientInfo(document, document->GetWindow());
data->mDocuments.AppendElement(clientInfo);
return PL_DHASH_NEXT;

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

@ -87,7 +87,8 @@ public:
ErrorResult result;
//FIXME(catalinb): Bug 1144660 - check if we are allowed to focus here.
window->Focus(result);
clientInfo.reset(new ServiceWorkerClientInfo(window->GetDocument()));
clientInfo.reset(new ServiceWorkerClientInfo(window->GetDocument(),
window->GetOuterWindow()));
}
DispatchResult(Move(clientInfo));

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

@ -11,6 +11,7 @@
#include "nsCOMPtr.h"
#include "nscore.h"
class nsILoadInfo;
class nsIPrincipal;
namespace IPC {

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

@ -286,12 +286,7 @@ ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder,
if (aProperty == eCSSProperty_transform && aFrame->Preserves3D()) {
return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty);
}
nsIContent* content = aFrame->GetContent();
if (content) {
return nsLayoutUtils::HasCurrentAnimationsForProperties(content, &aProperty, 1);
}
return false;
return nsLayoutUtils::HasCurrentAnimationsForProperties(aFrame, &aProperty, 1);
}
/* static */ bool

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

@ -4773,11 +4773,10 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
if (canDraw2D) {
// If the container's transform is animated off main thread, fix a suitable scale size
// for animation
if (aContainerFrame->GetContent() &&
aContainerItem &&
if (aContainerItem &&
aContainerItem->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
nsLayoutUtils::HasAnimationsForCompositor(
aContainerFrame->GetContent(), eCSSProperty_transform)) {
aContainerFrame, eCSSProperty_transform)) {
// Use the size of the nearest widget as the maximum size. This
// is important since it might be a popup that is bigger than the
// pres context's size.
@ -4795,7 +4794,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
// compute scale using the animation on the container (ignoring
// its ancestors)
scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(
aContainerFrame->GetContent(), aVisibleRect.Size(),
aContainerFrame, aVisibleRect.Size(),
displaySize);
// multiply by the scale inherited from ancestors
scale.width *= aIncomingScale.mXScale;

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

@ -515,14 +515,11 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
RestyleManager::GetMaxAnimationGenerationForFrame(aFrame);
aLayer->SetAnimationGeneration(animationGeneration);
nsIContent* content = aFrame->GetContent();
if (!content) {
return;
}
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* transitions =
nsTransitionManager::GetAnimationsForCompositor(content, aProperty);
presContext->TransitionManager()->GetAnimationsForCompositor(aFrame, aProperty);
AnimationCollection* animations =
nsAnimationManager::GetAnimationsForCompositor(content, aProperty);
presContext->AnimationManager()->GetAnimationsForCompositor(aFrame, aProperty);
if (!animations && !transitions) {
return;
@ -723,8 +720,7 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
nsRect overflowRect = aFrame->GetVisualOverflowRect();
if (aFrame->IsTransformed() &&
nsLayoutUtils::HasAnimationsForCompositor(aFrame->GetContent(),
eCSSProperty_transform)) {
nsLayoutUtils::HasAnimationsForCompositor(aFrame, eCSSProperty_transform)) {
/**
* Add a fuzz factor to the overflow rectangle so that elements only just
* out of view are pulled into the display list, so they can be
@ -3856,11 +3852,8 @@ nsDisplayOpacity::NeedsActiveLayer(nsDisplayListBuilder* aBuilder)
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_opacity) &&
!IsItemTooSmallForActiveLayer(this))
return true;
if (mFrame->GetContent()) {
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
eCSSProperty_opacity)) {
return true;
}
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame, eCSSProperty_opacity)) {
return true;
}
return false;
}
@ -5087,9 +5080,7 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
// might have only just had its transform animated in which case
// the ActiveLayerManager may not have been notified yet.
if (!ActiveLayerTracker::IsStyleMaybeAnimated(aFrame, eCSSProperty_transform) &&
(!aFrame->GetContent() ||
!nsLayoutUtils::HasAnimationsForCompositor(aFrame->GetContent(),
eCSSProperty_transform))) {
!nsLayoutUtils::HasAnimationsForCompositor(aFrame, eCSSProperty_transform)) {
if (aLogAnimations) {
nsCString message;
message.AppendLiteral("Performance warning: Async animation disabled because frame was not marked active for transform animation");
@ -5245,11 +5236,8 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_transform) &&
!IsItemTooSmallForActiveLayer(this))
return LAYER_ACTIVE;
if (mFrame->GetContent()) {
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
eCSSProperty_transform)) {
return LAYER_ACTIVE;
}
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame, eCSSProperty_transform)) {
return LAYER_ACTIVE;
}
const nsStyleDisplay* disp = mFrame->StyleDisplay();

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

@ -372,81 +372,79 @@ TextAlignTrueEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
}
bool
nsLayoutUtils::HasAnimationsForCompositor(nsIContent* aContent,
nsLayoutUtils::HasAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty)
{
return nsAnimationManager::GetAnimationsForCompositor(aContent, aProperty) ||
nsTransitionManager::GetAnimationsForCompositor(aContent, aProperty);
}
static AnimationCollection*
GetAnimationsOrTransitions(nsIContent* aContent,
nsIAtom* aAnimationProperty,
nsCSSProperty aProperty)
{
AnimationCollection* collection =
static_cast<AnimationCollection*>(aContent->GetProperty(
aAnimationProperty));
if (collection) {
bool propertyMatches = collection->HasAnimationOfProperty(aProperty);
if (propertyMatches) {
return collection;
}
}
return nullptr;
nsPresContext* presContext = aFrame->PresContext();
return presContext->AnimationManager()->GetAnimationsForCompositor(aFrame, aProperty) ||
presContext->TransitionManager()->GetAnimationsForCompositor(aFrame, aProperty);
}
bool
nsLayoutUtils::HasAnimations(nsIContent* aContent,
nsLayoutUtils::HasAnimations(const nsIFrame* aFrame,
nsCSSProperty aProperty)
{
if (!aContent->MayHaveAnimations())
return false;
return GetAnimationsOrTransitions(aContent, nsGkAtoms::animationsProperty,
aProperty) ||
GetAnimationsOrTransitions(aContent, nsGkAtoms::transitionsProperty,
aProperty);
}
bool
nsLayoutUtils::HasCurrentAnimations(nsIContent* aContent,
nsIAtom* aAnimationProperty)
{
if (!aContent->MayHaveAnimations())
return false;
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
static_cast<AnimationCollection*>(
aContent->GetProperty(aAnimationProperty));
return (collection && collection->HasCurrentAnimations());
presContext->AnimationManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasAnimationOfProperty(aProperty)) {
return true;
}
collection =
presContext->TransitionManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasAnimationOfProperty(aProperty)) {
return true;
}
return false;
}
bool
nsLayoutUtils::HasCurrentAnimationsForProperties(nsIContent* aContent,
nsLayoutUtils::HasCurrentAnimations(const nsIFrame* aFrame)
{
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
presContext->AnimationManager()->GetAnimationCollection(aFrame);
return collection &&
collection->HasCurrentAnimations();
}
bool
nsLayoutUtils::HasCurrentTransitions(const nsIFrame* aFrame)
{
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
presContext->TransitionManager()->GetAnimationCollection(aFrame);
return collection &&
collection->HasCurrentAnimations();
}
bool
nsLayoutUtils::HasCurrentAnimationsForProperties(const nsIFrame* aFrame,
const nsCSSProperty* aProperties,
size_t aPropertyCount)
{
if (!aContent->MayHaveAnimations())
return false;
static nsIAtom* const sAnimProps[] = { nsGkAtoms::transitionsProperty,
nsGkAtoms::animationsProperty,
nullptr };
for (nsIAtom* const* animProp = sAnimProps; *animProp; animProp++) {
AnimationCollection* collection =
static_cast<AnimationCollection*>(aContent->GetProperty(*animProp));
if (collection &&
collection->HasCurrentAnimationsForProperties(aProperties,
aPropertyCount)) {
return true;
}
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* collection =
presContext->AnimationManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasCurrentAnimationsForProperties(aProperties,
aPropertyCount)) {
return true;
}
collection =
presContext->TransitionManager()->GetAnimationCollection(aFrame);
if (collection &&
collection->HasCurrentAnimationsForProperties(aProperties,
aPropertyCount)) {
return true;
}
return false;
}
static gfxSize
GetScaleForValue(const StyleAnimationValue& aValue, nsIFrame* aFrame)
GetScaleForValue(const StyleAnimationValue& aValue, const nsIFrame* aFrame)
{
if (!aFrame) {
NS_WARNING("No frame.");
@ -491,7 +489,7 @@ GetSuitableScale(float aMaxScale, float aMinScale,
}
static void
GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
GetMinAndMaxScaleForAnimationProperty(const nsIFrame* aFrame,
AnimationCollection* aAnimations,
gfxSize& aMaxScale,
gfxSize& aMinScale)
@ -507,14 +505,12 @@ GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
if (prop.mProperty == eCSSProperty_transform) {
for (uint32_t segIdx = prop.mSegments.Length(); segIdx-- != 0; ) {
AnimationPropertySegment& segment = prop.mSegments[segIdx];
gfxSize from = GetScaleForValue(segment.mFromValue,
aContent->GetPrimaryFrame());
gfxSize from = GetScaleForValue(segment.mFromValue, aFrame);
aMaxScale.width = std::max<float>(aMaxScale.width, from.width);
aMaxScale.height = std::max<float>(aMaxScale.height, from.height);
aMinScale.width = std::min<float>(aMinScale.width, from.width);
aMinScale.height = std::min<float>(aMinScale.height, from.height);
gfxSize to = GetScaleForValue(segment.mToValue,
aContent->GetPrimaryFrame());
gfxSize to = GetScaleForValue(segment.mToValue, aFrame);
aMaxScale.width = std::max<float>(aMaxScale.width, to.width);
aMaxScale.height = std::max<float>(aMaxScale.height, to.height);
aMinScale.width = std::min<float>(aMinScale.width, to.width);
@ -526,7 +522,7 @@ GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
}
gfxSize
nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent,
nsLayoutUtils::ComputeSuitableScaleForAnimation(const nsIFrame* aFrame,
const nsSize& aVisibleSize,
const nsSize& aDisplaySize)
{
@ -534,20 +530,21 @@ nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent,
std::numeric_limits<gfxFloat>::min());
gfxSize minScale(std::numeric_limits<gfxFloat>::max(),
std::numeric_limits<gfxFloat>::max());
nsPresContext* presContext = aFrame->PresContext();
AnimationCollection* animations =
nsAnimationManager::GetAnimationsForCompositor(aContent,
eCSSProperty_transform);
presContext->AnimationManager()->GetAnimationsForCompositor(
aFrame, eCSSProperty_transform);
if (animations) {
GetMinAndMaxScaleForAnimationProperty(aContent, animations,
GetMinAndMaxScaleForAnimationProperty(aFrame, animations,
maxScale, minScale);
}
animations =
nsTransitionManager::GetAnimationsForCompositor(aContent,
eCSSProperty_transform);
presContext->TransitionManager()->GetAnimationsForCompositor(
aFrame, eCSSProperty_transform);
if (animations) {
GetMinAndMaxScaleForAnimationProperty(aContent, animations,
GetMinAndMaxScaleForAnimationProperty(aFrame, animations,
maxScale, minScale);
}

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

@ -2135,32 +2135,48 @@ public:
bool clear);
/**
* Returns true if the content node has animations or transitions that can be
* Given a frame with possibly animated content, finds the content node
* that contains its animations as well as the frame's pseudo-element type
* relative to the resulting content node. Returns true if animated content
* was found, otherwise it returns false and the output parameters are
* undefined.
*/
static bool GetAnimationContent(const nsIFrame* aFrame,
nsIContent* &aContentResult,
nsCSSPseudoElements::Type &aPseudoTypeResult);
/**
* Returns true if the frame has animations or transitions that can be
* performed on the compositor.
*/
static bool HasAnimationsForCompositor(nsIContent* aContent,
static bool HasAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty);
/**
* Returns true if the content node has animations or transitions for the
* Returns true if the frame has animations or transitions for the
* property.
*/
static bool HasAnimations(nsIContent* aContent, nsCSSProperty aProperty);
static bool HasAnimations(const nsIFrame* aFrame, nsCSSProperty aProperty);
/**
* Returns true if the content node has any current animations or transitions
* (depending on the value of |aAnimationProperty|).
* Returns true if the frame has any current animations.
* A current animation is any animation that has not yet finished playing
* including paused animations.
*/
static bool HasCurrentAnimations(nsIContent* aContent,
nsIAtom* aAnimationProperty);
static bool HasCurrentAnimations(const nsIFrame* aFrame);
/**
* Returns true if the content node has any current animations or transitions
* Returns true if the frame has any current transitions.
* A current transition is any transition that has not yet finished playing
* including paused transitions.
*/
static bool HasCurrentTransitions(const nsIFrame* aFrame);
/**
* Returns true if the frame has any current animations or transitions
* for any of the specified properties.
*/
static bool HasCurrentAnimationsForProperties(nsIContent* aContent,
static bool HasCurrentAnimationsForProperties(const nsIFrame* aFrame,
const nsCSSProperty* aProperties,
size_t aPropertyCount);
@ -2175,7 +2191,7 @@ public:
static bool IsAnimationLoggingEnabled();
/**
* Find a suitable scale for an element (aContent) over the course of any
* Find a suitable scale for a element (aFrame's content) over the course of any
* animations and transitions of the CSS transform property on the
* element that run on the compositor thread.
* It will check the maximum and minimum scale during the animations and
@ -2185,7 +2201,7 @@ public:
* @param aVisibleSize is the size of the area we want to paint
* @param aDisplaySize is the size of the display area of the pres context
*/
static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent,
static gfxSize ComputeSuitableScaleForAnimation(const nsIFrame* aFrame,
const nsSize& aVisibleSize,
const nsSize& aDisplaySize);

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

@ -27,6 +27,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/IntegerRange.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsRefreshDriver.h"
#include "nsITimer.h"
@ -1341,6 +1342,7 @@ nsRefreshDriver::ObserverCount() const
// style changes, etc.
sum += mStyleFlushObservers.Length();
sum += mLayoutFlushObservers.Length();
sum += mPendingEvents.Length();
sum += mFrameRequestCallbackDocs.Length();
sum += mThrottledFrameRequestCallbackDocs.Length();
sum += mViewManagerFlushIsPending;
@ -1476,6 +1478,17 @@ TakeFrameRequestCallbacksFrom(nsIDocument* aDocument,
aDocument->TakeFrameRequestCallbacks(aTarget.LastElement().mCallbacks);
}
void
nsRefreshDriver::DispatchPendingEvents()
{
// Swap out the current pending events
nsTArray<PendingEvent> pendingEvents(Move(mPendingEvents));
for (PendingEvent& event : pendingEvents) {
bool dummy;
event.mTarget->DispatchEvent(event.mEvent, &dummy);
}
}
void
nsRefreshDriver::RunFrameRequestCallbacks(int64_t aNowEpoch, TimeStamp aNowTime)
{
@ -1657,6 +1670,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
if (i == 0) {
// This is the Flush_Style case.
DispatchPendingEvents();
RunFrameRequestCallbacks(aNowEpoch, aNowTime);
if (mPresContext && mPresContext->GetPresShell()) {
@ -2131,4 +2145,22 @@ nsRefreshDriver::RevokeFrameRequestCallbacks(nsIDocument* aDocument)
// running; that will happen automatically when it fires.
}
void
nsRefreshDriver::ScheduleEventDispatch(nsINode* aTarget, nsIDOMEvent* aEvent)
{
mPendingEvents.AppendElement(PendingEvent{aTarget, aEvent});
// make sure that the timer is running
EnsureTimerStarted();
}
void
nsRefreshDriver::CancelPendingEvents(nsIDocument* aDocument)
{
for (auto i : Reversed(MakeRange(mPendingEvents.Length()))) {
if (mPendingEvents[i].mTarget->OwnerDoc() == aDocument) {
mPendingEvents.RemoveElementAt(i);
}
}
}
#undef LOG

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

@ -29,6 +29,8 @@ class nsPresContext;
class nsIPresShell;
class nsIDocument;
class imgIRequest;
class nsIDOMEvent;
class nsINode;
namespace mozilla {
class RefreshDriverTimer;
@ -222,6 +224,17 @@ public:
*/
void RevokeFrameRequestCallbacks(nsIDocument* aDocument);
/**
* Queue a new event to dispatch in next tick before the style flush
*/
void ScheduleEventDispatch(nsINode* aTarget, nsIDOMEvent* aEvent);
/**
* Cancel all pending events scheduled by ScheduleEventDispatch which
* targets any node in aDocument.
*/
void CancelPendingEvents(nsIDocument* aDocument);
/**
* Tell the refresh driver that it is done driving refreshes and
* should stop its timer and forget about its pres context. This may
@ -308,6 +321,7 @@ private:
};
typedef nsClassHashtable<nsUint32HashKey, ImageStartData> ImageStartTable;
void DispatchPendingEvents();
void RunFrameRequestCallbacks(int64_t aNowEpoch, mozilla::TimeStamp aNowTime);
void Tick(int64_t aNowEpoch, mozilla::TimeStamp aNowTime);
@ -403,6 +417,11 @@ private:
RequestTable mRequests;
ImageStartTable mStartTable;
struct PendingEvent {
nsCOMPtr<nsINode> mTarget;
nsCOMPtr<nsIDOMEvent> mEvent;
};
nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
nsAutoTArray<nsIPresShell*, 16> mPresShellsToInvalidateIfHidden;
@ -410,6 +429,7 @@ private:
nsTArray<nsIDocument*> mFrameRequestCallbackDocs;
nsTArray<nsIDocument*> mThrottledFrameRequestCallbackDocs;
nsTObserverArray<nsAPostRefreshObserver*> mPostRefreshObservers;
nsTArray<PendingEvent> mPendingEvents;
// Helper struct for processing image requests
struct ImageRequestParameters {

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

@ -1082,7 +1082,7 @@ nsIFrame::IsTransformed() const
(StyleDisplay()->HasTransform(this) ||
IsSVGTransformed() ||
(mContent &&
nsLayoutUtils::HasAnimationsForCompositor(mContent,
nsLayoutUtils::HasAnimationsForCompositor(this,
eCSSProperty_transform) &&
IsFrameOfType(eSupportsCSSTransforms) &&
mContent->GetPrimaryFrame() == this)));
@ -1096,7 +1096,7 @@ nsIFrame::HasOpacityInternal(float aThreshold) const
return StyleDisplay()->mOpacity < aThreshold ||
(displayStyle->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) ||
(mContent &&
nsLayoutUtils::HasAnimationsForCompositor(mContent,
nsLayoutUtils::HasAnimationsForCompositor(this,
eCSSProperty_opacity) &&
mContent->GetPrimaryFrame() == this);
}
@ -1946,7 +1946,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
if (disp->mOpacity == 0.0 && aBuilder->IsForPainting() &&
!aBuilder->WillComputePluginGeometry() &&
!(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
!nsLayoutUtils::HasAnimations(mContent, eCSSProperty_opacity) &&
!nsLayoutUtils::HasAnimations(this, eCSSProperty_opacity) &&
!needEventRegions) {
return;
}

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

@ -2591,7 +2591,7 @@ public:
*
* @return whether the frame correspods to generated content
*/
bool IsGeneratedContentFrame() {
bool IsGeneratedContentFrame() const {
return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
}

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

@ -134,15 +134,45 @@ CommonAnimationManager::NeedsRefresh() const
}
AnimationCollection*
CommonAnimationManager::GetAnimationsForCompositor(nsIContent* aContent,
nsIAtom* aElementProperty,
CommonAnimationManager::GetAnimationCollection(const nsIFrame* aFrame)
{
nsIContent* content = aFrame->GetContent();
if (!content) {
return nullptr;
}
nsIAtom* animProp;
if (aFrame->IsGeneratedContentFrame()) {
nsIFrame* parent = aFrame->GetParent();
if (parent->IsGeneratedContentFrame()) {
return nullptr;
}
nsIAtom* name = content->NodeInfo()->NameAtom();
if (name == nsGkAtoms::mozgeneratedcontentbefore) {
animProp = GetAnimationsBeforeAtom();
} else if (name == nsGkAtoms::mozgeneratedcontentafter) {
animProp = GetAnimationsAfterAtom();
} else {
return nullptr;
}
content = content->GetParent();
if (!content) {
return nullptr;
}
} else {
if (!content->MayHaveAnimations()) {
return nullptr;
}
animProp = GetAnimationsAtom();
}
return static_cast<AnimationCollection*>(content->GetProperty(animProp));
}
AnimationCollection*
CommonAnimationManager::GetAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty)
{
if (!aContent->MayHaveAnimations())
return nullptr;
AnimationCollection* collection =
static_cast<AnimationCollection*>(aContent->GetProperty(aElementProperty));
AnimationCollection* collection = GetAnimationCollection(aFrame);
if (!collection ||
!collection->HasAnimationOfProperty(aProperty) ||
!collection->CanPerformOnCompositorThread(
@ -337,11 +367,12 @@ CommonAnimationManager::GetAnimations(dom::Element *aElement,
&AnimationCollection::PropertyDtor, false);
if (NS_FAILED(rv)) {
NS_WARNING("SetProperty failed");
delete collection;
// The collection must be destroyed via PropertyDtor, otherwise
// mCalledPropertyDtor assertion is triggered in destructor.
AnimationCollection::PropertyDtor(aElement, propName, collection, nullptr);
return nullptr;
}
if (propName == nsGkAtoms::animationsProperty ||
propName == nsGkAtoms::transitionsProperty) {
if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
aElement->SetMayHaveAnimations();
}
@ -577,21 +608,12 @@ bool
AnimationCollection::CanPerformOnCompositorThread(
CanAnimateFlags aFlags) const
{
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement);
if (!frame) {
dom::Element* element = GetElementToRestyle();
if (!element) {
return false;
}
if (mElementProperty != nsGkAtoms::transitionsProperty &&
mElementProperty != nsGkAtoms::animationsProperty) {
if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
nsCString message;
message.AppendLiteral("Gecko bug: Async animation of pseudoelements"
" not supported. See bug 771367 (");
message.Append(nsAtomCString(mElementProperty));
message.Append(")");
LogAsyncAnimationFailure(message, mElement);
}
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(element);
if (!frame) {
return false;
}
@ -628,7 +650,7 @@ AnimationCollection::CanPerformOnCompositorThread(
for (size_t propIdx = 0, propEnd = effect->Properties().Length();
propIdx != propEnd; ++propIdx) {
const AnimationProperty& prop = effect->Properties()[propIdx];
if (!CanAnimatePropertyOnCompositor(mElement,
if (!CanAnimatePropertyOnCompositor(element,
prop.mProperty,
aFlags) ||
IsCompositorAnimationDisabledForFrame(frame)) {
@ -839,10 +861,15 @@ AnimationCollection::CanThrottleTransformChanges(TimeStamp aTime)
return true;
}
dom::Element* element = GetElementToRestyle();
if (!element) {
return false;
}
// If the nearest scrollable ancestor has overflow:hidden,
// we don't care about overflow.
nsIScrollableFrame* scrollable = nsLayoutUtils::GetNearestScrollableFrame(
nsLayoutUtils::GetStyleFrame(mElement));
nsLayoutUtils::GetStyleFrame(element));
if (!scrollable) {
return true;
}
@ -860,7 +887,11 @@ AnimationCollection::CanThrottleTransformChanges(TimeStamp aTime)
bool
AnimationCollection::CanThrottleAnimation(TimeStamp aTime)
{
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(mElement);
dom::Element* element = GetElementToRestyle();
if (!element) {
return false;
}
nsIFrame* frame = nsLayoutUtils::GetStyleFrame(element);
if (!frame) {
return false;
}

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

@ -161,19 +161,26 @@ protected:
return false;
}
public:
// Return an AnimationCollection* if we have an animation for
// the element aContent and pseudo-element indicator aElementProperty
// that can be performed on the compositor thread (as defined by
// AnimationCollection::CanPerformOnCompositorThread).
// the frame aFrame that can be performed on the compositor thread (as
// defined by AnimationCollection::CanPerformOnCompositorThread).
//
// Note that this does not test whether the element's layer uses
// Note that this does not test whether the frame's layer uses
// off-main-thread compositing, although it does check whether
// off-main-thread compositing is enabled as a whole.
static AnimationCollection*
GetAnimationsForCompositor(nsIContent* aContent,
nsIAtom* aElementProperty,
AnimationCollection*
GetAnimationsForCompositor(const nsIFrame* aFrame,
nsCSSProperty aProperty);
// Given the frame aFrame with possibly animated content, finds its
// associated collection of animations. If it is a generated content
// frame, it may examine the parent frame to search for such animations.
AnimationCollection*
GetAnimationCollection(const nsIFrame* aFrame);
protected:
PRCList mElementCollections;
nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
bool mIsObservingRefreshDriver;

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

@ -163,13 +163,6 @@ public:
{
}
static mozilla::AnimationCollection*
GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty)
{
return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor(
aContent, nsGkAtoms::animationsProperty, aProperty);
}
void UpdateStyleAndEvents(mozilla::AnimationCollection* aEA,
mozilla::TimeStamp aRefreshTime,
mozilla::EnsureStyleRuleFlags aFlags);

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

@ -117,13 +117,6 @@ public:
typedef mozilla::AnimationCollection AnimationCollection;
static AnimationCollection*
GetAnimationsForCompositor(nsIContent* aContent, nsCSSProperty aProperty)
{
return mozilla::css::CommonAnimationManager::GetAnimationsForCompositor(
aContent, nsGkAtoms::transitionsProperty, aProperty);
}
/**
* StyleContextChanged
*

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

@ -404,19 +404,23 @@ const ExpectComparisonTo = {
};
(function() {
window.omta_todo_is = function(elem, property, expected, runningOn, desc) {
window.omta_todo_is = function(elem, property, expected, runningOn, desc,
pseudo) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc,
ExpectComparisonTo.Fail);
ExpectComparisonTo.Fail, pseudo);
};
window.omta_is = function(elem, property, expected, runningOn, desc) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc);
window.omta_is = function(elem, property, expected, runningOn, desc,
pseudo) {
return omta_is_approx(elem, property, expected, 0, runningOn, desc,
ExpectComparisonTo.Pass, pseudo);
};
// Many callers of this method will pass 'undefined' for
// expectedComparisonResult.
window.omta_is_approx = function(elem, property, expected, tolerance,
runningOn, desc, expectedComparisonResult) {
runningOn, desc, expectedComparisonResult,
pseudo) {
// Check input
const omtaProperties = [ "transform", "opacity" ];
if (omtaProperties.indexOf(property) === -1) {
@ -434,8 +438,8 @@ const ExpectComparisonTo = {
// Get actual values
var compositorStr =
SpecialPowers.DOMWindowUtils.getOMTAStyle(elem, property);
var computedStr = window.getComputedStyle(elem)[property];
SpecialPowers.DOMWindowUtils.getOMTAStyle(elem, property, pseudo);
var computedStr = window.getComputedStyle(elem, pseudo)[property];
// Prepare expected value
var expectedValue = normalize(expected);

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

@ -86,6 +86,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=964646
from, to { transform: translate(50px) }
}
#withbefore::before, #withafter::after {
content: "test";
animation: anim4 1s linear alternate 3;
display:block;
}
@keyframes multiprop {
0% {
transform: translate(10px); opacity: 0.3;
@ -1436,8 +1442,72 @@ addAsyncAnimTest(function *() {
* http://dev.w3.org/csswg/css3-animations/#the-animation-shorthand-property-
*/
// (Unlike test_animations.html, pseudo-elements are not tested here since they
// are currently not run on the compositor thread.)
/**
* Basic tests of animations on pseudo-elements
*/
addAsyncAnimTest(function *() {
new_div("");
listen();
gDiv.id = "withbefore";
yield waitForPaintsFlushed();
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":before test at 0ms", "::before");
advance_clock(400);
omta_is("transform", { ty: 40 }, RunningOn.Compositor,
":before test at 400ms", "::before");
advance_clock(800);
omta_is("transform", { ty: 80 }, RunningOn.Compositor,
":before test at 1200ms", "::before");
omta_is("transform", { ty: 0 }, RunningOn.MainThread,
":before animation should not affect element");
advance_clock(800);
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":before test at 2000ms", "::before");
advance_clock(300);
omta_is("transform", { ty: 30 }, RunningOn.Compositor,
":before test at 2300ms", "::before");
advance_clock(700);
check_events([ { type: "animationstart", animationName: "anim4",
elapsedTime: 0, pseudoElement: "::before" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 1, pseudoElement: "::before" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 2, pseudoElement: "::before" },
{ type: "animationend", animationName: "anim4",
elapsedTime: 3, pseudoElement: "::before" }]);
done_div();
new_div("");
listen();
gDiv.id = "withafter";
yield waitForPaintsFlushed();
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":after test at 0ms", "::after");
advance_clock(400);
omta_is("transform", { ty: 40 }, RunningOn.Compositor,
":after test at 400ms", "::after");
advance_clock(800);
omta_is("transform", { ty: 80 }, RunningOn.Compositor,
":after test at 1200ms", "::after");
omta_is("transform", { ty: 0 }, RunningOn.MainThread,
":before animation should not affect element");
advance_clock(800);
omta_is("transform", { ty: 0 }, RunningOn.Compositor,
":after test at 2000ms", "::after");
advance_clock(300);
omta_is("transform", { ty: 30 }, RunningOn.Compositor,
":after test at 2300ms", "::after");
advance_clock(700);
check_events([ { type: "animationstart", animationName: "anim4",
elapsedTime: 0, pseudoElement: "::after" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 1, pseudoElement: "::after" },
{ type: "animationiteration", animationName: "anim4",
elapsedTime: 2, pseudoElement: "::after" },
{ type: "animationend", animationName: "anim4",
elapsedTime: 3, pseudoElement: "::after" }]);
done_div();
});
/**
* Test handling of properties that are present in only some of the

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

@ -521,8 +521,7 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
// for it to finish before firing the popupshown event.
if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::animate,
nsGkAtoms::open, eCaseMatters) &&
nsLayoutUtils::HasCurrentAnimations(mContent,
nsGkAtoms::transitionsProperty)) {
nsLayoutUtils::HasCurrentTransitions(this)) {
mPopupShownDispatcher = new nsXULPopupShownEvent(mContent, pc);
mContent->AddSystemEventListener(NS_LITERAL_STRING("transitionend"),
mPopupShownDispatcher, false, false);

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

@ -1473,8 +1473,7 @@ nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup,
if (!popupFrame)
return;
if (nsLayoutUtils::HasCurrentAnimations(aPopup,
nsGkAtoms::transitionsProperty)) {
if (nsLayoutUtils::HasCurrentTransitions(popupFrame)) {
nsRefPtr<TransitionEnder> ender = new TransitionEnder(aPopup, aDeselectMenu);
aPopup->AddSystemEventListener(NS_LITERAL_STRING("transitionend"),
ender, false, false);

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

@ -119,7 +119,7 @@ GetInterfaces(std::vector<NetworkInterface>* aInterfaces)
int
nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
int aDropLoopback, int* aCount)
int aDropLoopback, int aDropLinkLocal, int* aCount)
{
nsresult rv;
int r;
@ -141,7 +141,6 @@ nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
for (size_t i = 0; i < num_interface; ++i) {
NetworkInterface &interface = interfaces[i];
if (nr_sockaddr_to_transport_addr((sockaddr*)&(interface.addr),
sizeof(struct sockaddr_in),
IPPROTO_UDP, 0, &(aAddrs[n].addr))) {
r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address");
return R_FAILED;
@ -154,7 +153,7 @@ nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs,
}
*aCount = n;
r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aCount);
r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aDropLinkLocal, aCount);
if (r != 0) {
return r;
}

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

@ -337,20 +337,11 @@ static int nr_transport_addr_to_praddr(nr_transport_addr *addr,
naddr->inet.ip = addr->u.addr4.sin_addr.s_addr;
break;
case NR_IPV6:
#if 0
naddr->ipv6.family = PR_AF_INET6;
naddr->ipv6.port = addr->u.addr6.sin6_port;
#ifdef LINUX
memcpy(naddr->ipv6.ip._S6_un._S6_u8,
&addr->u.addr6.sin6_addr.__in6_u.__u6_addr8, 16);
#else
memcpy(naddr->ipv6.ip._S6_un._S6_u8,
&addr->u.addr6.sin6_addr.__u6_addr.__u6_addr8, 16);
#endif
#else
// TODO: make IPv6 work
ABORT(R_INTERNAL);
#endif
naddr->ipv6.flowinfo = addr->u.addr6.sin6_flowinfo;
memcpy(&naddr->ipv6.ip, &addr->u.addr6.sin6_addr, sizeof(in6_addr));
naddr->ipv6.scope_id = addr->u.addr6.sin6_scope_id;
break;
default:
ABORT(R_BAD_ARGS);
@ -440,6 +431,7 @@ int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
int _status;
int r;
struct sockaddr_in ip4;
struct sockaddr_in6 ip6;
switch(praddr->raw.family) {
case PR_AF_INET:
@ -447,18 +439,19 @@ int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
ip4.sin_addr.s_addr = praddr->inet.ip;
ip4.sin_port = praddr->inet.port;
if ((r = nr_sockaddr_to_transport_addr((sockaddr *)&ip4,
sizeof(ip4),
protocol, keep,
addr)))
ABORT(r);
break;
case PR_AF_INET6:
#if 0
r = nr_sockaddr_to_transport_addr((sockaddr *)&praddr->raw,
sizeof(struct sockaddr_in6),IPPROTO_UDP,keep,addr);
ip6.sin6_family = PF_INET6;
ip6.sin6_port = praddr->ipv6.port;
ip6.sin6_flowinfo = praddr->ipv6.flowinfo;
memcpy(&ip6.sin6_addr, &praddr->ipv6.ip, sizeof(in6_addr));
ip6.sin6_scope_id = praddr->ipv6.scope_id;
if ((r = nr_sockaddr_to_transport_addr((sockaddr *)&ip6,protocol,keep,addr)))
ABORT(r);
break;
#endif
ABORT(R_BAD_ARGS);
default:
MOZ_ASSERT(false);
ABORT(R_BAD_ARGS);
@ -516,14 +509,16 @@ int NrSocket::create(nr_transport_addr *addr) {
switch (addr->protocol) {
case IPPROTO_UDP:
if (!(fd_ = PR_NewUDPSocket())) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket");
if (!(fd_ = PR_OpenUDPSocket(naddr.raw.family))) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create UDP socket, "
"family=%d, err=%d", naddr.raw.family, PR_GetError());
ABORT(R_INTERNAL);
}
break;
case IPPROTO_TCP:
if (!(fd_ = PR_NewTCPSocket())) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create socket");
if (!(fd_ = PR_OpenTCPSocket(naddr.raw.family))) {
r_log(LOG_GENERIC,LOG_CRIT,"Couldn't create TCP socket, "
"family=%d, err=%d", naddr.raw.family, PR_GetError());
ABORT(R_INTERNAL);
}
// Set ReuseAddr for TCP sockets to enable having several
@ -686,7 +681,8 @@ int NrSocket::sendto(const void *msg, size_t len,
if (PR_GetError() == PR_WOULD_BLOCK_ERROR)
ABORT(R_WOULDBLOCK);
r_log(LOG_GENERIC, LOG_INFO, "Error in sendto: %s", to->as_string);
r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s: %d",
to->as_string, PR_GetError());
ABORT(R_IO_ERROR);
}

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

@ -380,7 +380,8 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
bool offerer,
bool set_interface_priorities,
bool allow_loopback,
bool tcp_enabled) {
bool tcp_enabled,
bool allow_link_local) {
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer);
@ -472,6 +473,10 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
if (allow_loopback) {
NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1);
}
if (allow_link_local) {
NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1);
}
}
// Create the ICE context

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

@ -212,7 +212,8 @@ class NrIceCtx {
bool offerer,
bool set_interface_priorities = true,
bool allow_loopback = false,
bool tcp_enabled = true);
bool tcp_enabled = true,
bool allow_link_local = false);
// Deinitialize all ICE global state. Used only for testing.
static void internal_DeinitializeGlobal();

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

@ -150,6 +150,7 @@ int NrIceResolver::resolve(nr_resolver_resource *resource,
MOZ_ASSERT(allocated_resolvers_ > 0);
ASSERT_ON_THREAD(sts_thread_);
nsRefPtr<PendingResolution> pr;
uint32_t resolve_flags = 0;
if (resource->transport_protocol != IPPROTO_UDP &&
resource->transport_protocol != IPPROTO_TCP) {
@ -162,8 +163,20 @@ int NrIceResolver::resolve(nr_resolver_resource *resource,
resource->transport_protocol :
IPPROTO_UDP,
cb, cb_arg);
switch(resource->address_family) {
case AF_INET:
resolve_flags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
break;
case AF_INET6:
resolve_flags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
break;
default:
ABORT(R_BAD_ARGS);
}
if (NS_FAILED(dns_->AsyncResolve(nsAutoCString(resource->domain_name),
nsIDNSService::RESOLVE_DISABLE_IPV6, pr,
resolve_flags, pr,
sts_thread_, getter_AddRefs(pr->request_)))) {
MOZ_MTLOG(ML_ERROR, "AsyncResolve failed.");
ABORT(R_NOT_FOUND);

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

@ -122,6 +122,7 @@ int NrIceResolverFake::resolve(void *obj,
resource->transport_protocol ?
resource->transport_protocol :
IPPROTO_UDP,
resource->address_family,
cb, cb_arg);
if ((r=NR_ASYNC_TIMER_SET(fake->delay_ms_,NrIceResolverFake::resolve_cb,
@ -140,7 +141,8 @@ void NrIceResolverFake::resolve_cb(NR_SOCKET s, int how, void *cb_arg) {
MOZ_ASSERT(cb_arg);
PendingResolution *pending = static_cast<PendingResolution *>(cb_arg);
const PRNetAddr *addr=pending->resolver_->Resolve(pending->hostname_);
const PRNetAddr *addr=pending->resolver_->Resolve(pending->hostname_,
pending->address_family_);
if (addr) {
nr_transport_addr transport_addr;

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

@ -63,7 +63,16 @@ class NrIceResolverFake {
~NrIceResolverFake();
void SetAddr(const std::string& hostname, const PRNetAddr& addr) {
addrs_[hostname] = addr;
switch (addr.raw.family) {
case AF_INET:
addrs_[hostname] = addr;
break;
case AF_INET6:
addrs6_[hostname] = addr;
break;
default:
MOZ_CRASH();
}
}
nr_resolver *AllocateResolver();
@ -83,11 +92,21 @@ private:
static int cancel(void *obj, void *handle);
// Get an address.
const PRNetAddr *Resolve(const std::string& hostname) {
if (!addrs_.count(hostname))
return nullptr;
const PRNetAddr *Resolve(const std::string& hostname, int address_family) {
switch (address_family) {
case AF_INET:
if (!addrs_.count(hostname))
return nullptr;
return &addrs_[hostname];
return &addrs_[hostname];
case AF_INET6:
if (!addrs6_.count(hostname))
return nullptr;
return &addrs6_[hostname];
default:
MOZ_CRASH();
}
}
@ -96,18 +115,21 @@ private:
const std::string& hostname,
uint16_t port,
int transport,
int address_family,
int (*cb)(void *cb_arg, nr_transport_addr *addr),
void *cb_arg) :
resolver_(resolver),
hostname_(hostname),
port_(port),
transport_(transport),
address_family_(address_family),
cb_(cb), cb_arg_(cb_arg) {}
NrIceResolverFake *resolver_;
std::string hostname_;
uint16_t port_;
int transport_;
int address_family_;
int (*cb_)(void *cb_arg, nr_transport_addr *addr);
void *cb_arg_;
void *timer_handle_;
@ -115,6 +137,7 @@ private:
nr_resolver_vtbl* vtbl_;
std::map<std::string, PRNetAddr> addrs_;
std::map<std::string, PRNetAddr> addrs6_;
uint32_t delay_ms_;
int allocated_resolvers_;
};

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

@ -18,7 +18,8 @@ public:
: key_(),
is_vpn_(-1),
estimated_speed_(-1),
type_preference_(-1) {}
type_preference_(-1),
ip_version_(-1) {}
bool Init(const nr_local_addr& local_addr) {
char buf[MAXIFNAME + 41];
@ -31,6 +32,7 @@ public:
is_vpn_ = (local_addr.interface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0;
estimated_speed_ = local_addr.interface.estimated_speed;
type_preference_ = GetNetworkTypePreference(local_addr.interface.type);
ip_version_ = local_addr.addr.ip_version;
return true;
}
@ -54,6 +56,11 @@ public:
return estimated_speed_ > rhs.estimated_speed_;
}
// Prefer IPV6 over IPV4
if (ip_version_ != rhs.ip_version_) {
return ip_version_ > rhs.ip_version_;
}
// All things above are the same, we can at least sort with key.
return key_ < rhs.key_;
}
@ -82,6 +89,7 @@ private:
int is_vpn_;
int estimated_speed_;
int type_preference_;
int ip_version_;
};
class InterfacePrioritizer {

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

@ -21,42 +21,51 @@ extern "C" {
namespace {
class NetAddressAdapter {
class NetAddrCompare {
public:
MOZ_IMPLICIT NetAddressAdapter(const mozilla::net::NetAddr& netaddr)
: addr_(ntohl(netaddr.inet.ip)),
port_(ntohs(netaddr.inet.port)) {
MOZ_ASSERT(netaddr.raw.family == AF_INET);
}
bool operator()(const mozilla::net::NetAddr& lhs,
const mozilla::net::NetAddr& rhs) const {
if (lhs.raw.family != rhs.raw.family) {
return lhs.raw.family < rhs.raw.family;
}
bool operator<(const NetAddressAdapter& rhs) const {
return addr_ != rhs.addr_ ? (addr_ < rhs.addr_) : (port_ < rhs.port_);
}
bool operator!=(const NetAddressAdapter& rhs) const {
return (*this < rhs) || (rhs < *this);
}
private:
const uint32_t addr_;
const uint16_t port_;
switch (lhs.raw.family) {
case AF_INET:
if (lhs.inet.port != rhs.inet.port) {
return lhs.inet.port < rhs.inet.port;
}
return lhs.inet.ip < rhs.inet.ip;
case AF_INET6:
if (lhs.inet6.port != rhs.inet6.port) {
return lhs.inet6.port < rhs.inet6.port;
}
return memcmp(&lhs.inet6.ip, &rhs.inet6.ip, sizeof(lhs.inet6.ip)) < 0;
default:
MOZ_ASSERT(false);
}
return false;
}
};
class PendingSTUNRequest {
public:
PendingSTUNRequest(const NetAddressAdapter& netaddr, const UINT12 &id)
PendingSTUNRequest(const mozilla::net::NetAddr& netaddr, const UINT12 &id)
: id_(id),
net_addr_(netaddr),
is_id_set_(true) {}
MOZ_IMPLICIT PendingSTUNRequest(const NetAddressAdapter& netaddr)
MOZ_IMPLICIT PendingSTUNRequest(const mozilla::net::NetAddr& netaddr)
: id_(),
net_addr_(netaddr),
is_id_set_(false) {}
bool operator<(const PendingSTUNRequest& rhs) const {
if (net_addr_ != rhs.net_addr_) {
return net_addr_ < rhs.net_addr_;
if (NetAddrCompare()(net_addr_, rhs.net_addr_)) {
return true;
}
if (NetAddrCompare()(rhs.net_addr_, net_addr_)) {
return false;
}
if (!is_id_set_ && !rhs.is_id_set_) {
@ -76,7 +85,7 @@ class PendingSTUNRequest {
private:
const UINT12 id_;
const NetAddressAdapter net_addr_;
const mozilla::net::NetAddr net_addr_;
const bool is_id_set_;
};
@ -101,7 +110,7 @@ class STUNUDPSocketFilter : public nsIUDPSocketFilter {
const uint8_t *data,
uint32_t len);
std::set<NetAddressAdapter> white_list_;
std::set<mozilla::net::NetAddr, NetAddrCompare> white_list_;
std::set<PendingSTUNRequest> pending_requests_;
std::set<PendingSTUNRequest> response_allowed_;
};
@ -114,12 +123,6 @@ STUNUDPSocketFilter::FilterPacket(const mozilla::net::NetAddr *remote_addr,
uint32_t len,
int32_t direction,
bool *result) {
// Allowing IPv4 address only.
if (remote_addr->raw.family != AF_INET) {
*result = false;
return NS_OK;
}
switch (direction) {
case nsIUDPSocketFilter::SF_INCOMING:
*result = filter_incoming_packet(remote_addr, data, len);

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

@ -64,7 +64,7 @@ class BufferedStunSocketTest : public ::testing::Test {
ASSERT_EQ(0, r);
dummy_ = dummy.forget(); // Now owned by test_socket_.
r = nr_ip4_str_port_to_transport_addr(
r = nr_str_port_to_transport_addr(
(char *)"192.0.2.133", 3333, IPPROTO_TCP, &remote_addr_);
ASSERT_EQ(0, r);
@ -184,7 +184,7 @@ TEST_F(BufferedStunSocketTest, TestSendToReject) {
TEST_F(BufferedStunSocketTest, TestSendToWrongAddr) {
nr_transport_addr addr;
int r = nr_ip4_str_port_to_transport_addr(
int r = nr_str_port_to_transport_addr(
(char *)"192.0.2.134", 3333, IPPROTO_TCP, &addr);
ASSERT_EQ(0, r);

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

@ -354,8 +354,8 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void UseTestStunServer() {
SetStunServer(TestStunServer::GetInstance()->addr(),
TestStunServer::GetInstance()->port());
SetStunServer(TestStunServer::GetInstance(AF_INET)->addr(),
TestStunServer::GetInstance(AF_INET)->port());
}
void SetTurnServer(const std::string addr, uint16_t port,
@ -382,15 +382,15 @@ class IceTestPeer : public sigslot::has_slots<> {
ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers)));
}
void SetFakeResolver() {
void SetFakeResolver(const std::string& ip = g_stun_server_address,
const std::string& fqdn = g_stun_server_hostname) {
ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
if (!g_stun_server_address.empty() && !g_stun_server_hostname.empty()) {
if (!ip.empty() && !fqdn.empty()) {
PRNetAddr addr;
PRStatus status = PR_StringToNetAddr(g_stun_server_address.c_str(),
&addr);
PRStatus status = PR_StringToNetAddr(ip.c_str(), &addr);
addr.inet.port = kDefaultStunServerPort;
ASSERT_EQ(PR_SUCCESS, status);
fake_resolver_.SetAddr(g_stun_server_hostname, addr);
fake_resolver_.SetAddr(fqdn, addr);
}
ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
fake_resolver_.AllocateResolver())));
@ -1098,9 +1098,16 @@ void SchedulableTrickleCandidate::Trickle() {
class IceGatherTest : public ::testing::Test {
public:
void SetUp() {
test_utils->sts_target()->Dispatch(WrapRunnable(TestStunServer::GetInstance(),
&TestStunServer::Reset),
NS_DISPATCH_SYNC);
test_utils->sts_target()->Dispatch(
WrapRunnable(TestStunServer::GetInstance(AF_INET),
&TestStunServer::Reset),
NS_DISPATCH_SYNC);
if (TestStunServer::GetInstance(AF_INET6)) {
test_utils->sts_target()->Dispatch(
WrapRunnable(TestStunServer::GetInstance(AF_INET6),
&TestStunServer::Reset),
NS_DISPATCH_SYNC);
}
}
void TearDown() {
@ -1135,54 +1142,90 @@ class IceGatherTest : public ::testing::Test {
ASSERT_TRUE_WAIT(peer_->gathering_complete(), waitTime);
}
void UseFakeStunUdpServerWithResponse(const std::string& fake_addr,
uint16_t fake_port) {
EnsurePeer();
TestStunServer::GetInstance()->SetResponseAddr(fake_addr, fake_port);
// Sets an additional stun server
peer_->SetStunServer(TestStunServer::GetInstance()->addr(),
TestStunServer::GetInstance()->port(),
kNrIceTransportUdp);
void AddStunServerWithResponse(
const std::string& fake_addr,
uint16_t fake_port,
const std::string& fqdn,
const std::string& proto,
std::vector<NrIceStunServer>* stun_servers) {
int family;
if (fake_addr.find(':') != std::string::npos) {
family = AF_INET6;
} else {
family = AF_INET;
}
std::string stun_addr;
uint16_t stun_port;
if (proto == kNrIceTransportUdp) {
TestStunServer::GetInstance(family)->SetResponseAddr(fake_addr,
fake_port);
stun_addr = TestStunServer::GetInstance(family)->addr();
stun_port = TestStunServer::GetInstance(family)->port();
} else if (proto == kNrIceTransportTcp) {
TestStunTcpServer::GetInstance(family)->SetResponseAddr(fake_addr,
fake_port);
stun_addr = TestStunTcpServer::GetInstance(family)->addr();
stun_port = TestStunTcpServer::GetInstance(family)->port();
} else {
MOZ_CRASH();
}
if (!fqdn.empty()) {
peer_->SetFakeResolver(stun_addr, fqdn);
stun_addr = fqdn;
}
stun_servers->push_back(*NrIceStunServer::Create(stun_addr,
stun_port,
proto.c_str()));
}
void UseFakeStunTcpServerWithResponse(const std::string& fake_addr,
uint16_t fake_port) {
EnsurePeer();
TestStunTcpServer::GetInstance()->SetResponseAddr(fake_addr, fake_port);
// Sets an additional stun server
peer_->SetStunServer(TestStunTcpServer::GetInstance()->addr(),
TestStunTcpServer::GetInstance()->port(),
kNrIceTransportTcp);
}
void UseFakeStunUdpTcpServersWithResponse(const std::string& fake_udp_addr,
uint16_t fake_udp_port,
const std::string& fake_tcp_addr,
uint16_t fake_tcp_port) {
void UseFakeStunUdpServerWithResponse(
const std::string& fake_addr,
uint16_t fake_port,
const std::string& fqdn = std::string()) {
EnsurePeer();
std::vector<NrIceStunServer> stun_servers;
AddStunServerWithResponse(fake_addr, fake_port, fqdn, "udp", &stun_servers);
peer_->SetStunServers(stun_servers);
}
stun_servers.push_back(*NrIceStunServer::Create(
TestStunServer::GetInstance()->addr(),
TestStunServer::GetInstance()->port(),
kNrIceTransportUdp));
stun_servers.push_back(*NrIceStunServer::Create(
TestStunTcpServer::GetInstance()->addr(),
TestStunTcpServer::GetInstance()->port(),
kNrIceTransportTcp));
void UseFakeStunTcpServerWithResponse(
const std::string& fake_addr,
uint16_t fake_port,
const std::string& fqdn = std::string()) {
EnsurePeer();
std::vector<NrIceStunServer> stun_servers;
AddStunServerWithResponse(fake_addr, fake_port, fqdn, "tcp", &stun_servers);
peer_->SetStunServers(stun_servers);
}
void UseFakeStunUdpTcpServersWithResponse(
const std::string& fake_udp_addr,
uint16_t fake_udp_port,
const std::string& fake_tcp_addr,
uint16_t fake_tcp_port) {
EnsurePeer();
std::vector<NrIceStunServer> stun_servers;
AddStunServerWithResponse(fake_udp_addr,
fake_udp_port,
"", // no fqdn
"udp",
&stun_servers);
AddStunServerWithResponse(fake_tcp_addr,
fake_tcp_port,
"", // no fqdn
"tcp",
&stun_servers);
TestStunServer::GetInstance()->SetResponseAddr(fake_udp_addr,
fake_udp_port);
TestStunTcpServer::GetInstance()->SetResponseAddr(fake_tcp_addr,
fake_tcp_port);
// Sets an additional stun server
peer_->SetStunServers(stun_servers);
}
void UseTestStunServer() {
TestStunServer::GetInstance()->Reset();
peer_->SetStunServer(TestStunServer::GetInstance()->addr(),
TestStunServer::GetInstance()->port());
TestStunServer::GetInstance(AF_INET)->Reset();
peer_->SetStunServer(TestStunServer::GetInstance(AF_INET)->addr(),
TestStunServer::GetInstance(AF_INET)->port());
}
// NB: Only does substring matching, watch out for stuff like "1.2.3.4"
@ -1314,7 +1357,7 @@ class IceConnectTest : public ::testing::Test {
}
void UseTestStunServer() {
TestStunServer::GetInstance()->Reset();
TestStunServer::GetInstance(AF_INET)->Reset();
p1_->UseTestStunServer();
p2_->UseTestStunServer();
}
@ -1482,8 +1525,8 @@ class PrioritizerTest : public ::testing::Test {
local_addr.interface.type = type;
local_addr.interface.estimated_speed = estimated_speed;
int r = nr_ip4_str_port_to_transport_addr(str_addr.c_str(), 0,
IPPROTO_UDP, &(local_addr.addr));
int r = nr_str_port_to_transport_addr(str_addr.c_str(), 0,
IPPROTO_UDP, &(local_addr.addr));
ASSERT_EQ(0, r);
strncpy(local_addr.addr.ifname, ifname.c_str(), MAXIFNAME);
@ -1791,12 +1834,48 @@ TEST_F(IceGatherTest, VerifyTestStunTcpServer) {
" tcptype "));
}
TEST_F(IceGatherTest, VerifyTestStunServerV6) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
}
UseFakeStunUdpServerWithResponse("beef::", 3333);
Gather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 "));
}
TEST_F(IceGatherTest, VerifyTestStunServerFQDN) {
UseFakeStunUdpServerWithResponse("192.0.2.133", 3333, "stun.example.com");
Gather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
}
TEST_F(IceGatherTest, VerifyTestStunServerV6FQDN) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
}
UseFakeStunUdpServerWithResponse("beef::", 3333, "stun.example.com");
Gather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, " beef:: 3333 "));
}
TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddr) {
UseFakeStunUdpServerWithResponse("0.0.0.0", 3333);
Gather(kDefaultTimeout * 3);
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 "));
}
TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddrV6) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
}
UseFakeStunUdpServerWithResponse("::", 3333);
Gather(kDefaultTimeout * 3);
ASSERT_FALSE(StreamHasMatchingCandidate(0, " :: "));
}
TEST_F(IceGatherTest, TestStunServerReturnsPort0) {
UseFakeStunUdpServerWithResponse("192.0.2.133", 0);
Gather(kDefaultTimeout * 3);
@ -1809,35 +1888,45 @@ TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) {
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
}
TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddrV6) {
if (!TestStunServer::GetInstance(AF_INET6)) {
// No V6 addresses
return;
}
UseFakeStunUdpServerWithResponse("::1", 3333);
Gather(kDefaultTimeout * 3);
ASSERT_FALSE(StreamHasMatchingCandidate(0, " ::1 "));
}
TEST_F(IceGatherTest, TestStunServerTrickle) {
UseFakeStunUdpServerWithResponse("192.0.2.1", 3333);
TestStunServer::GetInstance()->SetActive(false);
TestStunServer::GetInstance(AF_INET)->SetActive(false);
Gather(0);
ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1"));
TestStunServer::GetInstance()->SetActive(true);
TestStunServer::GetInstance(AF_INET)->SetActive(true);
WaitForGather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1"));
}
TEST_F(IceGatherTest, TestStunTcpServerTrickle) {
UseFakeStunTcpServerWithResponse("192.0.3.1", 3333);
TestStunTcpServer::GetInstance()->SetActive(false);
TestStunTcpServer::GetInstance(AF_INET)->SetActive(false);
Gather(0);
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
TestStunTcpServer::GetInstance()->SetActive(true);
TestStunTcpServer::GetInstance(AF_INET)->SetActive(true);
WaitForGather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
}
TEST_F(IceGatherTest, TestStunTcpAndUdpServerTrickle) {
UseFakeStunUdpTcpServersWithResponse("192.0.2.1", 3333, "192.0.3.1", 3333);
TestStunServer::GetInstance()->SetActive(false);
TestStunTcpServer::GetInstance()->SetActive(false);
TestStunServer::GetInstance(AF_INET)->SetActive(false);
TestStunTcpServer::GetInstance(AF_INET)->SetActive(false);
Gather(0);
ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1", "UDP"));
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
TestStunServer::GetInstance()->SetActive(true);
TestStunTcpServer::GetInstance()->SetActive(true);
TestStunServer::GetInstance(AF_INET)->SetActive(true);
TestStunTcpServer::GetInstance(AF_INET)->SetActive(true);
WaitForGather();
ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1", "UDP"));
ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.3.1 ", " tcptype "));
@ -2863,10 +2952,18 @@ int main(int argc, char **argv)
listeners.Append(new test::RingbufferDumper(test_utils));
test_utils->sts_target()->Dispatch(
WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC);
WrapRunnableNM(&TestStunServer::GetInstance, AF_INET),
NS_DISPATCH_SYNC);
test_utils->sts_target()->Dispatch(
WrapRunnableNM(&TestStunServer::GetInstance, AF_INET6),
NS_DISPATCH_SYNC);
test_utils->sts_target()->Dispatch(
WrapRunnableNM(&TestStunTcpServer::GetInstance), NS_DISPATCH_SYNC);
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET),
NS_DISPATCH_SYNC);
test_utils->sts_target()->Dispatch(
WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET6),
NS_DISPATCH_SYNC);
int rv = RUN_ALL_TESTS();

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

@ -112,7 +112,7 @@ class MultiTcpSocketTest : public ::testing::Test {
r = 1;
for (int tries=10; tries && r; --tries) {
r = nr_ip4_str_port_to_transport_addr(
r = nr_str_port_to_transport_addr(
(char *)"127.0.0.1", EnsureEphemeral(port_s++), IPPROTO_TCP, &local);
ASSERT_EQ(0, r);

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

@ -84,7 +84,7 @@ class DummyResolver {
void **handle) {
nr_transport_addr addr;
nr_ip4_str_port_to_transport_addr(
nr_str_port_to_transport_addr(
(char *)kProxyAddr.c_str(), kProxyPort, IPPROTO_TCP, &addr);
cb(cb_arg, &addr);
@ -120,11 +120,11 @@ class ProxyTunnelSocketTest : public ::testing::Test {
nr_resolver_ = resolver_impl_.get_nr_resolver();
int r = nr_ip4_str_port_to_transport_addr(
int r = nr_str_port_to_transport_addr(
(char *)kRemoteAddr.c_str(), kRemotePort, IPPROTO_TCP, &remote_addr_);
ASSERT_EQ(0, r);
r = nr_ip4_str_port_to_transport_addr(
r = nr_str_port_to_transport_addr(
(char *)kProxyAddr.c_str(), kProxyPort, IPPROTO_TCP, &proxy_addr_);
ASSERT_EQ(0, r);

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

@ -188,6 +188,8 @@ int nr_socket_wrapped_create(nr_socket *inner, nr_socket **outp) {
// we have no reason to expect this will be initted to a nullptr yet.
TestStunServer* TestStunServer::instance;
TestStunTcpServer* TestStunTcpServer::instance;
TestStunServer* TestStunServer::instance6;
TestStunTcpServer* TestStunTcpServer::instance6;
uint16_t TestStunServer::instance_port = 3478;
uint16_t TestStunTcpServer::instance_port = 3478;
@ -243,12 +245,14 @@ int TestStunServer::TryOpenListenSocket(nr_local_addr* addr, uint16_t port) {
return 0;
}
int TestStunServer::Initialize() {
nr_local_addr addrs[100];
int TestStunServer::Initialize(int address_family) {
static const size_t max_addrs = 100;
nr_local_addr addrs[max_addrs];
int addr_ct;
int r;
int i;
r = nr_stun_find_local_addresses(addrs, 100, &addr_ct);
r = nr_stun_find_local_addresses(addrs, max_addrs, &addr_ct);
if (r) {
MOZ_MTLOG(ML_ERROR, "Couldn't retrieve addresses");
return R_INTERNAL;
@ -259,10 +263,21 @@ int TestStunServer::Initialize() {
return R_INTERNAL;
}
for (i = 0; i < addr_ct; ++i) {
if (addrs[i].addr.addr->sa_family == address_family) {
break;
}
}
if (i == addr_ct) {
MOZ_MTLOG(ML_ERROR, "No local addresses of the configured IP version");
return R_INTERNAL;
}
int tries = 100;
while (tries--) {
// Bind to the first address (arbitrarily) on configured port (default 3478)
r = TryOpenListenSocket(&addrs[0], instance_port);
// Bind on configured port (default 3478)
r = TryOpenListenSocket(&addrs[i], instance_port);
// We interpret R_ALREADY to mean the addr is probably in use. Try another.
// Otherwise, it either worked or it didn't, and we check below.
if (r != R_ALREADY) {
@ -291,7 +306,7 @@ int TestStunServer::Initialize() {
// Cache the address and port.
char addr_string[INET6_ADDRSTRLEN];
r = nr_transport_addr_get_addrstring(&addrs[0].addr, addr_string,
r = nr_transport_addr_get_addrstring(&addrs[i].addr, addr_string,
sizeof(addr_string));
if (r) {
MOZ_MTLOG(ML_ERROR, "Failed to convert listen addr to a string representation");
@ -304,12 +319,12 @@ int TestStunServer::Initialize() {
return 0;
}
TestStunServer* TestStunServer::Create() {
TestStunServer* TestStunServer::Create(int address_family) {
NR_reg_init(NR_REG_MODE_LOCAL);
ScopedDeletePtr<TestStunServer> server(new TestStunServer());
if (server->Initialize())
if (server->Initialize(address_family))
return nullptr;
NR_SOCKET fd;
@ -328,18 +343,29 @@ void TestStunServer::ConfigurePort(uint16_t port) {
instance_port = port;
}
TestStunServer* TestStunServer::GetInstance() {
if (!instance)
instance = Create();
TestStunServer* TestStunServer::GetInstance(int address_family) {
switch (address_family) {
case AF_INET:
if (!instance)
instance = Create(address_family);
MOZ_ASSERT(instance);
return instance;
MOZ_ASSERT(instance);
return instance;
case AF_INET6:
if (!instance6)
instance6 = Create(address_family);
return instance6;
default:
MOZ_CRASH();
}
}
void TestStunServer::ShutdownInstance() {
delete instance;
instance = nullptr;
delete instance6;
instance6 = nullptr;
}
@ -453,9 +479,9 @@ nsresult TestStunServer::SetResponseAddr(const std::string& addr,
uint16_t port) {
nr_transport_addr addr2;
int r = nr_ip4_str_port_to_transport_addr(addr.c_str(),
port, IPPROTO_UDP,
&addr2);
int r = nr_str_port_to_transport_addr(addr.c_str(),
port, IPPROTO_UDP,
&addr2);
if (r)
return NS_ERROR_FAILURE;
@ -479,12 +505,22 @@ void TestStunTcpServer::ConfigurePort(uint16_t port) {
instance_port = port;
}
TestStunTcpServer* TestStunTcpServer::GetInstance() {
if (!instance)
instance = Create();
TestStunTcpServer* TestStunTcpServer::GetInstance(int address_family) {
switch (address_family) {
case AF_INET:
if (!instance)
instance = Create(address_family);
MOZ_ASSERT(instance);
return instance;
MOZ_ASSERT(instance);
return instance;
case AF_INET6:
if (!instance6)
instance6 = Create(address_family);
return instance6;
default:
MOZ_CRASH();
}
}
void TestStunTcpServer::ShutdownInstance() {
@ -523,12 +559,14 @@ int TestStunTcpServer::TryOpenListenSocket(nr_local_addr* addr, uint16_t port) {
return 0;
}
TestStunTcpServer* TestStunTcpServer::Create() {
TestStunTcpServer* TestStunTcpServer::Create(int address_family) {
NR_reg_init(NR_REG_MODE_LOCAL);
ScopedDeletePtr<TestStunTcpServer> server(new TestStunTcpServer());
server->Initialize();
if (server->Initialize(address_family)) {
return nullptr;
}
nr_socket_multi_tcp_set_readable_cb(server->listen_sock_,
&TestStunServer::readable_cb, server.get());

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

@ -24,12 +24,13 @@ class TestStunServer {
public:
// Generally, you should only call API in this class from the same thread that
// the initial |GetInstance| call was made from.
static TestStunServer *GetInstance();
static TestStunServer *GetInstance(int address_family = AF_INET);
static void ShutdownInstance();
// |ConfigurePort| will only have an effect if called before the first call
// to |GetInstance| (possibly following a |ShutdownInstance| call)
static void ConfigurePort(uint16_t port);
static TestStunServer *Create();
// AF_INET, AF_INET6
static TestStunServer *Create(int address_family);
virtual ~TestStunServer();
@ -59,7 +60,7 @@ class TestStunServer {
timer_handle_(nullptr) {}
int SetInternalPort(nr_local_addr* addr, uint16_t port);
int Initialize();
int Initialize(int address_family);
static void readable_cb(NR_SOCKET sock, int how, void *cb_arg);
private:
@ -82,12 +83,13 @@ class TestStunServer {
std::map<std::string, uint32_t> received_ct_;
static TestStunServer* instance;
static TestStunServer* instance6;
static uint16_t instance_port;
};
class TestStunTcpServer: public TestStunServer {
public:
static TestStunTcpServer *GetInstance();
static TestStunTcpServer *GetInstance(int address_family);
static void ShutdownInstance();
static void ConfigurePort(uint16_t port);
virtual ~TestStunTcpServer();
@ -98,9 +100,10 @@ class TestStunTcpServer: public TestStunServer {
nsRefPtr<NrIceCtx> ice_ctx_;
private:
virtual int TryOpenListenSocket(nr_local_addr* addr, uint16_t port);
static TestStunTcpServer *Create();
static TestStunTcpServer *Create(int address_family);
static TestStunTcpServer* instance;
static TestStunTcpServer* instance6;
static uint16_t instance_port;
};
} // End of namespace mozilla

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

@ -67,7 +67,7 @@ class TestNrSocketTest : public ::testing::Test {
// is how we simulate a non-natted socket.
nsRefPtr<TestNrSocket> sock(new TestNrSocket(nat ? nat : new TestNat));
nr_transport_addr address;
nr_ip4_str_port_to_transport_addr(ip_str, 0, IPPROTO_UDP, &address);
nr_str_port_to_transport_addr(ip_str, 0, IPPROTO_UDP, &address);
int r = sock->create(&address);
if (r) {
return nullptr;

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

@ -132,7 +132,7 @@ class TurnClient : public ::testing::Test {
net_socket_ = real_socket_;
}
r = nr_ip4_str_port_to_transport_addr(turn_server_.c_str(), 3478,
r = nr_str_port_to_transport_addr(turn_server_.c_str(), 3478,
protocol_, &addr);
ASSERT_EQ(0, r);
@ -237,10 +237,10 @@ class TurnClient : public ::testing::Test {
std::string host = target.substr(4, offset - 4);
std::string port = target.substr(offset + 1);
r = nr_ip4_str_port_to_transport_addr(host.c_str(),
atoi(port.c_str()),
IPPROTO_UDP,
&addr);
r = nr_str_port_to_transport_addr(host.c_str(),
atoi(port.c_str()),
IPPROTO_UDP,
&addr);
ASSERT_EQ(0, r);
r = nr_turn_client_ensure_perm(turn_ctx_, &addr);
@ -324,10 +324,10 @@ class TurnClient : public ::testing::Test {
std::string host = target.substr(4, offset - 4);
std::string port = target.substr(offset + 1);
r = nr_ip4_str_port_to_transport_addr(host.c_str(),
atoi(port.c_str()),
IPPROTO_UDP,
&addr);
r = nr_str_port_to_transport_addr(host.c_str(),
atoi(port.c_str()),
IPPROTO_UDP,
&addr);
ASSERT_EQ(0, r);
unsigned char test[100];
@ -488,8 +488,8 @@ int main(int argc, char **argv)
}
{
nr_transport_addr addr;
if (nr_ip4_str_port_to_transport_addr(g_turn_server.c_str(), 3478,
IPPROTO_UDP, &addr)) {
if (nr_str_port_to_transport_addr(g_turn_server.c_str(), 3478,
IPPROTO_UDP, &addr)) {
printf("Invalid TURN_SERVER_ADDRESS \"%s\". Only IP numbers supported.\n",
g_turn_server.c_str());
return 0;
@ -504,7 +504,7 @@ int main(int argc, char **argv)
std::string dummy("dummy");
RUN_ON_THREAD(test_utils->sts_target(),
WrapRunnableNM(&NrIceCtx::Create,
dummy, false, false, false, false),
dummy, false, false, false, false, false),
NS_DISPATCH_SYNC);
// Start the tests

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

@ -37,6 +37,8 @@
# STUN
./src/stun/addrs.c
./src/stun/addrs.h
./src/stun/ifaddrs-android.c
./src/stun/ifaddrs-android.h
./src/stun/nr_socket_turn.c
./src/stun/nr_socket_turn.h
./src/stun/stun.h

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

@ -88,6 +88,8 @@
# STUN
"./src/stun/addrs.c",
"./src/stun/addrs.h",
"./src/stun/ifaddrs-android.c",
"./src/stun/ifaddrs-android.h",
"./src/stun/nr_socket_turn.c",
"./src/stun/nr_socket_turn.h",
"./src/stun/nr_socket_buffered_stun.c",

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

@ -64,7 +64,7 @@ static char *RCSSTRING __UNUSED__="$Id: ice_candidate.c,v 1.2 2008/04/28 17:59:0
#include "nr_socket.h"
#include "nr_socket_multi_tcp.h"
static int next_automatic_preference = 224;
static int next_automatic_preference = 127;
static int nr_ice_candidate_initialize2(nr_ice_candidate *cand);
static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand);
@ -470,8 +470,12 @@ int nr_ice_candidate_compute_priority(nr_ice_candidate *cand)
if (r=NR_reg_set2_uchar(NR_ICE_REG_PREF_INTERFACE_PRFX,cand->base.ifname,next_automatic_preference)){
ABORT(r);
}
interface_preference=next_automatic_preference;
interface_preference=next_automatic_preference << 1;
next_automatic_preference--;
if (cand->base.ip_version == NR_IPV6) {
/* Prefer IPV6 over IPV4 on the same interface. */
interface_preference += 1;
}
}
else {
ABORT(r);
@ -550,6 +554,11 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo
cand->state=NR_ICE_CAND_STATE_INITIALIZING;
if(cand->stun_server->type == NR_ICE_STUN_SERVER_TYPE_ADDR) {
if(cand->base.ip_version != cand->stun_server->u.addr.ip_version) {
r_log(LOG_ICE, LOG_INFO, "ICE-CANDIDATE(%s): Skipping srflx/relayed candidate with different IP version (%d) than STUN/TURN server (%d).", cand->label,cand->base.ip_version,cand->stun_server->u.addr.ip_version);
ABORT(R_NOT_FOUND); /* Same error code when DNS lookup fails */
}
/* Just copy the address */
if (r=nr_transport_addr_copy(&cand->stun_server_addr,
&cand->stun_server->u.addr)) {
@ -567,6 +576,17 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo
resource.stun_turn=protocol;
resource.transport_protocol=cand->stun_server->transport;
switch (cand->base.ip_version) {
case NR_IPV4:
resource.address_family=AF_INET;
break;
case NR_IPV6:
resource.address_family=AF_INET6;
break;
default:
ABORT(R_BAD_ARGS);
}
/* Try to resolve */
if(!cand->ctx->resolver) {
r_log(LOG_ICE, LOG_ERR, "ICE-CANDIDATE(%s): Can't use DNS names without a resolver", cand->label);

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