This commit is contained in:
Ryan VanderMeulen 2013-05-17 12:51:20 -04:00
Родитель 504f602058 ce8615e289
Коммит 734b934f05
151 изменённых файлов: 2659 добавлений и 1090 удалений

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

@ -34,6 +34,13 @@ midl_enums = [
'IA2CommonTypes',
]
EXPORTS += [x + '.h' for x in midl_enums]
EXPORTS += [x + '.h' for x in midl_interfaces]
EXPORTS += [x + '_i.c' for x in midl_interfaces]
headers = ['%s.h' % x for x in midl_enums]
interfaces_h = ['%s.h' % x for x in midl_interfaces]
interfaces_c = ['%s_i.c' % x for x in midl_interfaces]
# The underscore throws off sorting and EXPORTS expects sorted lists.
interfaces_c.sort()
EXPORTS += headers
EXPORTS += interfaces_h
EXPORTS += interfaces_c

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

@ -951,12 +951,6 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
nsresult rv = Accessible::HandleAccEvent(aEvent);
NS_ENSURE_SUCCESS(rv, rv);
return FirePlatformEvent(aEvent);
}
nsresult
AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
{
Accessible* accessible = aEvent->GetAccessible();
NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);

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

@ -75,7 +75,6 @@ public:
}
protected:
virtual nsresult FirePlatformEvent(AccEvent* aEvent);
nsresult FireAtkStateChangeEvent(AccEvent* aEvent, AtkObject *aObject);
nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject *aObject);

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

@ -881,16 +881,6 @@ protected:
*/
AccGroupInfo* GetGroupInfo();
/**
* Fires platform accessible event. It's notification method only. It does
* change nothing on Gecko side. Don't use it until you're sure what you do
* (see example in XUL tree accessible), use nsEventShell::FireEvent()
* instead. MUST be overridden in wrap classes.
*
* @param aEvent the accessible event to fire.
*/
virtual nsresult FirePlatformEvent(AccEvent* aEvent) = 0;
// Data Members
nsRefPtr<Accessible> mParent;
nsTArray<nsRefPtr<Accessible> > mChildren;

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

@ -1014,32 +1014,24 @@ HyperTextAccessible::GetTextBeforeOffset(int32_t aOffset,
return NS_OK;
case BOUNDARY_WORD_START: {
if (offset == 0) { // no word before 0 offset
*aStartOffset = *aEndOffset = 0;
return NS_OK;
// If the offset is a word start (except text length offset) then move
// backward to find a start offset (end offset is the given offset).
// Otherwise move backward twice to find both start and end offsets.
if (offset == CharacterCount()) {
*aEndOffset = FindWordBoundary(offset, eDirPrevious, eStartWord);
*aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eStartWord);
} else {
*aStartOffset = FindWordBoundary(offset, eDirPrevious, eStartWord);
*aEndOffset = FindWordBoundary(*aStartOffset, eDirNext, eStartWord);
if (*aEndOffset != offset) {
*aEndOffset = *aStartOffset;
*aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eStartWord);
}
}
// If the offset is a word start then move backward to find start offset
// (end offset is the given offset). Otherwise move backward twice to find
// both start and end offsets.
int32_t midOffset = FindWordBoundary(offset, eDirPrevious, eStartWord);
*aEndOffset = FindWordBoundary(midOffset, eDirNext, eStartWord);
if (*aEndOffset == offset) {
*aStartOffset = midOffset;
return GetText(*aStartOffset, *aEndOffset, aText);
}
*aStartOffset = FindWordBoundary(midOffset, eDirPrevious, eStartWord);
*aEndOffset = midOffset;
return GetText(*aStartOffset, *aEndOffset, aText);
}
case BOUNDARY_WORD_END: {
if (offset == 0) { // no word before 0 offset
*aStartOffset = *aEndOffset = 0;
return NS_OK;
}
// Move word backward twice to find start and end offsets.
*aEndOffset = FindWordBoundary(offset, eDirPrevious, eEndWord);
*aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eEndWord);

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

@ -73,8 +73,6 @@ public: // construction, destruction
protected:
virtual nsresult FirePlatformEvent(AccEvent* aEvent);
/**
* Return true if the parent doesn't have children to expose to AT.
*/

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

@ -139,16 +139,6 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
nsresult rv = Accessible::HandleAccEvent(aEvent);
NS_ENSURE_SUCCESS(rv, rv);
return FirePlatformEvent(aEvent);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult
AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
uint32_t eventType = aEvent->GetEventType();
// ignore everything but focus-changed, value-changed, caret and selection

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

@ -21,12 +21,6 @@ class AccessibleWrap : public Accessible
public: // construction, destruction
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
virtual ~AccessibleWrap();
protected:
virtual nsresult FirePlatformEvent(AccEvent* aEvent)
{
return NS_OK;
}
};
} // namespace a11y

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

