This commit is contained in:
Phil Ringnalda 2013-05-03 19:38:56 -07:00
Родитель 94778e67e5 deae6a4519
Коммит 1aef9755fb
146 изменённых файлов: 2831 добавлений и 1420 удалений

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

@ -10,16 +10,12 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
XPIDL_SOURCES += [
'nsIAccessible.idl',
'nsIAccessibleApplication.idl',
'nsIAccessibleCaretMoveEvent.idl',
'nsIAccessibleCursorable.idl',
'nsIAccessibleDocument.idl',
'nsIAccessibleEditableText.idl',
'nsIAccessibleCaretMoveEvent.idl',
'nsIAccessibleEvent.idl',
'nsIAccessibleHideEvent.idl',
'nsIAccessibleStateChangeEvent.idl',
'nsIAccessibleTableChangeEvent.idl',
'nsIAccessibleTextChangeEvent.idl',
'nsIAccessibleVirtualCursorChangeEvent.idl',
'nsIAccessibleHyperLink.idl',
'nsIAccessibleHyperText.idl',
'nsIAccessibleImage.idl',
@ -29,11 +25,15 @@ XPIDL_SOURCES += [
'nsIAccessibleRetrieval.idl',
'nsIAccessibleRole.idl',
'nsIAccessibleSelectable.idl',
'nsIAccessibleStateChangeEvent.idl',
'nsIAccessibleStates.idl',
'nsIAccessibleTable.idl',
'nsIAccessibleTableChangeEvent.idl',
'nsIAccessibleText.idl',
'nsIAccessibleTextChangeEvent.idl',
'nsIAccessibleTypes.idl',
'nsIAccessibleValue.idl',
'nsIAccessibleVirtualCursorChangeEvent.idl',
'nsIXBLAccessible.idl',
]

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

@ -1078,28 +1078,15 @@ HyperTextAccessible::GetTextAtOffset(int32_t aOffset,
return GetCharAt(aOffset, eGetAt, aText, aStartOffset, aEndOffset) ?
NS_OK : NS_ERROR_INVALID_ARG;
case BOUNDARY_WORD_START: {
uint32_t textLen = CharacterCount();
if (offset == textLen) {
*aStartOffset = *aEndOffset = textLen;
return NS_OK;
}
case BOUNDARY_WORD_START:
*aEndOffset = FindWordBoundary(offset, eDirNext, eStartWord);
*aStartOffset = FindWordBoundary(*aEndOffset, eDirPrevious, eStartWord);
return GetText(*aStartOffset, *aEndOffset, aText);
}
case BOUNDARY_WORD_END: {
if (offset == 0) {
*aStartOffset = *aEndOffset = 0;
return NS_OK;
}
case BOUNDARY_WORD_END:
*aStartOffset = FindWordBoundary(offset, eDirPrevious, eEndWord);
*aEndOffset = FindWordBoundary(*aStartOffset, eDirNext, eEndWord);
return GetText(*aStartOffset, *aEndOffset, aText);
}
case BOUNDARY_LINE_START:
case BOUNDARY_LINE_END:

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

@ -335,12 +335,7 @@
testTextAtOffset(13, BOUNDARY_WORD_START, "words\n", 13, 19, IDs);
// BOUNDARY_WORD_END
testTextAtOffset(0, BOUNDARY_WORD_END, "oneword", 0, 7,
"div", kTodo, kOk, kTodo,
"divbr", kTodo, kOk, kTodo,
"editable", kTodo, kOk, kTodo,
"editablebr", kTodo, kOk, kTodo,
"textarea", kTodo, kOk, kTodo);
testTextAtOffset(0, BOUNDARY_WORD_END, "oneword", 0, 7, IDs);
testTextAtOffset(8, BOUNDARY_WORD_END, "\n\ntwo", 7, 12,
"div", kOk, kOk, kOk,
"divbr", kTodo, kTodo, kTodo,

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

@ -310,14 +310,10 @@
testTextAtOffset(9, BOUNDARY_WORD_START, "friend", 9, 15, IDs);
testTextAtOffset(10, BOUNDARY_WORD_START, "friend", 9, 15, IDs);
testTextAtOffset(14, BOUNDARY_WORD_START, "friend", 9, 15, IDs);
testTextAtOffset(15, BOUNDARY_WORD_START, "", 15, 15,
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kTodo, kTodo, kOk);
testTextAtOffset(15, BOUNDARY_WORD_START, "friend", 9, 15, IDs);
// BOUNDARY_WORD_END
testTextAtOffset(0, BOUNDARY_WORD_END, "", 0, 0, IDs);
testTextAtOffset(0, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
testTextAtOffset(1, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
testTextAtOffset(5, BOUNDARY_WORD_END, "hello", 0, 5, IDs);
testTextAtOffset(6, BOUNDARY_WORD_END, " my", 5, 8, IDs);

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

@ -333,14 +333,14 @@
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kTodo, kOk, kTodo);
testTextAtOffset(22, BOUNDARY_WORD_START, "", 22, 22,
testTextAtOffset(22, BOUNDARY_WORD_START, "ran", 19, 22,
"input", kOk, kOk, kOk,
"div", kOk, kOk, kOk,
"editable", kOk, kOk, kOk,
"textarea", kTodo, kTodo, kTodo);
"textarea", kTodo, kOk, kTodo);
// BOUNDARY_WORD_END
testTextAtOffset(0, BOUNDARY_WORD_END, "", 0, 0, IDs);
testTextAtOffset(0, BOUNDARY_WORD_END, "Brave", 0, 5, IDs);
testTextAtOffset(4, BOUNDARY_WORD_END, "Brave", 0, 5, IDs);
testTextAtOffset(5, BOUNDARY_WORD_END, "Brave", 0, 5, IDs);
testTextAtOffset(6, BOUNDARY_WORD_END, " Sir", 5, 9, IDs);

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

@ -27,6 +27,7 @@ MOCHITEST_A11Y_FILES =\
test_listbox.xul \
test_menu.xul \
test_menubutton.xul \
test_optgroup.html \
test_recreation.html \
test_select.html \
test_textleaf.html \

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

@ -0,0 +1,133 @@
<!DOCTYPE html>
<html>
<head>
<title>Add and remove optgroup test</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="../events.js"></script>
<script type="application/javascript">
function addOptGroup(aID)
{
this.selectNode = getNode(aID);
this.select = getAccessible(this.selectNode);
this.invoke = function addOptGroup_invoke()
{
var optGroup = document.createElement("optgroup");
for (i = 0; i < 2; i++) {
var opt = document.createElement("option");
opt.value = i;
opt.text = "Option: Value " + i;
optGroup.appendChild(opt);
}
this.selectNode.add(optGroup, null);
var option = document.createElement("option");
this.selectNode.add(option, null);
}
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.select)
];
this.finalCheck = function addOptGroup_finalCheck()
{
var tree =
{ COMBOBOX: [
{ COMBOBOX_LIST: [
{ GROUPING: [
{ COMBOBOX_OPTION: [
{ TEXT_LEAF: [] }
] },
{ COMBOBOX_OPTION: [
{ TEXT_LEAF: [] }
] },
]},
{ COMBOBOX_OPTION: [] }
] }
] };
testAccessibleTree(this.select, tree);
}
this.getID = function addOptGroup_getID()
{
return "test optgroup's insertion into a select";
}
}
function removeOptGroup(aID)
{
this.selectNode = getNode(aID);
this.select = getAccessible(this.selectNode);
this.invoke = function removeOptGroup_invoke()
{
this.option1Node = this.selectNode.firstChild.firstChild;
this.selectNode.removeChild(this.selectNode.firstChild);
}
this.eventSeq = [
new invokerChecker(EVENT_REORDER, this.select)
];
this.finalCheck = function removeOptGroup_finalCheck()
{
var tree =
{ COMBOBOX: [
{ COMBOBOX_LIST: [
{ COMBOBOX_OPTION: [] }
] }
] };
testAccessibleTree(this.select, tree);
is(isAccessible(this.option1Node), false, "removed option shouldn't be accessible anymore!");
}
this.getID = function removeOptGroup_getID()
{
return "test optgroup's removal from a select";
}
}
// gA11yEventDumpToConsole = true;
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new addOptGroup("select"));
gQueue.push(new removeOptGroup("select"));
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=616452"
title="Bug 616452 - Dynamically inserted select options aren't reflected in accessible tree">
Bug 616452</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<select id="select"></select>
<div id="debug"/>
</body>
</html>

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

@ -203,6 +203,8 @@ let FormAssistant = {
scrollIntoViewTimeout: null,
_focusedElement: null,
_documentEncoder: null,
_editor: null,
_editing: false,
get focusedElement() {
if (this._focusedElement && Cu.isDeadWrapper(this._focusedElement))
@ -228,6 +230,10 @@ let FormAssistant = {
}
this._documentEncoder = null;
if (this._editor) {
this._editor.removeEditorObserver(this);
this._editor = null;
}
if (element) {
element.addEventListener('mousedown', this);
@ -235,6 +241,12 @@ let FormAssistant = {
if (isContentEditable(element)) {
this._documentEncoder = getDocumentEncoder(element);
}
this._editor = getPlaintextEditor(element);
if (this._editor) {
// Add a nsIEditorObserver to monitor the text content of the focused
// element.
this._editor.addEditorObserver(this);
}
}
this.focusedElement = element;
@ -244,6 +256,15 @@ let FormAssistant = {
return this._documentEncoder;
},
// Implements nsIEditorObserver get notification when the text content of
// current input field has changed.
EditAction: function fa_editAction() {
if (this._editing) {
return;
}
this.sendKeyboardState(this.focusedElement);
},
handleEvent: function fa_handleEvent(evt) {
let target = evt.target;
@ -331,10 +352,14 @@ let FormAssistant = {
break;
case "keydown":
// Don't monitor the text change resulting from key event.
this._editing = true;
// We use 'setTimeout' to wait until the input element accomplishes the
// change in selection range
// change in selection range or text content.
content.setTimeout(function() {
this.updateSelection();
this._editing = false;
}.bind(this), 0);
break;
}
@ -346,6 +371,7 @@ let FormAssistant = {
return;
}
this._editing = true;
let json = msg.json;
switch (msg.name) {
case "Forms:Input:Value": {
@ -396,6 +422,8 @@ let FormAssistant = {
break;
}
}
this._editing = false;
},
showKeyboard: function fa_showKeyboard(target) {
@ -525,7 +553,7 @@ function getJSON(element) {
let attributeType = element.getAttribute("type") || "";
if (attributeType) {
var typeLowerCase = attributeType.toLowerCase();
var typeLowerCase = attributeType.toLowerCase();
switch (typeLowerCase) {
case "datetime":
case "datetime-local":
@ -724,3 +752,27 @@ function setSelectionRange(element, start, end) {
}
}
// Get nsIPlaintextEditor object from an input field
function getPlaintextEditor(element) {
let editor = null;
// Get nsIEditor
if (element instanceof HTMLInputElement ||
element instanceof HTMLTextAreaElement) {
// Get from the <input> and <textarea> elements
editor = element.QueryInterface(Ci.nsIDOMNSEditableElement).editor;
} else if (isContentEditable(element)) {
// Get from content editable element
let win = element.ownerDocument.defaultView;
let editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIEditingSession);
if (editingSession) {
editor = editingSession.getEditorForWindow(win);
}
}
if (editor) {
editor.QueryInterface(Ci.nsIPlaintextEditor);
}
return editor;
}

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

@ -37,9 +37,6 @@
label="&bookmarkThisLinkCmd.label;"
accesskey="&bookmarkThisLinkCmd.accesskey;"
oncommand="gContextMenu.bookmarkLink();"/>
<menuitem id="context-marklink"
accesskey="&social.marklink.accesskey;"
oncommand="gContextMenu.markLink();"/>
<menuitem id="context-savelink"
label="&saveLinkCmd.label;"
accesskey="&saveLinkCmd.accesskey;"
@ -225,9 +222,6 @@
label="&bookmarkPageCmd2.label;"
accesskey="&bookmarkPageCmd2.accesskey;"
oncommand="gContextMenu.bookmarkThisPage();"/>
<menuitem id="context-markpage"
accesskey="&social.markpage.accesskey;"
command="Social:TogglePageMark"/>
<menuitem id="context-savepage"
label="&savePageCmd.label;"
accesskey="&savePageCmd.accesskey2;"

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

@ -109,7 +109,8 @@
<command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
<command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
<command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/>
<command id="Social:TogglePageMark" oncommand="SocialMark.togglePageMark();" disabled="true"/>
<command id="Social:SharePage" oncommand="SocialShareButton.sharePage();" disabled="true"/>
<command id="Social:UnsharePage" oncommand="SocialShareButton.unsharePage();"/>
<command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
<command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();" hidden="true"/>
<command id="Social:FocusChat" oncommand="SocialChatBar.focus();" hidden="true" disabled="true"/>
@ -349,8 +350,8 @@
# overridden for other purposes there.
<key id="viewBookmarksSidebarWinKb" key="&bookmarksWinCmd.commandkey;" command="viewBookmarksSidebar" modifiers="accel"/>
#endif
<key id="markPage" key="&markPageCmd.commandkey;" command="Social:TogglePageMark" modifiers="accel,shift"/>
<key id="sharePage" key="&sharePageCmd.commandkey;" command="Social:SharePage" modifiers="accel,shift"/>
<key id="focusChatBar" key="&social.chatBar.commandkey;" command="Social:FocusChat" modifiers="accel,shift"/>
<key id="key_stop" keycode="VK_ESCAPE" command="Browser:Stop"/>

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

@ -6,7 +6,7 @@
let SocialUI,
SocialChatBar,
SocialFlyout,
SocialMark,
SocialShareButton,
SocialMenu,
SocialToolbar,
SocialSidebar;
@ -25,7 +25,7 @@ SocialUI = {
init: function SocialUI_init() {
Services.obs.addObserver(this, "social:ambient-notification-changed", false);
Services.obs.addObserver(this, "social:profile-changed", false);
Services.obs.addObserver(this, "social:page-mark-config", false);
Services.obs.addObserver(this, "social:recommend-info-changed", false);
Services.obs.addObserver(this, "social:frameworker-error", false);
Services.obs.addObserver(this, "social:provider-set", false);
Services.obs.addObserver(this, "social:providers-changed", false);
@ -42,7 +42,7 @@ SocialUI = {
});
SocialChatBar.init();
SocialMark.init();
SocialShareButton.init();
SocialMenu.init();
SocialToolbar.init();
SocialSidebar.init();
@ -61,7 +61,7 @@ SocialUI = {
uninit: function SocialUI_uninit() {
Services.obs.removeObserver(this, "social:ambient-notification-changed");
Services.obs.removeObserver(this, "social:profile-changed");
Services.obs.removeObserver(this, "social:page-mark-config");
Services.obs.removeObserver(this, "social:recommend-info-changed");
Services.obs.removeObserver(this, "social:frameworker-error");
Services.obs.removeObserver(this, "social:provider-set");
Services.obs.removeObserver(this, "social:providers-changed");
@ -88,7 +88,7 @@ SocialUI = {
SocialFlyout.unload();
SocialChatBar.update();
SocialSidebar.update();
SocialMark.update();
SocialShareButton.update();
SocialToolbar.update();
SocialMenu.populate();
break;
@ -109,13 +109,13 @@ SocialUI = {
case "social:profile-changed":
if (this._matchesCurrentProvider(data)) {
SocialToolbar.updateProfile();
SocialMark.update();
SocialShareButton.update();
SocialChatBar.update();
}
break;
case "social:page-mark-config":
case "social:recommend-info-changed":
if (this._matchesCurrentProvider(data)) {
SocialMark.updateMarkState();
SocialShareButton.updateShareState();
}
break;
case "social:frameworker-error":
@ -566,81 +566,146 @@ SocialFlyout = {
}
}
SocialMark = {
SocialShareButton = {
// Called once, after window load, when the Social.provider object is initialized
init: function SSB_init() {
},
get button() {
return document.getElementById("social-mark-button");
// Called when the Social.provider changes
update: function() {
this._updateButtonHiddenState();
let profileRow = document.getElementById("unsharePopupHeader");
let profile = SocialUI.enabled ? Social.provider.profile : null;
if (profile && profile.displayName) {
profileRow.hidden = false;
let portrait = document.getElementById("socialUserPortrait");
if (profile.portrait) {
portrait.setAttribute("src", profile.portrait);
} else {
portrait.removeAttribute("src");
}
let displayName = document.getElementById("socialUserDisplayName");
displayName.setAttribute("label", profile.displayName);
} else {
profileRow.hidden = true;
}
},
canMarkPage: function SSB_canMarkPage(aURI) {
get shareButton() {
return document.getElementById("share-button");
},
get unsharePopup() {
return document.getElementById("unsharePopup");
},
dismissUnsharePopup: function SSB_dismissUnsharePopup() {
this.unsharePopup.hidePopup();
},
canSharePage: function SSB_canSharePage(aURI) {
// We only allow sharing of http or https
return aURI && (aURI.schemeIs('http') || aURI.schemeIs('https'));
},
// Called when the Social.provider changes
update: function SSB_updateButtonState() {
let markButton = this.button;
// always show button if provider supports marks
markButton.hidden = !SocialUI.enabled || Social.provider.pageMarkInfo == null;
markButton.disabled = markButton.hidden || !this.canMarkPage(gBrowser.currentURI);
_updateButtonHiddenState: function SSB_updateButtonHiddenState() {
let shareButton = this.shareButton;
if (shareButton)
shareButton.hidden = !SocialUI.enabled || Social.provider.recommendInfo == null ||
!Social.haveLoggedInUser() ||
!this.canSharePage(gBrowser.currentURI);
// also update the relevent command's disabled state so the keyboard
// shortcut only works when available.
let cmd = document.getElementById("Social:TogglePageMark");
cmd.setAttribute("disabled", markButton.disabled ? "true" : "false");
let cmd = document.getElementById("Social:SharePage");
cmd.setAttribute("disabled", shareButton.hidden ? "true" : "false");
},
togglePageMark: function(aCallback) {
if (this.button.disabled)
onClick: function SSB_onClick(aEvent) {
if (aEvent.button != 0)
return;
this.toggleURIMark(gBrowser.currentURI, aCallback)
},
toggleURIMark: function(aURI, aCallback) {
let update = function(marked) {
this._updateMarkState(marked);
if (aCallback)
aCallback(marked);
}.bind(this);
Social.isURIMarked(aURI, function(marked) {
if (marked) {
Social.unmarkURI(aURI, update);
} else {
Social.markURI(aURI, update);
}
});
// Don't bubble to the textbox, to avoid unwanted selection of the address.
aEvent.stopPropagation();
this.sharePage();
},
updateMarkState: function SSB_updateMarkState() {
this.update();
Social.isURIMarked(gBrowser.currentURI, this._updateMarkState.bind(this));
panelShown: function SSB_panelShown(aEvent) {
function updateElement(id, attrs) {
let el = document.getElementById(id);
Object.keys(attrs).forEach(function(attr) {
el.setAttribute(attr, attrs[attr]);
});
}
let continueSharingButton = document.getElementById("unsharePopupContinueSharingButton");
continueSharingButton.focus();
let recommendInfo = Social.provider.recommendInfo;
updateElement("unsharePopupContinueSharingButton",
{label: recommendInfo.messages.unshareCancelLabel,
accesskey: recommendInfo.messages.unshareCancelAccessKey});
updateElement("unsharePopupStopSharingButton",
{label: recommendInfo.messages.unshareConfirmLabel,
accesskey: recommendInfo.messages.unshareConfirmAccessKey});
updateElement("socialUserPortrait",
{"aria-label": recommendInfo.messages.portraitLabel});
updateElement("socialUserRecommendedText",
{value: recommendInfo.messages.unshareLabel});
},
_updateMarkState: function(currentPageMarked) {
// callback for isURIMarked
let markButton = this.button;
let pageMarkInfo = SocialUI.enabled ? Social.provider.pageMarkInfo : null;
sharePage: function SSB_sharePage() {
this.unsharePopup.hidden = false;
// Update the mark button, if present
if (!markButton || markButton.hidden || !pageMarkInfo)
let uri = gBrowser.currentURI;
if (!Social.isPageShared(uri)) {
Social.sharePage(uri);
this.updateShareState();
} else {
this.unsharePopup.openPopup(this.shareButton, "bottomcenter topright");
}
},
unsharePage: function SSB_unsharePage() {
Social.unsharePage(gBrowser.currentURI);
this.updateShareState();
this.dismissUnsharePopup();
},
updateShareState: function SSB_updateShareState() {
this._updateButtonHiddenState();
let shareButton = this.shareButton;
let currentPageShared = shareButton && !shareButton.hidden && Social.isPageShared(gBrowser.currentURI);
let recommendInfo = SocialUI.enabled ? Social.provider.recommendInfo : null;
// Provide a11y-friendly notification of share.
let status = document.getElementById("share-button-status");
if (status) {
// XXX - this should also be capable of reflecting that the page was
// unshared (ie, it needs to manage three-states: (1) nothing done, (2)
// shared, (3) shared then unshared)
// Note that we *do* have an appropriate string from the provider for
// this (recommendInfo.messages.unsharedLabel) but currently lack a way of
// tracking this state)
let statusString = currentPageShared && recommendInfo ?
recommendInfo.messages.sharedLabel : "";
status.setAttribute("value", statusString);
}
// Update the share button, if present
if (!shareButton || shareButton.hidden)
return;
let imageURL;
if (!markButton.disabled && currentPageMarked) {
markButton.setAttribute("marked", "true");
markButton.setAttribute("label", pageMarkInfo.messages.markedLabel);
markButton.setAttribute("tooltiptext", pageMarkInfo.messages.markedTooltip);
imageURL = pageMarkInfo.images.marked;
if (currentPageShared) {
shareButton.setAttribute("shared", "true");
shareButton.setAttribute("tooltiptext", recommendInfo.messages.unshareTooltip);
imageURL = recommendInfo.images.unshare;
} else {
markButton.removeAttribute("marked");
markButton.setAttribute("label", pageMarkInfo.messages.unmarkedLabel);
markButton.setAttribute("tooltiptext", pageMarkInfo.messages.unmarkedTooltip);
imageURL = pageMarkInfo.images.unmarked;
shareButton.removeAttribute("shared");
shareButton.setAttribute("tooltiptext", recommendInfo.messages.shareTooltip);
imageURL = recommendInfo.images.share;
}
markButton.style.listStyleImage = "url(" + imageURL + ")";
shareButton.src = imageURL;
}
};
@ -729,12 +794,8 @@ SocialToolbar = {
let tbi = document.getElementById("social-toolbar-item");
if (tbi) {
// SocialMark is the last button allways
let next = SocialMark.button.previousSibling;
while (next != tbi.firstChild) {
tbi.removeChild(next);
next = SocialMark.button.previousSibling;
}
while (tbi.lastChild != tbi.firstChild)
tbi.removeChild(tbi.lastChild);
}
}
},
@ -882,7 +943,7 @@ SocialToolbar = {
toolbarButton.setAttribute("aria-label", ariaLabel);
}
let socialToolbarItem = document.getElementById("social-toolbar-item");
socialToolbarItem.insertBefore(toolbarButtons, SocialMark.button);
socialToolbarItem.appendChild(toolbarButtons);
for (let frame of createdFrames) {
if (frame.socialErrorListener) {

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

@ -3405,7 +3405,7 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
URLBarSetURI();
XULBrowserWindow.asyncUpdateUI();
BookmarksMenuButton.updateStarState();
SocialMark.updateMarkState();
SocialShareButton.updateShareState();
}
TabsInTitlebar.allowedBy("customizing-toolbars", true);
@ -3879,7 +3879,7 @@ var XULBrowserWindow = {
// Update starring UI
BookmarksMenuButton.updateStarState();
SocialMark.updateMarkState();
SocialShareButton.updateShareState();
}
// Show or hide browser chrome based on the whitelist

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

@ -205,6 +205,52 @@
</vbox>
</panel>
<panel id="unsharePopup"
type="arrow"
orient="vertical"
ignorekeys="true"
hidden="true"
onpopupshown="SocialShareButton.panelShown(event);"
consumeoutsideclicks="true"
level="top">
<!-- Note that 'label', 'accesskey', 'value' and 'aria-label' attributes
for many of these elements are supplied by the provider and filled
in at runtime
-->
<row id="unsharePopupHeader" align="center">
<vbox align="center">
<image id="socialUserPortrait" onclick="SocialUI.showProfile();"/>
</vbox>
<vbox id="unsharePopupText">
<button id="socialUserDisplayName" pack="start"
oncommand="SocialUI.showProfile();"/>
<spacer flex="1"/>
<label id="socialUserRecommendedText"/>
</vbox>
</row>
<hbox id="unsharePopupBottomButtons" pack="end">
#ifdef XP_UNIX
<button id="unsharePopupStopSharingButton"
class="unsharePopupBottomButton"
command="Social:UnsharePage"/>
<button id="unsharePopupContinueSharingButton"
class="unsharePopupBottomButton"
default="true"
autofocus="autofocus"
oncommand="SocialShareButton.dismissUnsharePopup();"/>
#else
<button id="unsharePopupContinueSharingButton"
class="unsharePopupBottomButton"
default="true"
autofocus="autofocus"
oncommand="SocialShareButton.dismissUnsharePopup();"/>
<button id="unsharePopupStopSharingButton"
class="unsharePopupBottomButton"
command="Social:UnsharePage"/>
#endif
</hbox>
</panel>
<panel id="social-notification-panel"
class="social-panel"
type="arrow"
@ -567,6 +613,13 @@
hidden="true"
tooltiptext="&pageReportIcon.tooltip;"
onclick="gPopupBlockerObserver.onReportButtonClick(event);"/>
<label id="share-button-status" collapsed="true" role="status"/>
<image id="share-button"
class="urlbar-icon"
hidden="true"
onclick="SocialShareButton.onClick(event);"/>
<image id="go-button"
class="urlbar-icon"
tooltiptext="&goEndCap.tooltip;"
@ -749,9 +802,6 @@
oncommand="SocialUI.showLearnMore();"/>
</menupopup>
</toolbarbutton>
<toolbarbutton id="social-mark-button"
class="toolbarbutton-1"
command="Social:TogglePageMark"/>
</toolbaritem>
<hbox id="window-controls" hidden="true" pack="end">

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

@ -292,32 +292,6 @@ nsContextMenu.prototype = {
this.onTextInput && top.gBidiUI);
this.showItem("context-bidi-page-direction-toggle",
!this.onTextInput && top.gBidiUI);
// SocialMarks
let marksEnabled = SocialUI.enabled && Social.provider.pageMarkInfo;
let enablePageMark = marksEnabled && !(this.isContentSelected ||
this.onTextInput || this.onLink || this.onImage ||
this.onVideo || this.onAudio || this.onSocial);
let enableLinkMark = marksEnabled && ((this.onLink && !this.onMailtoLink &&
!this.onSocial) || this.onPlainTextLink);
if (enablePageMark) {
Social.isURIMarked(gBrowser.currentURI, function(marked) {
let label = marked ? "social.unmarkpage.label" : "social.markpage.label";
let provider = Social.provider || Social.defaultProvider;
let menuLabel = gNavigatorBundle.getFormattedString(label, [provider.name]);
this.setItemAttr("context-markpage", "label", menuLabel);
}.bind(this));
}
this.showItem("context-markpage", enablePageMark);
if (enableLinkMark) {
Social.isURIMarked(this.linkURI, function(marked) {
let label = marked ? "social.unmarklink.label" : "social.marklink.label";
let provider = Social.provider || Social.defaultProvider;
let menuLabel = gNavigatorBundle.getFormattedString(label, [provider.name]);
this.setItemAttr("context-marklink", "label", menuLabel);
}.bind(this));
}
this.showItem("context-marklink", enableLinkMark);
},
initSpellingItems: function() {
@ -1493,11 +1467,6 @@ nsContextMenu.prototype = {
}
},
markLink: function CM_markLink() {
// send link to social
SocialMark.toggleURIMark(this.linkURI);
},
savePageAs: function CM_savePageAs() {
saveDocument(this.browser.contentDocument);
},

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

@ -20,7 +20,7 @@ _BROWSER_FILES = \
browser_social_activation.js \
browser_social_perwindowPB.js \
browser_social_toolbar.js \
browser_social_markButton.js \
browser_social_shareButton.js \
browser_social_sidebar.js \
browser_social_flyout.js \
browser_social_mozSocial_API.js \
@ -33,7 +33,7 @@ _BROWSER_FILES = \
social_activate.html \
social_activate_iframe.html \
social_panel.html \
social_mark_image.png \
social_share_image.png \
social_sidebar.html \
social_chat.html \
social_flyout.html \

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

@ -1,210 +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/. */
let prefName = "social.enabled",
gFinishCB;
function test() {
waitForExplicitFinish();
// Need to load a http/https/ftp/ftps page for the social mark button to appear
let tab = gBrowser.selectedTab = gBrowser.addTab("https://example.com", {skipAnimation: true});
tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
executeSoon(tabLoaded);
}, true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref(prefName);
gBrowser.removeTab(tab);
});
}
function tabLoaded() {
ok(Social, "Social module loaded");
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
};
runSocialTestWithProvider(manifest, function (finishcb) {
gFinishCB = finishcb;
testInitial();
});
}
function testInitial(finishcb) {
ok(Social.provider, "Social provider is active");
ok(Social.provider.enabled, "Social provider is enabled");
let port = Social.provider.getWorkerPort();
ok(port, "Social provider has a port to its FrameWorker");
port.close();
let markButton = SocialMark.button;
ok(markButton, "mark button exists");
// ensure the worker initialization and handshakes are all done and we
// have a profile and the worker has sent a page-mark-config msg.
waitForCondition(function() Social.provider.pageMarkInfo != null, function() {
is(markButton.hasAttribute("marked"), false, "SocialMark button should not have 'marked' attribute before mark button is clicked");
// Check the strings from our worker actually ended up on the button.
is(markButton.getAttribute("tooltiptext"), "Mark this page", "check tooltip text is correct");
// Check the relative URL was resolved correctly (note this image has offsets of zero...)
is(markButton.style.listStyleImage, 'url("https://example.com/browser/browser/base/content/test/social/social_mark_image.png")', "check image url is correct");
// Test the mark button command handler
SocialMark.togglePageMark(function() {
is(markButton.hasAttribute("marked"), true, "mark button should have 'marked' attribute after mark button is clicked");
is(markButton.getAttribute("tooltiptext"), "Unmark this page", "check tooltip text is correct");
// Check the URL and offsets were applied correctly
is(markButton.style.listStyleImage, 'url("https://example.com/browser/browser/base/content/test/social/social_mark_image.png")', "check image url is correct");
SocialMark.togglePageMark(function() {
is(markButton.hasAttribute("marked"), false, "mark button should not be marked");
executeSoon(function() {
testStillMarkedIn2Tabs();
});
});
});
markButton.click();
}, "provider didn't provide page-mark-config");
}
function testStillMarkedIn2Tabs() {
let toMark = "http://example.com";
let markUri = Services.io.newURI(toMark, null, null);
let markButton = SocialMark.button;
let initialTab = gBrowser.selectedTab;
is(markButton.hasAttribute("marked"), false, "SocialMark button should not have 'marked' for the initial tab");
let tab1 = gBrowser.selectedTab = gBrowser.addTab(toMark);
let tab1b = gBrowser.getBrowserForTab(tab1);
tab1b.addEventListener("load", function tabLoad(event) {
tab1b.removeEventListener("load", tabLoad, true);
let tab2 = gBrowser.selectedTab = gBrowser.addTab(toMark);
let tab2b = gBrowser.getBrowserForTab(tab2);
tab2b.addEventListener("load", function tabLoad(event) {
tab2b.removeEventListener("load", tabLoad, true);
// should start without either page being marked.
is(markButton.hasAttribute("marked"), false, "SocialMark button should not have 'marked' before we've done anything");
Social.isURIMarked(markUri, function(marked) {
ok(!marked, "page is unmarked in annotations");
markButton.click();
waitForCondition(function() markButton.hasAttribute("marked"), function() {
Social.isURIMarked(markUri, function(marked) {
ok(marked, "page is marked in annotations");
// and switching to the first tab (with the same URL) should still reflect marked.
gBrowser.selectedTab = tab1;
is(markButton.hasAttribute("marked"), true, "SocialMark button should reflect the marked state");
// but switching back the initial one should reflect not marked.
gBrowser.selectedTab = initialTab;
waitForCondition(function() !markButton.hasAttribute("marked"), function() {
gBrowser.selectedTab = tab1;
SocialMark.togglePageMark(function() {
Social.isURIMarked(gBrowser.currentURI, function(marked) {
ok(!marked, "page is unmarked in annotations");
is(markButton.hasAttribute("marked"), false, "mark button should not be marked");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
executeSoon(testStillMarkedAfterReopen);
});
});
}, "button has been unmarked");
});
}, "button has been marked");
});
}, true);
}, true);
}
function testStillMarkedAfterReopen() {
let toMark = "http://example.com";
let markButton = SocialMark.button;
is(markButton.hasAttribute("marked"), false, "Reopen: SocialMark button should not have 'marked' for the initial tab");
let tab = gBrowser.selectedTab = gBrowser.addTab(toMark);
let tabb = gBrowser.getBrowserForTab(tab);
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
SocialMark.togglePageMark(function() {
is(markButton.hasAttribute("marked"), true, "SocialMark button should reflect the marked state");
gBrowser.removeTab(tab);
// should be on the initial unmarked tab now.
waitForCondition(function() !markButton.hasAttribute("marked"), function() {
// now open the same URL - should be back to Marked.
tab = gBrowser.selectedTab = gBrowser.addTab(toMark, {skipAnimation: true});
tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
executeSoon(function() {
is(markButton.hasAttribute("marked"), true, "New tab to previously marked URL should reflect marked state");
SocialMark.togglePageMark(function() {
gBrowser.removeTab(tab);
executeSoon(testOnlyMarkCertainUrlsTabSwitch);
});
});
}, true);
}, "button is now unmarked");
});
}, true);
}
function testOnlyMarkCertainUrlsTabSwitch() {
let toMark = "http://example.com";
let notSharable = "about:blank";
let markButton = SocialMark.button;
let tab = gBrowser.selectedTab = gBrowser.addTab(toMark);
let tabb = gBrowser.getBrowserForTab(tab);
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(!markButton.hidden, "SocialMark button not hidden for http url");
let tab2 = gBrowser.selectedTab = gBrowser.addTab(notSharable);
let tabb2 = gBrowser.getBrowserForTab(tab2);
tabb2.addEventListener("load", function tabLoad(event) {
tabb2.removeEventListener("load", tabLoad, true);
ok(markButton.disabled, "SocialMark button disabled for about:blank");
gBrowser.selectedTab = tab;
ok(!markButton.disabled, "SocialMark button re-shown when switching back to http: url");
gBrowser.selectedTab = tab2;
ok(markButton.disabled, "SocialMark button re-hidden when switching back to about:blank");
gBrowser.removeTab(tab);
gBrowser.removeTab(tab2);
executeSoon(testOnlyMarkCertainUrlsSameTab);
}, true);
}, true);
}
function testOnlyMarkCertainUrlsSameTab() {
let toMark = "http://example.com";
let notSharable = "about:blank";
let markButton = SocialMark.button;
let tab = gBrowser.selectedTab = gBrowser.addTab(toMark);
let tabb = gBrowser.getBrowserForTab(tab);
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(!markButton.disabled, "SocialMark button not disabled for http url");
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(markButton.disabled, "SocialMark button disabled for about:blank");
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(!markButton.disabled, "SocialMark button re-enabled http url");
gBrowser.removeTab(tab);
executeSoon(testDisable);
}, true);
tabb.loadURI(toMark);
}, true);
tabb.loadURI(notSharable);
}, true);
}
function testDisable() {
let markButton = SocialMark.button;
Services.prefs.setBoolPref(prefName, false);
is(markButton.hidden, true, "SocialMark button should be hidden when pref is disabled");
gFinishCB();
}

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

@ -59,6 +59,10 @@ var tests = {
function checkUIStateMatchesProvider(provider) {
let profileData = getExpectedProfileData(provider);
// Bug 789863 - share button uses 'displayName', toolbar uses 'userName'
// Check the "share button"
let displayNameEl = document.getElementById("socialUserDisplayName");
is(displayNameEl.getAttribute("label"), profileData.displayName, "display name matches provider profile");
// The toolbar
let loginStatus = document.getElementsByClassName("social-statusarea-loggedInStatus");
for (let label of loginStatus) {

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

@ -0,0 +1,328 @@
/* 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/. */
let prefName = "social.enabled",
gFinishCB;
function test() {
waitForExplicitFinish();
// Need to load a http/https/ftp/ftps page for the social share button to appear
let tab = gBrowser.selectedTab = gBrowser.addTab("https://example.com", {skipAnimation: true});
tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
executeSoon(tabLoaded);
}, true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref(prefName);
gBrowser.removeTab(tab);
});
}
function tabLoaded() {
ok(Social, "Social module loaded");
let manifest = { // normal provider
name: "provider 1",
origin: "https://example.com",
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
};
runSocialTestWithProvider(manifest, function (finishcb) {
gFinishCB = finishcb;
testInitial();
});
}
function testInitial(finishcb) {
ok(Social.provider, "Social provider is active");
ok(Social.provider.enabled, "Social provider is enabled");
let port = Social.provider.getWorkerPort();
ok(port, "Social provider has a port to its FrameWorker");
port.close();
let {shareButton, unsharePopup} = SocialShareButton;
ok(shareButton, "share button exists");
ok(unsharePopup, "share popup exists");
let okButton = document.getElementById("unsharePopupContinueSharingButton");
let undoButton = document.getElementById("unsharePopupStopSharingButton");
let shareStatusLabel = document.getElementById("share-button-status");
// ensure the worker initialization and handshakes are all done and we
// have a profile and the worker has responsed to the recommend-prompt msg.
waitForCondition(function() Social.provider.profile && Social.provider.recommendInfo != null, function() {
is(shareButton.hasAttribute("shared"), false, "Share button should not have 'shared' attribute before share button is clicked");
// check dom values
let profile = Social.provider.profile;
let portrait = document.getElementById("socialUserPortrait").getAttribute("src");
is(profile.portrait, portrait, "portrait is set");
let displayName = document.getElementById("socialUserDisplayName");
is(displayName.label, profile.displayName, "display name is set");
ok(!document.getElementById("unsharePopupHeader").hidden, "user profile is visible");
// Check the strings from our worker actually ended up on the button.
is(shareButton.getAttribute("tooltiptext"), "Share this page", "check tooltip text is correct");
is(shareStatusLabel.getAttribute("value"), "", "check status label text is blank");
// Check the relative URL was resolved correctly (note this image has offsets of zero...)
is(shareButton.src, 'https://example.com/browser/browser/base/content/test/social/social_share_image.png', "check image url is correct");
// Test clicking the share button
shareButton.addEventListener("click", function listener() {
shareButton.removeEventListener("click", listener);
is(shareButton.hasAttribute("shared"), true, "Share button should have 'shared' attribute after share button is clicked");
is(shareButton.getAttribute("tooltiptext"), "Unshare this page", "check tooltip text is correct");
is(shareStatusLabel.getAttribute("value"), "This page has been shared", "check status label text is correct");
// Check the URL and offsets were applied correctly
is(shareButton.src, 'https://example.com/browser/browser/base/content/test/social/social_share_image.png', "check image url is correct");
executeSoon(testSecondClick.bind(window, testPopupOKButton));
});
shareButton.click();
}, "provider didn't provide user-recommend-prompt response");
}
function testSecondClick(nextTest) {
let {shareButton, unsharePopup} = SocialShareButton;
unsharePopup.addEventListener("popupshown", function listener() {
unsharePopup.removeEventListener("popupshown", listener);
ok(true, "popup was shown after second click");
executeSoon(nextTest);
});
shareButton.click();
}
function testPopupOKButton() {
let {shareButton, unsharePopup} = SocialShareButton;
let okButton = document.getElementById("unsharePopupContinueSharingButton");
unsharePopup.addEventListener("popuphidden", function listener() {
unsharePopup.removeEventListener("popuphidden", listener);
is(shareButton.hasAttribute("shared"), true, "Share button should still have 'shared' attribute after OK button is clicked");
executeSoon(testSecondClick.bind(window, testPopupUndoButton));
});
okButton.click();
}
function testPopupUndoButton() {
let {shareButton, unsharePopup} = SocialShareButton;
let undoButton = document.getElementById("unsharePopupStopSharingButton");
unsharePopup.addEventListener("popuphidden", function listener() {
unsharePopup.removeEventListener("popuphidden", listener);
is(shareButton.hasAttribute("shared"), false, "Share button should not have 'shared' attribute after Undo button is clicked");
executeSoon(testShortcut);
});
undoButton.click();
}
function testShortcut() {
let keyTarget = window;
keyTarget.addEventListener("keyup", function listener() {
keyTarget.removeEventListener("keyup", listener);
executeSoon(checkShortcutWorked.bind(window, keyTarget));
});
EventUtils.synthesizeKey("l", {accelKey: true, shiftKey: true}, keyTarget);
}
function checkShortcutWorked(keyTarget) {
let {unsharePopup, shareButton} = SocialShareButton;
is(shareButton.hasAttribute("shared"), true, "Share button should be in the 'shared' state after keyboard shortcut is used");
// Test a second invocation of the shortcut
unsharePopup.addEventListener("popupshown", function listener() {
unsharePopup.removeEventListener("popupshown", listener);
ok(true, "popup was shown after second use of keyboard shortcut");
executeSoon(checkOKButton);
});
EventUtils.synthesizeKey("l", {accelKey: true, shiftKey: true}, keyTarget);
}
function checkOKButton() {
let okButton = document.getElementById("unsharePopupContinueSharingButton");
let undoButton = document.getElementById("unsharePopupStopSharingButton");
is(document.activeElement, okButton, "ok button should be focused by default");
// the undo button text, label text, access keys, etc should be as
// specified by the provider.
function isEltAttr(eltid, attr, expected) {
is(document.getElementById(eltid).getAttribute(attr), expected,
"element '" + eltid + "' has correct value for attribute '" + attr + "'");
}
isEltAttr("socialUserRecommendedText", "value", "You have already shared this page");
isEltAttr("unsharePopupContinueSharingButton", "label", "Got it!");
isEltAttr("unsharePopupContinueSharingButton", "accesskey", "G");
isEltAttr("unsharePopupStopSharingButton", "label", "Unshare it!");
isEltAttr("unsharePopupStopSharingButton", "accesskey", "U");
isEltAttr("socialUserPortrait", "aria-label", "Your pretty face");
// This rest of particular test doesn't really apply on Mac, since buttons
// aren't focusable by default.
if (navigator.platform.contains("Mac")) {
executeSoon(testCloseBySpace);
return;
}
let displayName = document.getElementById("socialUserDisplayName");
// Linux has the buttons in the [unshare] [ok] order, so displayName will come first.
if (navigator.platform.contains("Linux")) {
checkNextInTabOrder(displayName, function () {
checkNextInTabOrder(undoButton, function () {
checkNextInTabOrder(okButton, testCloseBySpace);
});
});
} else {
checkNextInTabOrder(undoButton, function () {
checkNextInTabOrder(displayName, function () {
checkNextInTabOrder(okButton, testCloseBySpace);
});
});
}
}
function checkNextInTabOrder(element, next) {
function listener() {
element.removeEventListener("focus", listener);
is(document.activeElement, element, element.id + " should be next in tab order");
executeSoon(next);
}
element.addEventListener("focus", listener);
// Register a cleanup function to remove the listener in case this test fails
registerCleanupFunction(function () {
element.removeEventListener("focus", listener);
});
EventUtils.synthesizeKey("VK_TAB", {});
}
function testCloseBySpace() {
let unsharePopup = SocialShareButton.unsharePopup;
is(document.activeElement.id, "unsharePopupContinueSharingButton", "testCloseBySpace, the ok button should be focused");
unsharePopup.addEventListener("popuphidden", function listener() {
unsharePopup.removeEventListener("popuphidden", listener);
ok(true, "space closed the share popup");
executeSoon(testStillSharedIn2Tabs);
});
EventUtils.synthesizeKey("VK_SPACE", {});
}
function testStillSharedIn2Tabs() {
let toShare = "http://example.com";
let {shareButton} = SocialShareButton;
let initialTab = gBrowser.selectedTab;
if (shareButton.hasAttribute("shared")) {
SocialShareButton.unsharePage();
}
is(shareButton.hasAttribute("shared"), false, "Share button should not have 'shared' for the initial tab");
let tab1 = gBrowser.selectedTab = gBrowser.addTab(toShare);
let tab1b = gBrowser.getBrowserForTab(tab1);
tab1b.addEventListener("load", function tabLoad(event) {
tab1b.removeEventListener("load", tabLoad, true);
let tab2 = gBrowser.selectedTab = gBrowser.addTab(toShare);
let tab2b = gBrowser.getBrowserForTab(tab2);
tab2b.addEventListener("load", function tabLoad(event) {
tab2b.removeEventListener("load", tabLoad, true);
// should start without either page being shared.
is(shareButton.hasAttribute("shared"), false, "Share button should not have 'shared' before we've done anything");
shareButton.click();
is(shareButton.hasAttribute("shared"), true, "Share button should reflect the share");
// and switching to the first tab (with the same URL) should still reflect shared.
gBrowser.selectedTab = tab1;
is(shareButton.hasAttribute("shared"), true, "Share button should reflect the share");
// but switching back the initial one should reflect not shared.
gBrowser.selectedTab = initialTab;
is(shareButton.hasAttribute("shared"), false, "Initial tab should not reflect shared");
gBrowser.selectedTab = tab1;
SocialShareButton.unsharePage();
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
executeSoon(testStillSharedAfterReopen);
}, true);
}, true);
}
function testStillSharedAfterReopen() {
let toShare = "http://example.com";
let {shareButton} = SocialShareButton;
is(shareButton.hasAttribute("shared"), false, "Reopen: Share button should not have 'shared' for the initial tab");
let tab = gBrowser.selectedTab = gBrowser.addTab(toShare);
let tabb = gBrowser.getBrowserForTab(tab);
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
SocialShareButton.sharePage();
is(shareButton.hasAttribute("shared"), true, "Share button should reflect the share");
gBrowser.removeTab(tab);
// should be on the initial unshared tab now.
is(shareButton.hasAttribute("shared"), false, "Initial tab should be selected and be unshared.");
// now open the same URL - should be back to shared.
tab = gBrowser.selectedTab = gBrowser.addTab(toShare, {skipAnimation: true});
tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
tab.linkedBrowser.removeEventListener("load", tabLoad, true);
executeSoon(function() {
is(shareButton.hasAttribute("shared"), true, "New tab to previously shared URL should reflect shared");
SocialShareButton.unsharePage();
gBrowser.removeTab(tab);
executeSoon(testOnlyShareCertainUrlsTabSwitch);
});
}, true);
}, true);
}
function testOnlyShareCertainUrlsTabSwitch() {
let toShare = "http://example.com";
let notSharable = "about:blank";
let {shareButton} = SocialShareButton;
let tab = gBrowser.selectedTab = gBrowser.addTab(toShare);
let tabb = gBrowser.getBrowserForTab(tab);
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(!shareButton.hidden, "share button not hidden for http url");
let tab2 = gBrowser.selectedTab = gBrowser.addTab(notSharable);
let tabb2 = gBrowser.getBrowserForTab(tab2);
tabb2.addEventListener("load", function tabLoad(event) {
tabb2.removeEventListener("load", tabLoad, true);
ok(shareButton.hidden, "share button hidden for about:blank");
gBrowser.selectedTab = tab;
ok(!shareButton.hidden, "share button re-shown when switching back to http: url");
gBrowser.selectedTab = tab2;
ok(shareButton.hidden, "share button re-hidden when switching back to about:blank");
gBrowser.removeTab(tab);
gBrowser.removeTab(tab2);
executeSoon(testOnlyShareCertainUrlsSameTab);
}, true);
}, true);
}
function testOnlyShareCertainUrlsSameTab() {
let toShare = "http://example.com";
let notSharable = "about:blank";
let {shareButton} = SocialShareButton;
let tab = gBrowser.selectedTab = gBrowser.addTab(toShare);
let tabb = gBrowser.getBrowserForTab(tab);
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(!shareButton.hidden, "share button not hidden for http url");
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(shareButton.hidden, "share button hidden for about:blank");
tabb.addEventListener("load", function tabLoad(event) {
tabb.removeEventListener("load", tabLoad, true);
ok(!shareButton.hidden, "share button re-enabled http url");
gBrowser.removeTab(tab);
executeSoon(testDisable);
}, true);
tabb.loadURI(toShare);
}, true);
tabb.loadURI(notSharable);
}, true);
}
function testDisable() {
let shareButton = SocialShareButton.shareButton;
Services.prefs.setBoolPref(prefName, false);
is(shareButton.hidden, true, "Share button should be hidden when pref is disabled");
gFinishCB();
}

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