@ -1505,15 +1505,6 @@ AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
nsresult rv = Accessible::HandleAccEvent(aEvent);
NS_ENSURE_SUCCESS(rv, rv);
return FirePlatformEvent(aEvent);
}
////////////////////////////////////////////////////////////////////////////////
// AccessibleWrap
nsresult
AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
{
// Don't fire native MSAA events or mess with the system caret
// when running in metro mode. This confuses input focus tracking
// in metro's UIA implementation.
@ -1583,6 +1574,9 @@ AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// AccessibleWrap
//------- Helper methods ---------
int32_t

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

@ -243,7 +243,6 @@ public: // construction, destruction
static IDispatch *NativeAccessible(nsIAccessible *aXPAccessible);
protected:
virtual nsresult FirePlatformEvent(AccEvent* aEvent);
/**
* Creates ITypeInfo for LIBID_Accessibility if it's needed and returns it.

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

@ -105,7 +105,17 @@ function testCharAtOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset)
}
/**
* Test getTextAtOffset function over different elements
* Test getTextAtOffset function over different elements.
*
* @param aIDs [in] ID or array of IDs
* @param aBoundaryType [in] boundary type for text to be retrieved
* @param aTestList [in] array of sets:
* offset1 and offset2 defining the offset range
* the text in the range
* start offset of the text in the range
* end offset of the text in the range
*
* or
*
* @param aOffset [in] the offset to get the text at
* @param aBoundaryType [in] Boundary type for text to be retrieved
@ -118,35 +128,9 @@ function testCharAtOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset)
* kTodo or kOk for returned start offset
* kTodo or kOk for returned offset result
*/
function testTextAtOffset(aOffset, aBoundaryType, aText,
aStartOffset, aEndOffset)
function testTextAtOffset()
{
// List of IDs.
if (arguments[5] instanceof Array) {
var ids = arguments[5];
for (var i = 0; i < ids.length; i++) {
var acc = getAccessible(ids[i], nsIAccessibleText);
testTextHelper(ids[i], aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset,
kOk, kOk, kOk,
acc.getTextAtOffset, "getTextAtOffset ");
}
return;
}
for (var i = 5; i < arguments.length; i = i + 4) {
var ID = arguments[i];
var acc = getAccessible(ID, nsIAccessibleText);
var toDoFlag1 = arguments[i + 1];
var toDoFlag2 = arguments[i + 2];
var toDoFlag3 = arguments[i + 3];
testTextHelper(ID, aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset,
toDoFlag1, toDoFlag2, toDoFlag3,
acc.getTextAtOffset, "getTextAtOffset ");
}
testTextSuperHelper("getTextAtOffset", arguments);
}
/**
@ -174,6 +158,16 @@ function testCharAfterOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset)
/**
* Test getTextAfterOffset function over different elements
*
* @param aIDs [in] ID or array of IDs
* @param aBoundaryType [in] boundary type for text to be retrieved
* @param aTestList [in] array of sets:
* offset1 and offset2 defining the offset range
* the text in the range
* start offset of the text in the range
* end offset of the text in the range
*
* or
*
* @param aOffset [in] the offset to get the text after
* @param aBoundaryType [in] Boundary type for text to be retrieved
* @param aText [in] expected return text for getTextAfterOffset
@ -188,33 +182,7 @@ function testCharAfterOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset)
function testTextAfterOffset(aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset)
{
// List of IDs.
if (arguments[5] instanceof Array) {
var ids = arguments[5];
for (var i = 0; i < ids.length; i++) {
var acc = getAccessible(ids[i], nsIAccessibleText);
testTextHelper(ids[i], aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset,
kOk, kOk, kOk,
acc.getTextAfterOffset, "getTextAfterOffset ");
}
return;
}
// List of tuples.
for (var i = 5; i < arguments.length; i = i + 4) {
var ID = arguments[i];
var acc = getAccessible(ID, nsIAccessibleText);
var toDoFlag1 = arguments[i + 1];
var toDoFlag2 = arguments[i + 2];
var toDoFlag3 = arguments[i + 3];
testTextHelper(ID, aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset,
toDoFlag1, toDoFlag2, toDoFlag3,
acc.getTextAfterOffset, "getTextAfterOffset ");
}
testTextSuperHelper("getTextAfterOffset", arguments);
}
/**
@ -242,6 +210,16 @@ function testCharBeforeOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset)
/**
* Test getTextBeforeOffset function over different elements
*
* @param aIDs [in] ID or array of IDs
* @param aBoundaryType [in] boundary type for text to be retrieved
* @param aTestList [in] array of sets:
* offset1 and offset2 defining the offset range
* the text in the range
* start offset of the text in the range
* end offset of the text in the range
*
* or
*
* @param aOffset [in] the offset to get the text before
* @param aBoundaryType [in] Boundary type for text to be retrieved
* @param aText [in] expected return text for getTextBeforeOffset
@ -256,32 +234,7 @@ function testCharBeforeOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset)
function testTextBeforeOffset(aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset)
{
// List of IDs.
if (arguments[5] instanceof Array) {
var ids = arguments[5];
for (var i = 0; i < ids.length; i++) {
var acc = getAccessible(ids[i], nsIAccessibleText);
testTextHelper(ids[i], aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset,
kOk, kOk, kOk,
acc.getTextBeforeOffset, "getTextBeforeOffset ");
}
return;
}
for (var i = 5; i < arguments.length; i = i + 4) {
var ID = arguments[i];
var acc = getAccessible(ID, nsIAccessibleText);
var toDoFlag1 = arguments[i + 1];
var toDoFlag2 = arguments[i + 2];
var toDoFlag3 = arguments[i + 3];
testTextHelper(ID, aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset,
toDoFlag1, toDoFlag2, toDoFlag3,
acc.getTextBeforeOffset, "getTextBeforeOffset ");
}
testTextSuperHelper("getTextBeforeOffset", arguments);
}
/**
@ -502,6 +455,78 @@ function testTextGetSelection(aID, aStartOffset, aEndOffset, aSelectionIndex)
////////////////////////////////////////////////////////////////////////////////
// Private
function testTextSuperHelper(aFuncName, aArgs)
{
// List of tests.
if (aArgs[2] instanceof Array) {
var ids = (aArgs[0] instanceof Array) ? aArgs[0] : [ aArgs[0] ];
var boundaryType = aArgs[1];
var list = aArgs[2];
for (var i = 0; i < list.length; i++) {
var offset1 = list[i][0], offset2 = list[i][1];
var text = list[i][2], startOffset = list[i][3], endOffset = list[i][4];
var failureList = list[i][5];
for (var offset = offset1; offset <= offset2; offset++) {
for (var idIdx = 0; idIdx < ids.length; idIdx++) {
var id = ids[idIdx];
var flagOk1 = kOk, flagOk2 = kOk, flagOk3 = kOk;
if (failureList) {
for (var fIdx = 0; fIdx < failureList.length; fIdx++) {
if (offset == failureList[fIdx][0] && id == failureList[fIdx][1]) {
flagOk1 = failureList[fIdx][2];
flagOk2 = failureList[fIdx][3];
flagOk3 = failureList[fIdx][4];
break;
}
}
}
var acc = getAccessible(id, nsIAccessibleText);
testTextHelper(id, offset, boundaryType,
text, startOffset, endOffset,
flagOk1, flagOk2, flagOk3,
acc[aFuncName], aFuncName + " ");
}
}
}
return;
}
// Test at single offset. List of IDs.
var offset = aArgs[0];
var boundaryType = aArgs[1];
var text = aArgs[2];
var startOffset = aArgs[3];
var endOffset = aArgs[4];
if (aArgs[5] instanceof Array) {
var ids = aArgs[5];
for (var i = 0; i < ids.length; i++) {
var acc = getAccessible(ids[i], nsIAccessibleText);
testTextHelper(ids[i], offset, boundaryType,
text, startOffset, endOffset,
kOk, kOk, kOk,
acc[aFuncName], aFuncName + " ");
}
return;
}
// Each ID is tested separately.
for (var i = 5; i < aArgs.length; i = i + 4) {
var ID = aArgs[i];
var acc = getAccessible(ID, nsIAccessibleText);
var toDoFlag1 = aArgs[i + 1];
var toDoFlag2 = aArgs[i + 2];
var toDoFlag3 = aArgs[i + 3];
testTextHelper(ID, offset, boundaryType,
text, startOffset, endOffset,
toDoFlag1, toDoFlag2, toDoFlag3,
acc[aFuncName], aFuncName + " ");
}
}
function testTextHelper(aID, aOffset, aBoundaryType,
aText, aStartOffset, aEndOffset,
aToDoFlag1, aToDoFlag2, aToDoFlag3,

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

@ -22,6 +22,7 @@ MOCHITEST_A11Y_FILES = \
test_selection.html \
test_singleline.html \
test_whitespaces.html \
test_wordboundary.html \
test_words.html \
$(NULL)

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

@ -173,7 +173,7 @@
testTextBeforeOffset(9, BOUNDARY_WORD_START, "oneword\n\n", 0, 9, IDs);
testTextBeforeOffset(13, BOUNDARY_WORD_START, "two ", 9, 13, IDs);
testTextBeforeOffset(18, BOUNDARY_WORD_START, "two ", 9, 13, IDs);
testTextBeforeOffset(19, BOUNDARY_WORD_START, "words\n", 13, 19, IDs);
testTextBeforeOffset(19, BOUNDARY_WORD_START, "two ", 9, 13, IDs);
// BOUNDARY_WORD_END
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0, IDs);

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

@ -147,7 +147,11 @@
testTextBeforeOffset(9, BOUNDARY_WORD_START, "my ", 6, 9, IDs);
testTextBeforeOffset(10, BOUNDARY_WORD_START, "my ", 6, 9, IDs);
testTextBeforeOffset(14, BOUNDARY_WORD_START, "my ", 6, 9, IDs);
testTextBeforeOffset(15, BOUNDARY_WORD_START, "friend", 9, 15, IDs);
testTextBeforeOffset(15, BOUNDARY_WORD_START, "my ", 6, 9,
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kTodo, kTodo, kTodo);
// BOUNDARY_WORD_END
testTextBeforeOffset(0, BOUNDARY_WORD_END, "", 0, 0, IDs);

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

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<title>Word boundary text tests</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../text.js"></script>
<script type="application/javascript">
function doTest()
{
// "hello"
var ids = [ "i1", "d1", "e1" ];
testTextBeforeOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 5, "", 0, 0 ] ]);
testTextBeforeOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 5, "", 0, 0 ] ]);
testTextAtOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 5, "hello", 0, 5 ] ]);
testTextAtOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 5, "hello", 0, 5 ] ]);
testTextAfterOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 5, "", 5, 5 ] ]);
testTextAfterOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 5, "", 5, 5 ] ]);
// "hello "
var ids = [ "i2", "d2", "e2" ];
testTextBeforeOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 6, "", 0, 0 ] ]);
testTextBeforeOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 5, "", 0, 0 ],
[ 6, 6, "hello", 0, 5,
[ [6, "e2", kTodo, kOk, kTodo ] ]
]
]);
testTextAtOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 6, "hello ", 0, 6 ] ]);
testTextAtOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 4, "hello", 0, 5 ],
[ 5, 6, " ", 5, 6,
[ [ 5, "e2", kTodo, kTodo, kOk ],
[ 6, "e2", kTodo, kTodo, kOk ] ]
]
]);
testTextAfterOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 6, "", 6, 6 ] ]);
testTextAfterOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 5, " ", 5, 6,
[ [ 5, "e2", kTodo, kTodo, kOk ] ]
],
[ 6, 6, "", 6, 6 ]
]);
// "hello all"
ids = [ "i6", "d6", "e6" ];
testTextAtOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 5, "hello ", 0, 6 ],
[ 6, 9, "all", 6, 9 ] ]);
testTextAtOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 4, "hello", 0, 5 ],
[ 5, 9, " all", 5, 9 ] ]);
// "hello my friend"
ids = [ "i7", "d7", "e7" ];
testTextAtOffset(ids, BOUNDARY_WORD_START,
[ [ 0, 5, "hello ", 0, 6 ],
[ 6, 8, "my ", 6, 9 ],
[ 9, 15, "friend", 9, 15] ]);
testTextAtOffset(ids, BOUNDARY_WORD_END,
[ [ 0, 4, "hello", 0, 5 ],
[ 5, 7, " my", 5, 8 ],
[ 8, 15, " friend", 8, 15] ]);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="i1" value="hello"/>
<div id="d1">hello</div>
<div id="e1" contenteditable="true">hello</div>
<input id="i2" value="hello "/>
<pre><div id="d2">hello </div></pre>
<div id="e2" contenteditable="true">hello </div>
<input id="i6" value="hello all"/>
<div id="d6">hello all</div>
<div id="e6" contenteditable="true">hello all</div>
<input id="i7" value="hello my friend"/>
<div id="d7">hello my friend</div>
<div id="e7" contenteditable="true">hello my friend</div>
</body>
</html>

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

@ -1230,6 +1230,9 @@ pref("social.toast-notifications.enabled", true);
pref("dom.identity.enabled", false);
// Turn on the CSP 1.0 parser for Content Security Policy headers
pref("security.csp.speccompliant", true);
// Block insecure active content on https pages
pref("security.mixed_content.block_active_content", true);

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

@ -162,8 +162,10 @@ function test_TestEventListeners()
test_clicks("MozTapGesture", 3);
test_clicks("MozPressTapGesture", 1);
// simple delivery test for edgeui gesture
e("MozEdgeUIGesture", 0, 0, 0);
// simple delivery test for edgeui gestures
e("MozEdgeUIStarted", 0, 0, 0);
e("MozEdgeUICanceled", 0, 0, 0);
e("MozEdgeUICompleted", 0, 0, 0);
// event.shiftKey
let modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;

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

@ -147,7 +147,7 @@ var gPrivacyPane = {
getTrackingPrefs: function PPP_getTrackingPrefs()
{
// XXX avoid using bindings that might not be attached, see bug 859982
let dntValue = Services.prefs.getBoolPref("privacy.donottrackheader.value"),
let dntValue = Services.prefs.getIntPref("privacy.donottrackheader.value"),
dntEnabled = Services.prefs.getBoolPref("privacy.donottrackheader.enabled");
// if DNT is enbaled, select the value from the selected radio

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

@ -86,8 +86,10 @@ function test() {
ok(requestItem.attachment.requestHeaders,
"There should be a requestHeaders attachment available.");
is(requestItem.attachment.requestHeaders.headers.length, 7,
ok(requestItem.attachment.requestHeaders.headers.length >= 6,
"The requestHeaders attachment has an incorrect |headers| property.");
// Can't test for an exact total number of headers, because it seems to
// vary across pgo/non-pgo builds.
isnot(requestItem.attachment.requestHeaders.headersSize, 0,
"The requestHeaders attachment has an incorrect |headersSize| property.");
// Can't test for the exact request headers size because the value may

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

@ -63,8 +63,11 @@ function test() {
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
"There should be 2 header scopes displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".variable-or-property").length, 13,
"There should be 13 header values displayed in this tabpanel.");
ok(tabpanel.querySelectorAll(".variable-or-property").length >= 12,
"There should be at least 12 header values displayed in this tabpanel.");
// Can't test for an exact total number of headers, because it seems to
// vary across pgo/non-pgo builds.
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
"The empty notice should not be displayed in this tabpanel.");
@ -108,10 +111,18 @@ function test() {
"Connection", "The penultimate request header name was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"),
"\"keep-alive\"", "The penultimate request header value was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .name")[6].getAttribute("value"),
"Cache-Control", "The last request header name was incorrect.");
is(requestScope.querySelectorAll(".variables-view-variable .value")[6].getAttribute("value"),
"\"max-age=0\"", "The last request header value was incorrect.");
let lastReqHeaderName = requestScope.querySelectorAll(".variables-view-variable .name")[6];
let lastReqHeaderValue = requestScope.querySelectorAll(".variables-view-variable .value")[6];
if (lastReqHeaderName && lastReqHeaderValue) {
is(lastReqHeaderName.getAttribute("value"),
"Cache-Control", "The last request header name was incorrect.");
is(lastReqHeaderValue.getAttribute("value"),
"\"max-age=0\"", "The last request header value was incorrect.");
} else {
info("The number of request headers was 6 instead of 7. Technically, " +
"not a failure in this particular test, but needs investigation.");
}
}
function testCookiesTab() {

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

@ -46,7 +46,7 @@ const BrowserTouchHandler = {
// Send the MozEdgeUIGesture to input.js to
// toggle the context ui.
let event = document.createEvent("Events");
event.initEvent("MozEdgeUIGesture", true, false);
event.initEvent("MozEdgeUICompleted", true, false);
window.dispatchEvent(event);
}
},

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

@ -290,8 +290,7 @@ var ContentAreaObserver = {
},
_getContentHeightForWindow: function (windowHeight) {
let contextUIHeight = BrowserUI.isTabsOnly ? Elements.toolbar.getBoundingClientRect().bottom : 0;
return windowHeight - contextUIHeight;
return windowHeight;
},
_getViewableHeightForContent: function (contentHeight) {

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

@ -96,7 +96,6 @@ var BrowserUI = {
window.addEventListener("MozPrecisePointer", this, true);
window.addEventListener("MozImprecisePointer", this, true);
Services.prefs.addObserver("browser.tabs.tabsOnly", this, false);
Services.prefs.addObserver("browser.cache.disk_cache_ssl", this, false);
Services.obs.addObserver(this, "metro_viewstate_changed", false);
@ -143,7 +142,6 @@ var BrowserUI = {
messageManager.addMessageListener("Browser:MozApplicationManifest", OfflineApps);
try {
BrowserUI._updateTabsOnly();
Downloads.init();
DialogUI.init();
FormHelperUI.init();
@ -402,23 +400,18 @@ var BrowserUI = {
},
animateClosingTab: function animateClosingTab(tabToClose) {
if (this.isTabsOnly) {
Browser.closeTab(tabToClose, { forceClose: true } );
} else {
// Trigger closing animation
tabToClose.chromeTab.setAttribute("closing", "true");
tabToClose.chromeTab.setAttribute("closing", "true");
let wasCollapsed = !ContextUI.isExpanded;
if (wasCollapsed) {
ContextUI.displayTabs();
}
let wasCollapsed = !ContextUI.isExpanded;
if (wasCollapsed) {
ContextUI.displayTabs();
}
this.setOnTabAnimationEnd(function() {
Browser.closeTab(tabToClose, { forceClose: true } );
this.setOnTabAnimationEnd(function() {
Browser.closeTab(tabToClose, { forceClose: true } );
if (wasCollapsed)
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
});
}
});
},
/**
@ -525,32 +518,10 @@ var BrowserUI = {
ContextUI.cancelDismiss();
},
/*********************************
* Conventional tabs
*/
// Tabsonly displays the url bar with conventional tabs. Also
// the tray does not auto hide.
get isTabsOnly() {
return Services.prefs.getBoolPref("browser.tabs.tabsOnly");
},
_updateTabsOnly: function _updateTabsOnly() {
if (this.isTabsOnly) {
Elements.windowState.setAttribute("tabsonly", "true");
} else {
Elements.windowState.removeAttribute("tabsonly");
}
},
observe: function BrowserUI_observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "nsPref:changed":
switch (aData) {
case "browser.tabs.tabsOnly":
this._updateTabsOnly();
break;
case "browser.cache.disk_cache_ssl":
this._sslDiskCacheEnabled = Services.prefs.getBoolPref(aData);
break;
@ -1119,7 +1090,9 @@ var ContextUI = {
Elements.browsers.addEventListener("mousedown", this, true);
Elements.browsers.addEventListener("touchstart", this, true);
Elements.browsers.addEventListener("AlertActive", this, true);
window.addEventListener("MozEdgeUIGesture", this, true);
window.addEventListener("MozEdgeUIStarted", this, true);
window.addEventListener("MozEdgeUICanceled", this, true);
window.addEventListener("MozEdgeUICompleted", this, true);
window.addEventListener("keypress", this, true);
window.addEventListener("KeyboardChanged", this, false);
@ -1284,8 +1257,7 @@ var ContextUI = {
// tab tray state
_setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
// if the tray can't be expanded because we're in
// tabsonly mode, don't expand it.
// if the tray can't be expanded, don't expand it.
if (!this.isExpandable || this.isExpanded == aFlag)
return;
@ -1313,7 +1285,29 @@ var ContextUI = {
* Events
*/
_onEdgeUIEvent: function _onEdgeUIEvent(aEvent) {
_onEdgeUIStarted: function(aEvent) {
this._hasEdgeSwipeStarted = true;
this._clearDelayedTimeout();
if (StartUI.hide()) {
this.dismiss();
return;
}
this.toggle();
},
_onEdgeUICanceled: function(aEvent) {
this._hasEdgeSwipeStarted = false;
StartUI.hide();
this.dismiss();
},
_onEdgeUICompleted: function(aEvent) {
if (this._hasEdgeSwipeStarted) {
this._hasEdgeSwipeStarted = false;
return;
}
this._clearDelayedTimeout();
if (StartUI.hide()) {
this.dismiss();
@ -1324,8 +1318,14 @@ var ContextUI = {
handleEvent: function handleEvent(aEvent) {
switch (aEvent.type) {
case "MozEdgeUIGesture":
this._onEdgeUIEvent(aEvent);
case "MozEdgeUIStarted":
this._onEdgeUIStarted(aEvent);
break;
case "MozEdgeUICanceled":
this._onEdgeUICanceled(aEvent);
break;
case "MozEdgeUICompleted":
this._onEdgeUICompleted(aEvent);
break;
case "mousedown":
if (aEvent.button == 0 && this.isVisible)
@ -1471,7 +1471,7 @@ var StartUI = {
break;
case "contextmenu":
let event = document.createEvent("Events");
event.initEvent("MozEdgeUIGesture", true, false);
event.initEvent("MozEdgeUICompleted", true, false);
window.dispatchEvent(event);
break;
}

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

@ -98,12 +98,12 @@ var Browser = {
ContentAreaObserver.init();
function fullscreenHandler() {
if (!window.fullScreen)
Elements.toolbar.setAttribute("fullscreen", "true");
if (Browser.selectedBrowser.contentWindow.document.mozFullScreenElement)
Elements.stack.setAttribute("fullscreen", "true");
else
Elements.toolbar.removeAttribute("fullscreen");
Elements.stack.removeAttribute("fullscreen");
}
window.addEventListener("fullscreen", fullscreenHandler, false);
window.addEventListener("mozfullscreenchange", fullscreenHandler, true);
BrowserUI.init();

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

@ -367,11 +367,16 @@
</toolbar>
</appbar>
<!-- Selection overlay - this should be below any content that can have selectable text -->
<!-- onclick addresses dom bug 835175, str in bug 832957 -->
<box onclick="false" class="selection-overlay-hidden" id="selection-overlay"/>
<!-- Selection overlay - this should be below any content that can have selectable text -->
<!-- onclick addresses dom bug 835175, str in bug 832957 -->
<box onclick="false" class="selection-overlay-hidden" id="selection-overlay"/>
<flyoutpanel id="about-flyoutpanel" headertext="&aboutHeader.title;">
<html:div id="overlay-back" class="overlay-button"
observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_back');"></html:div>
<html:div id="overlay-plus" class="overlay-button"
observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_newTab');"></html:div>
<flyoutpanel id="about-flyoutpanel" headertext="&aboutHeader.title;">
<label id="about-product-label" value="&aboutHeader.product.label;"/>
<label value="&aboutHeader.company.label;"/>
#expand <label id="about-version-label">__MOZ_APP_VERSION__</label>
@ -425,7 +430,6 @@
</menulist>
</setting>
</settings>
<setting pref="browser.tabs.tabsOnly" title="&optionsHeader.tabs.title;" type="bool"/>
<settings id="prefs-charencoding" label="&optionsHeader.char.title;">
<setting pref="browser.menu.showCharacterEncoding" title="&optionsHeader.char.options.label;" type="bool"/>
</settings>
@ -681,9 +685,4 @@
</hbox>
</stack>
<html:div id="overlay-back" class="overlay-button"
observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_back');"></html:div>
<html:div id="overlay-plus" class="overlay-button"
observes="cmd_back" onclick="CommandUpdater.doCommand('cmd_newTab');"></html:div>
</window>

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

@ -185,7 +185,7 @@ var TouchModule = {
// a edge ui event when we get the contextmenu event.
if (this._treatMouseAsTouch) {
let event = document.createEvent("Events");
event.initEvent("MozEdgeUIGesture", true, false);
event.initEvent("MozEdgeUICompleted", true, false);
window.dispatchEvent(event);
return;
}

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

@ -88,6 +88,6 @@ gTests.push({
function doEdgeUIGesture() {
let event = document.createEvent("Events");
event.initEvent("MozEdgeUIGesture", true, false);
event.initEvent("MozEdgeUICompleted", true, false);
window.dispatchEvent(event);
}

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

@ -188,7 +188,7 @@ function fireAppBarDisplayEvent()
{
let promise = waitForEvent(Elements.tray, "transitionend");
let event = document.createEvent("Events");
event.initEvent("MozEdgeUIGesture", true, false);
event.initEvent("MozEdgeUICompleted", true, false);
gWindow.dispatchEvent(event);
purgeEventQueue();
return promise;
@ -735,4 +735,4 @@ function stubMethod(aObj, aMethod) {
};
aObj[aMethod] = func;
return func;
}
}

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

@ -14,7 +14,6 @@
<!ENTITY optionsHeader.homepage.title "When &brandShortName; starts, show">
<!ENTITY optionsHeader.homepage.startPage.button "start page">
<!ENTITY optionsHeader.homepage.sessionRestore.button "tabs from last time">
<!ENTITY optionsHeader.tabs.title "Always Show Tabs">
<!ENTITY optionsHeader.char.title "Character Encoding">
<!ENTITY optionsHeader.char.autodetect.label "Auto-detect">
<!ENTITY optionsHeader.char.options.label "Show encoding options on the App Bar">

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

@ -51,12 +51,10 @@ pref("toolkit.browser.cacheRatioHeight", 3000);
// expires.
pref("toolkit.browser.contentViewExpire", 3000);
pref("toolkit.defaultChromeURI", "chrome://browser/content/browser.xul");
pref("browser.chromeURL", "chrome://browser/content/");
// When true, always show the tab strip and use desktop-style tabs (no thumbnails)
pref("browser.tabs.tabsOnly", false);
pref("browser.tabs.remote", false);
// Telemetry

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

@ -48,9 +48,7 @@
width: 100%;
}
/* in non-tabsonly mode the navigation bar and tab tray float over content. In
tabsonly mode they are always visible and offset content. */
#tray:not([tabsonly]) {
#tray {
position: fixed;
}
@ -144,16 +142,16 @@
}
}
#tray:not([tabsonly]) .documenttab-container {
.documenttab-container {
animation: open-documenttab 0.4s ease-out;
}
#tray:not([tabsonly]) documenttab[closing] > .documenttab-container {
documenttab[closing] > .documenttab-container {
animation: close-documenttab 0.4s ease-out;
animation-fill-mode: forwards;
}
#tray:not([tabsonly]) .documenttab-favicon {
.documenttab-favicon {
visibility: collapse;
}
@ -203,87 +201,6 @@ documenttab[selected] .documenttab-selection {
display: none;
}
#tray[tabsonly] {
transform: none !important;
}
#tray[tabsonly] #tabs {
-moz-padding-start: @metro_spacing_small@;
}
#tray[tabsonly] #tabs-controls {
-moz-box-align: center;
-moz-box-orient: horizontal;
-moz-box-pack: end;
margin: 0;
}
#tray[tabsonly] #tabs-controls toolbarbutton {
margin-top: 0;
margin-bottom: 0;
}
#tray[tabsonly] documenttab {
height: @toolbar_height@;
margin: 0 -@tab_compression@;
}
#tray[tabsonly] documenttab:first-child {
-moz-margin-start: 0;
}
#tray[tabsonly] documenttab:last-child {
-moz-margin-end: 0;
}
#tray[tabsonly] .documenttab-thumbnail,
#tray[tabsonly] .documenttab-selection,
#tray[tabsonly] .documenttab-crop {
visibility: collapse;
}
#tray[tabsonly] .documenttab-container {
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: center;
padding: 0 @tab_spacing@;
}
#tray[tabsonly] .documenttab-favicon {
-moz-margin-start: @metro_spacing_normal@;
-moz-margin-end: @metro_spacing_snormal@;
}
#tray[tabsonly] .documenttab-title {
padding: 0;
margin: 0;
height: auto;
background: 0 none;
opacity: 1;
box-shadow: none;
width: @tab_inner_width@;
}
#tray[tabsonly] .documenttab-close {
list-style-image: url("chrome://browser/skin/images/closetab-tab.png");
position: relative;
padding: 0 !important;
z-index: 1;
}
#tray[tabsonly] documenttab[selected=true] {
background-color: @panel_light_color@;
background-image: url("chrome://browser/skin/images/tab-selection-left.png"),
url("chrome://browser/skin/images/tab-selection-right.png"),
@panel_light_background@;
background-position: left top, right top, center center;
background-repeat: no-repeat, no-repeat, repeat;
}
#tray[tabsonly] documenttab[selected=true] .documenttab-close {
list-style-image: url("chrome://browser/skin/images/closetab-tabselected.png");
}
#page,
.selection-overlay {
-moz-stack-sizing: ignore;
@ -301,10 +218,6 @@ documenttab[selected] .documenttab-selection {
display: none;
}
#tray[tabsonly] documenttab[selected=true] .documenttab-title {
color: #000;
}
#tabs-controls {
margin-top: @metro_spacing_small@;
-moz-box-align: start;
@ -968,34 +881,45 @@ setting[type="radio"] > vbox {
background-position: left 6px center;
}
#stack[fullscreen] > .overlay-button,
#appbar[visible] ~ .overlay-button,
.overlay-button[disabled] {
box-shadow: none;
visibility: collapse;
}
#stack[fullscreen] > #overlay-back:-moz-locale-dir(ltr),
#stack[fullscreen] > #overlay-plus:-moz-locale-dir(rtl),
#appbar[visible] ~ #overlay-back:-moz-locale-dir(ltr),
#appbar[visible] ~ #overlay-plus:-moz-locale-dir(rtl),
#overlay-back[disabled]:-moz-locale-dir(ltr),
#overlay-plus[disabled]:-moz-locale-dir(rtl) {
transform: translateX(-60px);
}
#stack[fullscreen] > #overlay-plus:-moz-locale-dir(ltr),
#stack[fullscreen] > #overlay-back:-moz-locale-dir(rtl),
#appbar[visible] ~ #overlay-plus:-moz-locale-dir(ltr),
#appbar[visible] ~ #overlay-back:-moz-locale-dir(rtl),
#overlay-plus[disabled]:-moz-locale-dir(ltr),
#overlay-back[disabled]:-moz-locale-dir(rtl) {
transform: translateX(60px);
}
.overlay-button:not([disabled]):hover {
.overlay-button:hover {
background-color: hsla(210,30%,10%,.4);
background-size: 90px;
border-color: hsla(0,0%,100%,.9);
}
#overlay-back:not([disabled]):-moz-locale-dir(ltr):hover,
#overlay-plus:not([disabled]):-moz-locale-dir(rtl):hover {
#overlay-back:-moz-locale-dir(ltr):hover,
#overlay-plus:-moz-locale-dir(rtl):hover {
background-position: right 12px center;
transform: translateX(40px) scale(1.2);
}
#overlay-plus:not([disabled]):-moz-locale-dir(ltr):hover,
#overlay-back:not([disabled]):-moz-locale-dir(rtl):hover {
#overlay-plus:-moz-locale-dir(ltr):hover,
#overlay-back:-moz-locale-dir(rtl):hover {
background-position: left 12px center;
transform: translateX(-40px) scale(1.2);
}

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

@ -23,27 +23,18 @@
%define tabs_height 178px
%define progress_height 5px
%define progress_start_color #0095dd
%define progress_end_color #97cbff
%define metro_orange #FF8000
%define label_height 30px
%define thumbnail_width 232px
%define thumbnail_height 148px
%define tile_border_color #dbdcde
%define tile_width 200px
%define tab_inner_width 180px
%define tab_spacing 45px;
%define tab_compression 40px;
%define scroller_thickness 4px
%define scroller_minimum 8px
%define metro_spacing_xxsmall 2px
%define metro_spacing_xsmall 3px
%define metro_spacing_small 5px
%define metro_spacing_snormal 10px
@ -52,7 +43,6 @@
%define metro_spacing_xxnormal 25px
%define metro_spacing_xxxnormal 30px
%define metro_spacing_large 40px
%define metro_spacing_xlarge 45px
%define metro_border_thin 1px
%define metro_border_thick 2px
@ -63,58 +53,30 @@
%define metro_font_large 25px
%define metro_font_xlarge 45px
%define font_xlarge 32px
%define font_xnormal 17px
%define font_normal 16px
%define font_snormal 15px
%define font_small 12px
%define font_xsmall 11px
%define font_tiny 9px
%define font_xtiny 8px
%define font_xxtiny 7px
%define touch_row 47px
%define touch_button_xlarge 48px
%define touch_button_large 43px
%define touch_button_small 37px
%define touch_action_minwidth 133px
%define touch_normal 43px
%define touch_small 36px
%define margin_context_popup 21px
%define margin_large 16px
%define margin_xxxnormal 11px
%define margin_xnormal 7px
%define margin_normal 5px
%define margin_snormal 4px
%define margin_small 3px
%define margin_tiny 1px
%define margin_xtiny 1px
%define padding_xlarge 21px
%define padding_large 16px
%define padding_xxxnormal 11px
%define padding_xxnormal 8px
%define padding_xnormal 7px
%define padding_normal 5px
%define padding_snormal 4px
%define padding_small 3px
%define padding_xsmall 1px
%define padding_tiny 1px
%define border_width_xxlarge 4px
%define border_width_xlarge 3px
%define border_width_large 2px
%define border_width_small 1px
%define border_width_tiny 1px
%define border_radius_normal 5px
%define border_radius_small 4px
%define border_radius_xsmall 2px
%define border_radius_tiny 1px
%define shadow_width_xlarge 7px
%define shadow_width_large 4px
%define shadow_width_small 1px
% easing function and duration for animations match winJS showPanel method

Двоичные данные
browser/metro/theme/images/closetab-tab.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 9.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 9.1 KiB

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

@ -28,13 +28,9 @@ chrome.jar:
skin/images/reload.png (images/reload.png)
skin/images/newtab-default.png (images/newtab-default.png)
skin/images/closetab-default.png (images/closetab-default.png)
skin/images/closetab-tab.png (images/closetab-tab.png)
skin/images/closetab-tabselected.png (images/closetab-tabselected.png)
skin/images/tab-arrows.png (images/tab-arrows.png)
skin/images/tab-crop.png (images/tab-crop.png)
skin/images/tab-overlay.png (images/tab-overlay.png)
skin/images/tab-selection-left.png (images/tab-selection-left.png)
skin/images/tab-selection-right.png (images/tab-selection-right.png)
skin/images/identity-icons-generic.png (images/identity-icons-generic.png)
skin/images/identity-icons-https-ev.png (images/identity-icons-https-ev.png)
skin/images/identity-icons-https-mixed.png (images/identity-icons-https-mixed.png)

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

@ -105,7 +105,7 @@ class RemoteAutomation(Automation):
#
# -> java.lang.NullPointerException at org.mozilla.gecko.GeckoApp$21.run(GeckoApp.java:1833)
found_exception = True
logre = re.compile(r".*\):\s(.*)")
logre = re.compile(r".*\): \t?(.*)")
m = logre.search(logcat[i+1])
if m and m.group(1):
top_frame = m.group(1)

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

@ -1,4 +1,4 @@
. "$topsrcdir/build/mozconfig.common"
CC=/tools/gcc-4.5-0moz3/bin/gcc
CXX=/tools/gcc-4.5-0moz3/bin/g++
CC="/tools/gcc-4.7.2-0moz1/bin/gcc"
CXX="/tools/gcc-4.7.2-0moz1/bin/g++"

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

@ -13,7 +13,7 @@ interface nsIDocShell;
* Describes an XPCOM component used to model an enforce CSPs.
*/
[scriptable, uuid(91E1F257-914C-4D4F-902C-F67F772839AB)]
[scriptable, uuid(230b126d-afc3-4588-9794-3e135594d626)]
interface nsIContentSecurityPolicy : nsISupports
{
@ -62,6 +62,21 @@ interface nsIContentSecurityPolicy : nsISupports
*/
boolean getAllowsEval(out boolean shouldReportViolation);
/**
* Whether this policy allows in-page styles.
* This includes <style> tags with text content and style="" attributes in
* HTML elements.
* @param shouldReportViolation
* Whether or not the use of eval should be reported.
* This function always returns "true" for report-only policies, but when
* the report-only policy is violated, shouldReportViolation is true as
* well.
* @return
* Whether or not the effects of the eval call should be allowed
* (block the call if false).
*/
boolean getAllowsInlineStyle(out boolean shouldReportViolation);
/**
* Log policy violation on the Error Console and send a report if a report-uri
* is present in the policy
@ -82,6 +97,7 @@ interface nsIContentSecurityPolicy : nsISupports
const unsigned short VIOLATION_TYPE_INLINE_SCRIPT = 1;
const unsigned short VIOLATION_TYPE_EVAL = 2;
const unsigned short VIOLATION_TYPE_INLINE_STYLE = 3;
/**
* Manually triggers violation report sending given a URI and reason.

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

@ -181,6 +181,9 @@ this.CSPRep = function CSPRep(aSpecCompliant) {
// Is this a 1.0 spec compliant CSPRep ?
// Default to false if not specified.
this._specCompliant = (aSpecCompliant !== undefined) ? aSpecCompliant : false;
// Only CSP 1.0 spec compliant policies block inline styles by default.
this._allowInlineStyles = !aSpecCompliant;
}
// Source directives for our original CSP implementation.
@ -717,7 +720,8 @@ CSPRep.prototype = {
}
}
return (this.allowsInlineScripts === that.allowsInlineScripts)
&& (this.allowsEvalInScripts === that.allowsEvalInScripts);
&& (this.allowsEvalInScripts === that.allowsEvalInScripts)
&& (this.allowsInlineStyles === that.allowsInlineStyles);
},
/**
@ -812,6 +816,9 @@ CSPRep.prototype = {
newRep._allowInlineScripts = this.allowsInlineScripts
&& aCSPRep.allowsInlineScripts;
newRep._allowInlineStyles = this.allowsInlineStyles
&& aCSPRep.allowsInlineStyles;
newRep._innerWindowID = this._innerWindowID ?
this._innerWindowID : aCSPRep._innerWindowID;
@ -872,6 +879,14 @@ CSPRep.prototype = {
return this._allowInlineScripts;
},
/**
* Returns true if inline styles are enabled through the "inline-style"
* keyword.
*/
get allowsInlineStyles () {
return this._allowInlineStyles;
},
/**
* Sends a warning message to the error console and web developer console.
* @param aMsg

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

@ -40,6 +40,7 @@ function ContentSecurityPolicy() {
// default options "wide open" since this policy will be intersected soon
this._policy._allowInlineScripts = true;
this._policy._allowInlineStyles = true;
this._policy._allowEval = true;
this._request = "";
@ -144,6 +145,14 @@ ContentSecurityPolicy.prototype = {
return this._reportOnlyMode || this._policy.allowsEvalInScripts;
},
getAllowsInlineStyle: function(shouldReportViolation) {
// report it?
shouldReportViolation.value = !this._policy.allowsInlineStyles;
// allow it to execute?
return this._reportOnlyMode || this._policy.allowsInlineStyles;
},
/**
* Log policy violation on the Error Console and send a report if a report-uri
* is present in the policy
@ -163,6 +172,12 @@ ContentSecurityPolicy.prototype = {
// is enabled, resulting in a call to this function. Therefore we need to
// check that the policy was in fact violated before logging any violations
switch (aViolationType) {
case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_STYLE:
if (!this._policy.allowsInlineStyles)
this._asyncReportViolation('self',null,'inline style base restriction',
'violated base restriction: Inline Stylesheets will not apply',
aSourceFile, aScriptSample, aLineNum);
break;
case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT:
if (!this._policy.allowsInlineScripts)
this._asyncReportViolation('self',null,'inline script base restriction',

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

@ -22,7 +22,6 @@ extern PRLogModuleInfo* GetDataChannelLog();
#include "nsIDOMFile.h"
#include "nsIJSNativeInitializer.h"
#include "nsIDOMDataChannel.h"
#include "nsIDOMRTCPeerConnection.h"
#include "nsIDOMMessageEvent.h"
#include "nsDOMClassInfo.h"
#include "nsDOMEventTargetHelper.h"
@ -114,11 +113,6 @@ private:
};
DOMCI_DATA(DataChannel, nsDOMDataChannel)
// A bit of a hack for RTCPeerConnection, since it doesn't have a .cpp file of
// its own. Note that it's not castable to anything in particular other than
// nsIDOMRTCPeerConnection, so we can just use nsIDOMRTCPeerConnection as the
// "class".
DOMCI_DATA(RTCPeerConnection, nsIDOMRTCPeerConnection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
nsDOMEventTargetHelper)
@ -167,10 +161,6 @@ nsDOMDataChannel::Init(nsPIDOMWindow* aDOMWindow)
rv = CheckInnerWindowCorrectness();
NS_ENSURE_SUCCESS(rv,rv);
// See bug 696085
// We don't need to observe for window destroyed or frozen; but PeerConnection needs
// to not allow itself to be bfcached (and get destroyed on navigation).
rv = nsContentUtils::GetUTFOrigin(principal,mOrigin);
LOG(("%s: origin = %s\n",__FUNCTION__,NS_LossyConvertUTF16toASCII(mOrigin).get()));
return rv;

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

@ -1737,7 +1737,9 @@ GK_ATOM(onMozRotateGestureUpdate, "onMozRotateGestureUpdate")
GK_ATOM(onMozRotateGesture, "onMozRotateGesture")
GK_ATOM(onMozTapGesture, "onMozTapGesture")
GK_ATOM(onMozPressTapGesture, "onMozPressTapGesture")
GK_ATOM(onMozEdgeUIGesture, "onMozEdgeUIGesture")
GK_ATOM(onMozEdgeUIStarted, "onMozEdgeUIStarted")
GK_ATOM(onMozEdgeUICanceled, "onMozEdgeUICanceled")
GK_ATOM(onMozEdgeUICompleted, "onMozEdgeUICompleted")
// orientation support
GK_ATOM(ondevicemotion, "ondevicemotion")

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

@ -2397,7 +2397,7 @@ nsINode::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
JS::Rooted<JSObject*> obj(aCx, WrapNode(aCx, aScope));
if (obj && ChromeOnlyAccess() &&
!nsContentUtils::IsSystemPrincipal(NodePrincipal()) &&
xpc::AllowXBLScope(js::GetContextCompartment(aCx)))
xpc::AllowXBLScope(js::GetObjectCompartment(obj)))
{
// Create a new wrapper and cache it.
JSAutoCompartment ac(aCx, obj);

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

@ -26,6 +26,7 @@
#include "nsXPCOMCIDInternal.h"
#include "nsUnicharInputStream.h"
#include "nsContentUtils.h"
#include "nsStyleUtil.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -366,6 +367,11 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument *aOldDocument,
nsAutoString text;
nsContentUtils::GetNodeTextContent(thisContent, false, text);
if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent->NodePrincipal(),
doc->GetDocumentURI(),
mLineNumber, text, &rv))
return rv;
// Parse the style sheet.
rv = doc->CSSLoader()->
LoadInlineStyle(thisContent, text, mLineNumber, title, media,

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

@ -20,6 +20,7 @@
#include "nsIDOMMutationEvent.h"
#include "nsXULElement.h"
#include "nsContentUtils.h"
#include "nsStyleUtil.h"
namespace css = mozilla::css;
using namespace mozilla::dom;
@ -235,6 +236,11 @@ nsStyledElementNotElementCSSInlineStyle::ParseStyleAttribute(const nsAString& aV
{
nsIDocument* doc = OwnerDoc();
if (!nsStyleUtil::CSPAllowsInlineStyle(NodePrincipal(),
doc->GetDocumentURI(), 0, aValue,
nullptr))
return;
if (aForceInDataDoc ||
!doc->IsLoadedAsData() ||
doc->IsStaticDocument()) {

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

@ -339,6 +339,7 @@ MOCHITEST_FILES_B = \
test_viewport_scroll.html \
test_CSP.html \
file_CSP.sjs \
file_CSP.css \
file_CSP_main.html \
file_CSP_main.html^headers^ \
file_CSP_main_spec_compliant.html \
@ -368,6 +369,13 @@ MOCHITEST_FILES_B = \
file_CSP_evalscript_main_spec_compliant.html^headers^ \
file_CSP_evalscript_main_spec_compliant_allowed.html \
file_CSP_evalscript_main_spec_compliant_allowed.html^headers^ \
test_CSP_inlinestyle.html \
file_CSP_inlinestyle_main.html \
file_CSP_inlinestyle_main.html^headers^ \
file_CSP_inlinestyle_main_spec_compliant.html \
file_CSP_inlinestyle_main_spec_compliant.html^headers^ \
file_CSP_inlinestyle_main_spec_compliant_allowed.html \
file_CSP_inlinestyle_main_spec_compliant_allowed.html^headers^ \
file_csp_bug768029.html \
file_csp_bug768029.sjs \
file_csp_bug773891.html \

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

@ -0,0 +1,20 @@
/*
* Moved this CSS from an inline stylesheet to an external file when we added
* inline-style blocking in bug 763879.
* This test may hang if the load for this .css file is blocked due to a
* malfunction of CSP, but should pass if the style_good test passes.
*/
/* CSS font embedding tests */
@font-face {
font-family: "arbitrary_good";
src: url('file_CSP.sjs?testid=font_good&type=application/octet-stream');
}
@font-face {
font-family: "arbitrary_bad";
src: url('http://example.org/tests/content/base/test/file_CSP.sjs?testid=font_bad&type=application/octet-stream');
}
.div_arbitrary_good { font-family: "arbitrary_good"; }
.div_arbitrary_bad { font-family: "arbitrary_bad"; }

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

@ -21,7 +21,6 @@ function handleRequest(request, response)
}
if ("content" in query) {
response.setHeader("Content-Type", "text/html", false);
response.write(unescape(query['content']));
}
}

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

@ -1,3 +1,8 @@
<!--
-- The original CSP implementation predates the CSP 1.0 spec and didn't
-- block inline styles, so when the prefixed X-Content-Security-Policy header is used,
-- as it is for this file, inline styles should be allowed.
-->
<html>
<head>
<title>CSP inline script tests</title>

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

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html>
<head>
<title>CSP inline script tests</title>
<!-- content= "div#linkstylediv { color: #0f0; }" -->
<link rel="stylesheet" type="text/css"
href='file_CSP.sjs?type=text/css&content=div%23linkstylediv%20%7B%20color%3A%20%230f0%3B%20%7D' />
</head>
<body>
<style type="text/css">
div#inlinestylediv {
color: #00ff00;
}
</style>
<div id='linkstylediv'>Link tag (external) stylesheet test (should be green)</div>
<div id='attrstylediv' style="color: #00ff00;">Attribute stylesheet test (should be green)</div>
<div id='inlinestylediv'>Inline stylesheet test (should be green)</div>
<!-- tests for SMIL stuff - animations -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%"
height="100px">
<!-- Animates XML attribute, which is mapped into style. -->
<text id="xmlTest" x="0" y="15">
This should be green since the animation should be allowed by CSP.
<animate attributeName="fill" attributeType="XML"
values="lime;green;lime" dur="2s"
repeatCount="indefinite" />
</text>
<!-- Animates override value for CSS property. -->
<text id="cssOverrideTest" x="0" y="35">
This should be green since the animation should be allowed by CSP.
<animate attributeName="fill" attributeType="CSS"
values="lime;green;lime" dur="2s"
repeatCount="indefinite" />
</text>
<!-- Animates override value for CSS property targeted via ID. -->
<text id="cssOverrideTestById" x="0" y="55">
This should be green since the animation should be allowed by CSP.
</text>
<animate xlink:href="#cssOverrideTestById"
attributeName="fill"
values="lime;green;lime"
dur="2s" repeatCount="indefinite" />
<!-- Sets value for CSS property targeted via ID. -->
<text id="cssSetTestById" x="0" y="75">
This should be green since the &lt;set&gt; should be allowed by CSP.
</text>
<set xlink:href="#cssSetTestById"
attributeName="fill"
to="lime" />
</svg>
</body>
</html>

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