@ -185,10 +185,8 @@ function checkSocialUI(win) {
isbool(win.SocialChatBar.isAvailable, enabled && Social.haveLoggedInUser(), "chatbar available?");
isbool(!win.SocialChatBar.chatbar.hidden, enabled && Social.haveLoggedInUser(), "chatbar visible?");
let markVisible = enabled && provider.pageMarkInfo;
let canMark = markVisible && win.SocialMark.canMarkPage(win.gBrowser.currentURI);
isbool(!win.SocialMark.button.hidden, markVisible, "SocialMark button visible?");
isbool(!win.SocialMark.button.disabled, canMark, "SocialMark button enabled?");
let canShare = enabled && provider.recommendInfo && Social.haveLoggedInUser() && win.SocialShareButton.canSharePage(win.gBrowser.currentURI)
isbool(!win.SocialShareButton.shareButton.hidden, canShare, "share button visible?");
isbool(!doc.getElementById("social-toolbar-item").hidden, active, "toolbar items visible?");
if (active)
is(win.SocialToolbar.button.style.listStyleImage, 'url("' + Social.defaultProvider.iconURL + '")', "toolbar button has provider icon");
@ -203,7 +201,7 @@ function checkSocialUI(win) {
isbool(!doc.getElementById("Social:ToggleNotifications").hidden, enabled, "Social:ToggleNotifications visible?");
isbool(!doc.getElementById("Social:FocusChat").hidden, enabled && Social.haveLoggedInUser(), "Social:FocusChat visible?");
isbool(doc.getElementById("Social:FocusChat").getAttribute("disabled"), enabled ? "false" : "true", "Social:FocusChat disabled?");
is(doc.getElementById("Social:TogglePageMark").getAttribute("disabled"), canMark ? "false" : "true", "Social:TogglePageMark enabled?");
is(doc.getElementById("Social:SharePage").getAttribute("disabled"), canShare ? "false" : "true", "Social:SharePage visible?");
// broadcasters.
isbool(!doc.getElementById("socialActiveBroadcaster").hidden, active, "socialActiveBroadcaster hidden?");

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

До

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

После

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

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

@ -100,23 +100,6 @@ onconnect = function(e) {
};
}
port.postMessage({topic: "social.user-profile", data: profile});
port.postMessage({
topic: "social.page-mark-config",
data: {
images: {
// this one is relative to test we handle relative ones.
marked: "/browser/browser/base/content/test/social/social_mark_image.png",
// absolute to check we handle them too.
unmarked: "https://example.com/browser/browser/base/content/test/social/social_mark_image.png"
},
messages: {
unmarkedTooltip: "Mark this page",
markedTooltip: "Unmark this page",
unmarkedLabel: "Mark",
markedLabel: "Unmark",
}
}
});
break;
case "test-ambient-notification":
let icon = {
@ -133,6 +116,31 @@ onconnect = function(e) {
case "test-isVisible-response":
testPort.postMessage({topic: "got-isVisible-response", result: event.data.result});
break;
case "social.user-recommend-prompt":
port.postMessage({
topic: "social.user-recommend-prompt-response",
data: {
images: {
// this one is relative to test we handle relative ones.
share: "browser/browser/base/content/test/social/social_share_image.png",
// absolute to check we handle them too.
unshare: "https://example.com/browser/browser/base/content/test/social/social_share_image.png"
},
messages: {
shareTooltip: "Share this page",
unshareTooltip: "Unshare this page",
sharedLabel: "This page has been shared",
unsharedLabel: "This page is no longer shared",
unshareLabel: "You have already shared this page",
portraitLabel: "Your pretty face",
unshareConfirmLabel: "Unshare it!",
unshareConfirmAccessKey: "U",
unshareCancelLabel: "Got it!",
unshareCancelAccessKey: "G"
}
}
});
break;
}
}
}

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