@ -0,0 +1,2 @@
X-Content-Security-Policy: default-src 'self'
Cache-Control: no-cache

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

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html>
<head>
<title>CSP inline script tests</title>
<!-- content= "div#linkstylediv { color: #0f0; }" -->
<link rel="stylesheet" type="text/css"
href='file_CSP.sjs?type=text/css&content=div%23linkstylediv%20%7B%20color%3A%20%230f0%3B%20%7D' />
<!-- content= "div#modifycsstextdiv { color: #0f0; }" -->
<link rel="stylesheet" type="text/css"
href='file_CSP.sjs?type=text/css&content=div%23modifycsstextdiv%20%7B%20color%3A%20%23f00%3B%20%7D' />
<script>
function cssTest() {
var elem = document.getElementById('csstextstylediv');
elem.style.cssText = "color: #00FF00;";
getComputedStyle(elem, null).color;
document.styleSheets[1].cssRules[0].style.cssText = "color: #00FF00;";
elem = document.getElementById('modifycsstextdiv');
getComputedStyle(elem, null).color;
}
</script>
</head>
<body onload='cssTest()'>
<style type="text/css">
div#inlinestylediv {
color: #FF0000;
}
</style>
<div id='linkstylediv'>Link tag (external) stylesheet test (should be green)</div>
<div id='inlinestylediv'>Inline stylesheet test (should be black)</div>
<div id='attrstylediv' style="color: #FF0000;">Attribute stylesheet test (should be black)</div>
<div id='csstextstylediv'>cssText test (should be black)</div>
<div id='modifycsstextdiv'> modify rule from style sheet via cssText(should be green) </div>
<!-- tests for SMIL stuff - animations -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%"
height="100px">
<!-- Animates XML attribute, which is mapped into style. -->
<text id="xmlTest" x="0" y="15">
This shouldn't be red since the animation should be blocked by CSP.
<animate attributeName="fill" attributeType="XML"
values="red;orange;red" dur="2s"
repeatCount="indefinite" />
</text>
<!-- Animates override value for CSS property. -->
<text id="cssOverrideTest" x="0" y="35">
This shouldn't be red since the animation should be blocked by CSP.
<animate attributeName="fill" attributeType="CSS"
values="red;orange;red" dur="2s"
repeatCount="indefinite" />
</text>
<!-- Animates override value for CSS property targeted via ID. -->
<text id="cssOverrideTestById" x="0" y="55">
This shouldn't be red since the animation should be blocked by CSP.
</text>
<animate xlink:href="#cssOverrideTestById"
attributeName="fill"
values="red;orange;red"
dur="2s" repeatCount="indefinite" />
<!-- Sets value for CSS property targeted via ID. -->
<text id="cssSetTestById" x="0" y="75">
This shouldn't be red since the &lt;set&gt; should be blocked by CSP.
</text>
<set xlink:href="#cssSetTestById"
attributeName="fill"
to="red" />
</svg>
</body>
</html>

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

@ -0,0 +1,2 @@
Content-Security-Policy: default-src 'self' ; script-src 'self' 'unsafe-inline'
Cache-Control: no-cache

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

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html>
<head>
<title>CSP inline script tests</title>
<!-- content= "div#linkstylediv { color: #0f0; }" -->
<link rel="stylesheet" type="text/css"
href='file_CSP.sjs?type=text/css&content=div%23linkstylediv%20%7B%20color%3A%20%230f0%3B%20%7D' />
<!-- content= "div#modifycsstextdiv { color: #f00; }" -->
<link rel="stylesheet" type="text/css"
href='file_CSP.sjs?type=text/css&content=div%23modifycsstextdiv%20%7B%20color%3A%20%23f00%3B%20%7D' />
<script>
function cssTest() {
// CSSStyleDeclaration.cssText
var elem = document.getElementById('csstextstylediv');
elem.style.cssText = "color: #00FF00;";
// If I call getComputedStyle as below, this test passes as the parent page
// correctly detects that the text is colored green - if I remove this, getComputedStyle
// thinks the text is black when called by the parent page.
getComputedStyle(elem, null).color;
document.styleSheets[1].cssRules[0].style.cssText = "color: #00FF00;";
elem = document.getElementById('modifycsstextdiv');
getComputedStyle(elem, null).color;
}
</script>
</head>
<body onload='cssTest()'>
<style type="text/css">
div#inlinestylediv {
color: #00FF00;
}
</style>
<div id='linkstylediv'>Link tag (external) stylesheet test (should be green)</div>
<div id='inlinestylediv'>Inline stylesheet test (should be green)</div>
<div id='attrstylediv' style="color: #00FF00;">Attribute stylesheet test (should be green)</div>
<div id='csstextstylediv'>style.cssText test (should be green)</div>
<div id='modifycsstextdiv'> modify rule from style sheet via cssText(should be green) </div>
<!-- tests for SMIL stuff - animations -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%"
height="100px">
<!-- Animates XML attribute, which is mapped into style. -->
<text id="xmlTest" x="0" y="15">
This should be green since the animation should be allowed by CSP.
<animate attributeName="fill" attributeType="XML"
values="lime;green;lime" dur="2s"
repeatCount="indefinite" />
</text>
<!-- Animates override value for CSS property. -->
<text id="cssOverrideTest" x="0" y="35">
This should be green since the animation should be allowed by CSP.
<animate attributeName="fill" attributeType="CSS"
values="lime;green;lime" dur="2s"
repeatCount="indefinite" />
</text>
<!-- Animates override value for CSS property targeted via ID. -->
<text id="cssOverrideTestById" x="0" y="55">
This should be green since the animation should be allowed by CSP.
</text>
<animate xlink:href="#cssOverrideTestById"
attributeName="fill"
values="lime;green;lime"
dur="2s" repeatCount="indefinite" />
<!-- Sets value for CSS property targeted via ID. -->
<text id="cssSetTestById" x="0" y="75">
This should be green since the &lt;set&gt; should be allowed by CSP.
</text>
<set xlink:href="#cssSetTestById"
attributeName="fill"
to="lime" />
</svg>
</body>
</html>

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

@ -0,0 +1,2 @@
Content-Security-Policy: default-src 'self' ; script-src 'self' 'unsafe-inline' ; style-src 'self' 'unsafe-inline'
Cache-Control: no-cache

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

@ -5,21 +5,11 @@
<link rel='stylesheet' type='text/css'
href='file_CSP.sjs?testid=style_good&type=text/css' />
<!-- Used to embed inline styles here for testing fonts, but can't do that -->
<!-- due to bug 763879 (block inline styles). Moved these to an external, CSS -->
<!-- file (file_CSP.css). -->
<link rel='stylesheet' type='text/css' href='file_CSP.css' />
<style>
/* CSS font embedding tests */
@font-face {
font-family: "arbitrary_good";
src: url('file_CSP.sjs?testid=font_good&type=application/octet-stream');
}
@font-face {
font-family: "arbitrary_bad";
src: url('http://example.org/tests/content/base/test/file_CSP.sjs?testid=font_bad&type=application/octet-stream');
}
.div_arbitrary_good { font-family: "arbitrary_good"; }
.div_arbitrary_bad { font-family: "arbitrary_bad"; }
</style>
</head>
<body>
<!-- these should be stopped by CSP. :) -->

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