@ -115,7 +115,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY bookmarksMenu.accesskey "B">
<!ENTITY bookmarkThisPageCmd.label "Bookmark This Page">
<!ENTITY bookmarkThisPageCmd.commandkey "d">
<!ENTITY markPageCmd.commandkey "l">
<!ENTITY sharePageCmd.commandkey "l">
<!ENTITY subscribeToPageMenupopup.label "Subscribe to This Page">
<!ENTITY subscribeToPageMenuitem.label "Subscribe to This Page…">
<!ENTITY addCurPagesCmd.label "Bookmark All Tabs…">
@ -644,10 +644,6 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY social.chatBar.label "Focus chats">
<!ENTITY social.chatBar.accesskey "c">
<!-- labels are set dynamically, see browser.properties -->
<!ENTITY social.markpage.accesskey "m">
<!ENTITY social.marklink.accesskey "M">
<!ENTITY getUserMedia.selectCamera.label "Camera to share:">
<!ENTITY getUserMedia.selectCamera.accesskey "C">
<!ENTITY getUserMedia.selectMicrophone.label "Microphone to share:">

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

@ -386,13 +386,6 @@ social.turnOff.accesskey=T
social.turnOn.label=Turn on %S
social.turnOn.accesskey=T
# LOCALIZATION NOTE (social.markpage.label): %S is the name of the social provider
social.markpage.label=Send Page to %S
social.unmarkpage.label=Remove Page from %S
# LOCALIZATION NOTE (social.marklink.label): %S is the name of the social provider
social.marklink.label=Send Link to %S
social.unmarklink.label=Remove Link from %S
# LOCALIZATION NOTE (social.error.message): %1$S is brandShortName (e.g. Firefox), %2$S is the name of the social provider
social.error.message=%1$S is unable to connect with %2$S right now.
social.error.tryAgain.label=Try Again

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

@ -15,10 +15,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
"resource://gre/modules/SocialService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
// Add a pref observer for the enabled state
function prefObserver(subject, topic, data) {
@ -36,46 +32,6 @@ Services.obs.addObserver(function xpcomShutdown() {
Services.prefs.removeObserver("social.enabled", prefObserver);
}, "xpcom-shutdown", false);
function promiseSetAnnotation(aURI, providerList) {
let deferred = Promise.defer();
// Delaying to catch issues with asynchronous behavior while waiting
// to implement asynchronous annotations in bug 699844.
Services.tm.mainThread.dispatch(function() {
try {
if (providerList && providerList.length > 0) {
PlacesUtils.annotations.setPageAnnotation(
aURI, "social/mark", JSON.stringify(providerList), 0,
PlacesUtils.annotations.EXPIRE_WITH_HISTORY);
} else {
PlacesUtils.annotations.removePageAnnotation(aURI, "social/mark");
}
} catch(e) {
Cu.reportError("SocialAnnotation failed: " + e);
}
deferred.resolve();
}, Ci.nsIThread.DISPATCH_NORMAL);
return deferred.promise;
}
function promiseGetAnnotation(aURI) {
let deferred = Promise.defer();
// Delaying to catch issues with asynchronous behavior while waiting
// to implement asynchronous annotations in bug 699844.
Services.tm.mainThread.dispatch(function() {
let val = null;
try {
val = PlacesUtils.annotations.getPageAnnotation(aURI, "social/mark");
} catch (ex) { }
deferred.resolve(val);
}, Ci.nsIThread.DISPATCH_NORMAL);
return deferred.promise;
}
this.Social = {
initialized: false,
lastEventReceived: 0,
@ -257,8 +213,8 @@ this.Social = {
SocialService.removeProvider(origin);
},
// Page Marking functionality
_getMarkablePageUrl: function Social_getMarkablePageUrl(aURI) {
// Sharing functionality
_getShareablePageUrl: function Social_getShareablePageUrl(aURI) {
let uri = aURI.clone();
try {
// Setting userPass on about:config throws.
@ -267,97 +223,53 @@ this.Social = {
return uri.spec;
},
isURIMarked: function(aURI, aCallback) {
promiseGetAnnotation(aURI).then(function(val) {
if (val) {
let providerList = JSON.parse(val);
val = providerList.indexOf(this.provider.origin) >= 0;
}
aCallback(!!val);
}.bind(this));
isPageShared: function Social_isPageShared(aURI) {
let url = this._getShareablePageUrl(aURI);
return this._sharedUrls.hasOwnProperty(url);
},
markURI: function(aURI, aCallback) {
sharePage: function Social_sharePage(aURI) {
// this should not be called if this.provider or the port is null
if (!this.provider) {
Cu.reportError("Can't mark a page when no provider is current");
Cu.reportError("Can't share a page when no provider is current");
return;
}
let port = this.provider.getWorkerPort();
if (!port) {
Cu.reportError("Can't mark page as no provider port is available");
Cu.reportError("Can't share page as no provider port is available");
return;
}
// update or set our annotation
promiseGetAnnotation(aURI).then(function(val) {
let providerList = val ? JSON.parse(val) : [];
let marked = providerList.indexOf(this.provider.origin) >= 0;
if (marked)
return;
providerList.push(this.provider.origin);
// we allow marking links in a page that may not have been visited yet.
// make sure there is a history entry for the uri, then annotate it.
let place = {
uri: aURI,
visits: [{
visitDate: Date.now() + 1000,
transitionType: Ci.nsINavHistoryService.TRANSITION_LINK
}]
};
PlacesUtils.asyncHistory.updatePlaces(place, {
handleError: function () Cu.reportError("couldn't update history for socialmark annotation"),
handleResult: function () {},
handleCompletion: function () {
promiseSetAnnotation(aURI, providerList).then();
// post to the provider
let url = this._getMarkablePageUrl(aURI);
port.postMessage({
topic: "social.page-mark",
data: { url: url, 'marked': true }
});
port.close();
if (aCallback)
schedule(function() { aCallback(true); } );
}.bind(this)
});
}.bind(this));
let url = this._getShareablePageUrl(aURI);
this._sharedUrls[url] = true;
port.postMessage({
topic: "social.user-recommend",
data: { url: url }
});
port.close();
},
unmarkURI: function(aURI, aCallback) {
unsharePage: function Social_unsharePage(aURI) {
// this should not be called if this.provider or the port is null
if (!this.provider) {
Cu.reportError("Can't mark a page when no provider is current");
Cu.reportError("Can't unshare a page when no provider is current");
return;
}
let port = this.provider.getWorkerPort();
if (!port) {
Cu.reportError("Can't mark page as no provider port is available");
Cu.reportError("Can't unshare page as no provider port is available");
return;
}
// set our annotation
promiseGetAnnotation(aURI).then(function(val) {
let providerList = val ? JSON.parse(val) : [];
let marked = providerList.indexOf(this.provider.origin) >= 0;
if (marked) {
// remove the annotation
providerList.splice(providerList.indexOf(this.provider.origin), 1);
promiseSetAnnotation(aURI, providerList).then();
}
// post to the provider regardless
let url = this._getMarkablePageUrl(aURI);
port.postMessage({
topic: "social.page-mark",
data: { url: url, 'marked': false }
});
port.close();
if (aCallback)
schedule(function() { aCallback(false); } );
}.bind(this));
let url = this._getShareablePageUrl(aURI);
delete this._sharedUrls[url];
port.postMessage({
topic: "social.user-unrecommend",
data: { url: url }
});
port.close();
},
_sharedUrls: {},
setErrorListener: function(iframe, errorHandler) {
if (iframe.socialErrorListener)
return iframe.socialErrorListener;

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

@ -1435,10 +1435,50 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
/* social recommending panel */
#social-mark-button {
#share-button {
-moz-image-region: rect(0, 16px, 16px, 0);
}
#socialUserPortrait {
width: 48px;
height: 48px;
list-style-image:url("chrome://global/skin/icons/information-32.png");
}
#socialUserDisplayName,
#socialUserPortrait {
cursor: pointer;
}
#socialUserDisplayName {
-moz-appearance: none;
border: none;
background-color: transparent;
margin-top: 0;
padding-top: 0;
font-size: 130%;
font-weight: bold;
}
#socialUserDisplayName > .button-box {
-moz-padding-start: 0;
padding-top: 0;
border-top-width: 0;
}
#socialUserDisplayName:hover {
color: -moz-nativehyperlinktext;
text-decoration: underline;
}
#unsharePopupText {
height: 48px;
}
#unsharePopupBottomButtons {
margin-top: 1em;
}
/* bookmarks menu-button */
#bookmarks-menu-button {

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

@ -1657,10 +1657,50 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s
/* social recommending panel */
#social-mark-button {
#share-button {
-moz-image-region: rect(0, 16px, 16px, 0);
}
#socialUserPortrait {
width: 48px;
height: 48px;
list-style-image:url("chrome://global/skin/icons/information-32.png");
}
#socialUserDisplayName,
#socialUserPortrait {
cursor: pointer;
}
#socialUserDisplayName {
-moz-appearance: none;
border: none;
background-color: transparent;
margin: 1px;
padding: 0;
font-size: 130%;
font-weight: bold;
}
#socialUserDisplayName > .button-box {
-moz-padding-start: 0;
padding-top: 0;
border-top-width: 0;
}
#socialUserDisplayName:hover {
color: -moz-nativehyperlinktext;
text-decoration: underline;
}
#unsharePopupText {
height: 48px;
}
#unsharePopupBottomButtons {
margin-top: 1em;
}
/* bookmarks menu-button */
#bookmarks-menu-button {

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

@ -1715,10 +1715,50 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
/* social recommending panel */
#social-mark-button {
#share-button {
-moz-image-region: rect(0, 16px, 16px, 0);
}
#socialUserPortrait {
width: 48px;
height: 48px;
list-style-image:url("chrome://global/skin/icons/information-32.png");
}
#socialUserDisplayName,
#socialUserPortrait {
cursor: pointer;
}
#socialUserDisplayName {
-moz-appearance: none;
border: none;
background-color: transparent;
margin-top: 0;
padding-top: 0;
font-size: 130%;
font-weight: bold;
}
#socialUserDisplayName > .button-box {
-moz-padding-start: 0;
padding-top: 0;
border-top-width: 0;
}
#socialUserDisplayName:hover {
color: -moz-nativehyperlinktext;
text-decoration: underline;
}
#unsharePopupText {
height: 48px;
}
#unsharePopupBottomButtons {
margin-top: 1em;
}
/* bookmarks menu-button */
#bookmarks-menu-button {

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

@ -74,7 +74,7 @@ class RemoteAutomation(Automation):
status = proc.wait(timeout = maxTime)
self.lastTestSeen = proc.getLastTestSeen
if (status == 1 and self._devicemanager.processExist(proc.procName)):
if (status == 1 and self._devicemanager.getTopActivity() == proc.procName):
# Then we timed out, make sure Fennec is dead
if maxTime:
print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
@ -269,7 +269,7 @@ class RemoteAutomation(Automation):
if timeout == None:
timeout = self.timeout
while (self.dm.processExist(self.procName)):
while (self.dm.getTopActivity() == self.procName):
t = self.stdout
if t != '': print t
time.sleep(interval)

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

@ -6,8 +6,8 @@
CONFIGURE_SUBST_FILES += [
'autoconf.mk',
'emptyvars.mk',
'doxygen.cfg',
'emptyvars.mk',
'makefiles/test/Makefile',
'tests/makefiles/autodeps/Makefile',
'tests/src-simple/Makefile',

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

@ -534,10 +534,9 @@ public:
* method is responsible for calling BeginObservingDocument() on the
* presshell if the presshell should observe document mutations.
*/
virtual nsresult CreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult) = 0;
virtual already_AddRefed<nsIPresShell> CreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet) = 0;
virtual void DeleteShell() = 0;
nsIPresShell* GetShell() const

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

@ -7,31 +7,31 @@
MODULE = 'content'
EXPORTS += [
'mozAutoDocUpdate.h',
'nsAtomListUtils.h',
'nsAttrAndChildArray.h',
'nsAttrName.h',
'nsAttrValue.h',
'nsAttrValueInlines.h',
'nsContentList.h',
'nsContentListDeclarations.h',
'nsContentSink.h',
'nsCrossSiteListenerProxy.h',
'nsDOMAttributeMap.h',
'nsFrameMessageManager.h',
'nsGkAtomList.h',
'nsGkAtoms.h',
'nsMappedAttributeElement.h',
'nsNodeInfoManager.h',
'nsNodeUtils.h',
'nsPropertyTable.h',
'nsRange.h',
'nsSandboxFlags.h',
'nsScriptLoader.h',
'nsStubDocumentObserver.h',
'nsStubMutationObserver.h',
'nsTextFragment.h',
'mozAutoDocUpdate.h',
'nsFrameMessageManager.h',
'nsAttrAndChildArray.h',
'nsAttrValue.h',
'nsAttrValueInlines.h',
'nsCrossSiteListenerProxy.h',
'nsDOMAttributeMap.h',
'nsMappedAttributeElement.h',
'nsStyledElement.h',
'nsSandboxFlags.h',
'nsTextFragment.h',
]
if CONFIG['MOZ_WEBRTC']:
@ -40,9 +40,9 @@ if CONFIG['MOZ_WEBRTC']:
EXPORTS.mozilla.dom += [
'Attr.h',
'Comment.h',
'DOMImplementation.h',
'DocumentFragment.h',
'DocumentType.h',
'DOMImplementation.h',
'EventSource.h',
'Link.h',
'NodeIterator.h',

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

@ -3337,35 +3337,30 @@ nsDocument::TryChannelCharset(nsIChannel *aChannel,
}
}
nsresult
already_AddRefed<nsIPresShell>
nsDocument::CreateShell(nsPresContext* aContext, nsViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult)
nsStyleSet* aStyleSet)
{
// Don't add anything here. Add it to |doCreateShell| instead.
// This exists so that subclasses can pass other values for the 4th
// parameter some of the time.
return doCreateShell(aContext, aViewManager, aStyleSet,
eCompatibility_FullStandards, aInstancePtrResult);
eCompatibility_FullStandards);
}
nsresult
already_AddRefed<nsIPresShell>
nsDocument::doCreateShell(nsPresContext* aContext,
nsViewManager* aViewManager, nsStyleSet* aStyleSet,
nsCompatibility aCompatMode,
nsIPresShell** aInstancePtrResult)
nsCompatibility aCompatMode)
{
*aInstancePtrResult = nullptr;
NS_ASSERTION(!mPresShell, "We have a presshell already!");
NS_ENSURE_FALSE(GetBFCacheEntry(), NS_ERROR_FAILURE);
NS_ENSURE_FALSE(GetBFCacheEntry(), nullptr);
FillStyleSet(aStyleSet);
nsRefPtr<PresShell> shell = new PresShell;
nsresult rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
NS_ENSURE_SUCCESS(rv, rv);
shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
// Note: we don't hold a ref to the shell (it holds a ref to us)
mPresShell = shell;
@ -3374,9 +3369,7 @@ nsDocument::doCreateShell(nsPresContext* aContext,
MaybeRescheduleAnimationFrameNotifications();
shell.forget(aInstancePtrResult);
return NS_OK;
return shell.forget();
}
void

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

@ -590,13 +590,12 @@ public:
/**
* Create a new presentation shell that will use aContext for
* its presentation context (presentation context's <b>must not</b> be
* shared among multiple presentation shell's).
* its presentation context (presentation contexts <b>must not</b> be
* shared among multiple presentation shells).
*/
virtual nsresult CreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult);
virtual already_AddRefed<nsIPresShell> CreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet) MOZ_OVERRIDE;
virtual void DeleteShell();
virtual nsresult GetAllowPlugins(bool* aAllowPlugins);
@ -1141,10 +1140,10 @@ public:
static void XPCOMShutdown();
protected:
nsresult doCreateShell(nsPresContext* aContext,
nsViewManager* aViewManager, nsStyleSet* aStyleSet,
nsCompatibility aCompatMode,
nsIPresShell** aInstancePtrResult);
already_AddRefed<nsIPresShell> doCreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsCompatibility aCompatMode);
void RemoveDocStyleSheetsFromStyleSets();
void RemoveStyleSheetsFromStyleSets(nsCOMArray<nsIStyleSheet>& aSheets,

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

@ -733,17 +733,8 @@ HTMLInputElement::Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const
nsresult rv = const_cast<HTMLInputElement*>(this)->CopyInnerTo(it);
NS_ENSURE_SUCCESS(rv, rv);
switch (mType) {
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_PASSWORD:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_NUMBER:
case NS_FORM_INPUT_DATE:
case NS_FORM_INPUT_TIME:
case NS_FORM_INPUT_RANGE:
switch (GetValueMode()) {
case VALUE_MODE_VALUE:
if (mValueChanged) {
// We don't have our default value anymore. Set our value on
// the clone.
@ -753,7 +744,7 @@ HTMLInputElement::Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const
it->SetValueInternal(value, false, true);
}
break;
case NS_FORM_INPUT_FILE:
case VALUE_MODE_FILENAME:
if (it->OwnerDoc()->IsStaticDocument()) {
// We're going to be used in print preview. Since the doc is static
// we can just grab the pretty string and use it as wallpaper
@ -763,21 +754,18 @@ HTMLInputElement::Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const
it->mFiles.AppendObjects(mFiles);
}
break;
case NS_FORM_INPUT_RADIO:
case NS_FORM_INPUT_CHECKBOX:
case VALUE_MODE_DEFAULT_ON:
if (mCheckedChanged) {
// We no longer have our original checked state. Set our
// checked state on the clone.
it->DoSetChecked(mChecked, false, true);
}
break;
case NS_FORM_INPUT_IMAGE:
if (it->OwnerDoc()->IsStaticDocument()) {
case VALUE_MODE_DEFAULT:
if (mType == NS_FORM_INPUT_IMAGE && it->OwnerDoc()->IsStaticDocument()) {
CreateStaticImageClone(it);
}
break;
default:
break;
}
it.forget(aResult);
@ -4415,53 +4403,40 @@ NS_IMETHODIMP
HTMLInputElement::SaveState()
{
nsRefPtr<HTMLInputElementState> inputState;
switch (mType) {
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_RADIO:
{
if (mCheckedChanged) {
inputState = new HTMLInputElementState();
inputState->SetChecked(mChecked);
}
switch (GetValueMode()) {
case VALUE_MODE_DEFAULT_ON:
if (mCheckedChanged) {
inputState = new HTMLInputElementState();
inputState->SetChecked(mChecked);
}
break;
case VALUE_MODE_FILENAME:
if (mFiles.Count()) {
inputState = new HTMLInputElementState();
inputState->SetFiles(mFiles);
}
break;
case VALUE_MODE_VALUE:
case VALUE_MODE_DEFAULT:
// VALUE_MODE_DEFAULT shouldn't have their value saved except 'hidden',
// mType shouldn't be NS_FORM_INPUT_PASSWORD and value should have changed.
if ((GetValueMode() == VALUE_MODE_DEFAULT &&
mType != NS_FORM_INPUT_HIDDEN) ||
mType == NS_FORM_INPUT_PASSWORD || !mValueChanged) {
break;
}
// Never save passwords in session history
case NS_FORM_INPUT_PASSWORD:
inputState = new HTMLInputElementState();
nsAutoString value;
GetValue(value);
DebugOnly<nsresult> rv =
nsLinebreakConverter::ConvertStringLineBreaks(
value,
nsLinebreakConverter::eLinebreakPlatform,
nsLinebreakConverter::eLinebreakContent);
NS_ASSERTION(NS_SUCCEEDED(rv), "Converting linebreaks failed!");
inputState->SetValue(value);
break;
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_NUMBER:
case NS_FORM_INPUT_DATE:
case NS_FORM_INPUT_TIME:
case NS_FORM_INPUT_RANGE:
{
if (mValueChanged) {
inputState = new HTMLInputElementState();
nsAutoString value;
GetValue(value);
DebugOnly<nsresult> rv =
nsLinebreakConverter::ConvertStringLineBreaks(
value,
nsLinebreakConverter::eLinebreakPlatform,
nsLinebreakConverter::eLinebreakContent);
NS_ASSERTION(NS_SUCCEEDED(rv), "Converting linebreaks failed!");
inputState->SetValue(value);
}
break;
}
case NS_FORM_INPUT_FILE:
{
if (mFiles.Count()) {
inputState = new HTMLInputElementState();
inputState->SetFiles(mFiles);
}
break;
}
}
nsresult rv = NS_OK;
@ -4605,37 +4580,29 @@ HTMLInputElement::RestoreState(nsPresState* aState)
(do_QueryInterface(aState->GetStateProperty()));
if (inputState) {
switch (mType) {
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_RADIO:
{
if (inputState->IsCheckedSet()) {
restoredCheckedState = true;
DoSetChecked(inputState->GetChecked(), true, true);
}
break;
switch (GetValueMode()) {
case VALUE_MODE_DEFAULT_ON:
if (inputState->IsCheckedSet()) {
restoredCheckedState = true;
DoSetChecked(inputState->GetChecked(), true, true);
}
case NS_FORM_INPUT_EMAIL:
case NS_FORM_INPUT_SEARCH:
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_TEL:
case NS_FORM_INPUT_URL:
case NS_FORM_INPUT_HIDDEN:
case NS_FORM_INPUT_NUMBER:
case NS_FORM_INPUT_DATE:
case NS_FORM_INPUT_TIME:
case NS_FORM_INPUT_RANGE:
{
SetValueInternal(inputState->GetValue(), false, true);
break;
}
case NS_FORM_INPUT_FILE:
break;
case VALUE_MODE_FILENAME:
{
const nsCOMArray<nsIDOMFile>& files = inputState->GetFiles();
SetFiles(files, true);
}
break;
case VALUE_MODE_VALUE:
case VALUE_MODE_DEFAULT:
if (GetValueMode() == VALUE_MODE_DEFAULT &&
mType != NS_FORM_INPUT_HIDDEN) {
break;
}
SetValueInternal(inputState->GetValue(), false, true);
break;
break;
}
}

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

@ -8,16 +8,16 @@ MODULE = 'content'
EXPORTS += [
'HTMLPropertiesCollection.h',
'nsGenericHTMLElement.h',
'nsClientRect.h',
'nsGenericHTMLElement.h',
'nsHTMLDNSPrefetch.h',
]
EXPORTS.mozilla.dom += [
'HTMLAnchorElement.h',
'HTMLAreaElement.h',
'HTMLBodyElement.h',
'HTMLBRElement.h',
'HTMLBodyElement.h',
'HTMLButtonElement.h',
'HTMLDataElement.h',
'HTMLDataListElement.h',
@ -26,14 +26,14 @@ EXPORTS.mozilla.dom += [
'HTMLFontElement.h',
'HTMLFrameElement.h',
'HTMLFrameSetElement.h',
'HTMLHeadingElement.h',
'HTMLHRElement.h',
'HTMLHeadingElement.h',
'HTMLIFrameElement.h',
'HTMLImageElement.h',
'HTMLInputElement.h',
'HTMLLIElement.h',
'HTMLLabelElement.h',
'HTMLLegendElement.h',
'HTMLLIElement.h',
'HTMLLinkElement.h',
'HTMLMapElement.h',
'HTMLMenuElement.h',
@ -42,9 +42,9 @@ EXPORTS.mozilla.dom += [
'HTMLMeterElement.h',
'HTMLModElement.h',
'HTMLObjectElement.h',
'HTMLOptGroupElement.h',
'HTMLOptionElement.h',
'HTMLOptionsCollection.h',
'HTMLOptGroupElement.h',
'HTMLOutputElement.h',
'HTMLParagraphElement.h',
'HTMLPreElement.h',

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

@ -304,14 +304,12 @@ nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
SetContentTypeInternal(nsDependentCString("text/html"));
}
nsresult
already_AddRefed<nsIPresShell>
nsHTMLDocument::CreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult)
nsStyleSet* aStyleSet)
{
return doCreateShell(aContext, aViewManager, aStyleSet, mCompatMode,
aInstancePtrResult);
return doCreateShell(aContext, aViewManager, aStyleSet, mCompatMode);
}
void

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

@ -54,10 +54,9 @@ public:
virtual void ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
nsIPrincipal* aPrincipal);
virtual nsresult CreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet,
nsIPresShell** aInstancePtrResult);
virtual already_AddRefed<nsIPresShell> CreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,
nsStyleSet* aStyleSet) MOZ_OVERRIDE;
virtual nsresult StartDocumentLoad(const char* aCommand,
nsIChannel* aChannel,

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

@ -19,11 +19,6 @@ struct ThreeDPoint;
class AudioNodeStream;
// We ensure that the graph advances in steps that are multiples of the Web
// Audio block size
const uint32_t WEBAUDIO_BLOCK_SIZE_BITS = 7;
const uint32_t WEBAUDIO_BLOCK_SIZE = 1 << WEBAUDIO_BLOCK_SIZE_BITS;
/**
* This class holds onto a set of immutable channel buffers. The storage
* for the buffers must be malloced, but the buffer pointers and the malloc
@ -154,7 +149,6 @@ public:
: mNode(aNode)
, mNodeMutex("AudioNodeEngine::mNodeMutex")
{
MOZ_ASSERT(mNode, "The engine is constructed with a null node");
MOZ_COUNT_CTOR(AudioNodeEngine);
}
virtual ~AudioNodeEngine()
@ -210,6 +204,11 @@ public:
Mutex& NodeMutex() { return mNodeMutex;}
bool HasNode() const
{
return !!mNode;
}
dom::AudioNode* Node() const
{
mNodeMutex.AssertCurrentThreadOwns();

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

@ -102,19 +102,19 @@ AudioNodeStream::SetInt32Parameter(uint32_t aIndex, int32_t aValue)
void
AudioNodeStream::SetTimelineParameter(uint32_t aIndex,
const AudioEventTimeline<ErrorResult>& aValue)
const AudioParamTimeline& aValue)
{
class Message : public ControlMessage {
public:
Message(AudioNodeStream* aStream, uint32_t aIndex,
const AudioEventTimeline<ErrorResult>& aValue)
const AudioParamTimeline& aValue)
: ControlMessage(aStream), mValue(aValue), mIndex(aIndex) {}
virtual void Run()
{
static_cast<AudioNodeStream*>(mStream)->Engine()->
SetTimelineParameter(mIndex, mValue);
}
AudioEventTimeline<ErrorResult> mValue;
AudioParamTimeline mValue;
uint32_t mIndex;
};
GraphImpl()->AppendMessage(new Message(this, aIndex, aValue));
@ -247,7 +247,8 @@ AudioNodeStream::ObtainInputBlock(AudioChunk* aTmpChunk)
MediaStream* s = mInputs[i]->GetSource();
AudioNodeStream* a = static_cast<AudioNodeStream*>(s);
MOZ_ASSERT(a == s->AsAudioNodeStream());
if (a->IsFinishedOnGraphThread()) {
if (a->IsFinishedOnGraphThread() ||
a->IsAudioParamStream()) {
continue;
}
AudioChunk* chunk = &a->mLastChunk;

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

@ -22,6 +22,7 @@ namespace mozilla {
namespace dom {
struct ThreeDPoint;
class AudioParamTimeline;
}
class ThreadSharedFloatArrayBufferList;
@ -49,7 +50,8 @@ public:
mEngine(aEngine),
mKind(aKind),
mNumberOfInputChannels(2),
mMarkAsFinishedAfterThisBlock(false)
mMarkAsFinishedAfterThisBlock(false),
mAudioParamStream(false)
{
mMixingMode.mChannelCountMode = dom::ChannelCountMode::Max;
mMixingMode.mChannelInterpretation = dom::ChannelInterpretation::Speakers;
@ -74,6 +76,11 @@ public:
void SetChannelMixingParameters(uint32_t aNumberOfChannels,
dom::ChannelCountMode aChannelCountMoe,
dom::ChannelInterpretation aChannelInterpretation);
void SetAudioParamHelperStream()
{
MOZ_ASSERT(!mAudioParamStream, "Can only do this once");
mAudioParamStream = true;
}
virtual AudioNodeStream* AsAudioNodeStream() { return this; }
@ -86,6 +93,14 @@ public:
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo);
TrackTicks GetCurrentPosition();
bool AllInputsFinished() const;
bool IsAudioParamStream() const
{
return mAudioParamStream;
}
const AudioChunk& LastChunk() const
{
return mLastChunk;
}
// Any thread
AudioNodeEngine* Engine() { return mEngine; }
@ -112,6 +127,8 @@ protected:
// Whether the stream should be marked as finished as soon
// as the current time range has been computed block by block.
bool mMarkAsFinishedAfterThisBlock;
// Whether the stream is an AudioParamHelper stream.
bool mAudioParamStream;
};
}

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

@ -20,6 +20,11 @@ class AudioStream;
*/
const int GUESS_AUDIO_CHANNELS = 2;
// We ensure that the graph advances in steps that are multiples of the Web
// Audio block size
const uint32_t WEBAUDIO_BLOCK_SIZE_BITS = 7;
const uint32_t WEBAUDIO_BLOCK_SIZE = 1 << WEBAUDIO_BLOCK_SIZE_BITS;
/**
* An AudioChunk represents a multi-channel buffer of audio samples.
* It references an underlying ThreadSharedObject which manages the lifetime

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

@ -2017,9 +2017,11 @@ MediaStreamGraph::CreateAudioNodeStream(AudioNodeEngine* aEngine,
NS_ADDREF(stream);
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this);
stream->SetGraphImpl(graph);
stream->SetChannelMixingParametersImpl(aEngine->NodeMainThread()->ChannelCount(),
aEngine->NodeMainThread()->ChannelCountModeValue(),
aEngine->NodeMainThread()->ChannelInterpretationValue());
if (aEngine->HasNode()) {
stream->SetChannelMixingParametersImpl(aEngine->NodeMainThread()->ChannelCount(),
aEngine->NodeMainThread()->ChannelCountModeValue(),
aEngine->NodeMainThread()->ChannelInterpretationValue());
}
graph->AppendMessage(new CreateMessage(stream));
return stream;
}

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

@ -0,0 +1,118 @@
/* -*- 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 <string.h>
#include "GStreamerReader.h"
#include "GStreamerMozVideoBuffer.h"
namespace mozilla {
static GstMozVideoBuffer *gst_moz_video_buffer_copy(GstMozVideoBuffer* self);
static void gst_moz_video_buffer_finalize(GstMozVideoBuffer* self);
G_DEFINE_TYPE(GstMozVideoBuffer, gst_moz_video_buffer, GST_TYPE_BUFFER);
static void
gst_moz_video_buffer_class_init(GstMozVideoBufferClass* klass)
{
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER_CLASS(klass));
GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS(klass);
mo_class->copy =(GstMiniObjectCopyFunction)gst_moz_video_buffer_copy;
mo_class->finalize =(GstMiniObjectFinalizeFunction)gst_moz_video_buffer_finalize;
}
static void
gst_moz_video_buffer_init(GstMozVideoBuffer* self)
{
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
}
static void
gst_moz_video_buffer_finalize(GstMozVideoBuffer* self)
{
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
if(self->data)
g_boxed_free(GST_TYPE_MOZ_VIDEO_BUFFER_DATA, self->data);
GST_MINI_OBJECT_CLASS(gst_moz_video_buffer_parent_class)->finalize(GST_MINI_OBJECT(self));
}
static GstMozVideoBuffer*
gst_moz_video_buffer_copy(GstMozVideoBuffer* self)
{
GstMozVideoBuffer* copy;
g_return_val_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self), NULL);
copy = gst_moz_video_buffer_new();
/* we simply copy everything from our parent */
GST_BUFFER_DATA(GST_BUFFER_CAST(copy)) =
(guint8*)g_memdup(GST_BUFFER_DATA(GST_BUFFER_CAST(self)), GST_BUFFER_SIZE(GST_BUFFER_CAST(self)));
/* make sure it gets freed(even if the parent is subclassed, we return a
normal buffer) */
GST_BUFFER_MALLOCDATA(GST_BUFFER_CAST(copy)) = GST_BUFFER_DATA(GST_BUFFER_CAST(copy));
GST_BUFFER_SIZE(GST_BUFFER_CAST(copy)) = GST_BUFFER_SIZE(GST_BUFFER_CAST(self));
/* copy metadata */
gst_buffer_copy_metadata(GST_BUFFER_CAST(copy),
GST_BUFFER_CAST(self),
(GstBufferCopyFlags)GST_BUFFER_COPY_ALL);
/* copy videobuffer */
if(self->data)
copy->data = (GstMozVideoBufferData*)g_boxed_copy(GST_TYPE_MOZ_VIDEO_BUFFER_DATA, self->data);
return copy;
}
GstMozVideoBuffer*
gst_moz_video_buffer_new(void)
{
GstMozVideoBuffer *self;
self =(GstMozVideoBuffer*)gst_mini_object_new(GST_TYPE_MOZ_VIDEO_BUFFER);
self->data = nullptr;
return self;
}
void
gst_moz_video_buffer_set_data(GstMozVideoBuffer* self, GstMozVideoBufferData* data)
{
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
self->data = data;
}
GstMozVideoBufferData*
gst_moz_video_buffer_get_data(const GstMozVideoBuffer* self)
{
g_return_val_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self), NULL);
return self->data;
}
GType
gst_moz_video_buffer_data_get_type(void)
{
static volatile gsize g_define_type_id__volatile = 0;
if(g_once_init_enter(&g_define_type_id__volatile)) {
GType g_define_type_id =
g_boxed_type_register_static(g_intern_static_string("GstMozVideoBufferData"),
(GBoxedCopyFunc)GstMozVideoBufferData::Copy,
(GBoxedFreeFunc)GstMozVideoBufferData::Free);
g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
}

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

@ -0,0 +1,60 @@
/* 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 __GST_MOZ_VIDEO_BUFFER_H__
#define __GST_MOZ_VIDEO_BUFFER_H__
#include <gst/gst.h>
#include "MediaDecoderReader.h"
namespace mozilla {
#define GST_TYPE_MOZ_VIDEO_BUFFER_DATA (gst_moz_video_buffer_data_get_type())
#define GST_IS_MOZ_VIDEO_BUFFER_DATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_VIDEO_BUFFER_DATA))
#define GST_TYPE_MOZ_VIDEO_BUFFER (gst_moz_video_buffer_get_type())
#define GST_IS_MOZ_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_VIDEO_BUFFER))
#define GST_IS_MOZ_VIDEO_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MOZ_VIDEO_BUFFER))
#define GST_MOZ_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MOZ_VIDEO_BUFFER, GstMozVideoBuffer))
typedef struct _GstMozVideoBuffer GstMozVideoBuffer;
typedef struct _GstMozVideoBufferClass GstMozVideoBufferClass;
class GstMozVideoBufferData;
struct _GstMozVideoBuffer {
GstBuffer buffer;
GstMozVideoBufferData* data;
};
struct _GstMozVideoBufferClass {
GstBufferClass buffer_class;
};
GType gst_moz_video_buffer_get_type(void);
GstMozVideoBuffer* gst_moz_video_buffer_new(void);
void gst_moz_video_buffer_set_data(GstMozVideoBuffer* buf, GstMozVideoBufferData* data);
GstMozVideoBufferData* gst_moz_video_buffer_get_data(const GstMozVideoBuffer* buf);
class GstMozVideoBufferData {
public:
GstMozVideoBufferData(layers::PlanarYCbCrImage* aImage) : mImage(aImage) {}
static void* Copy(void* aData) {
return new GstMozVideoBufferData(reinterpret_cast<GstMozVideoBufferData*>(aData)->mImage);
}
static void Free(void* aData) {
delete reinterpret_cast<GstMozVideoBufferData*>(aData);
}
nsRefPtr<layers::PlanarYCbCrImage> mImage;
};
GType gst_moz_video_buffer_data_get_type (void);
} // namespace mozilla
#endif /* __GST_MOZ_VIDEO_BUFFER_H__ */

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

@ -10,6 +10,7 @@
#include "MediaResource.h"
#include "GStreamerReader.h"
#include "GStreamerFormatHelper.h"
#include "GStreamerMozVideoBuffer.h"
#include "VideoUtils.h"
#include "mozilla/dom/TimeRanges.h"
#include "mozilla/Preferences.h"
@ -39,8 +40,6 @@ static const int SHORT_FILE_SIZE = 1024 * 1024;
// The default resource->Read() size when working in push mode
static const int DEFAULT_SOURCE_READ_SIZE = 50 * 1024;
G_DEFINE_BOXED_TYPE(BufferData, buffer_data, BufferData::Copy, BufferData::Free);
typedef enum {
GST_PLAY_FLAG_VIDEO = (1 << 0),
GST_PLAY_FLAG_AUDIO = (1 << 1),
@ -139,9 +138,7 @@ nsresult GStreamerReader::Init(MediaDecoderReader* aCloneDonor)
gst_pad_add_event_probe(sinkpad,
G_CALLBACK(&GStreamerReader::EventProbeCb), this);
gst_object_unref(sinkpad);
#if GST_VERSION_MICRO >= 36
gst_pad_set_bufferalloc_function(sinkpad, GStreamerReader::AllocateVideoBufferCb);
#endif
gst_pad_set_element_private(sinkpad, this);
mAudioSink = gst_parse_bin_from_description("capsfilter name=filter ! "
@ -532,15 +529,11 @@ bool GStreamerReader::DecodeVideoFrame(bool &aKeyFrameSkip,
return false;
nsRefPtr<PlanarYCbCrImage> image;
#if GST_VERSION_MICRO >= 36
const GstStructure* structure = gst_buffer_get_qdata(buffer,
g_quark_from_string("moz-reader-data"));
const GValue* value = gst_structure_get_value(structure, "image");
if (value) {
BufferData* data = reinterpret_cast<BufferData*>(g_value_get_boxed(value));
image = data->mImage;
}
#endif
GstMozVideoBufferData* bufferdata = reinterpret_cast<GstMozVideoBufferData*>
GST_IS_MOZ_VIDEO_BUFFER(buffer)?gst_moz_video_buffer_get_data(GST_MOZ_VIDEO_BUFFER(buffer)):nullptr;
if(bufferdata)
image = bufferdata->mImage;
if (!image) {
/* Ugh, upstream is not calling gst_pad_alloc_buffer(). Fallback to
@ -844,29 +837,18 @@ GstFlowReturn GStreamerReader::AllocateVideoBufferFull(GstPad* aPad,
nsRefPtr<PlanarYCbCrImage> image = dont_AddRef(img);
/* prepare a GstBuffer pointing to the underlying PlanarYCbCrImage buffer */
GstBuffer* buf = gst_buffer_new();
GstBuffer* buf = GST_BUFFER(gst_moz_video_buffer_new());
GST_BUFFER_SIZE(buf) = aSize;
/* allocate the actual YUV buffer */
GST_BUFFER_DATA(buf) = image->AllocateAndGetNewBuffer(aSize);
aImage = image;
#if GST_VERSION_MICRO >= 36
/* create a GBoxed handle to hold the image */
BufferData* data = new BufferData(image);
/* create a GstMozVideoBufferData to hold the image */
GstMozVideoBufferData* bufferdata = new GstMozVideoBufferData(image);
/* store it in a GValue so we can put it in a GstStructure */
GValue value = {0,};
g_value_init(&value, buffer_data_get_type());
g_value_take_boxed(&value, data);
/* store the value in the structure */
GstStructure* structure = gst_structure_new("moz-reader-data", nullptr);
gst_structure_take_value(structure, "image", &value);
/* and attach the structure to the buffer */
gst_buffer_set_qdata(buf, g_quark_from_string("moz-reader-data"), structure);
#endif
/* Attach bufferdata to our GstMozVideoBuffer, it will take care to free it */
gst_moz_video_buffer_set_data(GST_MOZ_VIDEO_BUFFER(buf), bufferdata);
*aBuf = buf;
return GST_FLOW_OK;

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

@ -153,21 +153,6 @@ private:
int fpsDen;
};
class BufferData {
public:
BufferData(layers::PlanarYCbCrImage* aImage) : mImage(aImage) {}
static void* Copy(void* aData) {
return new BufferData(reinterpret_cast<BufferData*>(aData)->mImage);
}
static void Free(void* aData) {
delete reinterpret_cast<BufferData*>(aData);
}
nsRefPtr<layers::PlanarYCbCrImage> mImage;
};
} // namespace mozilla
#endif

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

@ -18,6 +18,7 @@ CPPSRCS = \
GStreamerReader.cpp \
GStreamerDecoder.cpp \
GStreamerFormatHelper.cpp \
GStreamerMozVideoBuffer.cpp \
$(NULL)
FORCE_STATIC_LIB = 1

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

@ -21,6 +21,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioBufferSourceNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBuffer)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaybackRate)
if (tmp->Context()) {
// AudioNode's Unlink implementation disconnects us from the graph
// too, but we need to do this right here to make sure that
// UnregisterAudioBufferSourceNode can properly untangle us from
// the possibly connected PannerNodes.
tmp->DisconnectFromGraph();
tmp->Context()->UnregisterAudioBufferSourceNode(tmp);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode)
@ -304,12 +309,12 @@ public:
mSampleRate == IdealAudioRate());
}
void UpdateSampleRateIfNeeded(AudioNodeStream* aStream)
void UpdateSampleRateIfNeeded(AudioNodeStream* aStream, uint32_t aChannels)
{
if (mPlaybackRateTimeline.HasSimpleValue()) {
mPlaybackRate = mPlaybackRateTimeline.GetValue();
} else {
mPlaybackRate = mPlaybackRateTimeline.GetValueAtTime<TrackTicks>(aStream->GetCurrentPosition());
mPlaybackRate = mPlaybackRateTimeline.GetValueAtTime(aStream->GetCurrentPosition());
}
// Make sure the playback rate if something our resampler can work with.
@ -319,7 +324,7 @@ public:
uint32_t currentOutSampleRate, currentInSampleRate;
if (ShouldResample()) {
SpeexResamplerState* resampler = Resampler(mChannels);
SpeexResamplerState* resampler = Resampler(aChannels);
speex_resampler_get_rate(resampler, &currentInSampleRate, &currentOutSampleRate);
uint32_t finalSampleRate = ComputeFinalOutSampleRate();
if (currentOutSampleRate != finalSampleRate) {
@ -345,7 +350,7 @@ public:
// WebKit treats the playbackRate as a k-rate parameter in their code,
// despite the spec saying that it should be an a-rate parameter. We treat
// it as k-rate. Spec bug: https://www.w3.org/Bugs/Public/show_bug.cgi?id=21592
UpdateSampleRateIfNeeded(aStream);
UpdateSampleRateIfNeeded(aStream, channels);
uint32_t written = 0;
TrackTicks currentPosition = GetPosition(aStream);
@ -412,7 +417,6 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
, mOffset(0.0)
, mDuration(std::numeric_limits<double>::min())
, mPlaybackRate(new AudioParam(this, SendPlaybackRateToStream, 1.0f))
, mPannerNode(nullptr)
, mLoop(false)
, mStartCalled(false)
, mOffsetAndDurationRemembered(false)

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

@ -37,15 +37,6 @@ public:
{
return this;
}
void UnregisterPannerNode() {
mPannerNode = nullptr;
}
void RegisterPannerNode(PannerNode* aPannerNode) {
mPannerNode = aPannerNode;
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioBufferSourceNode, AudioNode)
@ -148,7 +139,6 @@ private:
double mDuration;
nsRefPtr<AudioBuffer> mBuffer;
nsRefPtr<AudioParam> mPlaybackRate;
PannerNode* mPannerNode;
SelfReference<AudioBufferSourceNode> mPlayingRef; // a reference to self while playing
bool mLoop;
bool mStartCalled;

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

@ -244,6 +244,7 @@ void
AudioContext::UnregisterAudioBufferSourceNode(AudioBufferSourceNode* aNode)
{
mAudioBufferSourceNodes.RemoveEntry(aNode);
UpdatePannerSource();
}
void
@ -258,13 +259,6 @@ AudioContext::UnregisterScriptProcessorNode(ScriptProcessorNode* aNode)
mScriptProcessorNodes.RemoveEntry(aNode);
}
static PLDHashOperator
UnregisterPannerNodeOn(nsPtrHashKey<AudioBufferSourceNode>* aEntry, void* aData)
{
aEntry->GetKey()->UnregisterPannerNode();
return PL_DHASH_NEXT;
}
static PLDHashOperator
FindConnectedSourcesOn(nsPtrHashKey<PannerNode>* aEntry, void* aData)
{
@ -275,7 +269,6 @@ FindConnectedSourcesOn(nsPtrHashKey<PannerNode>* aEntry, void* aData)
void
AudioContext::UpdatePannerSource()
{
mAudioBufferSourceNodes.EnumerateEntries(UnregisterPannerNodeOn, nullptr);
mPannerNodes.EnumerateEntries(FindConnectedSourcesOn, nullptr);
}

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

@ -13,14 +13,18 @@
namespace mozilla {
namespace dom {
static const uint32_t INVALID_PORT = 0xffffffff;
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper)
tmp->DisconnectFromGraph();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputNodes)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputParams)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputNodes)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputParams)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(AudioNode, nsDOMEventTargetHelper)
@ -59,21 +63,24 @@ AudioNode::~AudioNode()
{
MOZ_ASSERT(mInputNodes.IsEmpty());
MOZ_ASSERT(mOutputNodes.IsEmpty());
MOZ_ASSERT(mOutputParams.IsEmpty());
}
template <class InputNode>
static uint32_t
FindIndexOfNode(const nsTArray<AudioNode::InputNode>& aInputNodes, const AudioNode* aNode)
FindIndexOfNode(const nsTArray<InputNode>& aInputNodes, const AudioNode* aNode)
{
for (uint32_t i = 0; i < aInputNodes.Length(); ++i) {
if (aInputNodes[i].mInputNode == aNode) {
return i;
}
}
return nsTArray<AudioNode::InputNode>::NoIndex;
return nsTArray<InputNode>::NoIndex;
}
template <class InputNode>
static uint32_t
FindIndexOfNodeWithPorts(const nsTArray<AudioNode::InputNode>& aInputNodes, const AudioNode* aNode,
FindIndexOfNodeWithPorts(const nsTArray<InputNode>& aInputNodes, const AudioNode* aNode,
uint32_t aInputPort, uint32_t aOutputPort)
{
for (uint32_t i = 0; i < aInputNodes.Length(); ++i) {
@ -83,7 +90,7 @@ FindIndexOfNodeWithPorts(const nsTArray<AudioNode::InputNode>& aInputNodes, cons
return i;
}
}
return nsTArray<AudioNode::InputNode>::NoIndex;
return nsTArray<InputNode>::NoIndex;
}
void
@ -114,6 +121,16 @@ AudioNode::DisconnectFromGraph()
output->mInputNodes.RemoveElementAt(inputIndex);
}
while (!mOutputParams.IsEmpty()) {
uint32_t i = mOutputParams.Length() - 1;
nsRefPtr<AudioParam> output = mOutputParams[i].forget();
mOutputParams.RemoveElementAt(i);
uint32_t inputIndex = FindIndexOfNode(output->InputNodes(), this);
// It doesn't matter which one we remove, since we're going to remove all
// entries for this node anyway.
output->RemoveInputNode(inputIndex);
}
DestroyMediaStream();
}
@ -159,6 +176,40 @@ AudioNode::Connect(AudioNode& aDestination, uint32_t aOutput,
Context()->UpdatePannerSource();
}
void
AudioNode::Connect(AudioParam& aDestination, uint32_t aOutput,
ErrorResult& aRv)
{
if (aOutput >= NumberOfOutputs()) {
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
}
if (Context() != aDestination.GetParentObject()) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
if (FindIndexOfNodeWithPorts(aDestination.InputNodes(), this, INVALID_PORT, aOutput) !=
nsTArray<AudioNode::InputNode>::NoIndex) {
// connection already exists.
return;
}
mOutputParams.AppendElement(&aDestination);
InputNode* input = aDestination.AppendInputNode();
input->mInputNode = this;
input->mInputPort = INVALID_PORT;
input->mOutputPort = aOutput;
MediaStream* stream = aDestination.Stream();
MOZ_ASSERT(stream->AsProcessedStream());
ProcessedMediaStream* ps = static_cast<ProcessedMediaStream*>(stream);
// Setup our stream as an input to the AudioParam's stream
input->mStreamPort = ps->AllocateInputPort(mStream, MediaInputPort::FLAG_BLOCK_INPUT);
}
void
AudioNode::SendDoubleParameterToStream(uint32_t aIndex, double aValue)
{
@ -224,6 +275,21 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
}
}
for (int32_t i = mOutputParams.Length() - 1; i >= 0; --i) {
AudioParam* dest = mOutputParams[i];
for (int32_t j = dest->InputNodes().Length() - 1; j >= 0; --j) {
const InputNode& input = dest->InputNodes()[j];
if (input.mInputNode == this && input.mOutputPort == aOutput) {
dest->RemoveInputNode(j);
// Remove one instance of 'dest' from mOutputParams. There could be
// others, and it's not correct to remove them all since some of them
// could be for different output ports.
mOutputParams.RemoveElementAt(i);
break;
}
}
}
// This disconnection may have disconnected a panner and a source.
Context()->UpdatePannerSource();
}
@ -249,5 +315,11 @@ AudioNode::DestroyMediaStream()
}
}
void
AudioNode::RemoveOutputParam(AudioParam* aParam)
{
mOutputParams.RemoveElement(aParam);
}
}
}

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