@ -0,0 +1,142 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Content Security Policy inline stylesheets stuff</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<iframe style="width:100%;height:300px;" id='cspframe'></iframe>
<iframe style="width:100%;height:300px;" id='cspframe2'></iframe>
<iframe style="width:100%;height:300px;" id='cspframe3'></iframe>
<script class="testbody" type="text/javascript">
var path = "/tests/content/base/test/";
//////////////////////////////////////////////////////////////////////
// set up and go
SimpleTest.waitForExplicitFinish();
var done = 0;
// Our original CSP implementation does not block inline styles.
function checkStyles(evt) {
var cspframe = document.getElementById('cspframe');
var color;
// black means the style wasn't applied. green colors are used for styles
//expected to be applied. A color is red if a style is erroneously applied
color = window.getComputedStyle(cspframe.contentDocument.getElementById('linkstylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'External Stylesheet (original CSP implementation) (' + color + ')');
color = window.getComputedStyle(cspframe.contentDocument.getElementById('inlinestylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'Inline Style TAG (original CSP implementation) (' + color + ')');
color = window.getComputedStyle(cspframe.contentDocument.getElementById('attrstylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'Style Attribute (original CSP implementation) (' + color + ')');
// SMIL tests
color = window.getComputedStyle(cspframe.contentDocument.getElementById('xmlTest',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'XML Attribute styling (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe.contentDocument.getElementById('cssOverrideTest',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'CSS Override styling (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe.contentDocument.getElementById('cssOverrideTestById',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'CSS Override styling via ID lookup (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe.contentDocument.getElementById('cssSetTestById',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'CSS Set Element styling via ID lookup (SMIL) (' + color + ')');
checkIfDone();
}
// When a CSP 1.0 compliant policy is specified we should block inline
// styles applied by <style> element, style attribute, and SMIL <animate> and <set> tags
// (when it's not explicitly allowed.)
function checkStylesSpecCompliant(evt) {
var cspframe = document.getElementById('cspframe2');
var color;
// black means the style wasn't applied. green colors are used for styles
//expected to be applied. A color is red if a style is erroneously applied
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('linkstylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'External Stylesheet (CSP 1.0 spec compliant) (' + color + ')');
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('inlinestylediv'),null)['color'];
ok('rgb(0, 0, 0)' === color, 'Inline Style TAG (CSP 1.0 spec compliant) (' + color + ')');
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('attrstylediv'),null)['color'];
ok('rgb(0, 0, 0)' === color, 'Style Attribute (CSP 1.0 spec compliant) (' + color + ')');
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('csstextstylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'cssText (CSP 1.0 spec compliant) (' + color + ')');
// SMIL tests
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('xmlTest',null))['fill'];
ok('rgb(0, 0, 0)' === color, 'XML Attribute styling (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('cssOverrideTest',null))['fill'];
ok('rgb(0, 0, 0)' === color, 'CSS Override styling (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('cssOverrideTestById',null))['fill'];
ok('rgb(0, 0, 0)' === color, 'CSS Override styling via ID lookup (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('cssSetTestById',null))['fill'];
ok('rgb(0, 0, 0)' === color, 'CSS Set Element styling via ID lookup (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe2.contentDocument.getElementById('modifycsstextdiv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'Modify loaded style sheet via cssText (' + color + ')');
checkIfDone();
}
// When a CSP 1.0 compliant policy is specified we should allow inline
// styles when it is explicitly allowed.
function checkStylesSpecCompliantAllowed(evt) {
var cspframe = document.getElementById('cspframe3');
var color;
// black means the style wasn't applied. green colors are used for styles
// expected to be applied. A color is red if a style is erroneously applied
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('linkstylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'External Stylesheet (CSP 1.0 spec compliant, allowed) (' + color + ')');
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('inlinestylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'Inline Style TAG (CSP 1.0 spec compliant, allowed) (' + color + ')');
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('attrstylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'Style Attribute (CSP 1.0 spec compliant, allowed) (' + color + ')');
// Note that the below test will fail if "script-src: 'unsafe-inline'" breaks,
// since it relies on executing script to set .cssText
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('csstextstylediv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'style.cssText (CSP 1.0 spec compliant, allowed) (' + color + ')');
// SMIL tests
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('xmlTest',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'XML Attribute styling (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('cssOverrideTest',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'CSS Override styling (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('cssOverrideTestById',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'CSS Override styling via ID lookup (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('cssSetTestById',null))['fill'];
ok('rgb(0, 255, 0)' === color, 'CSS Set Element styling via ID lookup (SMIL) (' + color + ')');
color = window.getComputedStyle(cspframe3.contentDocument.getElementById('modifycsstextdiv'),null)['color'];
ok('rgb(0, 255, 0)' === color, 'Modify loaded style sheet via cssText (' + color + ')');
checkIfDone();
}
function checkIfDone() {
done++;
if (done == 3)
SimpleTest.finish();
}
SpecialPowers.pushPrefEnv(
{'set':[["security.csp.speccompliant", true]]},
function() {
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_CSP_inlinestyle_main.html';
document.getElementById('cspframe').addEventListener('load', checkStyles, false);
document.getElementById('cspframe2').src = 'file_CSP_inlinestyle_main_spec_compliant.html';
document.getElementById('cspframe2').addEventListener('load', checkStylesSpecCompliant, false);
document.getElementById('cspframe3').src = 'file_CSP_inlinestyle_main_spec_compliant_allowed.html';
document.getElementById('cspframe3').addEventListener('load', checkStylesSpecCompliantAllowed, false);
}
);
</script>
</pre>
</body>
</html>

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

@ -826,8 +826,16 @@ NON_IDL_EVENT(MozPressTapGesture,
NS_SIMPLE_GESTURE_PRESSTAP,
EventNameType_None,
NS_SIMPLE_GESTURE_EVENT)
NON_IDL_EVENT(MozEdgeUIGesture,
NS_SIMPLE_GESTURE_EDGEUI,
NON_IDL_EVENT(MozEdgeUIStarted,
NS_SIMPLE_GESTURE_EDGE_STARTED,
EventNameType_None,
NS_SIMPLE_GESTURE_EVENT)
NON_IDL_EVENT(MozEdgeUICanceled,
NS_SIMPLE_GESTURE_EDGE_CANCELED,
EventNameType_None,
NS_SIMPLE_GESTURE_EVENT)
NON_IDL_EVENT(MozEdgeUICompleted,
NS_SIMPLE_GESTURE_EDGE_COMPLETED,
EventNameType_None,
NS_SIMPLE_GESTURE_EVENT)
@ -853,6 +861,11 @@ NON_IDL_EVENT(audioprocess,
EventNameType_None,
NS_EVENT)
NON_IDL_EVENT(complete,
NS_AUDIO_COMPLETE,
EventNameType_None,
NS_EVENT)
#ifdef DEFINED_FORWARDED_EVENT
#undef DEFINED_FORWARDED_EVENT
#undef FORWARDED_EVENT

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

@ -34,6 +34,7 @@
#include "nsDOMClassInfoID.h"
#include "nsDOMEventTargetHelper.h"
#include "nsPIWindowRoot.h"
#include "nsGlobalWindow.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -43,6 +44,18 @@ static char *sPopupAllowedEvents;
nsDOMEvent::nsDOMEvent(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsEvent* aEvent)
{
ConstructorInit(aOwner, aPresContext, aEvent);
}
nsDOMEvent::nsDOMEvent(nsPIDOMWindow* aParent)
{
ConstructorInit(static_cast<nsGlobalWindow *>(aParent), nullptr, nullptr);
SetIsDOMBinding();
}
void nsDOMEvent::ConstructorInit(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsEvent* aEvent)
{
SetOwner(aOwner);

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

@ -38,7 +38,11 @@ class nsDOMEvent : public nsDOMEventBase,
protected:
nsDOMEvent(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext,
nsEvent* aEvent);
nsDOMEvent(nsPIDOMWindow* aWindow);
virtual ~nsDOMEvent();
private:
void ConstructorInit(mozilla::dom::EventTarget* aOwner,
nsPresContext* aPresContext, nsEvent* aEvent);
public:
void GetParentObject(nsIScriptGlobalObject** aParentObject)
{

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

@ -953,6 +953,15 @@ MediaStreamGraphImpl::RunThread()
NS_ASSERTION(!messageQueue.IsEmpty(),
"Shouldn't have started a graph with empty message queue!");
uint32_t ticksProcessed = 0;
if (!mRealtime) {
NS_ASSERTION(!mNonRealtimeIsRunning,
"We should not be running in non-realtime mode already");
NS_ASSERTION(mNonRealtimeTicksToProcess,
"We should have a non-zero number of ticks to process");
mNonRealtimeIsRunning = true;
}
for (;;) {
// Update mCurrentTime to the min of the playing audio times, or using the
// wall-clock time change if no audio is playing.
@ -1032,6 +1041,18 @@ MediaStreamGraphImpl::RunThread()
allBlockedForever = false;
}
}
if (!mRealtime) {
ticksProcessed += TimeToTicksRoundDown(IdealAudioRate(), mStateComputedTime - prevComputedTime);
// Terminate processing if we've produce enough non-realtime ticks.
if (ticksProcessed >= mNonRealtimeTicksToProcess) {
// Wait indefinitely when we've processed enough non-realtime ticks.
// We'll be woken up when the graph shuts down.
MonitorAutoLock lock(mMonitor);
PrepareUpdatesToMainThreadState();
mWaitState = WAITSTATE_WAITING_INDEFINITELY;
mMonitor.Wait(PR_INTERVAL_NO_TIMEOUT);
}
}
if (ensureNextIteration || !allBlockedForever || audioStreamsActive > 0) {
EnsureNextIteration();
}
@ -1082,6 +1103,10 @@ MediaStreamGraphImpl::RunThread()
messageQueue.SwapElements(mMessageQueue);
}
}
if (!mRealtime) {
mNonRealtimeIsRunning = false;
}
}
void
@ -1363,14 +1388,23 @@ MediaStreamGraphImpl::AppendMessage(ControlMessage* aMessage)
if (IsEmpty()) {
if (gGraph == this) {
gGraph = nullptr;
delete this;
}
delete this;
} else if (!mRealtime) {
// Make sure to mark the graph as not doing non-realtime processing,
// because otherwise AppendMessage will try to ensure that the graph
// is running, and we will never manage to release our resources.
mNonRealtimeProcessing = false;
}
return;
}
mCurrentTaskMessageQueue.AppendElement(aMessage);
EnsureRunInStableState();
// Do not start running the non-realtime graph unless processing has
// explicitly started.
if (mRealtime || mNonRealtimeProcessing) {
EnsureRunInStableState();
}
}
void
@ -1958,12 +1992,15 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(bool aRealtime)
, mMonitor("MediaStreamGraphImpl")
, mLifecycleState(LIFECYCLE_THREAD_NOT_STARTED)
, mWaitState(WAITSTATE_RUNNING)
, mNonRealtimeTicksToProcess(0)
, mNeedAnotherIteration(false)
, mForceShutDown(false)
, mPostedRunInStableStateEvent(false)
, mNonRealtimeIsRunning(false)
, mDetectedNotRunning(false)
, mPostedRunInStableState(false)
, mRealtime(aRealtime)
, mNonRealtimeProcessing(false)
{
#ifdef PR_LOGGING
if (!gMediaStreamGraphLog) {
@ -2028,7 +2065,6 @@ MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(aGraph);
graph->ForceShutDown();
delete graph;
}
SourceMediaStream*
@ -2071,4 +2107,19 @@ MediaStreamGraph::CreateAudioNodeStream(AudioNodeEngine* aEngine,
return stream;
}
void
MediaStreamGraph::StartNonRealtimeProcessing(uint32_t aTicksToProcess)
{
NS_ASSERTION(NS_IsMainThread(), "main thread only");
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
NS_ASSERTION(!graph->mRealtime, "non-realtime only");
if (graph->mNonRealtimeProcessing)
return;
graph->mNonRealtimeTicksToProcess = aTicksToProcess;
graph->mNonRealtimeProcessing = true;
graph->EnsureRunInStableState();
}
}

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

@ -939,6 +939,10 @@ public:
* in main-thread stream state.
*/
int64_t GetCurrentGraphUpdateIndex() { return mGraphUpdatesSent; }
/**
* Start processing non-realtime for a specific number of ticks.
*/
void StartNonRealtimeProcessing(uint32_t aTicksToProcess);
/**
* Media graph thread only.

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

@ -480,6 +480,10 @@ public:
WAITSTATE_WAKING_UP
};
WaitState mWaitState;
/**
* How many non-realtime ticks the graph should process.
*/
uint32_t mNonRealtimeTicksToProcess;
/**
* True when another iteration of the control loop is required.
*/
@ -493,6 +497,13 @@ public:
* RunInStableState() and the event hasn't run yet.
*/
bool mPostedRunInStableStateEvent;
/**
* True when the non-realtime graph thread is processing, as a result of
* a request from the main thread. When processing is finished, we post
* a message to the main thread in order to set mNonRealtimeProcessing
* back to false.
*/
bool mNonRealtimeIsRunning;
// Main thread only
@ -519,6 +530,11 @@ public:
* audio.
*/
bool mRealtime;
/**
* True when a non-realtime MediaStreamGraph has started to process input. This
* value is only accessed on the main thread.
*/
bool mNonRealtimeProcessing;
};
}

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

@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include <cutils/properties.h>
#include <stagefright/foundation/AMessage.h>
#include <stagefright/MediaExtractor.h>
#include <stagefright/MetaData.h>
#include <stagefright/OMXClient.h>
@ -58,7 +59,11 @@ VideoGraphicBuffer::Unlock()
{
android::sp<android::OmxDecoder> omxDecoder = mOmxDecoder.promote();
if (omxDecoder.get()) {
omxDecoder->ReleaseVideoBuffer(mMediaBuffer);
// Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
// The message is delivered to OmxDecoder on ALooper thread.
// MediaBuffer::release() could take a very long time.
// PostReleaseVideoBuffer() prevents long time locking.
omxDecoder->PostReleaseVideoBuffer(mMediaBuffer);
} else {
NS_WARNING("OmxDecoder is not present");
if (mMediaBuffer) {
@ -145,10 +150,24 @@ OmxDecoder::OmxDecoder(MediaResource *aResource,
mAudioMetadataRead(false),
mPaused(false)
{
mLooper = new ALooper;
mLooper->setName("OmxDecoder");
mReflector = new AHandlerReflector<OmxDecoder>(this);
// Register AMessage handler to ALooper.
mLooper->registerHandler(mReflector);
// Start ALooper thread.
mLooper->start();
}
OmxDecoder::~OmxDecoder()
{
{
// Free all pending video buffers.
Mutex::Autolock autoLock(mSeekLock);
ReleaseAllPendingVideoBuffersLocked();
}
ReleaseVideoBuffer();
ReleaseAudioBuffer();
@ -159,6 +178,11 @@ OmxDecoder::~OmxDecoder()
if (mAudioSource.get()) {
mAudioSource->stop();
}
// unregister AMessage handler from ALooper.
mLooper->unregisterHandler(mReflector->id());
// Stop ALooper thread.
mLooper->stop();
}
class AutoStopMediaSource {
@ -674,32 +698,6 @@ bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
return true;
}
bool OmxDecoder::ReleaseVideoBuffer(MediaBuffer *aBuffer)
{
Mutex::Autolock autoLock(mSeekLock);
if (!aBuffer) {
return false;
}
if (mIsVideoSeeking == true) {
mPendingVideoBuffers.push(aBuffer);
} else {
aBuffer->release();
}
return true;
}
void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
{
int size = mPendingVideoBuffers.size();
for (int i = 0; i < size; i++) {
MediaBuffer *buffer = mPendingVideoBuffers[i];
buffer->release();
}
mPendingVideoBuffers.clear();
}
nsresult OmxDecoder::Play() {
if (!mPaused) {
return NS_OK;
@ -729,3 +727,51 @@ void OmxDecoder::Pause() {
mPaused = true;
}
// Called on ALooper thread.
void OmxDecoder::onMessageReceived(const sp<AMessage> &msg)
{
Mutex::Autolock autoLock(mSeekLock);
// Free pending video buffers when OmxDecoder is not seeking video.
// If OmxDecoder is in seeking video, the buffers are freed on seek exit.
if (mIsVideoSeeking != true) {
ReleaseAllPendingVideoBuffersLocked();
}
}
void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer)
{
{
Mutex::Autolock autoLock(mPendingVideoBuffersLock);
mPendingVideoBuffers.push(aBuffer);
}
sp<AMessage> notify =
new AMessage(kNotifyPostReleaseVideoBuffer, mReflector->id());
// post AMessage to OmxDecoder via ALooper.
notify->post();
}
void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
{
Vector<MediaBuffer *> releasingVideoBuffers;
{
Mutex::Autolock autoLock(mPendingVideoBuffersLock);
int size = mPendingVideoBuffers.size();
for (int i = 0; i < size; i++) {
MediaBuffer *buffer = mPendingVideoBuffers[i];
releasingVideoBuffers.push(buffer);
}
mPendingVideoBuffers.clear();
}
// Free all pending video buffers without holding mPendingVideoBuffersLock.
int size = releasingVideoBuffers.size();
for (int i = 0; i < size; i++) {
MediaBuffer *buffer;
buffer = releasingVideoBuffers[i];
buffer->release();
}
releasingVideoBuffers.clear();
}

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

@ -1,3 +1,7 @@
#include <stagefright/foundation/ABase.h>
#include <stagefright/foundation/AHandlerReflector.h>
#include <stagefright/foundation/ALooper.h>
#include <stagefright/MediaSource.h>
#include <stagefright/DataSource.h>
#include <stagefright/MediaSource.h>
#include <utils/RefBase.h>
@ -79,6 +83,10 @@ class OmxDecoder : public RefBase {
kHardwareCodecsOnly = 16,
};
enum {
kNotifyPostReleaseVideoBuffer = 'noti'
};
AbstractMediaDecoder *mDecoder;
nsRefPtr<MediaResource> mResource;
sp<GonkNativeWindow> mNativeWindow;
@ -109,6 +117,9 @@ class OmxDecoder : public RefBase {
// OMXCodec does not accept MediaBuffer during seeking. If MediaBuffer is
// returned to OMXCodec during seeking, OMXCodec calls assert.
Vector<MediaBuffer *> mPendingVideoBuffers;
// The lock protects mPendingVideoBuffers.
Mutex mPendingVideoBuffersLock;
// Show if OMXCodec is seeking.
bool mIsVideoSeeking;
// The lock protects video MediaBuffer release()'s pending operations called
@ -117,6 +128,16 @@ class OmxDecoder : public RefBase {
// Holding time should be minimum.
Mutex mSeekLock;
// ALooper is a message loop used in stagefright.
// It creates a thread for messages and handles messages in the thread.
// ALooper is a clone of Looper in android Java.
// http://developer.android.com/reference/android/os/Looper.html
sp<ALooper> mLooper;
// deliver a message to a wrapped object(OmxDecoder).
// AHandlerReflector is similar to Handler in android Java.
// http://developer.android.com/reference/android/os/Handler.html
sp<AHandlerReflector<OmxDecoder> > mReflector;
// 'true' if a read from the audio stream was done while reading the metadata
bool mAudioMetadataRead;
@ -175,13 +196,18 @@ public:
return mResource;
}
bool ReleaseVideoBuffer(MediaBuffer *aBuffer);
//Change decoder into a playing state
nsresult Play();
//Change decoder into a paused state
void Pause();
// Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
void PostReleaseVideoBuffer(MediaBuffer *aBuffer);
// Receive a message from AHandlerReflector.
// Called on ALooper thread.
void onMessageReceived(const sp<AMessage> &msg);
};
}

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

@ -553,15 +553,16 @@ AudioBufferSourceNode::SendOffsetAndDurationParametersToStream(AudioNodeStream*
}
void
AudioBufferSourceNode::Stop(double aWhen, ErrorResult& aRv)
AudioBufferSourceNode::Stop(double aWhen, ErrorResult& aRv, bool aShuttingDown)
{
if (!mStartCalled) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (!mBuffer) {
if (!mBuffer || aShuttingDown) {
// We don't have a buffer, so the stream is never marked as finished.
// This can also happen if the AudioContext is being shut down.
// Therefore we need to drop our playing ref right now.
mPlayingRef.Drop(this);
}

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

@ -56,7 +56,7 @@ public:
duration.Construct(aDuration);
Start(aWhen, aOffset, duration, aRv);
}
void Stop(double aWhen, ErrorResult& aRv);
void Stop(double aWhen, ErrorResult& aRv, bool aShuttingDown = false);
void NoteOff(double aWhen, ErrorResult& aRv)
{
Stop(aWhen, aRv);

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

@ -8,6 +8,8 @@
#include "nsContentUtils.h"
#include "nsPIDOMWindow.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/AudioContextBinding.h"
#include "mozilla/dom/OfflineAudioContextBinding.h"
#include "MediaStreamGraph.h"
#include "mozilla/dom/AnalyserNode.h"
#include "AudioDestinationNode.h"
@ -44,8 +46,15 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
static uint8_t gWebAudioOutputKey;
AudioContext::AudioContext(nsPIDOMWindow* aWindow)
: mDestination(new AudioDestinationNode(this, MediaStreamGraph::GetInstance()))
AudioContext::AudioContext(nsPIDOMWindow* aWindow,
bool aIsOffline,
uint32_t aNumberOfChannels,
uint32_t aLength,
float aSampleRate)
: mDestination(new AudioDestinationNode(this, aIsOffline,
aNumberOfChannels,
aLength, aSampleRate))
, mIsOffline(aIsOffline)
{
// Actually play audio
mDestination->Stream()->AddAudioOutput(&gWebAudioOutputKey);
@ -64,7 +73,11 @@ AudioContext::~AudioContext()
JSObject*
AudioContext::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return AudioContextBinding::Wrap(aCx, aScope, this);
if (mIsOffline) {
return OfflineAudioContextBinding::Wrap(aCx, aScope, this);
} else {
return AudioContextBinding::Wrap(aCx, aScope, this);
}
}
/* static */ already_AddRefed<AudioContext>
@ -76,7 +89,35 @@ AudioContext::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
return nullptr;
}
nsRefPtr<AudioContext> object = new AudioContext(window);
nsRefPtr<AudioContext> object = new AudioContext(window, false);
window->AddAudioContext(object);
return object.forget();
}
/* static */ already_AddRefed<AudioContext>
AudioContext::Constructor(const GlobalObject& aGlobal,
uint32_t aNumberOfChannels,
uint32_t aLength,
float aSampleRate,
ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
if (!window) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
if (aSampleRate != IdealAudioRate()) {
// TODO: Add support for running OfflineAudioContext at other sampling rates
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return nullptr;
}
nsRefPtr<AudioContext> object = new AudioContext(window,
true,
aNumberOfChannels,
aLength,
aSampleRate);
window->AddAudioContext(object);
return object.forget();
}
@ -388,7 +429,7 @@ AudioContext::Shutdown()
GetHashtableElements(mAudioBufferSourceNodes, sourceNodes);
for (uint32_t i = 0; i < sourceNodes.Length(); ++i) {
ErrorResult rv;
sourceNodes[i]->Stop(0.0, rv);
sourceNodes[i]->Stop(0.0, rv, true);
}
// Stop all script processor nodes, to make sure that they release
// their self-references.
@ -397,6 +438,11 @@ AudioContext::Shutdown()
for (uint32_t i = 0; i < spNodes.Length(); ++i) {
spNodes[i]->Stop();
}
// For offline contexts, we can destroy the MediaStreamGraph at this point.
if (mIsOffline) {
mDestination->DestroyGraph();
}
}
void
@ -434,5 +480,13 @@ AudioContext::GetJSContext() const
return scriptContext->GetNativeContext();
}
void
AudioContext::StartRendering()
{
MOZ_ASSERT(mIsOffline, "This should only be called on OfflineAudioContext");
mDestination->StartRendering();
}
}
}

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

@ -50,6 +50,7 @@ class DelayNode;
class DynamicsCompressorNode;
class GainNode;
class GlobalObject;
class OfflineRenderSuccessCallback;
class PannerNode;
class ScriptProcessorNode;
class WaveShaperNode;
@ -57,7 +58,11 @@ class WaveShaperNode;
class AudioContext MOZ_FINAL : public nsDOMEventTargetHelper,
public EnableWebAudioCheck
{
explicit AudioContext(nsPIDOMWindow* aParentWindow);
AudioContext(nsPIDOMWindow* aParentWindow,
bool aIsOffline,
uint32_t aNumberOfChannels = 0,
uint32_t aLength = 0,
float aSampleRate = 0.0f);
~AudioContext();
public:
@ -77,9 +82,22 @@ public:
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
using nsDOMEventTargetHelper::DispatchTrustedEvent;
// Constructor for regular AudioContext
static already_AddRefed<AudioContext>
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
// Constructor for offline AudioContext
static already_AddRefed<AudioContext>
Constructor(const GlobalObject& aGlobal,
uint32_t aNumberOfChannels,
uint32_t aLength,
float aSampleRate,
ErrorResult& aRv);
// AudioContext methods
AudioDestinationNode* Destination() const
{
return mDestination;
@ -164,7 +182,12 @@ public:
DecodeSuccessCallback& aSuccessCallback,
const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback);
// OfflineAudioContext methods
void StartRendering();
IMPL_EVENT_HANDLER(complete)
uint32_t GetRate() const { return IdealAudioRate(); }
bool IsOffline() const { return mIsOffline; }
MediaStreamGraph* Graph() const;
MediaStream* DestinationStream() const;
@ -193,6 +216,7 @@ private:
// Hashset containing all ScriptProcessorNodes in order to stop them.
// These are all weak pointers.
nsTHashtable<nsPtrHashKey<ScriptProcessorNode> > mScriptProcessorNodes;
bool mIsOffline;
};
}

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

@ -9,20 +9,197 @@
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "MediaStreamGraph.h"
#include "OfflineAudioCompletionEvent.h"
namespace mozilla {
namespace dom {
class OfflineDestinationNodeEngine : public AudioNodeEngine
{
public:
typedef AutoFallibleTArray<nsAutoArrayPtr<float>, 2> InputChannels;
OfflineDestinationNodeEngine(AudioDestinationNode* aNode,
uint32_t aNumberOfChannels,
uint32_t aLength,
float aSampleRate)
: AudioNodeEngine(aNode)
, mWriteIndex(0)
, mLength(aLength)
, mSampleRate(aSampleRate)
{
// These allocations might fail if content provides a huge number of
// channels or size, but it's OK since we'll deal with the failure
// gracefully.
if (mInputChannels.SetLength(aNumberOfChannels)) {
static const fallible_t fallible = fallible_t();
for (uint32_t i = 0; i < aNumberOfChannels; ++i) {
mInputChannels[i] = new(fallible) float[aLength];
if (!mInputChannels[i]) {
mInputChannels.Clear();
break;
}
}
}
}
virtual void ProduceAudioBlock(AudioNodeStream* aStream,
const AudioChunk& aInput,
AudioChunk* aOutput,
bool* aFinished) MOZ_OVERRIDE
{
// Do this just for the sake of political correctness; this output
// will not go anywhere.
*aOutput = aInput;
// Handle the case of allocation failure in the input buffer
if (mInputChannels.IsEmpty()) {
return;
}
// Record our input buffer
MOZ_ASSERT(mWriteIndex < mLength, "How did this happen?");
const uint32_t duration = std::min(WEBAUDIO_BLOCK_SIZE, mLength - mWriteIndex);
for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
if (aInput.IsNull()) {
PodZero(mInputChannels[i] + mWriteIndex, duration);
} else {
const float* inputBuffer = static_cast<const float*>(aInput.mChannelData[i]);
if (duration == WEBAUDIO_BLOCK_SIZE) {
// Use the optimized version of the copy with scale operation
AudioBlockCopyChannelWithScale(inputBuffer, aInput.mVolume,
mInputChannels[i] + mWriteIndex);
} else {
if (aInput.mVolume == 1.0f) {
PodCopy(mInputChannels[i] + mWriteIndex, inputBuffer, duration);
} else {
for (uint32_t j = 0; j < duration; ++j) {
mInputChannels[i][mWriteIndex + j] = aInput.mVolume * inputBuffer[j];
}
}
}
}
}
mWriteIndex += duration;
if (mWriteIndex == mLength) {
SendBufferToMainThread(aStream);
*aFinished = true;
}
}
void SendBufferToMainThread(AudioNodeStream* aStream)
{
class Command : public nsRunnable
{
public:
Command(AudioNodeStream* aStream,
InputChannels& aInputChannels,
uint32_t aLength,
float aSampleRate)
: mStream(aStream)
, mLength(aLength)
, mSampleRate(aSampleRate)
{
mInputChannels.SwapElements(aInputChannels);
}
NS_IMETHODIMP Run()
{
// If it's not safe to run scripts right now, schedule this to run later
if (!nsContentUtils::IsSafeToRunScript()) {
nsContentUtils::AddScriptRunner(this);
return NS_OK;
}
nsRefPtr<AudioContext> context;
{
MutexAutoLock lock(mStream->Engine()->NodeMutex());
AudioNode* node = mStream->Engine()->Node();
if (node) {
context = node->Context();
}
}
if (!context) {
return NS_OK;
}
AutoPushJSContext cx(context->GetJSContext());
if (cx) {
JSAutoRequest ar(cx);
// Create the input buffer
nsRefPtr<AudioBuffer> renderedBuffer = new AudioBuffer(context,
mLength,
mSampleRate);
if (!renderedBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
return NS_OK;
}
for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
renderedBuffer->SetRawChannelContents(cx, i, mInputChannels[i]);
}
nsRefPtr<OfflineAudioCompletionEvent> event =
new OfflineAudioCompletionEvent(context, nullptr, nullptr);
event->InitEvent(renderedBuffer);
context->DispatchTrustedEvent(event);
}
return NS_OK;
}
private:
nsRefPtr<AudioNodeStream> mStream;
InputChannels mInputChannels;
uint32_t mLength;
float mSampleRate;
};
// Empty out the source array to make sure we don't attempt to collect
// more input data in the future.
NS_DispatchToMainThread(new Command(aStream, mInputChannels, mLength, mSampleRate));
}
private:
// The input to the destination node is recorded in the mInputChannels buffer.
// When this buffer fills up with mLength frames, the buffered input is sent
// to the main thread in order to dispatch OfflineAudioCompletionEvent.
InputChannels mInputChannels;
// An index representing the next offset in mInputChannels to be written to.
uint32_t mWriteIndex;
// How many frames the OfflineAudioContext intends to produce.
uint32_t mLength;
float mSampleRate;
};
NS_IMPL_ISUPPORTS_INHERITED0(AudioDestinationNode, AudioNode)
AudioDestinationNode::AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph)
AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
bool aIsOffline,
uint32_t aNumberOfChannels,
uint32_t aLength,
float aSampleRate)
: AudioNode(aContext,
2,
aIsOffline ? aNumberOfChannels : 2,
ChannelCountMode::Explicit,
ChannelInterpretation::Speakers)
, mFramesToProduce(aLength)
{
mStream = aGraph->CreateAudioNodeStream(new AudioNodeEngine(this),
MediaStreamGraph::EXTERNAL_STREAM);
MediaStreamGraph* graph = aIsOffline ?
MediaStreamGraph::CreateNonRealtimeInstance() :
MediaStreamGraph::GetInstance();
AudioNodeEngine* engine = aIsOffline ?
new OfflineDestinationNodeEngine(this, aNumberOfChannels,
aLength, aSampleRate) :
new AudioNodeEngine(this);
mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
}
void
AudioDestinationNode::DestroyGraph()
{
MOZ_ASSERT(Context() && Context()->IsOffline(),
"Should only be called on a valid OfflineAudioContext");
MediaStreamGraph::DestroyNonRealtimeInstance(mStream->Graph());
}
JSObject*
@ -31,5 +208,11 @@ AudioDestinationNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
return AudioDestinationNodeBinding::Wrap(aCx, aScope, this);
}
void
AudioDestinationNode::StartRendering()
{
mStream->Graph()->StartNonRealtimeProcessing(mFramesToProduce);
}
}
}

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

@ -17,7 +17,13 @@ class AudioContext;
class AudioDestinationNode : public AudioNode
{
public:
AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph);
// This node type knows what MediaStreamGraph to use based on
// whether it's in offline mode.
AudioDestinationNode(AudioContext* aContext,
bool aIsOffline,
uint32_t aNumberOfChannels = 0,
uint32_t aLength = 0,
float aSampleRate = 0.0f);
NS_DECL_ISUPPORTS_INHERITED
@ -29,6 +35,12 @@ public:
return 0;
}
void StartRendering();
void DestroyGraph();
private:
uint32_t mFramesToProduce;
};
}

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

@ -33,6 +33,7 @@ CPPSRCS := \
EnableWebAudioCheck.cpp \
GainNode.cpp \
MediaBufferDecoder.cpp \
OfflineAudioCompletionEvent.cpp \
PannerNode.cpp \
ScriptProcessorNode.cpp \
ThreeDPoint.cpp \

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

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OfflineAudioCompletionEvent.h"
#include "mozilla/dom/OfflineAudioCompletionEventBinding.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(OfflineAudioCompletionEvent, nsDOMEvent,
mRenderedBuffer)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(OfflineAudioCompletionEvent)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
NS_IMPL_ADDREF_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent)
OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(AudioContext* aOwner,
nsPresContext* aPresContext,
nsEvent* aEvent)
: nsDOMEvent(aOwner, aPresContext, aEvent)
{
SetIsDOMBinding();
}
JSObject*
OfflineAudioCompletionEvent::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return OfflineAudioCompletionEventBinding::Wrap(aCx, aScope, this);
}
}
}

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

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef OfflineAudioCompletionEvent_h_
#define OfflineAudioCompletionEvent_h_
#include "nsDOMEvent.h"
#include "AudioBuffer.h"
#include "AudioContext.h"
namespace mozilla {
namespace dom {
class OfflineAudioCompletionEvent : public nsDOMEvent,
public EnableWebAudioCheck
{
public:
OfflineAudioCompletionEvent(AudioContext* aOwner,
nsPresContext *aPresContext,
nsEvent *aEvent);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_TO_NSDOMEVENT
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OfflineAudioCompletionEvent, nsDOMEvent)
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
void InitEvent(AudioBuffer* aRenderedBuffer)
{
InitEvent(NS_LITERAL_STRING("complete"), false, false);
mRenderedBuffer = aRenderedBuffer;
}
AudioBuffer* RenderedBuffer() const
{
return mRenderedBuffer;
}
private:
nsRefPtr<AudioBuffer> mRenderedBuffer;
};
}
}
#endif

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