@ -26,6 +26,7 @@ class ErrorResult;
namespace dom {
class AudioParam;
struct ThreeDPoint;
template<class T>
@ -108,6 +109,9 @@ public:
virtual void Connect(AudioNode& aDestination, uint32_t aOutput,
uint32_t aInput, ErrorResult& aRv);
virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
ErrorResult& aRv);
virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv);
// The following two virtual methods must be implemented by each node type
@ -153,6 +157,7 @@ public:
AudioNode* mInputNode;
nsRefPtr<MediaInputPort> mStreamPort;
// The index of the input port this node feeds into.
// This is not used for connections to AudioParams.
uint32_t mInputPort;
// The index of the output port this node comes out of.
uint32_t mOutputPort;
@ -165,7 +170,10 @@ public:
return mInputNodes;
}
void RemoveOutputParam(AudioParam* aParam);
private:
friend class AudioBufferSourceNode;
// This could possibly delete 'this'.
void DisconnectFromGraph();
@ -197,6 +205,12 @@ private:
// exact matching entry, since mOutputNodes doesn't include the port
// identifiers and the same node could be connected on multiple ports.
nsTArray<nsRefPtr<AudioNode> > mOutputNodes;
// For every mOutputParams entry, there is a corresponding entry in
// AudioParam::mInputNodes of the mOutputParams entry. We won't necessarily be
// able to identify the exact matching entry, since mOutputParams doesn't
// include the port identifiers and the same node could be connected on
// multiple ports.
nsTArray<nsRefPtr<AudioParam> > mOutputParams;
uint32_t mChannelCount;
ChannelCountMode mChannelCountMode;
ChannelInterpretation mChannelInterpretation;

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

@ -9,11 +9,36 @@
#include "nsIDOMWindow.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/AudioParamBinding.h"
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(AudioParam, mNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioParam)
tmp->DisconnectFromGraphAndDestroyStream();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioParam)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AudioParam)
NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(AudioParam)
NS_IMETHODIMP_(nsrefcnt)
AudioParam::Release()
{
if (mRefCnt.get() == 1) {
// We are about to be deleted, disconnect the object from the graph before
// the derived type is destroyed.
DisconnectFromGraphAndDestroyStream();
}
NS_IMPL_CC_NATIVE_RELEASE_BODY(AudioParam)
}
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioParam, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioParam, Release)
@ -31,6 +56,7 @@ AudioParam::AudioParam(AudioNode* aNode,
AudioParam::~AudioParam()
{
MOZ_ASSERT(mInputNodes.IsEmpty());
}
JSObject*
@ -39,6 +65,81 @@ AudioParam::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
return AudioParamBinding::Wrap(aCx, aScope, this);
}
void
AudioParam::DisconnectFromGraphAndDestroyStream()
{
// Addref this temporarily so the refcount bumping below doesn't destroy us
// prematurely
nsRefPtr<AudioParam> kungFuDeathGrip = this;
while (!mInputNodes.IsEmpty()) {
uint32_t i = mInputNodes.Length() - 1;
nsRefPtr<AudioNode> input = mInputNodes[i].mInputNode;
mInputNodes.RemoveElementAt(i);
input->RemoveOutputParam(this);
}
if (mNodeStreamPort) {
mNodeStreamPort->Destroy();
mNodeStreamPort = nullptr;
}
if (mStream) {
mStream->Destroy();
mStream = nullptr;
}
}
MediaStream*
AudioParam::Stream()
{
if (mStream) {
return mStream;
}
AudioNodeEngine* engine = new AudioNodeEngine(nullptr);
nsRefPtr<AudioNodeStream> stream = mNode->Context()->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
// Force the input to have only one channel, and make it down-mix using
// the speaker rules if needed.
stream->SetChannelMixingParametersImpl(1, ChannelCountMode::Explicit, ChannelInterpretation::Speakers);
// Mark as an AudioParam helper stream
stream->SetAudioParamHelperStream();
mStream = stream.forget();
// Setup the AudioParam's stream as an input to the owner AudioNode's stream
MediaStream* nodeStream = mNode->Stream();
MOZ_ASSERT(nodeStream->AsProcessedStream());
ProcessedMediaStream* ps = static_cast<ProcessedMediaStream*>(nodeStream);
mNodeStreamPort = ps->AllocateInputPort(mStream, MediaInputPort::FLAG_BLOCK_INPUT);
// Let the MSG's copy of AudioParamTimeline know about the change in the stream
mCallback(mNode);
return mStream;
}
float
AudioParamTimeline::AudioNodeInputValue(size_t aCounter) const
{
MOZ_ASSERT(mStream);
// If we have a chunk produced by the AudioNode inputs to the AudioParam,
// get its value now. We use aCounter to tell us which frame of the last
// AudioChunk to look at.
float audioNodeInputValue = 0.0f;
const AudioChunk& lastAudioNodeChunk =
static_cast<AudioNodeStream*>(mStream.get())->LastChunk();
if (!lastAudioNodeChunk.IsNull()) {
MOZ_ASSERT(lastAudioNodeChunk.GetDuration() == WEBAUDIO_BLOCK_SIZE);
audioNodeInputValue =
static_cast<const float*>(lastAudioNodeChunk.mChannelData[0])[aCounter];
}
return audioNodeInputValue;
}
}
}

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

@ -37,7 +37,8 @@ public:
float aDefaultValue);
virtual ~AudioParam();
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AudioParam)
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioParam)
AudioContext* GetParentObject() const
@ -104,10 +105,44 @@ public:
return mDefaultValue;
}
AudioNode* Node() const
{
return mNode;
}
const nsTArray<AudioNode::InputNode>& InputNodes() const
{
return mInputNodes;
}
void RemoveInputNode(uint32_t aIndex)
{
mInputNodes.RemoveElementAt(aIndex);
}
AudioNode::InputNode* AppendInputNode()
{
return mInputNodes.AppendElement();
}
void DisconnectFromGraphAndDestroyStream();
// May create the stream if it doesn't exist
MediaStream* Stream();
protected:
nsCycleCollectingAutoRefCnt mRefCnt;
NS_DECL_OWNINGTHREAD
private:
nsRefPtr<AudioNode> mNode;
// For every InputNode, there is a corresponding entry in mOutputParams of the
// InputNode's mInputNode.
nsTArray<AudioNode::InputNode> mInputNodes;
CallbackType mCallback;
const float mDefaultValue;
// The input port used to connect the AudioParam's stream to its node's stream
nsRefPtr<MediaInputPort> mNodeStreamPort;
};
}

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

@ -7,17 +7,66 @@
#ifndef AudioParamTimeline_h_
#define AudioParamTimeline_h_
// This header is intended to make it possible to use AudioParamTimeline
// from multiple places without dealing with #include hell!
#include "AudioEventTimeline.h"
#include "mozilla/ErrorResult.h"
#include "nsAutoPtr.h"
#include "MediaStreamGraph.h"
#include "AudioSegment.h"
namespace mozilla {
namespace dom {
typedef AudioEventTimeline<ErrorResult> AudioParamTimeline;
// This helper class is used to represent the part of the AudioParam
// class that gets sent to AudioNodeEngine instances. In addition to
// AudioEventTimeline methods, it holds a pointer to an optional
// MediaStream which represents the AudioNode inputs to the AudioParam.
// This MediaStream is managed by the AudioParam subclass on the main
// thread, and can only be obtained from the AudioNodeEngine instances
// consuming this class.
class AudioParamTimeline : public AudioEventTimeline<ErrorResult>
{
typedef AudioEventTimeline<ErrorResult> BaseClass;
public:
explicit AudioParamTimeline(float aDefaultValue)
: BaseClass(aDefaultValue)
{
}
MediaStream* Stream() const
{
return mStream;
}
bool HasSimpleValue() const
{
return BaseClass::HasSimpleValue() && !mStream;
}
// Get the value of the AudioParam at time aTime + aCounter.
// aCounter here is an offset to aTime if we try to get the value in ticks,
// otherwise it should always be zero. aCounter is meant to be used when
// getting the value of an a-rate AudioParam for each tick inside an
// AudioNodeEngine implementation.
template<class TimeType>
float GetValueAtTime(TimeType aTime, size_t aCounter = 0) const
{
MOZ_ASSERT(aCounter < WEBAUDIO_BLOCK_SIZE);
MOZ_ASSERT(!aCounter || !HasSimpleValue());
// Mix the value of the AudioParam itself with that of the AudioNode inputs.
return BaseClass::GetValueAtTime(static_cast<TimeType>(aTime + aCounter)) +
(mStream ? AudioNodeInputValue(aCounter) : 0.0f);
}
private:
float AudioNodeInputValue(size_t aCounter) const;
protected:
// This is created lazily when needed.
nsRefPtr<MediaStream> mStream;
};
}
}

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

@ -185,7 +185,7 @@ public:
TrackTicks tick = aStream->GetCurrentPosition();
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
computedDelay[counter] = std::max(0.0, std::min(mMaxDelay,
double(mDelay.GetValueAtTime<TrackTicks>(tick + counter))));
double(mDelay.GetValueAtTime(tick, counter))));
}
}

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

@ -76,8 +76,8 @@ public:
// XXX we need to add a method to AudioEventTimeline to compute this buffer directly.
float computedGain[WEBAUDIO_BLOCK_SIZE];
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
TrackTicks tick = aStream->GetCurrentPosition() + counter;
computedGain[counter] = mGain.GetValueAtTime<TrackTicks>(tick) * aInput.mVolume;
TrackTicks tick = aStream->GetCurrentPosition();
computedGain[counter] = mGain.GetValueAtTime(tick, counter) * aInput.mVolume;
}
// Apply the gain to the output buffer

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

@ -482,9 +482,6 @@ PannerNode::FindConnectedSources()
mSources.Clear();
std::set<AudioNode*> cycleSet;
FindConnectedSources(this, mSources, cycleSet);
for (unsigned i = 0; i < mSources.Length(); i++) {
mSources[i]->RegisterPannerNode(this);
}
}
void

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