@ -34,6 +34,7 @@ EXPORTS.mozilla.dom += [
'DynamicsCompressorNode.h',
'EnableWebAudioCheck.h',
'GainNode.h',
'OfflineAudioCompletionEvent.h',
'PannerNode.h',
'ScriptProcessorNode.h',
'WaveShaperNode.h',

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

@ -58,6 +58,7 @@ MOCHITEST_FILES := \
test_mediaDecoding.html \
test_mixingRules.html \
test_nodeToParamConnection.html \
test_OfflineAudioContext.html \
test_pannerNode.html \
test_scriptProcessorNode.html \
test_scriptProcessorNodeChannelCount.html \

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

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test OfflineAudioContext</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="webaudio.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
var ctx = new OfflineAudioContext(2, 100, (new AudioContext()).sampleRate);
ok(ctx instanceof EventTarget, "OfflineAudioContexts must be EventTargets");
var buf = ctx.createBuffer(2, 100, ctx.sampleRate);
for (var i = 0; i < 2; ++i) {
for (var j = 0; j < 100; ++j) {
buf.getChannelData(i)[j] = Math.sin(2 * Math.PI * 200 * j / ctx.sampleRate);
}
}
var src = ctx.createBufferSource();
src.buffer = buf;
src.start(0);
src.connect(ctx.destination);
ctx.startRendering();
ctx.addEventListener("complete", function(e) {
ok(e instanceof OfflineAudioCompletionEvent, "Correct event received");
is(e.renderedBuffer.numberOfChannels, 2, "Correct expected number of buffers");
compareBuffers(e.renderedBuffer.getChannelData(0), buf.getChannelData(0));
compareBuffers(e.renderedBuffer.getChannelData(1), buf.getChannelData(1));
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
}, false);
});
</script>
</pre>
</body>
</html>

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

@ -31,8 +31,11 @@ function compareBuffers(buf1, buf2,
/*optional*/ offset,
/*optional*/ length,
/*optional*/ sourceOffset,
/*optional*/ destOffset) {
is(buf1.length, buf2.length, "Buffers must have the same length");
/*optional*/ destOffset,
/*optional*/ skipLengthCheck) {
if (!skipLengthCheck) {
is(buf1.length, buf2.length, "Buffers must have the same length");
}
if (length == undefined) {
length = buf1.length - (offset || 0);
}
@ -100,48 +103,89 @@ function runTest()
gTest.numberOfChannels = 2; // default
}
var context = new AudioContext();
if (!gTest.createExpectedBuffers) {
// Assume that the output is silence
var expectedBuffers = getEmptyBuffer(context, gTest.length);
} else {
var expectedBuffers = gTest.createExpectedBuffers(context);
}
if (!(expectedBuffers instanceof Array)) {
expectedBuffers = [expectedBuffers];
}
var expectedFrames = 0;
for (var i = 0; i < expectedBuffers.length; ++i) {
is(expectedBuffers[i].numberOfChannels, gTest.numberOfChannels,
"Correct number of channels for expected buffer " + i);
expectedFrames += expectedBuffers[i].length;
}
is(expectedFrames, gTest.length, "Correct number of expected frames");
var testLength;
if (gTest.createGraphAsync) {
gTest.createGraphAsync(context, function(nodeToInspect) {
testOutput(nodeToInspect);
});
} else {
testOutput(gTest.createGraph(context));
function runTestOnContext(context, callback, testOutput) {
if (!gTest.createExpectedBuffers) {
// Assume that the output is silence
var expectedBuffers = getEmptyBuffer(context, gTest.length);
} else {
var expectedBuffers = gTest.createExpectedBuffers(context);
}
if (!(expectedBuffers instanceof Array)) {
expectedBuffers = [expectedBuffers];
}
var expectedFrames = 0;
for (var i = 0; i < expectedBuffers.length; ++i) {
is(expectedBuffers[i].numberOfChannels, gTest.numberOfChannels,
"Correct number of channels for expected buffer " + i);
expectedFrames += expectedBuffers[i].length;
}
is(expectedFrames, gTest.length, "Correct number of expected frames");
if (gTest.createGraphAsync) {
gTest.createGraphAsync(context, function(nodeToInspect) {
testOutput(nodeToInspect, expectedBuffers, callback);
});
} else {
testOutput(gTest.createGraph(context), expectedBuffers, callback);
}
}
function testOutput(nodeToInspect) {
var sp = context.createScriptProcessor(expectedBuffers[0].length, gTest.numberOfChannels);
nodeToInspect.connect(sp);
sp.connect(context.destination);
sp.onaudioprocess = function(e) {
var expectedBuffer = expectedBuffers.shift();
is(e.inputBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
"Correct number of input buffer channels");
for (var i = 0; i < e.inputBuffer.numberOfChannels; ++i) {
compareBuffers(e.inputBuffer.getChannelData(i), expectedBuffer.getChannelData(i));
}
if (expectedBuffers.length == 0) {
sp.onaudioprocess = null;
done();
}
};
function testOnNormalContext(callback) {
function testOutput(nodeToInspect, expectedBuffers, callback) {
testLength = 0;
var sp = context.createScriptProcessor(expectedBuffers[0].length, gTest.numberOfChannels);
nodeToInspect.connect(sp);
sp.connect(context.destination);
sp.onaudioprocess = function(e) {
var expectedBuffer = expectedBuffers.shift();
testLength += expectedBuffer.length;
is(e.inputBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
"Correct number of input buffer channels");
for (var i = 0; i < e.inputBuffer.numberOfChannels; ++i) {
compareBuffers(e.inputBuffer.getChannelData(i), expectedBuffer.getChannelData(i));
}
if (expectedBuffers.length == 0) {
sp.onaudioprocess = null;
callback();
}
};
}
var context = new AudioContext();
runTestOnContext(context, callback, testOutput);
}
function testOnOfflineContext(callback) {
function testOutput(nodeToInspect, expectedBuffers, callback) {
nodeToInspect.connect(context.destination);
context.oncomplete = function(e) {
var samplesSeen = 0;
while (expectedBuffers.length) {
var expectedBuffer = expectedBuffers.shift();
is(e.renderedBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
"Correct number of input buffer channels");
for (var i = 0; i < e.renderedBuffer.numberOfChannels; ++i) {
compareBuffers(e.renderedBuffer.getChannelData(i),
expectedBuffer.getChannelData(i),
undefined,
expectedBuffer.length,
samplesSeen,
undefined,
true);
}
samplesSeen += expectedBuffer.length;
}
callback();
};
context.startRendering();
}
var context = new OfflineAudioContext(gTest.numberOfChannels, testLength, 48000);
runTestOnContext(context, callback, testOutput);
}
testOnNormalContext(function() {
testOnOfflineContext(done);
});
});
}

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

@ -15,6 +15,7 @@
#include "nsPresContext.h"
#include "mozilla/dom/Element.h"
#include "nsDebug.h"
#include "nsStyleUtil.h"
using namespace mozilla::dom;
@ -391,6 +392,13 @@ nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
return;
}
nsIDocument* doc = aTargetElement->GetCurrentDoc();
if (doc && !nsStyleUtil::CSPAllowsInlineStyle(doc->NodePrincipal(),
doc->GetDocumentURI(),
0, aString, nullptr)) {
return;
}
nsStyleAnimation::Value parsedValue;
if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
aString, parsedValue, aIsContextSensitive)) {

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

@ -2305,6 +2305,9 @@ nsXULPrototypeElement::SetAttrAt(uint32_t aPos, const nsAString& aValue,
nsCSSParser parser;
// XXX Get correct Base URI (need GetBaseURI on *prototype* element)
// TODO: If we implement Content Security Policy for chrome documents
// as has been discussed, the CSP should be checked here to see if
// inline styles are allowed to be applied.
parser.ParseStyleAttribute(aValue, aDocumentURI, aDocumentURI,
// This is basically duplicating what
// nsINode::NodePrincipal() does

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

@ -336,7 +336,6 @@ using mozilla::dom::workers::ResolveWorkerClasses;
#ifdef MOZ_WEBRTC
#include "nsIDOMDataChannel.h"
#include "nsIDOMRTCPeerConnection.h"
#endif
using namespace mozilla;
@ -915,8 +914,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
#ifdef MOZ_WEBRTC
NS_DEFINE_CLASSINFO_DATA(DataChannel, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(RTCPeerConnection, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
#endif
};
@ -2303,10 +2300,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataChannel)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(RTCPeerConnection, nsIDOMRTCPeerConnection)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMRTCPeerConnection)
DOM_CLASSINFO_MAP_END
#endif
MOZ_STATIC_ASSERT(MOZ_ARRAY_LENGTH(sClassInfoData) == eDOMClassInfoIDCount,

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

@ -242,5 +242,4 @@ DOMCI_CLASS(MozTimeManager)
#ifdef MOZ_WEBRTC
DOMCI_CLASS(DataChannel)
DOMCI_CLASS(RTCPeerConnection)
#endif

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

@ -1220,8 +1220,12 @@ nsDOMWindowUtils::SendSimpleGestureEvent(const nsAString& aType,
msg = NS_SIMPLE_GESTURE_TAP;
else if (aType.EqualsLiteral("MozPressTapGesture"))
msg = NS_SIMPLE_GESTURE_PRESSTAP;
else if (aType.EqualsLiteral("MozEdgeUIGesture"))
msg = NS_SIMPLE_GESTURE_EDGEUI;
else if (aType.EqualsLiteral("MozEdgeUIStarted"))
msg = NS_SIMPLE_GESTURE_EDGE_STARTED;
else if (aType.EqualsLiteral("MozEdgeUICanceled"))
msg = NS_SIMPLE_GESTURE_EDGE_CANCELED;
else if (aType.EqualsLiteral("MozEdgeUICompleted"))
msg = NS_SIMPLE_GESTURE_EDGE_COMPLETED;
else
return NS_ERROR_FAILURE;

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

@ -675,6 +675,17 @@ DOMInterfaces = {
'nativeType': 'nsDOMNotifyAudioAvailableEvent',
},
'OfflineAudioCompletionEvent': {
'resultNotAddRefed': [ 'renderedBuffer' ],
},
'OfflineAudioContext': {
'nativeType': 'mozilla::dom::AudioContext',
'implicitJSContext': [ 'createBuffer' ],
'nativeOwnership': 'refcounted',
'resultNotAddRefed': [ 'destination', 'listener' ],
},
'PaintRequest': {
'nativeType': 'nsPaintRequest',
},
@ -1542,6 +1553,7 @@ addExternalIface('DeviceRotationRate', headerFile='nsIDOMDeviceMotionEvent.h', n
addExternalIface('DOMError')
addExternalIface('CSSRuleList')
addExternalIface('DOMStringList')
addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
addExternalIface('File')
addExternalIface('FileCallback', nativeType='nsIFileCallback',
headerFile='nsIDOMHTMLCanvasElement.h')

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

@ -8311,7 +8311,8 @@ class CGNativeMember(ClassMethod):
# The holder is an nsRefPtr. If we're nullable and end up null,
# the holder will be null anyway, so it's safe to just always
# return it here.
returnCode = "return ${holderName}.forget();"
returnCode = ("(void)${declName}; // avoid warning. May end up not being read\n"
"return ${holderName}.forget();")
elif iface.isCallback():
# The decl is an OwningNonNull or nsRefPtr, depending
# on whether we're nullable.

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

@ -320,7 +320,8 @@ class IDLUnresolvedIdentifier(IDLObject):
[location])
if name[0] == '_' and not allowDoubleUnderscore:
name = name[1:]
if name in ["constructor", "iterator", "toString", "toJSON"] and not allowForbidden:
# TODO: Bug 872377, Restore "toJSON" to below list.
if name in ["constructor", "iterator", "toString"] and not allowForbidden:
raise WebIDLError("Cannot use reserved identifier '%s'" % (name),
[location])

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

@ -18,11 +18,11 @@ if CONFIG['MOZ_B2G_BT']:
MODULE = 'dom'
XPIDL_MODULE = 'dom_bluetooth'
XPIDL_SOURCES += [
'nsIDOMNavigatorBluetooth.idl',
'nsIDOMBluetoothManager.idl',
'nsIDOMBluetoothAdapter.idl',
'nsIDOMBluetoothDevice.idl',
'nsIDOMBluetoothDeviceEvent.idl'
'nsIDOMBluetoothDeviceEvent.idl',
'nsIDOMBluetoothManager.idl',
'nsIDOMNavigatorBluetooth.idl',
]
EXPORTS.mozilla.dom.bluetooth.ipc += [

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

@ -47,8 +47,8 @@ XPIDL_SOURCES += [
'nsIDOMSimpleGestureEvent.idl',
'nsIDOMSmartCardEvent.idl',
'nsIDOMStyleRuleChangeEvent.idl',
'nsIDOMStyleSheetChangeEvent.idl',
'nsIDOMStyleSheetApplicableStateChangeEvent.idl',
'nsIDOMStyleSheetChangeEvent.idl',
'nsIDOMTouchEvent.idl',
'nsIDOMTransitionEvent.idl',
'nsIDOMUIEvent.idl',

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

@ -13,11 +13,17 @@ const PC_CONTRACT = "@mozilla.org/dom/peerconnection;1";
const PC_ICE_CONTRACT = "@mozilla.org/dom/rtcicecandidate;1";
const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
const PC_ICEEVENT_CONTRACT = "@mozilla.org/dom/rtcpeerconnectioniceevent;1";
const MSEVENT_CONTRACT = "@mozilla.org/dom/mediastreamevent;1";
const DCEVENT_CONTRACT = "@mozilla.org/dom/datachannelevent;1";
const PC_CID = Components.ID("{7cb2b368-b1ce-4560-acac-8e0dbda7d3d0}");
const PC_ICE_CID = Components.ID("{8c5dbd70-2c8e-4ecb-a5ad-2fc919099f01}");
const PC_SESSION_CID = Components.ID("{5f21ffd9-b73f-4ba0-a685-56b4667aaf1c}");
const PC_CID = Components.ID("{9878b414-afaa-4176-a887-1e02b3b047c2}");
const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
const PC_ICEEVENT_CID = Components.ID("{b9cd25a7-9859-4f9e-8f84-ef5181ff36c0}");
const MSEVENT_CID = Components.ID("{a722a8a9-2290-4e99-a5ed-07b504292d08}");
const DCEVENT_CID = Components.ID("{d5ed7fbf-01a8-4b18-af6c-861cf2aac920}");
// Global list of PeerConnection objects, so they can be cleaned up when
// a page is torn down. (Maps inner window ID to an array of PC objects).
@ -33,17 +39,7 @@ GlobalPCList.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference,
Ci.IPeerConnectionManager]),
classID: PC_MANAGER_CID,
classInfo: XPCOMUtils.generateCI({classID: PC_MANAGER_CID,
contractID: PC_MANAGER_CONTRACT,
classDescription: "PeerConnectionManager",
interfaces: [
Ci.nsIObserver,
Ci.nsISupportsWeakReference,
Ci.IPeerConnectionManager
]}),
_xpcom_factory: {
createInstance: function(outer, iid) {
if (outer) {
@ -56,9 +52,9 @@ GlobalPCList.prototype = {
addPC: function(pc) {
let winID = pc._winID;
if (this._list[winID]) {
this._list[winID].push(Components.utils.getWeakReference(pc));
this._list[winID].push(Cu.getWeakReference(pc));
} else {
this._list[winID] = [Components.utils.getWeakReference(pc)];
this._list[winID] = [Cu.getWeakReference(pc)];
}
this.removeNullRefs(winID);
},
@ -123,82 +119,116 @@ GlobalPCList.prototype = {
};
let _globalPCList = new GlobalPCList();
function IceCandidate(candidate) {
this.candidate = candidate;
this.sdpMid = null;
this.sdpMLineIndex = null;
function RTCIceCandidate() {
this.candidate = this.sdpMid = this.sdpMLineIndex = null;
}
IceCandidate.prototype = {
RTCIceCandidate.prototype = {
classDescription: "mozRTCIceCandidate",
classID: PC_ICE_CID,
contractID: PC_ICE_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
classInfo: XPCOMUtils.generateCI({classID: PC_ICE_CID,
contractID: PC_ICE_CONTRACT,
classDescription: "IceCandidate",
interfaces: [
Ci.nsIDOMRTCIceCandidate
],
flags: Ci.nsIClassInfo.DOM_OBJECT}),
init: function(win) { this._win = win; },
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIDOMRTCIceCandidate, Ci.nsIDOMGlobalObjectConstructor
]),
constructor: function(win, candidateInitDict) {
if (this._win) {
throw new Components.Exception("Constructor already called");
}
this._win = win;
if (candidateInitDict !== undefined) {
this.candidate = candidateInitDict.candidate || null;
this.sdpMid = candidateInitDict.sdpMid || null;
this.sdpMLineIndex = candidateInitDict.sdpMLineIndex === null ?
null : candidateInitDict.sdpMLineIndex + 1;
} else {
this.candidate = this.sdpMid = this.sdpMLineIndex = null;
}
__init: function(dict) {
this.candidate = dict.candidate;
this.sdpMid = dict.sdpMid;
this.sdpMLineIndex = ("sdpMLineIndex" in dict)? dict.sdpMLineIndex+1 : null;
}
};
function SessionDescription(type, sdp) {
this.type = type;
this.sdp = sdp;
function RTCSessionDescription() {
this.type = this.sdp = null;
}
SessionDescription.prototype = {
RTCSessionDescription.prototype = {
classDescription: "mozRTCSessionDescription",
classID: PC_SESSION_CID,
contractID: PC_SESSION_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
classInfo: XPCOMUtils.generateCI({classID: PC_SESSION_CID,
contractID: PC_SESSION_CONTRACT,
classDescription: "SessionDescription",
interfaces: [
Ci.nsIDOMRTCSessionDescription
],
flags: Ci.nsIClassInfo.DOM_OBJECT}),
init: function(win) { this._win = win; },
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIDOMRTCSessionDescription, Ci.nsIDOMGlobalObjectConstructor
]),
constructor: function(win, descriptionInitDict) {
if (this._win) {
throw new Components.Exception("Constructor already called");
}
this._win = win;
if (descriptionInitDict !== undefined) {
this.type = descriptionInitDict.type || null;
this.sdp = descriptionInitDict.sdp || null;
} else {
this.type = this.sdp = null;
}
__init: function(dict) {
this.type = dict.type;
this.sdp = dict.sdp;
},
toString: function() {
return JSON.stringify({
type: this.type, sdp: this.sdp
});
// Bug 863402 serializer support workaround
toJSON: function() {
return { type: this.type, sdp: this.sdp,
__exposedProps__: { type: "rw", sdp: "rw" } };
}
};
function PeerConnection() {
function MediaStreamEvent() {
this.type = this._stream = null;
}
MediaStreamEvent.prototype = {
classDescription: "MediaStreamEvent",
classID: MSEVENT_CID,
contractID: MSEVENT_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
init: function(win) { this._win = win; },
__init: function(type, dict) {
this.type = type;
this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
dict.cancelable || false);
this._stream = dict.stream;
},
get stream() { return this._stream; }
};
function RTCDataChannelEvent() {
this.type = this._channel = null;
}
RTCDataChannelEvent.prototype = {
classDescription: "RTCDataChannelEvent",
classID: DCEVENT_CID,
contractID: DCEVENT_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
init: function(win) { this._win = win; },
__init: function(type, dict) {
this.type = type;
this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
dict.cancelable || false);
this._channel = dict.channel;
},
get channel() { return this._channel; }
};
function RTCPeerConnectionIceEvent() {
this.type = this._candidate = null;
}
RTCPeerConnectionIceEvent.prototype = {
classDescription: "RTCPeerConnectionIceEvent",
classID: PC_ICEEVENT_CID,
contractID: PC_ICEEVENT_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer]),
init: function(win) { this._win = win; },
__init: function(type, dict) {
this.type = type;
this.__DOM_IMPL__.initEvent(type, dict.bubbles || false,
dict.cancelable || false);
this._candidate = dict.candidate;
},
get candidate() { return this._candidate; }
};
function RTCPeerConnection() {
this._queue = [];
this._pc = null;
@ -224,40 +254,24 @@ function PeerConnection() {
*/
this._pending = false;
// Public attributes.
this.onaddstream = null;
this.onopen = null;
this.onremovestream = null;
this.onicecandidate = null;
this.onstatechange = null;
this.ongatheringchange = null;
this.onicechange = null;
// States
this._iceGatheringState = this._iceConnectionState = "new";
// Data channel.
this.ondatachannel = null;
this.onconnection = null;
this.onclosedconnection = null;
// Deprecated callbacks
this._ongatheringchange = null;
this._onicechange = null;
}
PeerConnection.prototype = {
RTCPeerConnection.prototype = {
classDescription: "mozRTCPeerConnection",
classID: PC_CID,
contractID: PC_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
Ci.nsIDOMGlobalPropertyInitializer,
Ci.nsISupportsWeakReference]),
init: function(win) { this._win = win; },
classInfo: Cu.getDOMClassInfo("RTCPeerConnection"),
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIDOMRTCPeerConnection,
Ci.nsIDOMGlobalObjectConstructor,
Ci.nsISupportsWeakReference
]),
// Constructor is an explicit function, because of nsIDOMGlobalObjectConstructor.
constructor: function(win, rtcConfig) {
if (!Services.prefs.getBoolPref("media.peerconnection.enabled")) {
throw new Components.Exception("PeerConnection not enabled (did you set the pref?)");
}
if (this._win) {
throw new Components.Exception("RTCPeerConnection constructor already called");
}
if (!rtcConfig ||
__init: function(rtcConfig) {
if (!rtcConfig.iceServers ||
!Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) {
rtcConfig = {iceServers:
JSON.parse(Services.prefs.getCharPref("media.peerconnection.default_iceservers"))};
@ -268,6 +282,16 @@ PeerConnection.prototype = {
throw new Components.Exception("Can't create RTCPeerConnections when the network is down");
}
this.makeGetterSetterEH("onaddstream");
this.makeGetterSetterEH("onicecandidate");
this.makeGetterSetterEH("onnegotiationneeded");
this.makeGetterSetterEH("onsignalingstatechange");
this.makeGetterSetterEH("onremovestream");
this.makeGetterSetterEH("ondatachannel");
this.makeGetterSetterEH("onconnection");
this.makeGetterSetterEH("onclosedconnection");
this.makeGetterSetterEH("oniceconnectionstatechange");
this._pc = Cc["@mozilla.org/peerconnection;1"].
createInstance(Ci.IPeerConnection);
this._observer = new PeerConnectionObserver(this);
@ -275,11 +299,10 @@ PeerConnection.prototype = {
// Nothing starts until ICE gathering completes.
this._queueOrRun({
func: this._getPC().initialize,
args: [this._observer, win, rtcConfig, Services.tm.currentThread],
args: [this._observer, this._win, rtcConfig, Services.tm.currentThread],
wait: true
});
this._win = win;
this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
@ -289,7 +312,7 @@ PeerConnection.prototype = {
_getPC: function() {
if (!this._pc) {
throw new Components.Exception("PeerConnection is gone (did you turn on Offline mode?)");
throw new Components.Exception("RTCPeerConnection is gone (did you enter Offline mode?)");
}
return this._pc;
},
@ -335,19 +358,14 @@ PeerConnection.prototype = {
* An RTCConfiguration looks like this:
*
* { "iceServers": [ { url:"stun:23.21.150.121" },
* { url:"turn:user@turn.example.org", credential:"mypass"} ] }
* { url:"turn:turn.example.org",
* username:"jib", credential:"mypass"} ] }
*
* We check for basic structure and well-formed stun/turn urls, but not
* validity of servers themselves, before passing along to C++.
* WebIDL normalizes structure for us, so we test well-formed stun/turn urls,
* but not validity of servers themselves, before passing along to C++.
* ErrorMsg is passed in to detail which array-entry failed, if any.
*/
_mustValidateRTCConfiguration: function(rtcConfig, errorMsg) {
function isObject(obj) {
return obj && (typeof obj === "object");
}
function isArraylike(obj) {
return isObject(obj) && ("length" in obj);
}
function nicerNewURI(uriStr, errorMsg) {
let ios = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
try {
@ -363,21 +381,13 @@ PeerConnection.prototype = {
throw new Components.Exception(errorMsg + " - improper scheme: " + url.scheme,
Cr.NS_ERROR_MALFORMED_URI);
}
if (server.credential && isObject(server.credential)) {
throw new Components.Exception(errorMsg + " - invalid credential");
}
if (rtcConfig.iceServers) {
let len = rtcConfig.iceServers.length;
for (let i=0; i < len; i++) {
mustValidateServer (rtcConfig.iceServers[i], errorMsg);
}
}
if (!isObject(rtcConfig)) {
throw new Components.Exception(errorMsg);
}
if (!isArraylike(rtcConfig.iceServers)) {
throw new Components.Exception(errorMsg +
" - iceServers [] property not present");
}
let len = rtcConfig.iceServers.length;
for (let i=0; i < len; i++) {
mustValidateServer (rtcConfig.iceServers[i], errorMsg);
}
},
/**
@ -466,11 +476,87 @@ PeerConnection.prototype = {
}
},
dispatchEvent: function(event) {
this.__DOM_IMPL__.dispatchEvent(event);
},
// Log error message to web console and window.onerror, if present.
reportError: function(msg, file, line) {
this.reportMsg(msg, file, line, Ci.nsIScriptError.exceptionFlag);
},
reportWarning: function(msg, file, line) {
this.reportMsg(msg, file, line, Ci.nsIScriptError.warningFlag);
},
reportMsg: function(msg, file, line, flag) {
let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(msg, file, null, line, 0, flag,
"content javascript", this._winID);
let console = Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
console.logMessage(scriptError);
if (flag != Ci.nsIScriptError.warningFlag) {
// Safely call onerror directly if present (necessary for testing)
try {
if (typeof this._win.onerror === "function") {
this._win.onerror(msg, file, line);
}
} catch(e) {
// If onerror itself throws, service it.
try {
let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(e.message, e.fileName, null, e.lineNumber,
0, Ci.nsIScriptError.exceptionFlag,
"content javascript",
this._winID);
console.logMessage(scriptError);
} catch(e) {}
}
}
},
getEH: function(type) {
return this.__DOM_IMPL__.getEventHandler(type);
},
setEH: function(type, handler) {
this.__DOM_IMPL__.setEventHandler(type, handler);
},
makeGetterSetterEH: function(name) {
Object.defineProperty(this, name,
{
get:function() { return this.getEH(name); },
set:function(h) { return this.setEH(name, h); }
});
},
get onicechange() { return this._onicechange; },
get ongatheringchange() { return this._ongatheringchange; },
set onicechange(cb) {
this.deprecated("onicechange");
this._onicechange = cb;
},
set ongatheringchange(cb) {
this.deprecated("ongatheringchange");
this._ongatheringchange = cb;
},
deprecated: function(name) {
this.reportWarning(name + " is deprecated!", null, 0);
},
createOffer: function(onSuccess, onError, constraints) {
if (!constraints) {
constraints = {};
}
if (!onError) {
this.deprecated("calling createOffer without failureCallback");
}
this._mustValidateConstraints(constraints, "createOffer passed invalid constraints");
this._onCreateOfferSuccess = onSuccess;
this._onCreateOfferFailure = onError;
@ -483,6 +569,9 @@ PeerConnection.prototype = {
},
_createAnswer: function(onSuccess, onError, constraints, provisional) {
if (!onError) {
this.deprecated("calling createAnswer without failureCallback");
}
this._onCreateAnswerSuccess = onSuccess;
this._onCreateAnswerFailure = onError;
@ -538,10 +627,12 @@ PeerConnection.prototype = {
case "answer":
type = Ci.IPeerConnection.kActionAnswer;
break;
case "pranswer":
throw new Components.Exception("pranswer not yet implemented",
Cr.NS_ERROR_NOT_IMPLEMENTED);
default:
throw new Components.Exception("Invalid type " + desc.type +
" provided to setLocalDescription");
break;
}
this._queueOrRun({
@ -567,10 +658,12 @@ PeerConnection.prototype = {
case "answer":
type = Ci.IPeerConnection.kActionAnswer;
break;
case "pranswer":
throw new Components.Exception("pranswer not yet implemented",
Cr.NS_ERROR_NOT_IMPLEMENTED);
default:
throw new Components.Exception("Invalid type " + desc.type +
" provided to setRemoteDescription");
break;
}
this._queueOrRun({
@ -581,21 +674,17 @@ PeerConnection.prototype = {
});
},
updateIce: function(config, constraints, restart) {
return Cr.NS_ERROR_NOT_IMPLEMENTED;
updateIce: function(config, constraints) {
throw new Components.Exception("updateIce not yet implemented",
Cr.NS_ERROR_NOT_IMPLEMENTED);
},
addIceCandidate: function(cand, onSuccess, onError) {
if (!cand) {
throw new Components.Exception("NULL candidate passed to addIceCandidate!");
}
if (!cand.candidate || !cand.sdpMLineIndex) {
if (!cand.candidate && !cand.sdpMLineIndex) {
throw new Components.Exception("Invalid candidate passed to addIceCandidate!");
}
this._onAddIceCandidateSuccess = onSuccess;
this._onAddIceCandidateError = onError;
this._onAddIceCandidateSuccess = onSuccess || null;
this._onAddIceCandidateError = onError || null;
this._queueOrRun({
func: this._getPC().addIceCandidate,
@ -605,6 +694,9 @@ PeerConnection.prototype = {
},
addStream: function(stream, constraints) {
if (stream.currentTime === undefined) {
throw new Components.Exception("Invalid stream passed to addStream!");
}
// TODO: Implement constraints.
this._queueOrRun({
func: this._getPC().addStream,
@ -614,8 +706,14 @@ PeerConnection.prototype = {
},
removeStream: function(stream) {
//Bug844295: Not implemeting this functionality.
return Cr.NS_ERROR_NOT_IMPLEMENTED;
//Bug 844295: Not implementing this functionality.
throw new Components.Exception("removeStream not yet implemented",
Cr.NS_ERROR_NOT_IMPLEMENTED);
},
getStreamById: function(id) {
throw new Components.Exception("getStreamById not yet implemented",
Cr.NS_ERROR_NOT_IMPLEMENTED);
},
close: function() {
@ -625,28 +723,37 @@ PeerConnection.prototype = {
wait: false
});
this._closed = true;
this.changeIceConnectionState("closed");
},
get localStreams() {
getLocalStreams: function() {
this._checkClosed();
return this._getPC().localStreams;
},
get remoteStreams() {
getRemoteStreams: function() {
this._checkClosed();
return this._getPC().remoteStreams;
},
// Backwards-compatible attributes
get localStreams() {
this.deprecated("localStreams");
return this.getLocalStreams();
},
get remoteStreams() {
this.deprecated("remoteStreams");
return this.getRemoteStreams();
},
get localDescription() {
this._checkClosed();
let sdp = this._getPC().localDescription;
if (sdp.length == 0) {
return null;
}
return {
type: this._localType, sdp: sdp,
__exposedProps__: { type: "rw", sdp: "rw" }
};
return new this._win.mozRTCSessionDescription({ type: this._localType,
sdp: sdp });
},
get remoteDescription() {
@ -655,13 +762,25 @@ PeerConnection.prototype = {
if (sdp.length == 0) {
return null;
}
return {
type: this._remoteType, sdp: sdp,
__exposedProps__: { type: "rw", sdp: "rw" }
};
return new this._win.mozRTCSessionDescription({ type: this._remoteType,
sdp: sdp });
},
get signalingState() { return "stable"; }, // not yet implemented
get iceGatheringState() { return this._iceGatheringState; },
get iceConnectionState() { return this._iceConnectionState; },
changeIceGatheringState: function(state) {
this._iceGatheringState = state;
},
changeIceConnectionState: function(state) {
this._iceConnectionState = state;
this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
},
get readyState() {
this.deprecated("readyState");
// checking for our local pc closed indication
// before invoking the pc methods.
if(this._closed) {
@ -692,7 +811,7 @@ PeerConnection.prototype = {
createDataChannel: function(label, dict) {
this._checkClosed();
if (dict == undefined) {
dict = {};
dict = {};
}
if (dict.maxRetransmitTime != undefined &&
dict.maxRetransmitNum != undefined) {
@ -765,85 +884,27 @@ PeerConnectionObserver.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver,
Ci.nsISupportsWeakReference]),
dispatchEvent: function(event) {
this._dompc.dispatchEvent(event);
},
callCB: function(callback, arg) {
if (callback) {
try {
callback.onCallback(arg);
callback(arg);
} catch(e) {
// A content script (user-provided) callback threw an error. We don't
// want this to take down peerconnection, but we still want the user
// to see it, so we catch it, report it, and move on.
//
// We do stack parsing in two different places for different reasons:
var msg;
if (e.result == Cr.NS_ERROR_XPC_JS_THREW_JS_OBJECT) {
// TODO(jib@mozilla.com): Revisit once bug 862153 is fixed.
//
// The actual content script frame is unavailable due to bug 862153,
// so users see file and line # into this file, which is not helpful.
//
// 1) Fix up the error message itself to differentiate between the
// 22 places we call callCB() in this file, using plain JS stack.
//
// Tweak the existing NS_ERROR_XPC_JS_THREW_JS_OBJECT message:
// -'Error: x' when calling method: [RTCPeerConCallback::onCallback]
// +'Error: x' when calling method: [RTCPeerConCallback::onCreateOfferError]
let caller = Error().stack.split("\n")[1].split("@")[0];
// caller ~= "PeerConnectionObserver.prototype.onCreateOfferError"
msg = e.message.replace("::onCallback", "::" + caller.split(".")[2]);
} else {
msg = e.message;
}
// Log error message to web console and window.onerror, if present.
//
// 2) nsIScriptError doesn't understand the nsIStackFrame format, so
// do the translation by extracting file and line from XPCOM stack:
//
// e.location ~= "JS frame :: file://.js :: RTCPCCb::onCallback :: line 1"
let stack = e.location.toString().split(" :: ");
let file = stack[1];
let line = parseInt(stack[3].split(" ")[1]);
let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(msg, file, null, line, 0,
Ci.nsIScriptError.exceptionFlag,
"content javascript",
this._dompc._winID);
let console = Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
console.logMessage(scriptError);
// Safely call onerror directly if present (necessary for testing)
try {
if (typeof this._dompc._win.onerror === "function") {
this._dompc._win.onerror(msg, file, line);
}
} catch(e) {
// If onerror itself throws, service it.
try {
let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
scriptError.initWithWindowID(e.message, e.fileName, null,
e.lineNumber, 0,
Ci.nsIScriptError.exceptionFlag,
"content javascript",
this._dompc._winID);
console.logMessage(scriptError);
} catch(e) {}
}
this._dompc.reportError(e.message, e.fileName, e.lineNumber);
}
}
},
onCreateOfferSuccess: function(offer) {
onCreateOfferSuccess: function(sdp) {
this.callCB(this._dompc._onCreateOfferSuccess,
{ type: "offer", sdp: offer,
__exposedProps__: { type: "rw", sdp: "rw" } });
new this._dompc._win.mozRTCSessionDescription({ type: "offer",
sdp: sdp }));
this._dompc._executeNext();
},
@ -852,10 +913,10 @@ PeerConnectionObserver.prototype = {
this._dompc._executeNext();
},
onCreateAnswerSuccess: function(answer) {
onCreateAnswerSuccess: function(sdp) {
this.callCB (this._dompc._onCreateAnswerSuccess,
{ type: "answer", sdp: answer,
__exposedProps__: { type: "rw", sdp: "rw" } });
new this._dompc._win.mozRTCSessionDescription({ type: "answer",
sdp: sdp }));
this._dompc._executeNext();
},
@ -919,23 +980,29 @@ PeerConnectionObserver.prototype = {
}
switch (this._dompc._pc.iceState) {
case Ci.IPeerConnection.kIceGathering:
this.callCB(this._dompc.ongatheringchange, "gathering");
break;
case Ci.IPeerConnection.kIceWaiting:
this.callCB(this._dompc.onicechange, "starting");
this._dompc.changeIceConnectionState("completed");
this.callCB(this._dompc.ongatheringchange, "complete");
this.callCB(this._onicechange, "starting");
// Now that the PC is ready to go, execute any pending operations.
this._dompc._executeNext();
break;
case Ci.IPeerConnection.kIceChecking:
this.callCB(this._dompc.onicechange, "checking");
this._dompc.changeIceConnectionState("checking");
this.callCB(this._onicechange, "checking");
break;
case Ci.IPeerConnection.kIceGathering:
this._dompc.changeIceGatheringState("gathering");
this.callCB(this._ongatheringchange, "gathering");
break;
case Ci.IPeerConnection.kIceConnected:
// ICE gathering complete.
this.callCB(this._dompc.onicechange, "connected");
this.callCB(this._dompc.ongatheringchange, "complete");
this._dompc.changeIceConnectionState("connected");
this.callCB(this._onicechange, "connected");
break;
case Ci.IPeerConnection.kIceFailed:
this.callCB(this._dompc.onicechange, "failed");
this._dompc.changeIceConnectionState("failed");
this.callCB(this._onicechange, "failed");
break;
default:
// Unknown state!
@ -943,37 +1010,36 @@ PeerConnectionObserver.prototype = {
}
},
onAddStream: function(stream, type) {
this.callCB(this._dompc.onaddstream,
{ stream: stream, type: type,
__exposedProps__: { stream: "r", type: "r" } });
onAddStream: function(stream) {
this.dispatchEvent(new this._dompc._win.MediaStreamEvent("addstream",
{ stream: stream }));
},
onRemoveStream: function(stream, type) {
this.callCB(this._dompc.onremovestream,
{ stream: stream, type: type,
__exposedProps__: { stream: "r", type: "r" } });
this.dispatchEvent(new this._dompc._win.MediaStreamEvent("removestream",
{ stream: stream }));
},
foundIceCandidate: function(cand) {
this.callCB(this._dompc.onicecandidate,
{candidate: cand, __exposedProps__: { candidate: "rw" } });
foundIceCandidate: function(c) {
this.dispatchEvent(new this._dompc._win.RTCPeerConnectionIceEvent("icecandidate",
{ candidate: c }));
},
notifyDataChannel: function(channel) {
this.callCB(this._dompc.ondatachannel,
{ channel: channel, __exposedProps__: { channel: "r" } });
this.dispatchEvent(new this._dompc._win.RTCDataChannelEvent("datachannel",
{ channel: channel }));
},
notifyConnection: function() {
this.callCB (this._dompc.onconnection);
this.dispatchEvent(new this._dompc._win.Event("connection"));
},
notifyClosedConnection: function() {
this.callCB (this._dompc.onclosedconnection);
this.dispatchEvent(new this._dompc._win.Event("closedconnection"));
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
[GlobalPCList, IceCandidate, SessionDescription, PeerConnection]
[GlobalPCList, RTCIceCandidate, RTCSessionDescription, RTCPeerConnection,
RTCPeerConnectionIceEvent, MediaStreamEvent, RTCDataChannelEvent]
);

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

@ -1,13 +1,15 @@
component {7cb2b368-b1ce-4560-acac-8e0dbda7d3d0} PeerConnection.js
component {8c5dbd70-2c8e-4ecb-a5ad-2fc919099f01} PeerConnection.js
component {5f21ffd9-b73f-4ba0-a685-56b4667aaf1c} PeerConnection.js
component {9878b414-afaa-4176-a887-1e02b3b047c2} PeerConnection.js
component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
component {b9cd25a7-9859-4f9e-8f84-ef5181ff36c0} PeerConnection.js
component {a722a8a9-2290-4e99-a5ed-07b504292d08} PeerConnection.js
component {d5ed7fbf-01a8-4b18-af6c-861cf2aac920} PeerConnection.js
contract @mozilla.org/dom/peerconnection;1 {7cb2b368-b1ce-4560-acac-8e0dbda7d3d0}
contract @mozilla.org/dom/rtcicecandidate;1 {8c5dbd70-2c8e-4ecb-a5ad-2fc919099f01}
contract @mozilla.org/dom/rtcsessiondescription;1 {5f21ffd9-b73f-4ba0-a685-56b4667aaf1c}
contract @mozilla.org/dom/peerconnection;1 {9878b414-afaa-4176-a887-1e02b3b047c2}
contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}
contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}
category JavaScript-global-constructor mozRTCPeerConnection @mozilla.org/dom/peerconnection;1
category JavaScript-global-constructor mozRTCIceCandidate @mozilla.org/dom/rtcicecandidate;1
category JavaScript-global-constructor mozRTCSessionDescription @mozilla.org/dom/rtcsessiondescription;1
contract @mozilla.org/dom/rtcpeerconnectioniceevent;1 {b9cd25a7-9859-4f9e-8f84-ef5181ff36c0}
contract @mozilla.org/dom/mediastreamevent;1 {a722a8a9-2290-4e99-a5ed-07b504292d08}
contract @mozilla.org/dom/datachannelevent;1 {d5ed7fbf-01a8-4b18-af6c-861cf2aac920}

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

@ -54,7 +54,7 @@ interface IPeerConnectionObserver : nsISupports
void onStateChange(in unsigned long state);
/* Changes to MediaStreams */
void onAddStream(in nsIDOMMediaStream stream, in string type);
void onAddStream(in nsIDOMMediaStream stream);
void onRemoveStream();
void onAddTrack();
void onRemoveTrack();

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

@ -12,7 +12,6 @@ TEST_DIRS += ['tests/mochitest']
XPIDL_SOURCES += [
'nsIDOMMediaStream.idl',
'nsIDOMNavigatorUserMedia.idl',
'nsIDOMRTCPeerConnection.idl',
'nsIMediaManager.idl',
]

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

@ -1,100 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsIDOMMediaStream.idl"
interface nsIDOMDataChannel;
[scriptable, function, uuid(eb9c563c-3b09-4565-9317-eca96ae0c538)]
interface RTCPeerConnectionCallback : nsISupports
{
void onCallback(in jsval value);
};
[scriptable, function, uuid(55546efd-287b-4460-8283-0592875b890f)]
interface RTCPeerConnectionCallbackVoid : nsISupports
{
void onCallback();
};
[scriptable, uuid(05d7375e-b024-4951-a570-c6642105ad35)]
interface nsIDOMRTCSessionDescription : nsISupports
{
attribute DOMString sdp;
attribute DOMString type;
};
[scriptable, uuid(df176474-e20a-4f42-a85b-b0414d634cf0)]
interface nsIDOMRTCIceCandidate : nsISupports
{
attribute DOMString candidate;
attribute DOMString sdpMid;
attribute unsigned short sdpMLineIndex;
};
/* See http://dev.w3.org/2011/webrtc/editor/webrtc.html */
[scriptable, uuid(474074ab-11f9-4933-a200-8ea1a5f84e4c)]
interface nsIDOMRTCPeerConnection : nsISupports
{
void createOffer(in RTCPeerConnectionCallback successCallback,
[optional] in RTCPeerConnectionCallback failureCallback,
[optional] in jsval constraints);
void createAnswer(in RTCPeerConnectionCallback successCallback,
[optional] in RTCPeerConnectionCallback failureCallback,
[optional] in jsval constraints,
[optional] in bool createProvisionalAnswer);
void setLocalDescription(in nsIDOMRTCSessionDescription desc,
[optional] in RTCPeerConnectionCallbackVoid successCallback,
[optional] in RTCPeerConnectionCallback failureCallback);
void setRemoteDescription(in nsIDOMRTCSessionDescription desc,
[optional] in RTCPeerConnectionCallbackVoid successCallback,
[optional] in RTCPeerConnectionCallback failureCallback);
void updateIce([optional] in jsval configuration,
[optional] in jsval constraints,
[optional] in bool restart);
void addIceCandidate(in nsIDOMRTCIceCandidate candidate,
[optional] in RTCPeerConnectionCallbackVoid successCallback,
[optional] in RTCPeerConnectionCallback failureCallback);
void addStream(in nsIDOMMediaStream stream,
[optional] in jsval constraints);
void removeStream(in nsIDOMMediaStream stream);
void close();
/* Readonly attributes */
readonly attribute DOMString iceState;
readonly attribute DOMString iceGatheringState;
readonly attribute DOMString readyState;
readonly attribute jsval localDescription;
readonly attribute jsval remoteDescription;
readonly attribute jsval localStreams; // MediaStream[]
readonly attribute jsval remoteStreams; // MediaStream[]
/* Event handlers. TODO: Use real EventTarget */
attribute RTCPeerConnectionCallback onaddstream;
attribute RTCPeerConnectionCallback onopen;
attribute RTCPeerConnectionCallback onremovestream;
attribute RTCPeerConnectionCallback onicecandidate;
attribute RTCPeerConnectionCallback onstatechange;
attribute RTCPeerConnectionCallback ongatheringchange;
attribute RTCPeerConnectionCallback onicechange;
/* Data channels */
nsIDOMDataChannel createDataChannel([optional] in ACString label,
[optional] in jsval options);
void connectDataConnection(in unsigned short localport,
in unsigned short remoteport, [optional] in unsigned short numstreams);
attribute RTCPeerConnectionCallback ondatachannel;
attribute RTCPeerConnectionCallbackVoid onconnection;
attribute RTCPeerConnectionCallbackVoid onclosedconnection;
};

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

@ -1,34 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=837421
-->
<head>
<meta charset="utf-8">
<title>Bug 837421</title>
<script type="application/javascript">
function finish() {
document.documentElement.removeAttribute("class");
}
function start() {
var o0 = mozRTCPeerConnection();
var o1 = new mozRTCIceCandidate({"candidate":"127 15 UDP 1 stun.sipgate.net 134117531 type 2001:db8:85a3:0:0:8a2e:370:3478 rport","sdpMid":"application 3566220586 RTP/AVP 5000","sdpMLineIndex":-32767});
o0.connectDataConnection(3478,-1);
o0.connectDataConnection(-1,3478,2);
var o2 = mozRTCPeerConnection();
try {o2.addIceCandidate(o1);} catch(e) {} // bug 842075 - remove try when fixed
o2.connectDataConnection(-1,3478,0.5);
o2.connectDataConnection(3478,-1,0.5);
var o3 = new mozRTCIceCandidate({"candidate":"31 2097151 IP 33554431 ::ffff:192.0.2.128 3999799469 type numb.viagenie.ca host","sdpMid":"application 1261077875 RTP/AVP 5000","sdpMLineIndex":16777215});
o2.connectDataConnection(1,3478);
o2.connectDataConnection(3478,1);
try {o2.updateIce()} catch(e) {}
try {o2.addIceCandidate(o3);} catch(e) {} // bug 842075 - remove try when fixed
finish();
}
</script>
</head>
<body onload="setTimeout(start, 100)">
</html>

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

@ -10,7 +10,6 @@ load 812785.html
load 834100.html
load 836349.html
load 837324.html
load 837421.html
load 855796.html
load 860143.html
load 861958.html

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

@ -558,15 +558,14 @@ PeerConnectionWrapper.prototype = {
/**
* Sets the local description and automatically handles the failure case.
*
* @param {object} sdp
* SDP for the local description request
* @param {object} desc
* mozRTCSessionDescription for the local description request
* @param {function} onSuccess
* Callback to execute if the local description was set successfully
*/
setLocalDescription : function PCW_setLocalDescription(sdp, onSuccess) {
setLocalDescription : function PCW_setLocalDescription(desc, onSuccess) {
var self = this;
this._pc.setLocalDescription(sdp, function () {
this._pc.setLocalDescription(desc, function () {
info("Successfully set the local description for " + self.label);
onSuccess();
}, unexpectedCallbackAndFinish(new Error));
@ -575,15 +574,14 @@ PeerConnectionWrapper.prototype = {
/**
* Sets the remote description and automatically handles the failure case.
*
* @param {object} sdp
* SDP for the remote description request
* @param {object} desc
* mozRTCSessionDescription for the remote description request
* @param {function} onSuccess
* Callback to execute if the remote description was set successfully
*/
setRemoteDescription : function PCW_setRemoteDescription(sdp, onSuccess) {
setRemoteDescription : function PCW_setRemoteDescription(desc, onSuccess) {
var self = this;
this._pc.setRemoteDescription(sdp, function () {
this._pc.setRemoteDescription(desc, function () {
info("Successfully set remote description for " + self.label);
onSuccess();
}, unexpectedCallbackAndFinish(new Error));

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

@ -42,11 +42,7 @@
makePC(1, false);
makePC({}, false);
makePC([], false);
makePC({ iceServers: {}}, false);
makePC({}, true);
makePC({ iceServers: [] }, true);
@ -61,8 +57,6 @@
{ url:"turns:x.org:42", username:"p", credential:"p" }
]}, true);
makePC({ iceServers: [{ url:"stun:0.0.0.0", credential:{}}] }, false);
pcs = null;
SimpleTest.finish();
});

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

@ -54,10 +54,10 @@
[
"SET_REMOTE_DESCRIPTION",
function (test) {
var osd = new mozRTCSessionDescription(offer);
test.pcLocal.setRemoteDescription(osd, function () {
test.next();
});
test.pcLocal.setRemoteDescription(new mozRTCSessionDescription(offer),
function () {
test.next();
});
}
],
[

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