@ -46,6 +46,15 @@ public:
}
}
virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
ErrorResult& aRv) MOZ_OVERRIDE
{
AudioNode::Connect(aDestination, aOutput, aRv);
if (!aRv.Failed()) {
mPlayingRef.Take(this);
}
}
virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv) MOZ_OVERRIDE
{
AudioNode::Disconnect(aOutput, aRv);

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

@ -20,11 +20,14 @@ MOCHITEST_FILES := \
test_bug866570.html \
test_bug866737.html \
test_bug867089.html \
test_bug867203.html \
test_analyserNode.html \
test_AudioBuffer.html \
test_AudioContext.html \
test_AudioListener.html \
test_AudioParam.html \
test_audioParamExponentialRamp.html \
test_audioParamLinearRamp.html \
test_audioBufferSourceNode.html \
test_audioBufferSourceNodeLazyLoopParam.html \
test_audioBufferSourceNodeLoop.html \
@ -40,6 +43,7 @@ MOCHITEST_FILES := \
test_dynamicsCompressorNode.html \
test_gainNode.html \
test_mixingRules.html \
test_nodeToParamConnection.html \
test_pannerNode.html \
test_scriptProcessorNode.html \
test_scriptProcessorNodeChannelCount.html \

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

@ -0,0 +1,63 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test AudioParam.exponentialRampToValue</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 context = new AudioContext();
var V0 = 0.1;
var V1 = 0.9;
var T0 = 0;
var T1 = 2048 / context.sampleRate;
var sourceBuffer = context.createBuffer(1, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
sourceBuffer.getChannelData(0)[i] = 1;
}
var expectedBuffer = context.createBuffer(1, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
var t = i / context.sampleRate;
expectedBuffer.getChannelData(0)[i] = V0 * Math.pow(V1 / V0, (t - T0) / (T1 - T0));
}
var destination = context.destination;
var source = context.createBufferSource();
source.buffer = sourceBuffer;
var gain = context.createGain();
gain.gain.setValueAtTime(V0, 0);
gain.gain.exponentialRampToValueAtTime(V1, 2048/context.sampleRate);
var sp = context.createScriptProcessor(2048, 1);
source.connect(gain);
gain.connect(sp);
sp.connect(destination);
source.start(0);
sp.onaudioprocess = function(e) {
is(e.inputBuffer.numberOfChannels, 1, "Correct input channel count");
compareBuffers(e.inputBuffer.getChannelData(0), expectedBuffer.getChannelData(0));
sp.onaudioprocess = null;
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
};
});
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,63 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test AudioParam.linearRampToValue</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 context = new AudioContext();
var V0 = 0.1;
var V1 = 0.9;
var T0 = 0;
var T1 = 2048 / context.sampleRate;
var sourceBuffer = context.createBuffer(1, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
sourceBuffer.getChannelData(0)[i] = 1;
}
var expectedBuffer = context.createBuffer(1, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
var t = i / context.sampleRate;
expectedBuffer.getChannelData(0)[i] = V0 + (V1 - V0) * ((t - T0) / (T1 - T0));
}
var destination = context.destination;
var source = context.createBufferSource();
source.buffer = sourceBuffer;
var gain = context.createGain();
gain.gain.setValueAtTime(V0, 0);
gain.gain.linearRampToValueAtTime(V1, 2048/context.sampleRate);
var sp = context.createScriptProcessor(2048, 1);
source.connect(gain);
gain.connect(sp);
sp.connect(destination);
source.start(0);
sp.onaudioprocess = function(e) {
is(e.inputBuffer.numberOfChannels, 1, "Correct input channel count");
compareBuffers(e.inputBuffer.getChannelData(0), expectedBuffer.getChannelData(0));
sp.onaudioprocess = null;
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
};
});
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,36 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Crashtest for bug 867203</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
var ctx = new AudioContext();
var panner1 = ctx.createPanner();
panner1.setVelocity(1, 1, 1);
ctx.listener.setVelocity(1, 1, 1);
(function() {
ctx.createBufferSource().connect(panner1);
})();
SpecialPowers.forceGC();
SpecialPowers.forceCC();
ctx.createPanner();
ok(true, "We did not crash.");
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,69 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test connecting an AudioNode to an AudioParam</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 context = new AudioContext();
var buffer = context.createBuffer(2, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
for (var j = 0; j < 2; ++j) {
buffer.getChannelData(j)[i] = Math.sin(440 * 2 * (j + 1) * Math.PI * i / context.sampleRate);
}
}
var sourceBuffer = context.createBuffer(2, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
sourceBuffer.getChannelData(0)[i] = 1;
sourceBuffer.getChannelData(1)[i] = -1;
}
var expectedBuffer = context.createBuffer(2, 2048, context.sampleRate);
for (var i = 0; i < 2048; ++i) {
expectedBuffer.getChannelData(0)[i] = 1 + (buffer.getChannelData(0)[i] + buffer.getChannelData(1)[i]) / 2;
expectedBuffer.getChannelData(1)[i] = -(1 + (buffer.getChannelData(0)[i] + buffer.getChannelData(1)[i]) / 2);
}
var destination = context.destination;
var paramSource = context.createBufferSource();
paramSource.buffer = buffer;
var source = context.createBufferSource();
source.buffer = sourceBuffer;
var gain = context.createGain();
paramSource.connect(gain.gain);
source.connect(gain);
var sp = context.createScriptProcessor(2048);
gain.connect(sp);
sp.connect(destination);
paramSource.start(0);
source.start(0);
sp.onaudioprocess = function(e) {
is(e.inputBuffer.numberOfChannels, 2, "Correct input channel count");
compareBuffers(e.inputBuffer.getChannelData(0), expectedBuffer.getChannelData(0));
compareBuffers(e.inputBuffer.getChannelData(1), expectedBuffer.getChannelData(1));
sp.onaudioprocess = null;
SpecialPowers.clearUserPref("media.webaudio.enabled");
SimpleTest.finish();
};
});
</script>
</pre>
</body>
</html>

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

@ -24,7 +24,7 @@ function expectTypeError(func) {
}
function fuzzyCompare(a, b) {
return Math.abs(a - b) < 5e-5;
return Math.abs(a - b) < 9e-3;
}
function compareBuffers(buf1, buf2,

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

@ -8,8 +8,8 @@ MODULE = 'content'
XPIDL_MODULE = 'dom_webspeechrecognition'
XPIDL_SOURCES = [
'nsIDOMSpeechRecognitionEvent.idl',
'nsIDOMSpeechRecognitionError.idl',
'nsIDOMSpeechRecognitionEvent.idl',
'nsISpeechRecognitionService.idl'
]

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

@ -15,17 +15,16 @@ EXPORTS += [
]
EXPORTS.mozilla.dom += [
'nsSVGAnimatedTransformList.h',
'SVGAElement.h',
'SVGAltGlyphElement.h',
'SVGAngle.h',
'SVGAnimateElement.h',
'SVGAnimateMotionElement.h',
'SVGAnimateTransformElement.h',
'SVGAnimatedAngle.h',
'SVGAnimatedBoolean.h',
'SVGAnimatedLength.h',
'SVGAnimatedTransformList.h',
'SVGAnimateElement.h',
'SVGAnimateMotionElement.h',
'SVGAnimateTransformElement.h',
'SVGAnimationElement.h',
'SVGCircleElement.h',
'SVGClipPathElement.h',
@ -58,38 +57,39 @@ EXPORTS.mozilla.dom += [
'SVGGElement.h',
'SVGGradientElement.h',
'SVGGraphicsElement.h',
'SVGImageElement.h',
'SVGIRect.h',
'SVGImageElement.h',
'SVGLineElement.h',
'SVGMPathElement.h',
'SVGMarkerElement.h',
'SVGMaskElement.h',
'SVGMatrix.h',
'SVGMetadataElement.h',
'SVGMPathElement.h',
'SVGPathElement.h',
'SVGPatternElement.h',
'SVGPolygonElement.h',
'SVGPolylineElement.h',
'SVGRectElement.h',
'SVGRect.h',
'SVGRectElement.h',
'SVGSVGElement.h',
'SVGScriptElement.h',
'SVGSetElement.h',
'SVGStopElement.h',
'SVGStyleElement.h',
'SVGSVGElement.h',
'SVGSwitchElement.h',
'SVGSymbolElement.h',
'SVGTSpanElement.h',
'SVGTests.h',
'SVGTextContentElement.h',
'SVGTextElement.h',
'SVGTextPathElement.h',
'SVGTextPositioningElement.h',
'SVGTitleElement.h',
'SVGTransformableElement.h',
'SVGTransform.h',
'SVGTSpanElement.h',
'SVGTransformableElement.h',
'SVGUseElement.h',
'SVGViewElement.h',
'SVGZoomEvent.h',
'nsSVGAnimatedTransformList.h',
]

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

@ -1063,10 +1063,10 @@ FindObjectClass(JSContext* cx, JSObject* aGlobalObject)
{
NS_ASSERTION(!sObjectClass,
"Double set of sObjectClass");
JSObject *obj, *proto = aGlobalObject;
JS::Rooted<JSObject*> obj(cx), proto(cx, aGlobalObject);
do {
obj = proto;
js::GetObjectProto(cx, obj, &proto);
js::GetObjectProto(cx, obj, proto.address());
} while (proto);
sObjectClass = js::GetObjectJSClass(obj);
@ -1206,7 +1206,7 @@ WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
// implement nsWrapperCache, and nativeWrapperCache must be |native|'s
// nsWrapperCache.
static inline nsresult
WrapNativeParent(JSContext *cx, JSObject *scope, nsISupports *native,
WrapNativeParent(JSContext *cx, JS::Handle<JSObject*> scope, nsISupports *native,
nsWrapperCache *nativeWrapperCache, JSObject **parentObj)
{
// In the common case, |native| is a wrapper cache with an existing wrapper
@ -1217,7 +1217,7 @@ WrapNativeParent(JSContext *cx, JSObject *scope, nsISupports *native,
cache == nativeWrapperCache, "What happened here?");
#endif
JSObject* obj = nativeWrapperCache->GetWrapper();
JS::Rooted<JSObject*> obj(cx, nativeWrapperCache->GetWrapper());
if (obj) {
#ifdef DEBUG
jsval debugVal;
@ -1230,16 +1230,16 @@ WrapNativeParent(JSContext *cx, JSObject *scope, nsISupports *native,
return NS_OK;
}
jsval v;
nsresult rv = WrapNative(cx, scope, native, nativeWrapperCache, false, &v);
JS::Rooted<JS::Value> v(cx);
nsresult rv = WrapNative(cx, scope, native, nativeWrapperCache, false, v.address());
NS_ENSURE_SUCCESS(rv, rv);
*parentObj = JSVAL_TO_OBJECT(v);
*parentObj = v.toObjectOrNull();
return NS_OK;
}
template<class P>
static inline nsresult
WrapNativeParent(JSContext *cx, JSObject *scope, P *parent,
WrapNativeParent(JSContext *cx, JS::Handle<JSObject*> scope, P *parent,
JSObject **parentObj)
{
return WrapNativeParent(cx, scope, ToSupports(parent), parent, parentObj);
@ -2658,11 +2658,11 @@ nsresult
nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *obj,
JSObject **objp)
{
JSObject *global = ::JS_GetGlobalForObject(cx, obj);
JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, obj));
jsval val;
JS::Rooted<JS::Value> val(cx);
JSAutoRequest ar(cx);
if (!::JS_LookupProperty(cx, global, mData->mName, &val)) {
if (!::JS_LookupProperty(cx, global, mData->mName, val.address())) {
return NS_ERROR_UNEXPECTED;
}
@ -2731,9 +2731,9 @@ nsDOMClassInfo::CheckAccess(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
if ((mode_type == JSACC_WATCH || mode_type == JSACC_PROTO) && sSecMan) {
nsresult rv;
JSObject *real_obj;
JS::Rooted<JSObject*> real_obj(cx);
if (wrapper) {
rv = wrapper->GetJSObject(&real_obj);
rv = wrapper->GetJSObject(real_obj.address());
NS_ENSURE_SUCCESS(rv, rv);
}
else {
@ -2837,7 +2837,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
NS_IMETHODIMP
nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
{
uint32_t flags = (mData->mScriptableFlags & DONT_ENUM_STATIC_PROPS)
? 0
@ -2848,6 +2848,7 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
count++;
}
JS::Rooted<JSObject*> proto(cx, aProto);
if (!xpc::DOM_DefineQuickStubs(cx, proto, flags, count, mData->mInterfaces)) {
JS_ClearPendingException(cx);
}
@ -2893,7 +2894,7 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
// HTMLElement.prototype.foopy = function () { ... } Now, calling
// document.body.foopy() needs to ensure that looking up foopy on
// document.body's prototype will find the right function.
JSObject *global = ::JS_GetGlobalForObject(cx, proto);
JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, proto));
// Only do this if the global object is a window.
// XXX Is there a better way to check this?
@ -3141,9 +3142,9 @@ ChildWindowGetter(JSContext *cx, JSHandleObject obj, JSHandleId id,
return true;
// Wrap the child for JS.
jsval v;
JS::Rooted<JS::Value> v(cx);
nsresult rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), child,
/* aAllowWrapping = */ true, &v);
/* aAllowWrapping = */ true, v.address());
NS_ENSURE_SUCCESS(rv, false);
vp.set(v);
return true;
@ -3198,8 +3199,8 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
}
}
JSObject *proto;
if (!::JS_GetPrototype(cx, obj, &proto)) {
JS::Rooted<JSObject*> proto(cx);
if (!::JS_GetPrototype(cx, obj, proto.address())) {
return JS_FALSE;
}
JSBool hasProp;
@ -3235,13 +3236,13 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
}
if (result) {
jsval v;
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, result, cache, true, &v,
nsresult rv = WrapNative(cx, obj, result, cache, true, v.address(),
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, JS_FALSE);
if (!JS_WrapValue(cx, &v) ||
if (!JS_WrapValue(cx, v.address()) ||
!JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub, JS_StrictPropertyStub, 0)) {
return JS_FALSE;
}
@ -3256,12 +3257,12 @@ nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
JSBool
nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
{
JSObject *proto;
JS::Rooted<JSObject*> proto(cx);
JSAutoRequest ar(cx);
for (;;) {
if (!::JS_GetPrototype(cx, obj, &proto)) {
if (!::JS_GetPrototype(cx, obj, proto.address())) {
return JS_FALSE;
}
if (!proto) {
@ -3270,8 +3271,8 @@ nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
if (JS_GetClass(proto) == &sGlobalScopePolluterClass) {
JSObject *proto_proto;
if (!::JS_GetPrototype(cx, proto, &proto_proto)) {
JS::Rooted<JSObject*> proto_proto(cx);
if (!::JS_GetPrototype(cx, proto, proto_proto.address())) {
return JS_FALSE;
}
@ -3290,22 +3291,22 @@ nsWindowSH::InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj)
// static
nsresult
nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JSObject *obj)
nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JS::Handle<JSObject*> obj)
{
JSAutoRequest ar(cx);
JSObject *gsp = ::JS_NewObjectWithUniqueType(cx, &sGlobalScopePolluterClass, nullptr, obj);
JS::Rooted<JSObject*> gsp(cx, ::JS_NewObjectWithUniqueType(cx, &sGlobalScopePolluterClass, nullptr, obj));
if (!gsp) {
return NS_ERROR_OUT_OF_MEMORY;
}
JSObject *o = obj, *proto;
JS::Rooted<JSObject*> o(cx, obj), proto(cx);
// Find the place in the prototype chain where we want this global
// scope polluter (right before Object.prototype).
for (;;) {
if (!::JS_GetPrototype(cx, o, &proto)) {
if (!::JS_GetPrototype(cx, o, proto.address())) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (!proto) {
@ -3353,8 +3354,9 @@ ResolveGlobalName(const nsAString& aName, void* aClosure)
NS_IMETHODIMP
nsWindowSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, bool *_retval)
JSObject *aObj, bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
if (!xpc::WrapperFactory::IsXrayWrapper(obj)) {
*_retval = JS_EnumerateStandardClasses(cx, obj);
if (!*_retval) {
@ -3390,8 +3392,9 @@ FindConstructorFunc(const nsDOMClassInfoData *aDOMClassInfoData)
static nsresult
BaseStubConstructor(nsIWeakReference* aWeakOwner,
const nsGlobalNameStruct *name_struct, JSContext *cx,
JSObject *obj, unsigned argc, jsval *argv, jsval *rval)
JSObject *aObj, unsigned argc, jsval *argv, jsval *rval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
MOZ_ASSERT(obj);
nsresult rv;
@ -3440,8 +3443,8 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
} else {
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(native);
JSObject* object = nullptr;
wrappedJS->GetJSObject(&object);
JS::Rooted<JSObject*> object(cx);
wrappedJS->GetJSObject(object.address());
if (!object) {
return NS_ERROR_UNEXPECTED;
}
@ -3452,9 +3455,9 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
JSAutoRequest ar(cx);
JSAutoCompartment ac(cx, object);
JS::Value thisValue = JSVAL_VOID;
JS::Value funval;
if (!JS_GetProperty(cx, object, "constructor", &funval) || !funval.isObject()) {
JS::Rooted<JS::Value> thisValue(cx, JS::UndefinedValue());
JS::Rooted<JS::Value> funval(cx);
if (!JS_GetProperty(cx, object, "constructor", funval.address()) || !funval.isObject()) {
return NS_ERROR_UNEXPECTED;
}
@ -3463,7 +3466,7 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
thisValue.setObject(*object);
{
JSObject* thisObject = &thisValue.toObject();
JS::Rooted<JSObject*> thisObject(cx, &thisValue.toObject());
// wrap parameters in the target compartment
// we also pass in the calling window as the first argument
@ -3500,7 +3503,7 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
}
static nsresult
DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
DefineInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj, const nsIID *aIID)
{
nsCOMPtr<nsIInterfaceInfoManager>
iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
@ -3767,7 +3770,7 @@ public:
return ok ? NS_OK : NS_ERROR_UNEXPECTED;
}
nsresult ResolveInterfaceConstants(JSContext *cx, JSObject *obj);
nsresult ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj);
private:
const nsGlobalNameStruct *GetNameStruct()
@ -3934,7 +3937,7 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
return NS_OK;
}
JSObject *dom_obj = JSVAL_TO_OBJECT(v);
JS::Rooted<JSObject*> dom_obj(cx, v.toObjectOrNull());
NS_ASSERTION(dom_obj, "nsDOMConstructor::HasInstance couldn't get object");
// This might not be the right object, if there are wrappers. Unwrap if we can.
@ -3957,8 +3960,8 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
if (!name_struct) {
// This isn't a normal DOM object, see if this constructor lives on its
// prototype chain.
jsval val;
if (!JS_GetProperty(cx, obj, "prototype", &val)) {
JS::Rooted<JS::Value> val(cx);
if (!JS_GetProperty(cx, obj, "prototype", val.address())) {
return NS_ERROR_UNEXPECTED;
}
@ -3966,11 +3969,11 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
return NS_OK;
}
JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
JS::Rooted<JSObject*> dot_prototype(cx, val.toObjectOrNull());
JSObject *proto = dom_obj;
JS::Rooted<JSObject*> proto(cx, dom_obj);
for (;;) {
if (!JS_GetPrototype(cx, proto, &proto)) {
if (!JS_GetPrototype(cx, proto, proto.address())) {
return NS_ERROR_UNEXPECTED;
}
if (!proto) {
@ -4091,7 +4094,7 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
}
nsresult
nsDOMConstructor::ResolveInterfaceConstants(JSContext *cx, JSObject *obj)
nsDOMConstructor::ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj)
{
const nsGlobalNameStruct *class_name_struct = GetNameStruct();
if (!class_name_struct)
@ -4188,9 +4191,9 @@ GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
aProto);
NS_ENSURE_SUCCESS(rv, rv);
JSObject *proto_obj;
(*aProto)->GetJSObject(&proto_obj);
if (!JS_WrapObject(cx, &proto_obj)) {
JS::Rooted<JSObject*> proto_obj(cx);
(*aProto)->GetJSObject(proto_obj.address());
if (!JS_WrapObject(cx, proto_obj.address())) {
return NS_ERROR_FAILURE;
}
@ -4219,10 +4222,10 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval v;
JS::Rooted<JS::Value> v(cx);
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
false, &v, getter_AddRefs(holder));
false, v.address(), getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
if (install) {
@ -4230,8 +4233,8 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
}
JSObject *class_obj;
holder->GetJSObject(&class_obj);
JS::Rooted<JSObject*> class_obj(cx);
holder->GetJSObject(class_obj.address());
NS_ASSERTION(class_obj, "The return value lied");
const nsIID *primary_iid = &NS_GET_IID(nsISupports);
@ -4309,20 +4312,20 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
}
{
JSObject *winobj = aWin->FastGetGlobalJSObject();
JS::Rooted<JSObject*> winobj(cx, aWin->FastGetGlobalJSObject());
JSObject *proto = nullptr;
JS::Rooted<JSObject*> proto(cx);
if (class_parent_name) {
JSAutoCompartment ac(cx, winobj);
JS::Value val;
if (!JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), &val)) {
JS::Rooted<JS::Value> val(cx);
if (!JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), val.address())) {
return NS_ERROR_UNEXPECTED;
}
if (val.isObject()) {
if (!JS_LookupProperty(cx, &val.toObject(), "prototype", &val)) {
if (!JS_LookupProperty(cx, &val.toObject(), "prototype", val.address())) {
return NS_ERROR_UNEXPECTED;
}
@ -4334,15 +4337,15 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
if (dot_prototype) {
JSAutoCompartment ac(cx, dot_prototype);
JSObject *xpc_proto_proto;
if (!::JS_GetPrototype(cx, dot_prototype, &xpc_proto_proto)) {
JS::Rooted<JSObject*> xpc_proto_proto(cx);
if (!::JS_GetPrototype(cx, dot_prototype, xpc_proto_proto.address())) {
return NS_ERROR_UNEXPECTED;
}
if (proto &&
(!xpc_proto_proto ||
JS_GetClass(xpc_proto_proto) == sObjectClass)) {
if (!JS_WrapObject(cx, &proto) ||
if (!JS_WrapObject(cx, proto.address()) ||
!JS_SetPrototype(cx, dot_prototype, proto)) {
return NS_ERROR_UNEXPECTED;
}
@ -4365,7 +4368,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
JSAutoCompartment ac(cx, class_obj);
// Per ECMA, the prototype property is {DontEnum, DontDelete, ReadOnly}
if (!JS_WrapValue(cx, &v) ||
if (!JS_WrapValue(cx, v.address()) ||
!JS_DefineProperty(cx, class_obj, "prototype", v,
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT | JSPROP_READONLY)) {
@ -4463,7 +4466,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
}
bool enabled;
JSObject* interfaceObject = define(cx, global, id, &enabled);
JS::Rooted<JSObject*> interfaceObject(cx, define(cx, global, id, &enabled));
if (enabled) {
if (!interfaceObject) {
return NS_ERROR_FAILURE;
@ -4472,7 +4475,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
if (defineOnXray) {
// This really should be handled by the Xray for the window.
ac.destroy();
if (!JS_WrapObject(cx, &interfaceObject) ||
if (!JS_WrapObject(cx, interfaceObject.address()) ||
!JS_DefinePropertyById(cx, obj, id,
JS::ObjectValue(*interfaceObject), JS_PropertyStub,
JS_StrictPropertyStub, 0)) {
@ -4499,16 +4502,16 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval v;
JS::Rooted<JS::Value> v(cx);
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
false, &v, getter_AddRefs(holder));
false, v.address(), getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
rv = constructor->Install(cx, obj, v);
NS_ENSURE_SUCCESS(rv, rv);
JSObject *class_obj;
holder->GetJSObject(&class_obj);
JS::Rooted<JSObject*> class_obj(cx);
holder->GetJSObject(class_obj.address());
NS_ASSERTION(class_obj, "The return value lied");
// ... and define the constants from the DOM interface on that
@ -4536,8 +4539,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
getter_AddRefs(proto_holder));
if (NS_SUCCEEDED(rv) && obj != aWin->GetGlobalJSObject()) {
JSObject* dot_prototype;
rv = proto_holder->GetJSObject(&dot_prototype);
JS::Rooted<JSObject*> dot_prototype(cx);
rv = proto_holder->GetJSObject(dot_prototype.address());
NS_ENSURE_SUCCESS(rv, rv);
const nsDOMClassInfoData *ci_data;
@ -4603,10 +4606,10 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
getter_AddRefs(constructor));
NS_ENSURE_SUCCESS(rv, rv);
jsval val;
JS::Rooted<JS::Value> val(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, constructor, &NS_GET_IID(nsIDOMDOMConstructor),
false, &val, getter_AddRefs(holder));
false, val.address(), getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
rv = constructor->Install(cx, obj, val);
@ -4628,12 +4631,12 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
jsval prop_val = JSVAL_VOID; // Property value.
JS::Rooted<JS::Value> prop_val(cx, JS::UndefinedValue()); // Property value.
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
if (gpi) {
rv = gpi->Init(aWin, &prop_val);
rv = gpi->Init(aWin, prop_val.address());
NS_ENSURE_SUCCESS(rv, rv);
}
@ -4649,13 +4652,13 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
scope = aWin->GetGlobalJSObject();
}
rv = WrapNative(cx, scope, native, true, &prop_val,
rv = WrapNative(cx, scope, native, true, prop_val.address(),
getter_AddRefs(holder));
}
NS_ENSURE_SUCCESS(rv, rv);
if (!JS_WrapValue(cx, &prop_val)) {
if (!JS_WrapValue(cx, prop_val.address())) {
return NS_ERROR_UNEXPECTED;
}
@ -4717,7 +4720,7 @@ LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
NS_ENSURE_SUCCESS(rv, rv);
// Grab the value we're being set to before we stomp on |vp|
JSString *val = ::JS_ValueToString(cx, *vp);
JS::Rooted<JSString*> val(cx, ::JS_ValueToString(cx, *vp));
NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
// Make sure |val| stays alive below
@ -4821,14 +4824,14 @@ DefineComponentsShim(JSContext *cx, JS::HandleObject global)
Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);
// Create a fake Components object.
JSObject *components = JS_NewObject(cx, nullptr, nullptr, global);
JS::Rooted<JSObject*> components(cx, JS_NewObject(cx, nullptr, nullptr, global));
NS_ENSURE_TRUE(components, NS_ERROR_OUT_OF_MEMORY);
bool ok = JS_DefineProperty(cx, global, "Components", JS::ObjectValue(*components),
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
// Create a fake interfaces object.
JSObject *interfaces = JS_NewObject(cx, nullptr, nullptr, global);
JS::Rooted<JSObject*> interfaces(cx, JS_NewObject(cx, nullptr, nullptr, global));
NS_ENSURE_TRUE(interfaces, NS_ERROR_OUT_OF_MEMORY);
ok = JS_DefineProperty(cx, components, "interfaces", JS::ObjectValue(*interfaces),
JS_PropertyStub, JS_StrictPropertyStub,
@ -4844,8 +4847,8 @@ DefineComponentsShim(JSContext *cx, JS::HandleObject global)
const char *domName = kInterfaceShimMap[i].domName;
// Look up the appopriate interface object on the global.
JS::Value v = JS::UndefinedValue();
ok = JS_GetProperty(cx, global, domName, &v);
JS::Rooted<JS::Value> v(cx, JS::UndefinedValue());
ok = JS_GetProperty(cx, global, domName, v.address());
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
if (!v.isObject()) {
NS_WARNING("Unable to find interface object on global");
@ -4890,7 +4893,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
if (!xpc::WrapperFactory::IsXrayWrapper(obj)) {
JSBool did_resolve = JS_FALSE;
JSBool ok = JS_TRUE;
JS::Value exn = JSVAL_VOID;
JS::Rooted<JS::Value> exn(cx, JSVAL_VOID);
{
// Resolve standard classes on my_context's JSContext (or on cx,
@ -4909,7 +4912,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Trust the JS engine (or the script security manager) to set
// the exception in the JS engine.
if (!JS_GetPendingException(my_cx, &exn)) {
if (!JS_GetPendingException(my_cx, exn.address())) {
return NS_ERROR_UNEXPECTED;
}
@ -4959,16 +4962,16 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
// Make sure we wrap the location object in the window's scope.
JSObject *scope = nullptr;
wrapper->GetJSObject(&scope);
JS::Rooted<JSObject*> scope(cx);
wrapper->GetJSObject(scope.address());
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval v;
JS::Rooted<JS::Value> v(cx);
rv = WrapNative(cx, scope, location, &NS_GET_IID(nsIDOMLocation), true,
&v, getter_AddRefs(holder));
v.address(), getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
JSBool ok = JS_WrapValue(cx, &v) &&
JSBool ok = JS_WrapValue(cx, v.address()) &&
JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub,
LocationSetterUnwrapper,
JSPROP_PERMANENT | JSPROP_ENUMERATE);
@ -4987,10 +4990,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsresult rv = win->GetScriptableTop(getter_AddRefs(top));
NS_ENSURE_SUCCESS(rv, rv);
jsval v;
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, top, &NS_GET_IID(nsIDOMWindow), true,
&v, getter_AddRefs(holder));
v.address(), getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Hold on to the top window object as a global property so we
@ -5034,10 +5037,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// compatibility, this should spit out an message on the JS
// console.
JSObject* windowObj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
JS::Rooted<JSObject*> windowObj(cx, js::CheckedUnwrap(obj, /* stopAtOuter = */ false));
NS_ENSURE_TRUE(windowObj, NS_ERROR_DOM_SECURITY_ERR);
JSObject *funObj;
JSObject* funObj = nullptr;
{
JSAutoCompartment ac(cx, windowObj);
JSFunction *fun = ::JS_NewFunction(cx, ContentWindowGetter, 0, 0,
@ -5084,10 +5087,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
rv = win->GetNavigator(getter_AddRefs(navigator));
NS_ENSURE_SUCCESS(rv, rv);
jsval v;
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), true,
&v, getter_AddRefs(holder));
v.address(), getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Hold on to the navigator object as a global property so we
@ -5105,10 +5108,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
if (sDocument_id == id) {
nsCOMPtr<nsIDocument> document = win->GetDoc();
JS::Value v;
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), document, document,
&NS_GET_IID(nsIDOMDocument), &v, getter_AddRefs(holder),
&NS_GET_IID(nsIDOMDocument), v.address(), getter_AddRefs(holder),
false);
NS_ENSURE_SUCCESS(rv, rv);
@ -5121,7 +5124,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// Unless our object is a native wrapper, in which case we have to
// define it ourselves.
*_retval = JS_WrapValue(cx, &v) &&
*_retval = JS_WrapValue(cx, v.address()) &&
JS_DefineProperty(cx, obj, "document", v,
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_READONLY | JSPROP_ENUMERATE);
@ -5164,21 +5167,21 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// defined on our prototype chain. This way we can access this
// expando w/o ever getting back into XPConnect.
if (flags & JSRESOLVE_ASSIGNING) {
JSObject *realObj;
wrapper->GetJSObject(&realObj);
JS::Rooted<JSObject*> realObj(cx);
wrapper->GetJSObject(realObj.address());
if (obj == realObj) {
JSObject *proto;
if (!js::GetObjectProto(cx, obj, &proto)) {
JS::Rooted<JSObject*> proto(cx);
if (!js::GetObjectProto(cx, obj, proto.address())) {
*_retval = JS_FALSE;
return NS_OK;
}
if (proto) {
JSObject *pobj = NULL;
JS::Rooted<JSObject*> pobj(cx);
jsval val;
if (!::JS_LookupPropertyWithFlagsById(cx, proto, id, flags,
&pobj, &val)) {
pobj.address(), &val)) {
*_retval = JS_FALSE;
return NS_OK;
@ -5246,14 +5249,14 @@ nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
return NS_ERROR_UNEXPECTED;
}
JSObject *winObj = win->FastGetGlobalJSObject();
JS::Rooted<JSObject*> winObj(cx, win->FastGetGlobalJSObject());
MOZ_ASSERT(winObj);
// Note that while |wrapper| is same-compartment with cx, the outer window
// might not be. If we're running script in an inactive scope and evalute
// |this|, the outer window is actually a cross-compartment wrapper. So we
// need to wrap here.
if (!JS_WrapObject(cx, &winObj)) {
if (!JS_WrapObject(cx, winObj.address())) {
*_retval = nullptr;
return NS_ERROR_UNEXPECTED;
}
@ -5395,7 +5398,7 @@ nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
jsval prop_val = JSVAL_VOID; // Property value.
JS::Rooted<JS::Value> prop_val(cx, JS::UndefinedValue()); // Property value.
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
@ -5404,19 +5407,19 @@ nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsIDOMWindow *window = static_cast<Navigator*>(navigator.get())->GetWindow();
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
rv = gpi->Init(window, &prop_val);
rv = gpi->Init(window, prop_val.address());
NS_ENSURE_SUCCESS(rv, rv);
}
if (JSVAL_IS_PRIMITIVE(prop_val) && !JSVAL_IS_NULL(prop_val)) {
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, native, true, &prop_val,
rv = WrapNative(cx, obj, native, true, prop_val.address(),
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
}
if (!JS_WrapValue(cx, &prop_val)) {
if (!JS_WrapValue(cx, prop_val.address())) {
return NS_ERROR_UNEXPECTED;
}
@ -5461,9 +5464,10 @@ nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
// DOM Node helper
NS_IMETHODIMP
nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *aGlobalObj,
JSObject **parentObj)
{
JS::Rooted<JSObject*> globalObj(cx, aGlobalObj);
nsINode *node = static_cast<nsINode*>(nativeObj);
#ifdef DEBUG
@ -5572,9 +5576,10 @@ nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_IMETHODIMP
nsNodeSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, uint32_t flags,
JSObject *aObj, jsid id, uint32_t flags,
JSObject **objp, bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
if (id == sOnload_id || id == sOnerror_id) {
// Make sure that this node can't go away while waiting for a
// network load that could fire an event handler.
@ -5870,8 +5875,8 @@ nsGenericArraySH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
{
*length = 0;
jsval lenval;
if (!JS_GetProperty(cx, obj, "length", &lenval)) {
JS::Rooted<JS::Value> lenval(cx);
if (!JS_GetProperty(cx, obj, "length", lenval.address())) {
return NS_ERROR_UNEXPECTED;
}
@ -5908,9 +5913,9 @@ nsGenericArraySH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
sCurrentlyEnumerating = true;
jsval len_val;
JS::Rooted<JS::Value> len_val(cx);
JSAutoRequest ar(cx);
JSBool ok = ::JS_GetProperty(cx, obj, "length", &len_val);
JSBool ok = ::JS_GetProperty(cx, obj, "length", len_val.address());
if (ok && JSVAL_IS_INT(len_val)) {
int32_t length = JSVAL_TO_INT(len_val);
@ -5995,10 +6000,10 @@ nsNamedArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
!ObjectIsNativeWrapper(cx, obj)) {
{
JSObject *realObj;
JS::Rooted<JSObject*> realObj(cx);
if (wrapper) {
wrapper->GetJSObject(&realObj);
wrapper->GetJSObject(realObj.address());
} else {
realObj = obj;
}
@ -6092,11 +6097,11 @@ nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
rv = doc->GetLocation(getter_AddRefs(location));
NS_ENSURE_SUCCESS(rv, rv);
jsval v;
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), location,
&NS_GET_IID(nsIDOMLocation), true, &v,
&NS_GET_IID(nsIDOMLocation), true, v.address(),
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
@ -6147,11 +6152,11 @@ nsDocumentSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
nsIDocument* currentDoc = win->GetExtantDoc();
if (SameCOMIdentity(doc, currentDoc)) {
jsval winVal;
JS::Rooted<JS::Value> winVal(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, obj, win, &NS_GET_IID(nsIDOMWindow), false,
&winVal, getter_AddRefs(holder));
winVal.address(), getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_STRING(doc_str, "document");
@ -6258,11 +6263,11 @@ nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx, JSObject *obj,
// in a reserved slot (0) on the document.all JSObject.
nsresult rv = NS_OK;
jsval collection = JS_GetReservedSlot(obj, 0);
JS::Rooted<JS::Value> collection(cx, JS_GetReservedSlot(obj, 0));
if (!JSVAL_IS_PRIMITIVE(collection)) {
// We already have a node list in our reserved slot, use it.
JSObject *obj = JSVAL_TO_OBJECT(collection);
JS::Rooted<JSObject*> obj(cx, JSVAL_TO_OBJECT(collection));
nsIHTMLCollection* htmlCollection;
rv = mozilla::dom::UnwrapObject<nsIHTMLCollection>(cx, obj, htmlCollection);
if (NS_SUCCEEDED(rv)) {
@ -6290,7 +6295,7 @@ nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx, JSObject *obj,
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult tmp = WrapNative(cx, JS_GetGlobalForScopeChain(cx),
static_cast<nsINodeList*>(list), list, false,
&collection, getter_AddRefs(holder));
collection.address(), getter_AddRefs(holder));
if (NS_FAILED(tmp)) {
rv = tmp;
}
@ -6314,7 +6319,7 @@ JSBool
nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSHandleObject obj_,
JSHandleId id, JSMutableHandleValue vp)
{
JSObject *obj = obj_;
JS::Rooted<JSObject*> obj(cx, obj_);
// document.all.item and .namedItem get their value in the
// newResolve hook, so nothing to do for those properties here. And
@ -6325,7 +6330,7 @@ nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSHandleObject obj_,
}
while (js::GetObjectJSClass(obj) != &sHTMLDocumentAllClass) {
if (!js::GetObjectProto(cx, obj, &obj)) {
if (!js::GetObjectProto(cx, obj, obj.address())) {
return JS_FALSE;
}
@ -6492,7 +6497,7 @@ nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
}
// Convert all types to string.
JSString *str = ::JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
JS::Rooted<JSString*> str(cx, ::JS_ValueToString(cx, JS_ARGV(cx, vp)[0]));
if (!str) {
return JS_FALSE;
}
@ -6575,8 +6580,8 @@ nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
{
if (nsDOMClassInfo::sAll_id == id) {
// document.all is resolved for the first time. Define it.
JSObject *helper;
if (!GetDocumentAllHelper(cx, obj, &helper)) {
JS::Rooted<JSObject*> helper(cx);
if (!GetDocumentAllHelper(cx, obj, helper.address())) {
return JS_FALSE;
}
@ -6602,8 +6607,8 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
if (JSID_IS_STRING(id)) {
nsDocument *doc = GetDocument(obj);
JSObject *proto;
if (!::JS_GetPrototype(cx, obj, &proto)) {
JS::Rooted<JSObject*> proto(cx);
if (!::JS_GetPrototype(cx, obj, proto.address())) {
return JS_FALSE;
}
if (MOZ_UNLIKELY(!proto)) {
@ -6623,11 +6628,11 @@ nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
doc->GetElementsByTagName(nsDependentJSString(id));
if (tags) {
jsval v;
JS::Rooted<JS::Value> v(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx),
static_cast<nsINodeList*>(tags), tags, true,
&v, getter_AddRefs(holder));
v.address(), getter_AddRefs(holder));
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
@ -6676,11 +6681,11 @@ ResolveAll(JSContext* cx, nsIDocument* doc, JSObject* obj)
// Our helper's prototype now has an "all" property, remove
// the helper out of the prototype chain to prevent
// shadowing of the now defined "all" property.
JSObject *tmp = obj, *tmpProto = tmp;
JS::Rooted<JSObject*> tmp(cx, obj), tmpProto(cx, tmp);
do {
tmp = tmpProto;
if (!::JS_GetPrototype(cx, tmp, &tmpProto)) {
if (!::JS_GetPrototype(cx, tmp, tmpProto.address())) {
return NS_ERROR_UNEXPECTED;
}
} while (tmpProto != helper);
@ -6775,9 +6780,10 @@ nsHTMLDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_IMETHODIMP
nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj, jsid id,
JSContext *cx, JSObject *aObj, jsid id,
jsval *vp, bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
nsCOMPtr<nsISupports> result;
JSAutoRequest ar(cx);
@ -6801,10 +6807,11 @@ nsHTMLDocumentSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
NS_IMETHODIMP
nsHTMLFormElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj, jsid id,
JSContext *cx, JSObject *aObj, jsid id,
uint32_t flags, JSObject **objp,
bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
// For native wrappers, do not resolve random names on form
if ((!(JSRESOLVE_ASSIGNING & flags)) && JSID_IS_STRING(id) &&
(!ObjectIsNativeWrapper(cx, obj) ||
@ -7169,21 +7176,21 @@ nsStorage2SH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
JSObject *realObj;
wrapper->GetJSObject(&realObj);
JS::Rooted<JSObject*> realObj(cx);
wrapper->GetJSObject(realObj.address());
JSAutoCompartment ac(cx, realObj);
// First check to see if the property is defined on our prototype,
// after converting id to a string if it's an integer.
JSString *jsstr = IdToString(cx, id);
JS::Rooted<JSString*> jsstr(cx, IdToString(cx, id));
if (!jsstr) {
return NS_OK;
}
JSObject *proto;
if (!::JS_GetPrototype(cx, realObj, &proto)) {
JS::Rooted<JSObject*> proto(cx);
if (!::JS_GetPrototype(cx, realObj, proto.address())) {
return NS_ERROR_FAILURE;
}
JSBool hasProp;
@ -7417,7 +7424,7 @@ nsDOMConstructorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx
return NS_OK;
}
JSObject *nativePropsObj = xpc::XrayUtils::GetNativePropertiesObject(cx, obj);
JS::Rooted<JSObject*> nativePropsObj(cx, xpc::XrayUtils::GetNativePropertiesObject(cx, obj));
nsDOMConstructor *wrapped =
static_cast<nsDOMConstructor *>(wrapper->Native());
nsresult rv = wrapped->ResolveInterfaceConstants(cx, nativePropsObj);
@ -7441,9 +7448,10 @@ nsDOMConstructorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx
NS_IMETHODIMP
nsDOMConstructorSH::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, uint32_t argc, jsval *argv, jsval *vp,
JSObject *aObj, uint32_t argc, jsval *argv, jsval *vp,
bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
MOZ_ASSERT(obj);
nsDOMConstructor *wrapped =

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

@ -375,8 +375,9 @@ public:
JS::MutableHandle<JSObject*> objp);
static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
JSHandleId id, JSMutableHandleValue vp);
static JSBool InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj);
static JSBool InvalidateGlobalScopePolluter(JSContext *cx, JSObject* obj);
static nsresult InstallGlobalScopePolluter(JSContext *cx,
JS::Handle<JSObject*> obj);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsWindowSH(aData);

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

@ -2467,7 +2467,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// alive etc.
if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) {
nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject);
JS::Rooted<JSObject*> obj(cx, newInnerWindow->mJSObject);
nsWindowSH::InstallGlobalScopePolluter(cx, obj);
}
aDocument->SetScriptGlobalObject(newInnerWindow);

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

@ -5,8 +5,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'nsIDOMContactManager.idl',
'nsIContactProperties.idl',
'nsIDOMContactManager.idl',
'nsIDOMMozContactChangeEvent.idl',
]

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

@ -25,6 +25,9 @@ XPIDL_SOURCES += [
'nsIDOMEvent.idl',
'nsIDOMEventListener.idl',
'nsIDOMEventTarget.idl',
'nsIDOMGamepadAxisMoveEvent.idl',
'nsIDOMGamepadButtonEvent.idl',
'nsIDOMGamepadEvent.idl',
'nsIDOMHashChangeEvent.idl',
'nsIDOMKeyEvent.idl',
'nsIDOMMessageEvent.idl',
@ -50,9 +53,6 @@ XPIDL_SOURCES += [
'nsIDOMUIEvent.idl',
'nsIDOMUserProximityEvent.idl',
'nsIDOMWheelEvent.idl',
'nsIDOMGamepadButtonEvent.idl',
'nsIDOMGamepadAxisMoveEvent.idl',
'nsIDOMGamepadEvent.idl',
]
XPIDL_MODULE = 'dom_events'

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

@ -5,27 +5,27 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.dom.mobilemessage += [
'Constants.h',
'MobileMessageCallback.h',
'MobileMessageService.h',
'SmsChild.h',
'SmsParent.h',
'MobileMessageService.h',
'SmsServicesFactory.h',
'Constants.h',
'Types.h',
'MobileMessageCallback.h',
]
if not CONFIG['MOZ_B2G_RIL']:
EXPORTS.mozilla.dom.mobilemessage += [
'MobileMessageDatabaseService.h',
'MmsService.h',
'MobileMessageDatabaseService.h',
]
EXPORTS.mozilla.dom += [
'SmsManager.h',
'MobileMessageManager.h',
'SmsMessage.h',
'MmsMessage.h',
'SmsSegmentInfo.h',
'MobileMessageManager.h',
'SmsFilter.h',
'SmsManager.h',
'SmsMessage.h',
'SmsSegmentInfo.h',
]

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

@ -7,7 +7,7 @@
MODULE = 'dom'
EXPORTS.mozilla.dom += [
'Notification.h',
'DesktopNotification.h',
'Notification.h',
]

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

@ -26,10 +26,8 @@ interface AudioNode : EventTarget {
[Throws]
void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
// [Throws]
// void connect(AudioParam destination, optional unsigned long output = 0);
[Throws]
void connect(AudioParam destination, optional unsigned long output = 0);
[Throws]
void disconnect(optional unsigned long output = 0);

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

@ -60,8 +60,8 @@ if CONFIG['BUILD_CAIRO_SVG']:
if CONFIG['MOZ_X11']:
EXPORTS.cairo += [
'cairo-xlib.h',
'cairo-xlib-xrender.h',
'cairo-xlib.h',
]
if CONFIG['MOZ_ENABLE_CAIRO_FT']:

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

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/Effects.h"
namespace mozilla {
namespace layers {
@ -15,5 +16,41 @@ Compositor::GetBackend()
return sBackend;
}
void
Compositor::DrawDiagnostics(const gfx::Color& aColor,
const gfx::Rect& rect,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform,
const gfx::Point& aOffset)
{
if (!mDrawColoredBorders) {
return;
}
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(aColor);
int lWidth = 1;
float opacity = 0.8;
// left
this->DrawQuad(gfx::Rect(rect.x, rect.y,
lWidth, rect.height),
aClipRect, effects, opacity,
aTransform, aOffset);
// top
this->DrawQuad(gfx::Rect(rect.x + lWidth, rect.y,
rect.width - 2 * lWidth, lWidth),
aClipRect, effects, opacity,
aTransform, aOffset);
// right
this->DrawQuad(gfx::Rect(rect.x + rect.width - lWidth, rect.y,
lWidth, rect.height),
aClipRect, effects, opacity,
aTransform, aOffset);
// bottom
this->DrawQuad(gfx::Rect(rect.x + lWidth, rect.y + rect.height-lWidth,
rect.width - 2 * lWidth, lWidth),
aClipRect, effects, opacity,
aTransform, aOffset);
}
} // namespace
} // namespace

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

@ -170,6 +170,7 @@ class Compositor : public RefCounted<Compositor>
public:
Compositor()
: mCompositorID(0)
, mDrawColoredBorders(false)
{
MOZ_COUNT_CTOR(Compositor);
}
@ -322,6 +323,22 @@ public:
*/
virtual bool SupportsPartialTextureUpdate() = 0;
void EnableColoredBorders()
{
mDrawColoredBorders = true;
}
void DisableColoredBorders()
{
mDrawColoredBorders = false;
}
void DrawDiagnostics(const gfx::Color& color,
const gfx::Rect& visibleRect,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& transform,
const gfx::Point& aOffset);
#ifdef MOZ_DUMP_PAINTING
virtual const char* Name() const = 0;
#endif // MOZ_DUMP_PAINTING
@ -380,6 +397,7 @@ public:
protected:
uint32_t mCompositorID;
static LayersBackend sBackend;
bool mDrawColoredBorders;
};
} // namespace layers

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

@ -36,6 +36,10 @@ ColorLayerComposite::RenderLayer(const nsIntPoint& aOffset,
mCompositor->DrawQuad(rect, clipRect, effects, opacity,
transform, gfx::Point(aOffset.x, aOffset.y));
mCompositor->DrawDiagnostics(gfx::Color(0.0, 1.0, 1.0, 1.0),
rect, clipRect,
transform, gfx::Point(aOffset.x, aOffset.y));
}
} /* layers */

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

@ -174,6 +174,9 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
Float(tileRegionRect.width) / texRect.width,
Float(tileRegionRect.height) / texRect.height);
GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform, aOffset);
GetCompositor()->DrawDiagnostics(gfx::Color(0.0,1.0,0.0,1.0),
rect, aClipRect, aTransform, aOffset);
}
}
}

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

@ -103,6 +103,8 @@ ImageHostSingle::Composite(EffectChain& aEffectChain,
gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
aOpacity, aTransform, aOffset);
GetCompositor()->DrawDiagnostics(gfx::Color(0.5,0.0,0.0,1.0),
rect, aClipRect, aTransform, aOffset);
} while (it->NextTile());
it->EndTileIteration();
} else {
@ -127,6 +129,8 @@ ImageHostSingle::Composite(EffectChain& aEffectChain,
GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
aOpacity, aTransform, aOffset);
GetCompositor()->DrawDiagnostics(gfx::Color(1.0,0.1,0.1,1.0),
rect, aClipRect, aTransform, aOffset);
}
mTextureHost->Unlock();

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

@ -205,6 +205,8 @@ TiledContentHost::RenderTile(const TiledTexture& aTile,
textureRect.width / aTextureBounds.width,
textureRect.height / aTextureBounds.height);
mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform, aOffset);
mCompositor->DrawDiagnostics(gfx::Color(0.0,0.5,0.0,1.0),
graphicsRect, aClipRect, aTransform, aOffset);
}
aTile.mTextureHost->Unlock();

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

@ -232,6 +232,7 @@ struct OpRemoveChild { PLayer container; PLayer childLayer; };
struct OpRepositionChild { PLayer container; PLayer childLayer; PLayer after; };
struct OpRaiseToTopChild { PLayer container; PLayer childLayer; };
struct OpSetColoredBorders { bool enabled; };
// Paint (buffer update)
struct OpPaintTiledLayerBuffer {
@ -291,6 +292,7 @@ union Edit {
OpCreateRefLayer;
OpSetLayerAttributes;
OpSetColoredBorders;
OpSetRoot;
OpInsertAfter;

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

@ -238,7 +238,7 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
break;
}
// Attributes
// Attributes
case Edit::TOpSetLayerAttributes: {
MOZ_LAYERS_LOG(("[ParentSide] SetLayerAttributes"));
@ -329,6 +329,14 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
}
break;
}
case Edit::TOpSetColoredBorders: {
if (edit.get_OpSetColoredBorders().enabled()) {
mLayerManager->GetCompositor()->EnableColoredBorders();
} else {
mLayerManager->GetCompositor()->DisableColoredBorders();
}
break;
}
// Tree ops
case Edit::TOpSetRoot: {
MOZ_LAYERS_LOG(("[ParentSide] SetRoot"));

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

@ -165,6 +165,7 @@ CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIden
ShadowLayerForwarder::ShadowLayerForwarder()
: mShadowManager(NULL)
, mIsFirstPaint(false)
, mDrawColoredBorders(false)
{
mTxn = new Transaction();
}
@ -360,6 +361,11 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
NS_ABORT_IF_FALSE(!mTxn->Finished(), "forgot BeginTransaction?");
if (mDrawColoredBorders != gfxPlatform::DrawLayerBorders()) {
mDrawColoredBorders = gfxPlatform::DrawLayerBorders();
mTxn->AddEdit(OpSetColoredBorders(mDrawColoredBorders));
}
AutoTxnEnd _(mTxn);
if (mTxn->Empty() && !mTxn->RotationChanged()) {

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

@ -432,6 +432,7 @@ private:
Transaction* mTxn;
bool mIsFirstPaint;
bool mDrawColoredBorders;
};
class CompositableClient;

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

@ -12,35 +12,35 @@ EXPORTS += [
'BasicLayers.h',
'BasicLayersImpl.h',
'BasicThebesLayer.h',
'CompositableHost.h',
'CopyableCanvasLayer.h',
'ClientLayerManager.h',
'ClientCanvasLayer.h',
'ClientContainerLayer.h',
'ClientLayerManager.h',
'ClientThebesLayer.h',
'ClientTiledThebesLayer.h',
'ClientCanvasLayer.h',
'Composer2D.h',
'GonkIOSurfaceImage.h',
'FrameMetrics.h',
'CompositableHost.h',
'CompositorChild.h',
'CompositorParent.h',
'CopyableCanvasLayer.h',
'FrameMetrics.h',
'GonkIOSurfaceImage.h',
'ImageContainer.h',
'ImageLayers.h',
'ImageLayerOGL.h',
'ImageHost.h',
'ImageLayerOGL.h',
'ImageLayers.h',
'ImageTypes.h',
'Layers.h',
'LayersLogging.h',
'LayerManagerOGLShaders.h',
'LayerManagerOGL.h',
'LayerManagerOGLProgram.h',
'LayerManagerOGLShaders.h',
'LayerSorter.h',
'LayerTreeInvalidation.h',
'Layers.h',
'LayersLogging.h',
'ReadbackLayer.h',
'ShadowLayersManager.h',
'SharedTextureImage.h',
'TexturePoolOGL.h',
'ShmemYCbCrImage.h',
'TexturePoolOGL.h',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
@ -71,41 +71,41 @@ EXPORTS.mozilla.layers += [
'CanvasLayerComposite.h',
'ColorLayerComposite.h',
'CompositableClient.h',
'CompositableForwarder.h',
'CompositableTransactionParent.h',
'CompositingRenderTargetOGL.h',
'Compositor.h',
'CompositorChild.h',
'CompositorCocoaWidgetHelper.h',
'CompositorOGL.h',
'CompositorParent.h',
'CompositorTypes.h',
'ContainerLayerComposite.h',
'ContentHost.h',
'CompositingRenderTargetOGL.h',
'CompositorCocoaWidgetHelper.h',
'CompositorChild.h',
'CompositorParent.h',
'CompositableForwarder.h',
'ContentClient.h',
'ContentHost.h',
'Effects.h',
'GeckoContentController.h',
'GestureEventListener.h',
'ISurfaceAllocator.h',
'ImageBridgeChild.h',
'ImageBridgeParent.h',
'ImageClient.h',
'ImageLayerComposite.h',
'ImageHost.h',
'ISurfaceAllocator.h',
'ImageLayerComposite.h',
'LayerManagerComposite.h',
'LayersTypes.h',
'LayerTransactionChild.h',
'LayerTransactionParent.h',
'LayersTypes.h',
'RenderTrace.h',
'ShadowLayers.h',
'ShadowLayersManager.h',
'RenderTrace.h',
'SharedRGBImage.h',
'SharedPlanarYCbCrImage.h',
'SharedRGBImage.h',
'ShmemYCbCrImage.h',
'TaskThrottler.h',
'TextureClient.h',
'TextureHost.h',
'TextureClientOGL.h',
'TextureHost.h',
'TextureHostOGL.h',
'ThebesLayerComposite.h',
'TiledContentClient.h',

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

@ -140,18 +140,18 @@ typedef struct _D3DKMTQS_QUERY_SEGMENT
typedef struct _D3DKMTQS
{
__in D3DKMTQS_TYPE Type;
__in LUID AdapterLuid;
__in_opt HANDLE hProcess;
__out D3DKMTQS_RESULT QueryResult;
D3DKMTQS_TYPE Type;
LUID AdapterLuid;
HANDLE hProcess;
D3DKMTQS_RESULT QueryResult;
union
{
__in D3DKMTQS_QUERY_SEGMENT QuerySegment;
__in D3DKMTQS_QUERY_SEGMENT QueryProcessSegment;
D3DKMTQS_QUERY_SEGMENT QuerySegment;
D3DKMTQS_QUERY_SEGMENT QueryProcessSegment;
};
} D3DKMTQS;
extern "C" {
typedef __checkReturn NTSTATUS (APIENTRY *PFND3DKMTQS)(__in const D3DKMTQS *);
typedef __checkReturn NTSTATUS (APIENTRY *PFND3DKMTQS)(const D3DKMTQS *);
}

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

@ -96,6 +96,8 @@ static int gCMSIntent = -2;
static void ShutdownCMS();
static void MigratePrefs();
static bool sDrawLayerBorders = false;
#include "mozilla/gfx/2D.h"
using namespace mozilla::gfx;
@ -400,6 +402,10 @@ gfxPlatform::Init()
gPlatform->mOrientationSyncMillis = Preferences::GetUint("layers.orientation.sync.timeout", (uint32_t)0);
mozilla::Preferences::AddBoolVarCache(&sDrawLayerBorders,
"layers.draw-borders",
false);
CreateCMSOutputProfile();
}
@ -1103,6 +1109,13 @@ gfxPlatform::IsLangCJK(eFontPrefLang aLang)
}
}
bool
gfxPlatform::DrawLayerBorders()
{
return sDrawLayerBorders;
}
void
gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
{

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

@ -530,6 +530,8 @@ public:
uint32_t GetOrientationSyncMillis() const;
static bool DrawLayerBorders();
protected:
gfxPlatform();
virtual ~gfxPlatform();

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

@ -168,7 +168,7 @@ typedef HRESULT(WINAPI*CreateDXGIFactory1Func)(
class GPUAdapterMultiReporter : public nsIMemoryMultiReporter {
// Callers must Release the DXGIAdapter after use or risk mem-leak
static bool GetDXGIAdapter(__out IDXGIAdapter **DXGIAdapter)
static bool GetDXGIAdapter(IDXGIAdapter **DXGIAdapter)
{
ID3D10Device1 *D2D10Device;
IDXGIDevice *DXGIDevice;

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

@ -80,8 +80,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
if CONFIG['MOZ_X11']:
EXPORTS += [
'gfxXlibSurface.h',
'gfxXlibNativeRenderer.h',
'gfxXlibSurface.h',
]
if CONFIG['MOZ_PANGO']:

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

@ -213,6 +213,7 @@ VPATH += $(srcdir)/ion
VPATH += $(srcdir)/ion/shared
CPPSRCS += MIR.cpp \
BytecodeAnalysis.cpp \
BaselineCompiler.cpp \
BaselineIC.cpp \
BaselineFrame.cpp \

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

@ -28,6 +28,13 @@ function indirectCallCannotGC(caller, name)
if (/CallDestroyScriptHook/.test(caller))
return true;
// template method called during marking and hence cannot GC
if (name == "op" &&
/^bool js::WeakMap<Key, Value, HashPolicy>::keyNeedsMark\(JSObject\*\)/.test(caller))
{
return true;
}
return false;
}

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

@ -19,7 +19,7 @@ function processCSU(csu, body)
if (type.Kind == "CSU") {
// Ignore nesting in classes which are AutoGCRooters. We only consider
// types with fields that may not be properly rooted.
if (type.Name == "JS::AutoGCRooter")
if (type.Name == "JS::AutoGCRooter" || type.Name == "JS::CustomAutoRooter")
return;
addNestedStructure(csu, type.Name);
}

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

@ -29,6 +29,9 @@ BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script)
bool
BaselineCompiler::init()
{
if (!analysis_.init())
return false;
if (!labels_.init(script->length))
return false;
@ -64,8 +67,12 @@ BaselineCompiler::compile()
IonSpew(IonSpew_BaselineScripts, "Baseline compiling script %s:%d (%p)",
script->filename(), script->lineno, script.get());
if (!script->ensureRanAnalysis(cx))
return Method_Error;
// Only need to analyze scripts which are marked |argumensHasVarBinding|, to
// compute |needsArgsObj| flag.
if (script->argumentsHasVarBinding()) {
if (!script->ensureRanAnalysis(cx))
return Method_Error;
}
// Pin analysis info during compilation.
types::AutoEnterAnalysis autoEnterAnalysis(cx);
@ -519,7 +526,7 @@ BaselineCompiler::emitSPSPop()
Label noPop;
masm.branchTest32(Assembler::Zero, frame.addressOfFlags(),
Imm32(BaselineFrame::HAS_PUSHED_SPS_FRAME), &noPop);
masm.spsPopFrame(&cx->runtime->spsProfiler, R1.scratchReg());
masm.spsPopFrameSafe(&cx->runtime->spsProfiler, R1.scratchReg());
masm.bind(&noPop);
}
@ -537,10 +544,10 @@ BaselineCompiler::emitBody()
IonSpew(IonSpew_BaselineOp, "Compiling op @ %d: %s",
int(pc - script->code), js_CodeName[op]);
analyze::Bytecode *code = script->analysis()->maybeCode(pc);
BytecodeInfo *info = analysis_.maybeInfo(pc);
// Skip unreachable ops.
if (!code) {
if (!info) {
if (op == JSOP_STOP)
break;
pc += GetBytecodeLength(pc);
@ -549,9 +556,9 @@ BaselineCompiler::emitBody()
}
// Fully sync the stack if there are incoming jumps.
if (code->jumpTarget) {
if (info->jumpTarget) {
frame.syncStack(0);
frame.setStackDepth(code->stackDepth);
frame.setStackDepth(info->stackDepth);
}
// Always sync in debug mode.
@ -2419,7 +2426,7 @@ BaselineCompiler::emit_JSOP_ARGUMENTS()
frame.syncStack(0);
Label done;
if (!script->needsArgsObj()) {
if (!script->argumentsHasVarBinding() || !script->needsArgsObj()) {
// We assume the script does not need an arguments object. However, this
// assumption can be invalidated later, see argumentsOptimizationFailed
// in JSScript. Because we can't invalidate baseline JIT code, we set a

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

@ -13,9 +13,11 @@
#include "jsinfer.h"
#include "jsinterp.h"
#include "IonAllocPolicy.h"
#include "BaselineJIT.h"
#include "BaselineIC.h"
#include "FixedList.h"
#include "BytecodeAnalysis.h"
#if defined(JS_CPU_X86)
# include "x86/BaselineCompiler-x86.h"

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

@ -6,6 +6,7 @@
#include "BaselineFrameInfo.h"
#include "IonSpewer.h"
#include "shared/BaselineCompiler-shared.h"
#include "jsanalyze.h"
#include "jsinferinlines.h"
@ -147,8 +148,8 @@ void
FrameInfo::assertValidState(jsbytecode *pc)
{
// Check stack depth.
analyze::Bytecode *code = script->analysis()->maybeCode(pc);
JS_ASSERT_IF(code, stackDepth() == code->stackDepth);
BytecodeInfo *info = compiler.analysis().maybeInfo(pc);
JS_ASSERT_IF(info, stackDepth() == info->stackDepth);
// Start at the bottom, find the first value that's not synced.
uint32_t i = 0;

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

@ -13,6 +13,7 @@
#include "BaselineJIT.h"
#include "BaselineFrame.h"
#include "BaselineRegisters.h"
#include "BytecodeAnalysis.h"
#include "IonMacroAssembler.h"
#include "FixedList.h"
@ -158,8 +159,11 @@ class StackValue
enum StackAdjustment { AdjustStack, DontAdjustStack };
class BaselineCompilerShared;
class FrameInfo
{
BaselineCompilerShared &compiler;
RootedScript script;
MacroAssembler &masm;
@ -167,8 +171,10 @@ class FrameInfo
size_t spIndex;
public:
FrameInfo(JSContext *cx, HandleScript script, MacroAssembler &masm)
: script(cx, script),
FrameInfo(JSContext *cx, BaselineCompilerShared &compiler, HandleScript script,
MacroAssembler &masm)
: compiler(compiler),
script(cx, script),
masm(masm),
stack(),
spIndex(0)

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

@ -0,0 +1,138 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 "ion/BytecodeAnalysis.h"
#include "jsopcode.h"
#include "jsopcodeinlines.h"
using namespace js;
using namespace js::ion;
BytecodeAnalysis::BytecodeAnalysis(JSScript *script)
: script_(script),
infos_()
{
}
bool
BytecodeAnalysis::init()
{
if (!infos_.growByUninitialized(script_->length))
return false;
jsbytecode *end = script_->code + script_->length;
// Clear all BytecodeInfo.
mozilla::PodZero(infos_.begin(), infos_.length());
infos_[0].init(/*stackDepth=*/0);
for (jsbytecode *pc = script_->code; pc < end; pc += GetBytecodeLength(pc)) {
JSOp op = JSOp(*pc);
unsigned offset = pc - script_->code;
IonSpew(IonSpew_BaselineOp, "Analyzing op @ %d (end=%d): %s",
int(pc - script_->code), int(end - script_->code), js_CodeName[op]);
// If this bytecode info has not yet been initialized, it's not reachable.
if (!infos_[offset].initialized)
continue;
unsigned stackDepth = infos_[offset].stackDepth;
#ifdef DEBUG
for (jsbytecode *chkpc = pc + 1; chkpc < (pc + GetBytecodeLength(pc)); chkpc++)
JS_ASSERT(!infos_[chkpc - script_->code].initialized);
#endif
// Treat decompose ops as no-ops which do not adjust the stack. We will
// pick up the stack depths as we go through the decomposed version.
if (!(js_CodeSpec[op].format & JOF_DECOMPOSE)) {
unsigned nuses = GetUseCount(script_, offset);
unsigned ndefs = GetDefCount(script_, offset);
JS_ASSERT(stackDepth >= nuses);
stackDepth -= nuses;
stackDepth += ndefs;
// If stack depth exceeds max allowed by analysis, fail fast.
JS_ASSERT(stackDepth <= BytecodeInfo::MAX_STACK_DEPTH);
}
if (op == JSOP_TABLESWITCH) {
unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
int32_t low = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
int32_t high = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
infos_[defaultOffset].init(stackDepth);
infos_[defaultOffset].jumpTarget = true;
for (int32_t i = low; i <= high; i++) {
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
if (targetOffset != offset) {
infos_[targetOffset].init(stackDepth);
infos_[targetOffset].jumpTarget = true;
}
pc2 += JUMP_OFFSET_LEN;
}
} else if (op == JSOP_TRY) {
JSTryNote *tn = script_->trynotes()->vector;
JSTryNote *tnlimit = tn + script_->trynotes()->length;
for (; tn < tnlimit; tn++) {
unsigned startOffset = script_->mainOffset + tn->start;
if (startOffset == offset + 1) {
unsigned catchOffset = startOffset + tn->length;
if (tn->kind != JSTRY_ITER) {
infos_[catchOffset].init(stackDepth);
infos_[catchOffset].jumpTarget = true;
}
}
}
}
bool jump = IsJumpOpcode(op);
if (jump) {
// Case instructions do not push the lvalue back when branching.
unsigned newStackDepth = stackDepth;
if (op == JSOP_CASE)
newStackDepth--;
unsigned targetOffset = offset + GET_JUMP_OFFSET(pc);
// If this is a a backedge to an un-analyzed segment, analyze from there.
bool jumpBack = (targetOffset < offset) && !infos_[targetOffset].initialized;
infos_[targetOffset].init(newStackDepth);
infos_[targetOffset].jumpTarget = true;
if (jumpBack)
pc = script_->code + targetOffset;
}
// Handle any fallthrough from this opcode.
if (BytecodeFallsThrough(op)) {
jsbytecode *nextpc = pc + GetBytecodeLength(pc);
JS_ASSERT(nextpc < end);
unsigned nextOffset = nextpc - script_->code;
infos_[nextOffset].init(stackDepth);
if (jump)
infos_[nextOffset].jumpFallthrough = true;
// Treat the fallthrough of a branch instruction as a jump target.
if (jump)
infos_[nextOffset].jumpTarget = true;
else
infos_[nextOffset].fallthrough = true;
}
}
return true;
}

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