Merge latest green birch changeset and mozilla-central

This commit is contained in:
Ed Morley 2013-06-28 14:33:47 +01:00
commit 38df1ffab0
430 changed files with 5140 additions and 2748 deletions

View File

@ -542,7 +542,7 @@ var Input = {
switch (gestureName) {
case 'dwell1':
case 'explore1':
this.moveCursor('moveToPoint', 'Simple', 'gesture',
this.moveCursor('moveToPoint', 'SimpleTouch', 'gesture',
aGesture.x, aGesture.y);
break;
case 'doubletap1':

View File

@ -57,8 +57,7 @@ this.EventManager.prototype = {
this.present(Presentation.tabStateChanged(null, 'newtab'));
} catch (x) {
Logger.error('Failed to start EventManager');
Logger.logException(x);
Logger.logException(x, 'Failed to start EventManager');
}
},
@ -117,8 +116,7 @@ this.EventManager.prototype = {
}
}
} catch (x) {
Logger.error('Error handling DOM event');
Logger.logException(x);
Logger.logException(x, 'Error handling DOM event');
}
},
@ -140,7 +138,7 @@ this.EventManager.prototype = {
let pivot = aEvent.accessible.
QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
let position = pivot.position;
if (position.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME)
if (position && position.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME)
break;
let event = aEvent.
QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
@ -421,8 +419,7 @@ const AccessibilityEventObserver = {
try {
eventManager.handleAccEvent(event);
} catch (x) {
Logger.error('Error handing accessible event');
Logger.logException(x);
Logger.logException(x, 'Error handing accessible event');
} finally {
return;
}

View File

@ -22,6 +22,11 @@ XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'PrefCache',
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
'resource://gre/modules/accessibility/Utils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm',
'resource://gre/modules/PluralForm.jsm');
let gUtteranceOrder = new PrefCache('accessibility.accessfu.utterance');
@ -46,7 +51,7 @@ this.OutputGenerator = {
let output = [];
let self = this;
let addOutput = function addOutput(aAccessible) {
output.push.apply(output, self.genForObject(aAccessible));
output.push.apply(output, self.genForObject(aAccessible, aContext));
};
let ignoreSubtree = function ignoreSubtree(aAccessible) {
let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
@ -83,14 +88,18 @@ this.OutputGenerator = {
* Generates output for an object.
* @param {nsIAccessible} aAccessible accessible object to generate utterance
* for.
* @param {PivotContext} aContext object that generates and caches
* context information for a given accessible and its relationship with
* another accessible.
* @return {Array} Two string array. The first string describes the object
* and its states. The second string is the object's name. Whether the
* object's description or it's role is included is determined by
* {@link roleRuleMap}.
*/
genForObject: function genForObject(aAccessible) {
genForObject: function genForObject(aAccessible, aContext) {
let roleString = Utils.AccRetrieval.getStringRole(aAccessible.role);
let func = this.objectOutputFunctions[roleString.replace(' ', '')] ||
let func = this.objectOutputFunctions[
OutputGenerator._getOutputName(roleString)] ||
this.objectOutputFunctions.defaultFunc;
let flags = this.roleRuleMap[roleString] || 0;
@ -103,7 +112,7 @@ this.OutputGenerator = {
aAccessible.getState(state, extState);
let states = {base: state.value, ext: extState.value};
return func.apply(this, [aAccessible, roleString, states, flags]);
return func.apply(this, [aAccessible, roleString, states, flags, aContext]);
},
/**
@ -158,10 +167,20 @@ this.OutputGenerator = {
}
},
_getOutputName: function _getOutputName(aName) {
return aName.replace(' ', '');
},
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {},
_getLocalizedStates: function _getLocalizedStates(aStates) {},
_getPluralFormString: function _getPluralFormString(aString, aCount) {
let str = gStringBundle.GetStringFromName(this._getOutputName(aString));
str = PluralForm.get(aCount, str);
return str.replace('#1', aCount);
},
roleRuleMap: {
'menubar': INCLUDE_DESC,
'scrollbar': INCLUDE_DESC,
@ -170,10 +189,11 @@ this.OutputGenerator = {
'menupopup': INCLUDE_DESC,
'menuitem': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'tooltip': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'columnheader': NAME_FROM_SUBTREE_RULE,
'rowheader': NAME_FROM_SUBTREE_RULE,
'columnheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'rowheader': INCLUDE_DESC | NAME_FROM_SUBTREE_RULE,
'column': NAME_FROM_SUBTREE_RULE,
'row': NAME_FROM_SUBTREE_RULE,
'cell': INCLUDE_DESC | INCLUDE_NAME,
'application': INCLUDE_NAME,
'document': INCLUDE_NAME,
'grouping': INCLUDE_DESC | INCLUDE_NAME,
@ -263,6 +283,32 @@ this.OutputGenerator = {
this._addName(output, aAccessible, aFlags);
return output;
},
table: function table(aAccessible, aRoleStr, aStates, aFlags) {
let output = [];
let table;
try {
table = aAccessible.QueryInterface(Ci.nsIAccessibleTable);
} catch (x) {
Logger.logException(x);
return output;
} finally {
// Check if it's a layout table, and bail out if true.
// We don't want to speak any table information for layout tables.
if (table.isProbablyForLayout()) {
return output;
}
let tableColumnInfo = this._getPluralFormString('tableColumnInfo',
table.columnCount);
let tableRowInfo = this._getPluralFormString('tableRowInfo',
table.rowCount);
output.push(gStringBundle.formatStringFromName(
this._getOutputName('tableInfo'), [this._getLocalizedRole(aRoleStr),
tableColumnInfo, tableRowInfo], 3));
this._addName(output, aAccessible, aFlags);
return output;
}
}
}
};
@ -341,12 +387,11 @@ this.UtteranceGenerator = {
},
objectOutputFunctions: {
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
return OutputGenerator.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
},
entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
return OutputGenerator.objectOutputFunctions.entry.apply(this, arguments);
__proto__: OutputGenerator.objectOutputFunctions,
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
return this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
},
heading: function heading(aAccessible, aRoleStr, aStates, aFlags) {
@ -392,6 +437,53 @@ this.UtteranceGenerator = {
[aAccessible, aRoleStr, aStates, aFlags]);
return [];
},
cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
let utterance = [];
let cell = aContext.getCellInfo(aAccessible);
if (cell) {
let desc = [];
let addCellChanged = function addCellChanged(aDesc, aChanged, aString, aIndex) {
if (aChanged) {
aDesc.push(gStringBundle.formatStringFromName(aString,
[aIndex + 1], 1));
}
};
let addExtent = function addExtent(aDesc, aExtent, aString) {
if (aExtent > 1) {
aDesc.push(gStringBundle.formatStringFromName(aString,
[aExtent], 1));
}
};
let addHeaders = function addHeaders(aDesc, aHeaders) {
if (aHeaders.length > 0) {
aDesc.push.apply(aDesc, aHeaders);
}
};
addCellChanged(desc, cell.columnChanged, 'columnInfo', cell.columnIndex);
addCellChanged(desc, cell.rowChanged, 'rowInfo', cell.rowIndex);
addExtent(desc, cell.columnExtent, 'spansColumns');
addExtent(desc, cell.rowExtent, 'spansRows');
addHeaders(desc, cell.columnHeaders);
addHeaders(desc, cell.rowHeaders);
utterance.push(desc.join(' '));
}
this._addName(utterance, aAccessible, aFlags);
return utterance;
},
columnheader: function columnheader() {
return this.objectOutputFunctions.cell.apply(this, arguments);
},
rowheader: function rowheader() {
return this.objectOutputFunctions.cell.apply(this, arguments);
}
},
@ -401,7 +493,7 @@ this.UtteranceGenerator = {
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {
try {
return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
return gStringBundle.GetStringFromName(this._getOutputName(aRoleStr));
} catch (x) {
return '';
}
@ -467,8 +559,11 @@ this.BrailleGenerator = {
defaultOutputOrder: OUTPUT_DESC_LAST,
objectOutputFunctions: {
__proto__: OutputGenerator.objectOutputFunctions,
defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
let braille = OutputGenerator.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
let braille = this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
if (aAccessible.indexInParent === 1 &&
aAccessible.parent.role == Ci.nsIAccessibleRole.ROLE_LISTITEM &&
@ -492,6 +587,38 @@ this.BrailleGenerator = {
return braille;
},
cell: function cell(aAccessible, aRoleStr, aStates, aFlags, aContext) {
let braille = [];
let cell = aContext.getCellInfo(aAccessible);
if (cell) {
let desc = [];
let addHeaders = function addHeaders(aDesc, aHeaders) {
if (aHeaders.length > 0) {
aDesc.push.apply(aDesc, aHeaders);
}
};
desc.push(gStringBundle.formatStringFromName(
this._getOutputName('cellInfo'), [cell.columnIndex + 1,
cell.rowIndex + 1], 2));
addHeaders(desc, cell.columnHeaders);
addHeaders(desc, cell.rowHeaders);
braille.push(desc.join(' '));
}
this._addName(braille, aAccessible, aFlags);
return braille;
},
columnheader: function columnheader() {
return this.objectOutputFunctions.cell.apply(this, arguments);
},
rowheader: function rowheader() {
return this.objectOutputFunctions.cell.apply(this, arguments);
},
statictext: function statictext(aAccessible, aRoleStr, aStates, aFlags) {
// Since we customize the list bullet's output, we add the static
// text from the first node in each listitem, so skip it here.
@ -523,10 +650,6 @@ this.BrailleGenerator = {
togglebutton: function radiobutton(aAccessible, aRoleStr, aStates, aFlags) {
return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
},
entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
return OutputGenerator.objectOutputFunctions.entry.apply(this, arguments);
}
},
@ -538,12 +661,17 @@ this.BrailleGenerator = {
return [];
},
_getOutputName: function _getOutputName(aName) {
return OutputGenerator._getOutputName(aName) + 'Abbr';
},
_getLocalizedRole: function _getLocalizedRole(aRoleStr) {
try {
return gStringBundle.GetStringFromName(aRoleStr.replace(' ', '') + 'Abbr');
return gStringBundle.GetStringFromName(this._getOutputName(aRoleStr));
} catch (x) {
try {
return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
return gStringBundle.GetStringFromName(
OutputGenerator._getOutputName(aRoleStr));
} catch (y) {
return '';
}

View File

@ -155,7 +155,7 @@ VisualPresenter.prototype = {
}
};
} catch (e) {
Logger.error('Failed to get bounds: ' + e);
Logger.logException(e, 'Failed to get bounds');
return null;
}
},
@ -398,6 +398,19 @@ SpeechPresenter.prototype = {
]
}
};
},
actionInvoked: function SpeechPresenter_actionInvoked(aObject, aActionName) {
return {
type: this.type,
details: {
actions: [
{method: 'speak',
data: UtteranceGenerator.genForAction(aObject, aActionName).join(' '),
options: {enqueue: false}}
]
}
};
}
};

View File

@ -9,6 +9,10 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
const FILTER_IGNORE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
const FILTER_MATCH = Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
const FILTER_IGNORE_SUBTREE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
this.EXPORTED_SYMBOLS = ['TraversalRules'];
Cu.import('resource://gre/modules/accessibility/Utils.jsm');
@ -35,14 +39,13 @@ BaseTraversalRule.prototype = {
{
if (aAccessible.role == Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME) {
return (Utils.getMessageManager(aAccessible.DOMNode)) ?
Ci.nsIAccessibleTraversalRule.FILTER_MATCH :
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
FILTER_MATCH | FILTER_IGNORE_SUBTREE : FILTER_IGNORE;
}
if (this._matchFunc)
return this._matchFunc(aAccessible);
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
@ -78,40 +81,40 @@ this.TraversalRules = {
case Ci.nsIAccessibleRole.ROLE_COMBOBOX:
// We don't want to ignore the subtree because this is often
// where the list box hangs out.
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
case Ci.nsIAccessibleRole.ROLE_TEXT_LEAF:
{
// Nameless text leaves are boring, skip them.
let name = aAccessible.name;
if (name && name.trim())
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
else
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
return FILTER_IGNORE;
}
case Ci.nsIAccessibleRole.ROLE_LINK:
// If the link has children we should land on them instead.
// Image map links don't have children so we need to match those.
if (aAccessible.childCount == 0)
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
else
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
return FILTER_IGNORE;
case Ci.nsIAccessibleRole.ROLE_STATICTEXT:
{
let parent = aAccessible.parent;
// Ignore prefix static text in list items. They are typically bullets or numbers.
if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
parent.role == Ci.nsIAccessibleRole.ROLE_LISTITEM)
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
return FILTER_IGNORE;
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
}
case Ci.nsIAccessibleRole.ROLE_GRAPHIC:
return TraversalRules._shouldSkipImage(aAccessible);
default:
// Ignore the subtree, if there is one. So that we don't land on
// the same content that was already presented by its parent.
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
return FILTER_MATCH |
FILTER_IGNORE_SUBTREE;
}
}
),
@ -119,8 +122,8 @@ this.TraversalRules = {
SimpleTouch: new BaseTraversalRule(
gSimpleTraversalRoles,
function Simple_match(aAccessible) {
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH |
Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
return FILTER_MATCH |
FILTER_IGNORE_SUBTREE;
}
),
@ -133,9 +136,9 @@ this.TraversalRules = {
let extraState = {};
aAccessible.getState(state, extraState);
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
return FILTER_IGNORE;
} else {
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
}
}),
@ -193,9 +196,9 @@ this.TraversalRules = {
let extraState = {};
aAccessible.getState(state, extraState);
if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
} else {
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
return FILTER_IGNORE;
}
}),
@ -222,8 +225,8 @@ this.TraversalRules = {
_shouldSkipImage: function _shouldSkipImage(aAccessible) {
if (gSkipEmptyImages.value && aAccessible.name === '') {
return Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
return FILTER_IGNORE;
}
return Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
return FILTER_MATCH;
}
};

View File

@ -191,15 +191,18 @@ this.Utils = {
},
getAttributes: function getAttributes(aAccessible) {
let attributesEnum = aAccessible.attributes.enumerate();
let attributes = {};
// Populate |attributes| object with |aAccessible|'s attribute key-value
// pairs.
while (attributesEnum.hasMoreElements()) {
let attribute = attributesEnum.getNext().QueryInterface(
Ci.nsIPropertyElement);
attributes[attribute.key] = attribute.value;
if (aAccessible && aAccessible.attributes) {
let attributesEnum = aAccessible.attributes.enumerate();
// Populate |attributes| object with |aAccessible|'s attribute key-value
// pairs.
while (attributesEnum.hasMoreElements()) {
let attribute = attributesEnum.getNext().QueryInterface(
Ci.nsIPropertyElement);
attributes[attribute.key] = attribute.value;
}
}
return attributes;
@ -268,12 +271,27 @@ this.Logger = {
this, [this.ERROR].concat(Array.prototype.slice.call(arguments)));
},
logException: function logException(aException) {
logException: function logException(
aException, aErrorMessage = 'An exception has occured') {
try {
let args = [aException.message];
args.push.apply(args, aException.stack ? ['\n', aException.stack] :
['(' + aException.fileName + ':' + aException.lineNumber + ')']);
this.error.apply(this, args);
let stackMessage = '';
if (aException.stack) {
stackMessage = ' ' + aException.stack.replace(/\n/g, '\n ');
} else if (aException.location) {
let frame = aException.location;
let stackLines = [];
while (frame && frame.lineNumber) {
stackLines.push(
' ' + frame.name + '@' + frame.filename + ':' + frame.lineNumber);
frame = frame.caller;
}
stackMessage = stackLines.join('\n');
} else {
stackMessage = '(' + aException.fileName + ':' + aException.lineNumber + ')';
}
this.error(aErrorMessage + ':\n ' +
aException.message + '\n' +
stackMessage);
} catch (x) {
this.error(x);
}
@ -350,6 +368,45 @@ PivotContext.prototype = {
return this._oldAccessible;
},
/**
* Get a list of |aAccessible|'s ancestry up to the root.
* @param {nsIAccessible} aAccessible.
* @return {Array} Ancestry list.
*/
_getAncestry: function _getAncestry(aAccessible) {
let ancestry = [];
let parent = aAccessible;
while (parent && (parent = parent.parent)) {
ancestry.push(parent);
}
return ancestry.reverse();
},
/**
* A list of the old accessible's ancestry.
*/
get oldAncestry() {
if (!this._oldAncestry) {
if (!this._oldAccessible) {
this._oldAncestry = [];
} else {
this._oldAncestry = this._getAncestry(this._oldAccessible);
this._oldAncestry.push(this._oldAccessible);
}
}
return this._oldAncestry;
},
/**
* A list of the current accessible's ancestry.
*/
get currentAncestry() {
if (!this._currentAncestry) {
this._currentAncestry = this._getAncestry(this._accessible);
}
return this._currentAncestry;
},
/*
* This is a list of the accessible's ancestry up to the common ancestor
* of the accessible and the old accessible. It is useful for giving the
@ -357,32 +414,10 @@ PivotContext.prototype = {
*/
get newAncestry() {
if (!this._newAncestry) {
let newLineage = [];
let oldLineage = [];
let parent = this._accessible;
while (parent && (parent = parent.parent))
newLineage.push(parent);
parent = this._oldAccessible;
while (parent && (parent = parent.parent))
oldLineage.push(parent);
this._newAncestry = [];
while (true) {
let newAncestor = newLineage.pop();
let oldAncestor = oldLineage.pop();
if (newAncestor == undefined)
break;
if (newAncestor != oldAncestor)
this._newAncestry.push(newAncestor);
}
this._newAncestry = [currentAncestor for (
[index, currentAncestor] of Iterator(this.currentAncestry)) if (
currentAncestor !== this.oldAncestry[index])];
}
return this._newAncestry;
},
@ -426,6 +461,99 @@ PivotContext.prototype = {
return this._traverse(this._accessible, aPreorder, aStop);
},
getCellInfo: function getCellInfo(aAccessible) {
if (!this._cells) {
this._cells = new WeakMap();
}
let domNode = aAccessible.DOMNode;
if (this._cells.has(domNode)) {
return this._cells.get(domNode);
}
let cellInfo = {};
let getAccessibleCell = function getAccessibleCell(aAccessible) {
if (!aAccessible) {
return null;
}
if ([Ci.nsIAccessibleRole.ROLE_CELL,
Ci.nsIAccessibleRole.ROLE_COLUMNHEADER,
Ci.nsIAccessibleRole.ROLE_ROWHEADER].indexOf(
aAccessible.role) < 0) {
return null;
}
try {
return aAccessible.QueryInterface(Ci.nsIAccessibleTableCell);
} catch (x) {
Logger.logException(x);
return null;
}
};
let getHeaders = function getHeaders(aHeaderCells) {
let enumerator = aHeaderCells.enumerate();
while (enumerator.hasMoreElements()) {
yield enumerator.getNext().QueryInterface(Ci.nsIAccessible).name;
}
};
cellInfo.current = getAccessibleCell(aAccessible);
if (!cellInfo.current) {
Logger.warning(aAccessible,
'does not support nsIAccessibleTableCell interface.');
this._cells.set(domNode, null);
return null;
}
let table = cellInfo.current.table;
if (table.isProbablyForLayout()) {
this._cells.set(domNode, null);
return null;
}
cellInfo.previous = null;
let oldAncestry = this.oldAncestry.reverse();
let ancestor = oldAncestry.shift();
while (!cellInfo.previous && ancestor) {
let cell = getAccessibleCell(ancestor);
if (cell && cell.table === table) {
cellInfo.previous = cell;
}
ancestor = oldAncestry.shift();
}
if (cellInfo.previous) {
cellInfo.rowChanged = cellInfo.current.rowIndex !==
cellInfo.previous.rowIndex;
cellInfo.columnChanged = cellInfo.current.columnIndex !==
cellInfo.previous.columnIndex;
} else {
cellInfo.rowChanged = true;
cellInfo.columnChanged = true;
}
cellInfo.rowExtent = cellInfo.current.rowExtent;
cellInfo.columnExtent = cellInfo.current.columnExtent;
cellInfo.columnIndex = cellInfo.current.columnIndex;
cellInfo.rowIndex = cellInfo.current.rowIndex;
cellInfo.columnHeaders = [];
if (cellInfo.columnChanged && cellInfo.current.role !==
Ci.nsIAccessibleRole.ROLE_COLUMNHEADER) {
cellInfo.columnHeaders = [headers for (headers of getHeaders(
cellInfo.current.columnHeaderCells))];
}
cellInfo.rowHeaders = [];
if (cellInfo.rowChanged && cellInfo.current.role ===
Ci.nsIAccessibleRole.ROLE_CELL) {
cellInfo.rowHeaders = [headers for (headers of getHeaders(
cellInfo.current.rowHeaderCells))];
}
this._cells.set(domNode, cellInfo);
return cellInfo;
},
get bounds() {
if (!this._bounds) {
let objX = {}, objY = {}, objW = {}, objH = {};

View File

@ -93,7 +93,7 @@ function virtualCursorControl(aMessage) {
sendAsyncMessage('AccessFu:VirtualCursor', aMessage.json);
}
} catch (x) {
Logger.error(x);
Logger.logException(x, 'Failed to move virtual cursor');
}
}

View File

@ -15,9 +15,10 @@ MOCHITEST_A11Y_FILES =\
jsatcommon.js \
output.js \
test_alive.html \
test_explicit_names.html \
test_utterance_order.html \
test_braille.html \
test_explicit_names.html \
test_tables.html \
test_utterance_order.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -37,7 +37,8 @@ function testContextOutput(expected, aAccOrElmOrID, aOldAccOrElmOrID, aGenerator
*/
function testObjectOutput(aAccOrElmOrID, aGenerator) {
var accessible = getAccessible(aAccOrElmOrID);
var output = aGenerator.genForObject(accessible);
var context = new PivotContext(accessible);
var output = aGenerator.genForObject(accessible, context);
var outputOrder;
try {
outputOrder = SpecialPowers.getIntPref(PREF_UTTERANCE_ORDER);

View File

@ -54,9 +54,10 @@
expected: ["list 2 items", "Test List", "Last item", "2.", "list two"]
}, {
accOrElmOrID: "cell",
expected: ["table", "Fruits and vegetables", "List of Fruits",
"list 4 items","First item", "link", "Apples", "link", "Bananas",
"link", "Peaches", "Last item", "link", "Plums"]
expected: ["table with 1 column and 1 row", "Fruits and vegetables",
"Column 1 Row 1", "List of Fruits", "list 4 items", "First item",
"link", "Apples", "link", "Bananas", "link", "Peaches", "Last item",
"link", "Plums"]
}, {
accOrElmOrID: "app.net",
expected: ["list 2 items", "First item", "link", "star", "Last item",
@ -71,13 +72,12 @@
// Test pivot to li_one from list.
accOrElmOrID: "li_one",
oldAccOrElmOrID: "list",
expected: ["list 2 items", "Test List", "First item", "Top of the list"]
expected: ["First item", "Top of the list"]
}, {
// Test pivot to "apples" link from the table cell.
accOrElmOrID: "apples",
oldAccOrElmOrID: "cell",
expected: ["List of Fruits", "list 4 items", "First item", "link",
"Apples"]
expected: ["list 4 items", "First item", "link", "Apples"]
}, {
// Test pivot to the table cell from the "apples" link.
accOrElmOrID: "cell",

View File

@ -0,0 +1,297 @@
<html>
<head>
<title>[AccessFu] Improve reading of table semantics</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="output.js"></script>
<script type="application/javascript">
function doTest() {
// Test the following accOrElmOrID.
var tests = [{
accOrElmOrID: "table1",
expectedUtterance: [["table with 2 columns and 2 rows",
"Column 1 Row 1", "col1", "Column 2 Row 1", "col2",
"Column 1 Row 2 col1", "cell1", "Column 2 Row 2 col2", "cell2"], [
"col1", "Column 1 Row 1", "col2", "Column 2 Row 1", "cell1",
"Column 1 Row 2 col1", "cell2", "Column 2 Row 2 col2",
"table with 2 columns and 2 rows"]],
expectedBraille: [["tbl 2c 2r", "c1r1", "col1", "c2r1", "col2",
"c1r2 col1", "cell1", "c2r2 col2", "cell2"], ["col1", "c1r1", "col2",
"c2r1", "cell1", "c1r2 col1", "cell2", "c2r2 col2", "tbl 2c 2r"]]
}, {
accOrElmOrID: "table2",
expectedUtterance: [["table with 2 columns and 2 rows",
"Column 1 Row 1 col1", "cell1", "Column 2 Row 1 col2",
"table with 1 column and 2 rows", "Column 1 Row 1", "colheader",
"Column 1 Row 2 colheader", "bla", "Column 1 Row 2", "col1",
"Column 2 Row 2", "col2"], ["cell1", "Column 1 Row 1 col1",
"colheader", "Column 1 Row 1", "bla", "Column 1 Row 2 colheader",
"table with 1 column and 2 rows", "Column 2 Row 1 col2", "col1",
"Column 1 Row 2", "col2", "Column 2 Row 2",
"table with 2 columns and 2 rows"]],
expectedBraille: [["tbl 2c 2r", "c1r1 col1", "cell1", "c2r1 col2",
"tbl 1c 2r", "c1r1", "colheader", "c1r2 colheader", "bla", "c1r2",
"col1", "c2r2", "col2"], ["cell1", "c1r1 col1", "colheader", "c1r1",
"bla", "c1r2 colheader", "tbl 1c 2r", "c2r1 col2", "col1", "c1r2",
"col2", "c2r2", "tbl 2c 2r"]]
}, {
accOrElmOrID: "table3",
expectedUtterance: [["table with 2 columns and 2 rows",
"Column 2 Row 1 col2", "table with 1 column and 2 rows",
"Column 1 Row 1", "colheader", "Column 1 Row 2 colheader", "bla"], [
"colheader", "Column 1 Row 1", "bla", "Column 1 Row 2 colheader",
"table with 1 column and 2 rows", "Column 2 Row 1 col2",
"table with 2 columns and 2 rows"]],
expectedBraille: [["tbl 1c 2r", "c1r1", "colheader", "c1r2 colheader",
"bla"], ["colheader", "c1r1", "bla", "c1r2 colheader", "tbl 1c 2r"]]
}, {
accOrElmOrID: "table4",
expectedUtterance: [["table with 4 columns and 3 rows",
"Column 1 Row 1", "col1", "Column 2 Row 1", "col2", "Column 3 Row 1",
"col3", "Column 1 Row 2 spans 2 columns col1", "row1",
"Column 3 Row 2 col3 row1", "cell1",
"Column 4 Row 2 spans 2 rows row1", "cell2", "Column 1 Row 3 col1",
"row2", "Column 2 Row 3 col2 row2", "cell3",
"Column 3 Row 3 col3 row2", "cell4"], ["col1", "Column 1 Row 1",
"col2", "Column 2 Row 1", "col3", "Column 3 Row 1", "row1",
"Column 1 Row 2 spans 2 columns col1", "cell1",
"Column 3 Row 2 col3 row1", "cell2",
"Column 4 Row 2 spans 2 rows row1", "row2", "Column 1 Row 3 col1",
"cell3", "Column 2 Row 3 col2 row2", "cell4",
"Column 3 Row 3 col3 row2", "table with 4 columns and 3 rows"]],
expectedBraille: [["tbl 4c 3r", "c1r1", "col1", "c2r1", "col2", "c3r1",
"col3", "c1r2 col1", "row1", "c3r2 col3 row1", "cell1", "c4r2 row1",
"cell2", "c1r3 col1", "row2", "c2r3 col2 row2", "cell3",
"c3r3 col3 row2", "cell4"], ["col1", "c1r1", "col2", "c2r1", "col3",
"c3r1", "row1", "c1r2 col1", "cell1", "c3r2 col3 row1", "cell2",
"c4r2 row1", "row2", "c1r3 col1", "cell3", "c2r3 col2 row2", "cell4",
"c3r3 col3 row2", "tbl 4c 3r"]]
}, {
accOrElmOrID: "table5",
expectedUtterance: [["Row1", "Row2"], ["Row1", "Row2"]],
expectedBraille: [["Row1", "Row2"], ["Row1", "Row2"]]
}, {
// Test pivot to table1_th1 from table1.
accOrElmOrID: "table1_th1",
oldAccOrElmOrID: "table1",
expectedUtterance: [["Column 1 Row 1", "col1"], ["col1",
"Column 1 Row 1"]],
expectedBraille: [["c1r1", "col1"], ["col1", "c1r1"]]
}, {
// Test pivot to table1_td2 from table1.
accOrElmOrID: "table1_td2",
oldAccOrElmOrID: "table1",
expectedUtterance: [["Column 2 Row 2 col2", "cell2"], ["cell2",
"Column 2 Row 2 col2"]],
expectedBraille: [["c2r2 col2", "cell2"], ["cell2", "c2r2 col2"]]
}, {
// Test pivot to table1_td2 from table1_th1.
accOrElmOrID: "table1_td2",
oldAccOrElmOrID: "table1_th1",
expectedUtterance: [["Column 2 Row 2 col2", "cell2"], ["cell2",
"Column 2 Row 2 col2"]],
expectedBraille: [["c2r2 col2", "cell2"], ["cell2", "c2r2 col2"]]
}, {
// Test pivot to table1_td2 from table1_td1.
accOrElmOrID: "table1_td2",
oldAccOrElmOrID: "table1_td1",
expectedUtterance: [["Column 2 col2", "cell2"], ["cell2",
"Column 2 col2"]],
expectedBraille: [["c2r2 col2", "cell2"], ["cell2", "c2r2 col2"]]
}, {
// Test pivot to table2_cell_1 from table2.
accOrElmOrID: "table2_cell_1",
oldAccOrElmOrID: "table2",
expectedUtterance: [["Column 1 Row 1 col1", "cell1"], ["cell1",
"Column 1 Row 1 col1"]],
expectedBraille: [["c1r1 col1", "cell1"], ["cell1", "c1r1 col1"]]
}, {
// Test pivot to table2_cell_2 from table2.
accOrElmOrID: "table2_cell_2",
oldAccOrElmOrID: "table2",
expectedUtterance: [["Column 2 Row 1 col2",
"table with 1 column and 2 rows", "Column 1 Row 1", "colheader",
"Column 1 Row 2 colheader", "bla"], ["colheader", "Column 1 Row 1",
"bla", "Column 1 Row 2 colheader", "table with 1 column and 2 rows",
"Column 2 Row 1 col2"]],
expectedBraille: [["c2r1 col2", "tbl 1c 2r", "c1r1", "colheader",
"c1r2 colheader", "bla"], ["colheader", "c1r1", "bla",
"c1r2 colheader", "tbl 1c 2r", "c2r1 col2"]]
}, {
// Test pivot to table2_cell_1 from table2_cell_2.
accOrElmOrID: "table2_cell_1",
oldAccOrElmOrID: "table2_cell_2",
expectedUtterance: [["Column 1 col1", "cell1"], ["cell1",
"Column 1 col1"]],
expectedBraille: [["c1r1 col1", "cell1"], ["cell1", "c1r1 col1"]]
}, {
// Test pivot to table3_cell from table2.
accOrElmOrID: "table3_cell",
oldAccOrElmOrID: "table2",
expectedUtterance: [["Column 2 Row 1 col2",
"table with 1 column and 2 rows", "Column 1 Row 2 colheader",
"bla"], ["bla", "Column 1 Row 2 colheader",
"table with 1 column and 2 rows", "Column 2 Row 1 col2"]],
expectedBraille: [["c1r2 colheader", "bla"], ["bla", "c1r2 colheader"]]
}, {
// Test pivot to table3_cell from table2_cell_1.
accOrElmOrID: "table3_cell",
oldAccOrElmOrID: "table2_cell_1",
expectedUtterance: [["Column 2 col2", "table with 1 column and 2 rows",
"Column 1 Row 2 colheader", "bla"], ["bla",
"Column 1 Row 2 colheader", "table with 1 column and 2 rows",
"Column 2 Row 1 col2"]],
expectedBraille: [["c1r2 colheader", "bla"], ["bla", "c1r2 colheader"]]
}, {
// Test pivot to table3_cell from table3_ch.
accOrElmOrID: "table3_cell",
oldAccOrElmOrID: "table3_ch",
expectedUtterance: [["Row 2", "bla"], ["bla", "Row 2"]],
expectedBraille: [["c1r2", "bla"], ["bla", "c1r2"]]
}, {
// Test pivot to table3_cell from table1_td1.
accOrElmOrID: "table3_cell",
oldAccOrElmOrID: "table1_td1",
expectedUtterance: [["table with 2 columns and 2 rows",
"Column 2 Row 1 col2", "table with 1 column and 2 rows",
"Column 1 Row 2 colheader", "bla"], ["bla",
"Column 1 Row 2 colheader", "table with 1 column and 2 rows",
"Column 2 Row 1 col2", "table with 2 columns and 2 rows"]],
expectedBraille: [["c1r2 colheader", "bla"], ["bla", "c1r2 colheader"]]
}, {
// Test pivot to table4_ch_3 from table4.
accOrElmOrID: "table4_ch_3",
oldAccOrElmOrID: "table4",
expectedUtterance: [["Column 3 Row 1", "col3"], ["col3",
"Column 3 Row 1"]],
expectedBraille: [["c3r1", "col3"], ["col3", "c3r1"]]
}, {
// Test pivot to table4_rh_1 from table4_ch_3.
accOrElmOrID: "table4_rh_1",
oldAccOrElmOrID: "table4_ch_3",
expectedUtterance: [["Column 1 Row 2 spans 2 columns col1", "row1"], [
"row1", "Column 1 Row 2 spans 2 columns col1"]],
expectedBraille: [["c1r2 col1", "row1"], ["row1", "c1r2 col1"]]
}, {
// Test pivot to table4_cell_3 from table4_rh_1.
accOrElmOrID: "table4_cell_3",
oldAccOrElmOrID: "table4_rh_1",
expectedUtterance: [["Column 4 spans 2 rows", "cell2"], ["cell2",
"Column 4 spans 2 rows"]],
expectedBraille: [["c4r2", "cell2"], ["cell2", "c4r2"]]
}, {
// Test pivot to table4_cell_5 from table4_cell_3.
accOrElmOrID: "table4_cell_5",
oldAccOrElmOrID: "table4_cell_3",
expectedUtterance: [["Column 2 Row 3 col2 row2", "cell3"], ["cell3",
"Column 2 Row 3 col2 row2"]],
expectedBraille: [["c2r3 col2 row2", "cell3"], ["cell3",
"c2r3 col2 row2"]]
}];
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, 0);
// Test outputs (utterance and braille) for tables including their
// headers and cells.
tests.forEach(function run(test) {
var outputOrderValues = [0, 1];
outputOrderValues.forEach(function testOutputOrder(outputOrder) {
SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, outputOrder);
testOutput(test.expectedUtterance[outputOrder], test.accOrElmOrID,
test.oldAccOrElmOrID, 1);
testOutput(test.expectedBraille[outputOrder], test.accOrElmOrID,
test.oldAccOrElmOrID, 0);
});
});
// If there was an original utterance order preference, revert to it.
SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<div id="root">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=830748"
title="[AccessFu] Improve reading of table semantics">
Mozilla Bug 830748
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<table id="table1">
<thead>
<tr>
<th id="table1_th1">col1</th>
<th>col2</th>
</tr>
</thead>
<tbody>
<tr>
<td id="table1_td1">cell1</td>
<td id="table1_td2">cell2</td>
</tr>
</tbody>
</table>
<table id="table2" border="1">
<tr>
<td id="table2_cell_1" headers="table2_ch_1">cell1</td>
<td id="table2_cell_2" headers="table2_ch_2">
<table id="table3">
<thead>
<tr>
<th id="table3_ch">colheader</th>
</tr>
</thead>
<tbody>
<tr>
<td id="table3_cell">bla</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td id="table2_ch_1" scope="col">col1</td>
<td id="table2_ch_2" scope="col">col2</td>
</tr>
</table>
<table id="table4" border="1">
<thead>
<tr>
<th id="table4_ch_1">col1</th>
<th id="table4_ch_2">col2</th>
<td id="table4_ch_3" scope="col">col3</td>
</tr>
</thead>
<tbody>
<tr>
<th id="table4_rh_1" colspan="2">row1</th>
<td id="table4_cell_2">cell1</td>
<td id="table4_cell_3" rowspan="2">cell2</td>
</tr>
<tr>
<td id="table4_rh_2" scope="row">row2</td>
<td id="table4_cell_5">cell3</td>
<td id="table4_cell_6">cell4</td>
</tr>
</tbody>
</table>
<table id="table5">
<tr><td>Row1</td></tr>
<tr><td>Row2</td></tr>
</table>
</div>
</body>
</html>

View File

@ -57,13 +57,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984
}, {
accOrElmOrID: "cell",
expected: [[
"table", "Fruits and vegetables", "list 4 items", "First item",
"link", "Apples", "link", "Bananas", "link", "Peaches",
"Last item", "link", "Plums"
"table with 1 column and 1 row", "Fruits and vegetables",
"Column 1 Row 1", "list 4 items", "First item", "link", "Apples",
"link", "Bananas", "link", "Peaches", "Last item", "link", "Plums"
], [
"Apples", "link", "First item", "Bananas", "link", "Peaches",
"link", "Plums", "link", "Last item", "list 4 items",
"Fruits and vegetables", "table"
"Column 1 Row 1", "Fruits and vegetables",
"table with 1 column and 1 row"
]]
}, {
// Test pivot to list from li_one.

View File

@ -180,6 +180,11 @@
label="&viewImageInfoCmd.label;"
accesskey="&viewImageInfoCmd.accesskey;"
oncommand="gContextMenu.viewImageInfo();"/>
<menuitem id="context-viewimagedesc"
label="&viewImageDescCmd.label;"
accesskey="&viewImageDescCmd.accesskey;"
oncommand="gContextMenu.viewImageDesc(event);"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-savevideo"
label="&saveVideoCmd.label;"
accesskey="&saveVideoCmd.accesskey;"

View File

@ -261,6 +261,7 @@ nsContextMenu.prototype = {
.disabled = !this.hasBGImage;
this.showItem("context-viewimageinfo", this.onImage);
this.showItem("context-viewimagedesc", this.onImage && this.imageDescURL !== "");
},
initMiscItems: function CM_initMiscItems() {
@ -499,6 +500,7 @@ nsContextMenu.prototype = {
this.onImage = false;
this.onLoadedImage = false;
this.onCompletedImage = false;
this.imageDescURL = "";
this.onCanvas = false;
this.onVideo = false;
this.onAudio = false;
@ -548,6 +550,11 @@ nsContextMenu.prototype = {
this.onCompletedImage = true;
this.mediaURL = this.target.currentURI.spec;
var descURL = this.target.getAttribute("longdesc");
if (descURL) {
this.imageDescURL = makeURLAbsolute(this.target.ownerDocument.body.baseURI, descURL);
}
}
else if (this.target instanceof HTMLCanvasElement) {
this.onCanvas = true;
@ -874,6 +881,14 @@ nsContextMenu.prototype = {
"mediaTab", this.target);
},
viewImageDesc: function(e) {
var doc = this.target.ownerDocument;
urlSecurityCheck(this.imageDescURL, this.browser.contentPrincipal,
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
openUILink(this.imageDescURL, e, { disallowInheritPrincipal: true,
referrerURI: doc.documentURIObject });
},
viewFrameInfo: function() {
BrowserPageInfo(this.target.ownerDocument);
},

View File

@ -66,5 +66,6 @@ Browser context menu subtest.
<input id="test-select-input-text" type="text" value="input">
<input id="test-select-input-text-type-password" type="password" value="password">
<embed id="test-plugin" style="width: 200px; height: 200px;" type="application/x-test"></embed>
<img id="test-longdesc" src="ctxmenu-image.png" longdesc="http://www.mozilla.org"></embed>
</body>
</html>

View File

@ -939,6 +939,22 @@ function runTest(testNum) {
tag.enabledState = SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED;
}
}
openContextMenuFor(longdesc);
return;
case 30:
// Context menu for an image with longdesc
checkContextMenu(["context-viewimage", true,
"context-copyimage-contents", true,
"context-copyimage", true,
"---", null,
"context-saveimage", true,
"context-sendimage", true,
"context-setDesktopBackground", true,
"context-viewimageinfo", true,
"context-viewimagedesc", true
].concat(inspectItems));
closeContextMenu();
// finish test
subwindow.close();
@ -968,7 +984,7 @@ var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
iframe, video_in_iframe, image_in_iframe, textarea, contenteditable,
inputspell, pagemenu, dom_full_screen, plainTextItems, audio_in_video,
selecttext, selecttextlink, imagelink, select_inputtext, select_inputtext_password,
plugin;
plugin, longdesc;
function startTest() {
chromeWin = SpecialPowers.wrap(subwindow)
@ -1017,6 +1033,7 @@ function startTest() {
select_inputtext = subwindow.document.getElementById("test-select-input-text");
select_inputtext_password = subwindow.document.getElementById("test-select-input-text-type-password");
plugin = subwindow.document.getElementById("test-plugin");
longdesc = subwindow.document.getElementById("test-longdesc");
contextMenu.addEventListener("popupshown", function() { runTest(++testNum); }, false);
runTest(1);

View File

@ -63,7 +63,7 @@ richlistitem[type="download"]:not([selected]) button {
display: none;
}
/*** Visibility of download buttons and indicator controls. ***/
/*** Visibility of download buttons ***/
.download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
[state="5"], /* Starting (queued) */
@ -76,16 +76,7 @@ richlistitem[type="download"]:not([selected]) button {
.downloadRetry,
.download-state:not( [state="1"] /* Finished */)
.downloadShow,
#downloads-indicator:-moz-any([progress],
[counter],
[paused]) #downloads-indicator-icon,
#downloads-indicator:not(:-moz-any([progress],
[counter],
[paused]))
#downloads-indicator-progress-area
.downloadShow
{
visibility: hidden;
@ -103,21 +94,3 @@ richlistitem[type="download"]:not([selected]) button {
{
display: none;
}
/* Hacks for toolbar full and text modes, until bug 573329 removes them */
toolbar[mode="text"] > #downloads-indicator {
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-pack: center;
}
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-text {
-moz-box-ordinal-group: 1;
}
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-icon {
display: -moz-box;
-moz-box-ordinal-group: 2;
visibility: collapse;
}

View File

@ -0,0 +1,36 @@
/* 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/. */
/*** Visibility of indicator controls ***/
#downloads-indicator:-moz-any([progress],
[counter],
[paused]) #downloads-indicator-icon,
#downloads-indicator:not(:-moz-any([progress],
[counter],
[paused]))
#downloads-indicator-progress-area
{
visibility: hidden;
}
/* Hacks for toolbar full and text modes, until bug 573329 removes them */
toolbar[mode="text"] > #downloads-indicator {
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-pack: center;
}
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-text {
-moz-box-ordinal-group: 1;
}
toolbar[mode="text"] > #downloads-indicator > .toolbarbutton-icon {
display: -moz-box;
-moz-box-ordinal-group: 2;
visibility: collapse;
}

View File

@ -6,8 +6,8 @@
- 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/. -->
<?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css"?>
<?xml-stylesheet href="chrome://browser/content/downloads/indicator.css"?>
<?xml-stylesheet href="chrome://browser/skin/downloads/indicator.css"?>
<!DOCTYPE overlay [
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >

View File

@ -8,6 +8,7 @@ browser.jar:
content/browser/downloads/downloads.css (content/downloads.css)
* content/browser/downloads/downloads.js (content/downloads.js)
* content/browser/downloads/downloadsOverlay.xul (content/downloadsOverlay.xul)
content/browser/downloads/indicator.css (content/indicator.css)
content/browser/downloads/indicator.js (content/indicator.js)
content/browser/downloads/indicatorOverlay.xul (content/indicatorOverlay.xul)
* content/browser/downloads/allDownloadsViewOverlay.xul (content/allDownloadsViewOverlay.xul)

View File

@ -408,6 +408,8 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY viewImageCmd.accesskey "I">
<!ENTITY viewImageInfoCmd.label "View Image Info">
<!ENTITY viewImageInfoCmd.accesskey "f">
<!ENTITY viewImageDescCmd.label "View Description">
<!ENTITY viewImageDescCmd.accesskey "D">
<!ENTITY viewVideoCmd.label "View Video">
<!ENTITY viewVideoCmd.accesskey "I">
<!ENTITY viewBGImageCmd.label "View Background Image">

View File

@ -0,0 +1,334 @@
/* 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/. */
// Fired when any context ui is displayed
const kContextUIShowEvent = "MozContextUIShow";
// Fired when any context ui is dismissed
const kContextUIDismissEvent = "MozContextUIDismiss";
// Fired when the tabtray is displayed
const kContextUITabsShowEvent = "MozContextUITabsShow";
// add more as needed...
// delay for ContextUI's dismissWithDelay
const kHideContextAndTrayDelayMsec = 3000;
// delay when showing the tab bar briefly as a new tab opens
const kNewTabAnimationDelayMsec = 1000;
/*
* Manages context UI (navbar, tabbar, appbar) and track visibility. Also
* tracks events that summon and hide the context UI.
*/
var ContextUI = {
_expandable: true,
_hidingId: 0,
/*******************************************
* init
*/
init: function init() {
Elements.browsers.addEventListener("mousedown", this, true);
Elements.browsers.addEventListener("touchstart", this, true);
Elements.browsers.addEventListener("AlertActive", this, true);
Elements.browsers.addEventListener('URLChanged', this, true);
Elements.tabList.addEventListener('TabSelect', this, true);
Elements.panelUI.addEventListener('ToolPanelShown', this, false);
Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
window.addEventListener("MozEdgeUIStarted", this, true);
window.addEventListener("MozEdgeUICanceled", this, true);
window.addEventListener("MozEdgeUICompleted", this, true);
window.addEventListener("keypress", this, true);
window.addEventListener("KeyboardChanged", this, false);
Elements.tray.addEventListener("transitionend", this, true);
Appbar.init();
},
/*******************************************
* Context UI state getters & setters
*/
// any visiblilty
get isVisible() {
return this.navbarVisible || this.tabbarVisible || this.contextAppbarVisible;
},
// navbar visiblilty
get navbarVisible() {
return (Elements.navbar.hasAttribute("visible") ||
Elements.navbar.hasAttribute("startpage"));
},
// tabbar visiblilty
get tabbarVisible() {
return Elements.tray.hasAttribute("expanded");
},
// appbar visiblilty
get contextAppbarVisible() {
return Elements.contextappbar.isShowing;
},
// currently not in use, for the always show tabs feature
get isExpandable() { return this._expandable; },
set isExpandable(aFlag) {
this._expandable = aFlag;
if (!this._expandable)
this.dismiss();
},
/*******************************************
* Public api
*/
/*
* Toggle the current nav UI state. Fires context ui events.
*/
toggleNavUI: function () {
// The navbar is forced open when the start page is visible. appbar.js
// controls the "visible" property, and browser-ui controls the "startpage"
// property. Hence we rely on the tabbar for current toggle state.
if (this.tabbarVisible) {
this.dismiss();
} else {
this.displayNavUI();
}
},
/*
* Show the nav and tabs bar. Returns true if any non-visible UI
* was shown. Fires context ui events.
*/
displayNavUI: function () {
let shown = false;
if (!this.navbarVisible) {
this.displayNavbar();
shown = true;
}
if (!this.tabbarVisible) {
this.displayTabs();
shown = true;
}
if (shown) {
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
this._fire(kContextUIShowEvent);
}
return shown;
},
/*
* Dismiss any context UI currently visible. Returns true if any
* visible UI was dismissed. Fires context ui events.
*/
dismiss: function () {
let dismissed = false;
this._clearDelayedTimeout();
// No assurances this will hide the nav bar. It may have the
// 'startpage' property set. This removes the 'visible' property.
if (this.navbarVisible) {
this.dismissNavbar();
dismissed = true;
}
if (this.tabbarVisible) {
this.dismissTabs();
dismissed = true;
}
if (Elements.contextappbar.isShowing) {
this.dismissContextAppbar();
dismissed = true;
}
if (dismissed) {
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
this._fire(kContextUIDismissEvent);
}
return dismissed;
},
/*
* Briefly show the tab bar and then hide it. Fires context ui events.
*/
peekTabs: function peekTabs() {
if (this.tabbarVisible) {
setTimeout(function () {
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
}, 0);
} else {
BrowserUI.setOnTabAnimationEnd(function () {
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
});
this.displayTabs();
}
},
/*
* Dismiss all context ui after a delay. Fires context ui events.
*/
dismissWithDelay: function dismissWithDelay(aDelay) {
aDelay = aDelay || kHideContextAndTrayDelayMsec;
this._clearDelayedTimeout();
this._hidingId = setTimeout(function () {
ContextUI.dismiss();
}, aDelay);
},
// Cancel any pending delayed dismiss
cancelDismiss: function cancelDismiss() {
this._clearDelayedTimeout();
},
// Display the nav bar
displayNavbar: function () {
this._clearDelayedTimeout();
Elements.navbar.show();
},
// Display the tab tray
displayTabs: function () {
this._clearDelayedTimeout();
this._setIsExpanded(true);
},
// Display the app bar
displayContextAppbar: function () {
this._clearDelayedTimeout();
Elements.contextappbar.show();
},
// Dismiss the navbar if visible.
dismissNavbar: function dismissNavbar() {
Elements.navbar.dismiss();
},
// Dismiss the tabstray if visible.
dismissTabs: function dimissTabs() {
this._clearDelayedTimeout();
this._setIsExpanded(false);
},
// Dismiss the appbar if visible.
dismissContextAppbar: function dismissContextAppbar() {
Elements.contextappbar.dismiss();
},
/*******************************************
* Internal utils
*/
// tabtray state
_setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
// if the tray can't be expanded, don't expand it.
if (!this.isExpandable || this.tabbarVisible == aFlag)
return;
if (aFlag)
Elements.tray.setAttribute("expanded", "true");
else
Elements.tray.removeAttribute("expanded");
if (!setSilently)
this._fire(kContextUITabsShowEvent);
},
_clearDelayedTimeout: function _clearDelayedTimeout() {
if (this._hidingId) {
clearTimeout(this._hidingId);
this._hidingId = 0;
}
},
/*******************************************
* Events
*/
_onEdgeUIStarted: function(aEvent) {
this._hasEdgeSwipeStarted = true;
this._clearDelayedTimeout();
if (StartUI.hide()) {
this.dismiss();
return;
}
this.toggleNavUI();
},
_onEdgeUICanceled: function(aEvent) {
this._hasEdgeSwipeStarted = false;
StartUI.hide();
this.dismiss();
},
_onEdgeUICompleted: function(aEvent) {
if (this._hasEdgeSwipeStarted) {
this._hasEdgeSwipeStarted = false;
return;
}
this._clearDelayedTimeout();
if (StartUI.hide()) {
this.dismiss();
return;
}
this.toggleNavUI();
},
handleEvent: function handleEvent(aEvent) {
switch (aEvent.type) {
case "MozEdgeUIStarted":
this._onEdgeUIStarted(aEvent);
break;
case "MozEdgeUICanceled":
this._onEdgeUICanceled(aEvent);
break;
case "MozEdgeUICompleted":
this._onEdgeUICompleted(aEvent);
break;
case "keypress":
if (String.fromCharCode(aEvent.which) == "z" &&
aEvent.getModifierState("Win"))
this.toggleNavUI();
break;
case "transitionend":
setTimeout(function () {
ContentAreaObserver.updateContentArea();
}, 0);
break;
case "KeyboardChanged":
this.dismissTabs();
break;
case "mousedown":
if (aEvent.button == 0 && this.isVisible)
this.dismiss();
break;
case 'URLChanged':
this.dismissTabs();
break;
case 'TabSelect':
case 'ToolPanelShown':
case 'ToolPanelHidden':
case "touchstart":
case "AlertActive":
this.dismiss();
break;
}
},
_fire: function (name) {
let event = document.createEvent("Events");
event.initEvent(name, true, true);
window.dispatchEvent(event);
}
};

View File

@ -12,16 +12,16 @@ var Appbar = {
activeTileset: null,
init: function Appbar_init() {
window.addEventListener('MozContextUIShow', this);
window.addEventListener('MozContextUIDismiss', this);
window.addEventListener('MozAppbarDismiss', this);
// fired from appbar bindings
Elements.contextappbar.addEventListener('MozAppbarShowing', this, false);
Elements.contextappbar.addEventListener('MozAppbarDismissing', this, false);
// fired when a context sensitive item (bookmarks) changes state
window.addEventListener('MozContextActionsChange', this, false);
// browser events we need to update button state on
Elements.browsers.addEventListener('URLChanged', this, true);
Elements.tabList.addEventListener('TabSelect', this, true);
Elements.panelUI.addEventListener('ToolPanelShown', this, false);
Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
// tilegroup selection events for all modules get bubbled up
window.addEventListener("selectionchange", this, false);
@ -31,22 +31,10 @@ var Appbar = {
switch (aEvent.type) {
case 'URLChanged':
case 'TabSelect':
this.update();
Elements.navbar.dismiss();
Elements.contextappbar.dismiss();
break;
case 'MozContextUIShow':
Elements.navbar.show();
break;
case 'MozAppbarDismiss':
case 'MozContextUIDismiss':
case 'ToolPanelShown':
case 'ToolPanelHidden':
Elements.navbar.dismiss();
Elements.contextappbar.dismiss();
break;
case 'MozAppbarShowing':
this.update();
break;
case 'MozAppbarDismissing':
if (this.activeTileset) {
this.activeTileset.clearSelection();
@ -54,11 +42,13 @@ var Appbar = {
this.clearContextualActions();
this.activeTileset = null;
break;
case 'MozContextActionsChange':
let actions = aEvent.actions;
// could transition in old, new buttons?
this.showContextualActions(actions);
break;
case "selectionchange":
let nodeName = aEvent.target.nodeName;
if ('richgrid' === nodeName) {

View File

@ -28,7 +28,7 @@
<![CDATA[
window.addEventListener('MozContextUIShow', this);
window.addEventListener('MozContextUIDismiss', this);
window.addEventListener('MozAppbarDismiss', this);
window.addEventListener('MozAppbarDismissing', this);
]]>
</constructor>
@ -36,7 +36,7 @@
<![CDATA[
window.removeEventListener('MozContextUIShow', this);
window.removeEventListener('MozContextUIDismiss', this);
window.removeEventListener('MozAppbarDismiss', this);
window.removeEventListener('MozAppbarDismissing', this);
]]>
</destructor>
@ -92,7 +92,7 @@
<![CDATA[
switch (aEvent.type) {
case 'MozContextUIShow':
case 'MozAppbarDismiss':
case 'MozAppbarDismissing':
case 'MozContextUIDismiss':
this.hide();
break;

View File

@ -114,13 +114,13 @@
<implementation implements="nsIDOMEventListener">
<constructor>
<![CDATA[
window.addEventListener("MozContextUIExpand", this, true);
window.addEventListener("MozContextUITabsShow", this, true);
]]>
</constructor>
<destructor>
<![CDATA[
window.removeEventListener("MozContextUIExpand", this, true);
window.removeEventListener("MozContextUITabsShow", this, true);
]]>
</destructor>
@ -129,7 +129,7 @@
<body>
<![CDATA[
switch (event.type) {
case "MozContextUIExpand":
case "MozContextUITabsShow":
this.strip.ensureElementIsVisible(this.selectedTab, false);
break;
}

View File

@ -136,6 +136,7 @@ let ScriptContexts = {};
["SSLExceptions", "chrome://browser/content/exceptions.js"],
["ItemPinHelper", "chrome://browser/content/helperui/ItemPinHelper.js"],
["NavButtonSlider", "chrome://browser/content/NavButtonSlider.js"],
["ContextUI", "chrome://browser/content/ContextUI.js"],
#ifdef MOZ_SERVICES_SYNC
["Sync", "chrome://browser/content/sync.js"],
["SyncPairDevice", "chrome://browser/content/sync.js"],

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Cu.import("resource://gre/modules/PageThumbs.jsm");
Cu.import("resource://gre/modules/devtools/dbg-server.jsm")
/**
* Constants
@ -14,13 +15,6 @@ Cu.import("resource://gre/modules/PageThumbs.jsm");
const TOOLBARSTATE_LOADING = 1;
const TOOLBARSTATE_LOADED = 2;
// delay for ContextUI's dismissWithDelay
const kHideContextAndTrayDelayMsec = 3000;
// delay when showing the tab bar briefly as a new tab opens
const kNewTabAnimationDelayMsec = 500;
// Page for which the start UI is shown
const kStartOverlayURI = "about:start";
@ -448,7 +442,7 @@ var BrowserUI = {
animateClosingTab: function animateClosingTab(tabToClose) {
tabToClose.chromeTab.setAttribute("closing", "true");
let wasCollapsed = !ContextUI.isExpanded;
let wasCollapsed = !ContextUI.tabbarVisible;
if (wasCollapsed) {
ContextUI.displayTabs();
}
@ -1254,7 +1248,7 @@ var BrowserUI = {
this._editURI(true);
break;
case "cmd_addBookmark":
Elements.navbar.show();
ContextUI.displayNavbar();
Appbar.onStarButton(true);
break;
case "cmd_bookmarks":
@ -1319,266 +1313,6 @@ var BrowserUI = {
}
};
/**
* Tracks whether context UI (app bar, tab bar, url bar) is shown or hidden.
* Manages events to summon and hide the context UI.
*/
var ContextUI = {
_expandable: true,
_hidingId: 0,
/*******************************************
* init
*/
init: function init() {
Elements.browsers.addEventListener("mousedown", this, true);
Elements.browsers.addEventListener("touchstart", this, true);
Elements.browsers.addEventListener("AlertActive", this, true);
window.addEventListener("MozEdgeUIStarted", this, true);
window.addEventListener("MozEdgeUICanceled", this, true);
window.addEventListener("MozEdgeUICompleted", this, true);
window.addEventListener("keypress", this, true);
window.addEventListener("KeyboardChanged", this, false);
Elements.tray.addEventListener("transitionend", this, true);
Appbar.init();
},
/*******************************************
* Context UI state getters & setters
*/
get isVisible() {
return (Elements.navbar.hasAttribute("visible") ||
Elements.navbar.hasAttribute("startpage"));
},
get isExpanded() { return Elements.tray.hasAttribute("expanded"); },
get isExpandable() { return this._expandable; },
set isExpandable(aFlag) {
this._expandable = aFlag;
if (!this._expandable)
this.dismiss();
},
/*******************************************
* Context UI state control
*/
toggle: function toggle() {
if (!this._expandable) {
// exandable setter takes care of resetting state
// so if we're not expandable, there's nothing to do here
return;
}
// if we're not showing, show
if (!this.dismiss()) {
dump("* ContextUI is hidden, show it\n");
this.show();
}
},
// show all context UI
// returns true if any non-visible UI was shown
show: function() {
let shown = false;
if (!this.isExpanded) {
// show the tab tray
this._setIsExpanded(true);
shown = true;
}
if (!Elements.navbar.isShowing) {
// show the navbar
Elements.navbar.show();
shown = true;
}
this._clearDelayedTimeout();
if (shown) {
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
}
return shown;
},
// Display the nav bar
displayNavbar: function displayNavbar() {
this._clearDelayedTimeout();
Elements.navbar.show();
},
// Display the toolbar and tabs
displayTabs: function displayTabs() {
this._clearDelayedTimeout();
this._setIsExpanded(true, true);
},
/** Briefly show the tab bar and then hide it */
peekTabs: function peekTabs() {
if (this.isExpanded) {
setTimeout(function () {
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
}, 0);
} else {
BrowserUI.setOnTabAnimationEnd(function () {
ContextUI.dismissWithDelay(kNewTabAnimationDelayMsec);
});
this.displayTabs();
}
},
// Dismiss all context UI.
// Returns true if any visible UI was dismissed.
dismiss: function dismiss() {
let dismissed = false;
if (this.isExpanded) {
this._setIsExpanded(false);
dismissed = true;
}
if (Elements.navbar.isShowing) {
this.dismissAppbar();
dismissed = true;
}
this._clearDelayedTimeout();
if (dismissed) {
ContentAreaObserver.update(window.innerWidth, window.innerHeight);
}
return dismissed;
},
// Dismiss all context ui after a delay
dismissWithDelay: function dismissWithDelay(aDelay) {
aDelay = aDelay || kHideContextAndTrayDelayMsec;
this._clearDelayedTimeout();
this._hidingId = setTimeout(function () {
ContextUI.dismiss();
}, aDelay);
},
// Cancel any pending delayed dismiss
cancelDismiss: function cancelDismiss() {
this._clearDelayedTimeout();
},
dismissTabs: function dimissTabs() {
this._clearDelayedTimeout();
this._setIsExpanded(false, true);
},
dismissAppbar: function dismissAppbar() {
this._fire("MozAppbarDismiss");
},
/*******************************************
* Internal tray state setters
*/
// tab tray state
_setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
// if the tray can't be expanded, don't expand it.
if (!this.isExpandable || this.isExpanded == aFlag)
return;
if (aFlag)
Elements.tray.setAttribute("expanded", "true");
else
Elements.tray.removeAttribute("expanded");
if (!setSilently)
this._fire("MozContextUIExpand");
},
/*******************************************
* Internal utils
*/
_clearDelayedTimeout: function _clearDelayedTimeout() {
if (this._hidingId) {
clearTimeout(this._hidingId);
this._hidingId = 0;
}
},
/*******************************************
* Events
*/
_onEdgeUIStarted: function(aEvent) {
this._hasEdgeSwipeStarted = true;
this._clearDelayedTimeout();
if (StartUI.hide()) {
this.dismiss();
return;
}
this.toggle();
},
_onEdgeUICanceled: function(aEvent) {
this._hasEdgeSwipeStarted = false;
StartUI.hide();
this.dismiss();
},
_onEdgeUICompleted: function(aEvent) {
if (this._hasEdgeSwipeStarted) {
this._hasEdgeSwipeStarted = false;
return;
}
this._clearDelayedTimeout();
if (StartUI.hide()) {
this.dismiss();
return;
}
this.toggle();
},
handleEvent: function handleEvent(aEvent) {
switch (aEvent.type) {
case "MozEdgeUIStarted":
this._onEdgeUIStarted(aEvent);
break;
case "MozEdgeUICanceled":
this._onEdgeUICanceled(aEvent);
break;
case "MozEdgeUICompleted":
this._onEdgeUICompleted(aEvent);
break;
case "mousedown":
if (aEvent.button == 0 && this.isVisible)
this.dismiss();
break;
case "touchstart":
// ContextUI can hide the notification bar. Workaround until bug 845348 is fixed.
case "AlertActive":
this.dismiss();
break;
case "keypress":
if (String.fromCharCode(aEvent.which) == "z" &&
aEvent.getModifierState("Win"))
this.toggle();
break;
case "transitionend":
setTimeout(function () {
ContentAreaObserver.updateContentArea();
}, 0);
break;
case "KeyboardChanged":
this.dismissTabs();
break;
}
},
_fire: function (name) {
let event = document.createEvent("Events");
event.initEvent(name, true, true);
window.dispatchEvent(event);
}
};
var StartUI = {
get isVisible() { return this.isStartPageVisible || this.isFiltering; },
get isStartPageVisible() { return Elements.windowState.hasAttribute("startpage"); },
@ -1608,6 +1342,13 @@ var StartUI = {
if (section.init)
section.init();
});
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
DebuggerServer.addActors('chrome://browser/content/dbg-metro-actors.js');
}
DebuggerServer.openListener(6000);
},
uninit: function() {

View File

@ -974,8 +974,8 @@ var Browser = {
onAboutPolicyClick: function() {
FlyoutPanelsUI.hide();
BrowserUI.newTab(Services.prefs.getCharPref("app.privacyURL"),
Browser.selectedTab);
let linkStr = Services.urlFormatter.formatURLPref("app.privacyURL");
BrowserUI.newTab(linkStr, Browser.selectedTab);
}
};

View File

@ -0,0 +1,66 @@
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
"use strict";
const error = Components.utils.reportError;
/* Metrofx specific actors, modelled from the android fennec actors */
/** aConnection DebuggerServerConnection, the conection to the client.
*/
function createRootActor(aConnection) {
let parameters = {
tabList: new MetroTabList(aConnection),
globalActorFactories: DebuggerServer.globalActorFactories,
onShutdown: sendShutdownEvent
};
return new RootActor(aConnection, parameters);
}
/** aConnection DebuggerServerConnection, the conection to the client.
*/
function MetroTabList(aConnection) {
BrowserTabList.call(this, aConnection);
}
MetroTabList.prototype = Object.create(BrowserTabList.prototype);
MetroTabList.prototype.constructor = MetroTabList;
/**
* We want to avoid mysterious behavior if tabs are closed or opened mid-iteration.
* We want at the end, a list of the actors that were live when we began the iteration.
* So, we update the map first, iterate over it again to yield the actors.
*/
MetroTabList.prototype.iterator = function() {
let initialMapSize = this._actorByBrowser.size;
let foundCount = 0;
for (let win of allAppShellDOMWindows("navigator:browser")) {
let selectedTab = win.Browser.selectedBrowser;
for (let browser of win.Browser.browsers) {
let actor = this._actorByBrowser.get(browser);
if (actor) {
foundCount++;
} else {
actor = new BrowserTabActor(this._connection, browser);
this._actorByBrowser.set(browser, actor);
}
// Set the 'selected' properties on all actors correctly.
actor.selected = (browser === selectedTab);
}
}
if (this._testing && initialMapSize !== foundCount) {
throw error("_actorByBrowser map contained actors for dead tabs");
}
this._mustNotify = true;
this._checkListening();
for (let [browser, actor] of this._actorByBrowser) {
yield actor;
}
};

View File

@ -58,7 +58,6 @@ var FindHelperUI = {
Elements.tabList.addEventListener("TabSelect", this, true);
Elements.browsers.addEventListener("URLChanged", this, true);
window.addEventListener("MozContextUIShow", this, true);
window.addEventListener("MozContextUIExpand", this, true);
},
receiveMessage: function findHelperReceiveMessage(aMessage) {
@ -81,7 +80,6 @@ var FindHelperUI = {
handleEvent: function findHelperHandleEvent(aEvent) {
switch (aEvent.type) {
case "MozContextUIShow":
case "MozContextUIExpand":
case "TabSelect":
this.hide();
break;

View File

@ -88,11 +88,13 @@ chrome.jar:
content/TopSites.js (content/TopSites.js)
content/console.js (content/console.js)
content/AnimatedZoom.js (content/AnimatedZoom.js)
content/dbg-metro-actors.js (content/dbg-metro-actors.js)
#ifdef MOZ_SERVICES_SYNC
* content/sync.js (content/sync.js)
content/RemoteTabs.js (content/RemoteTabs.js)
#endif
content/NavButtonSlider.js (content/NavButtonSlider.js)
content/ContextUI.js (content/ContextUI.js)
% override chrome://global/content/config.xul chrome://browser/content/config.xul
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml

View File

@ -19,27 +19,27 @@ gTests.push({
});
is(StartUI.isVisible, true, "Start UI is displayed on about:start");
is(ContextUI.isVisible, true, "Navbar is displayed on about:start");
is(ContextUI.isExpanded, false, "Tabbar is not displayed initially");
is(Elements.navbar.isShowing, false, "Appbar is not displayed initially");
is(ContextUI.navbarVisible, true, "Navbar is displayed on about:start");
is(ContextUI.tabbarVisible, false, "Tabbar is not displayed initially");
is(ContextUI.contextAppbarVisible, false, "Appbar is not displayed initially");
// toggle on
doEdgeUIGesture();
is(ContextUI.isVisible, true, "Navbar is still visible after one swipe");
is(ContextUI.isExpanded, true, "Tabbar is visible after one swipe");
is(Elements.navbar.isShowing, true, "Appbar is visible after one swipe");
is(ContextUI.navbarVisible, true, "Navbar is still visible after one swipe");
is(ContextUI.tabbarVisible, true, "Tabbar is visible after one swipe");
is(ContextUI.contextAppbarVisible, false, "Appbar is hidden after one swipe");
// toggle off
doEdgeUIGesture();
is(ContextUI.isVisible, true, "Navbar is still visible after second swipe");
is(ContextUI.isExpanded, false, "Tabbar is hidden after second swipe");
is(Elements.navbar.isShowing, false, "Appbar is hidden after second swipe");
is(ContextUI.navbarVisible, true, "Navbar is still visible after second swipe");
is(ContextUI.tabbarVisible, false, "Tabbar is hidden after second swipe");
is(ContextUI.contextAppbarVisible, false, "Appbar is hidden after second swipe");
// sanity check - toggle on again
doEdgeUIGesture();
is(ContextUI.isVisible, true, "Navbar is still visible after third swipe");
is(ContextUI.isExpanded, true, "Tabbar is visible after third swipe");
is(Elements.navbar.isShowing, true, "Appbar is visible after third swipe");
is(ContextUI.navbarVisible, true, "Navbar is still visible after third swipe");
is(ContextUI.tabbarVisible, true, "Tabbar is visible after third swipe");
is(ContextUI.contextAppbarVisible, false, "Appbar is hidden after third swipe");
is(StartUI.isVisible, true, "Start UI is still visible");
}
@ -51,19 +51,16 @@ gTests.push({
yield addTab("about:");
ContextUI.dismiss();
is(StartUI.isVisible, false, "Start UI is not visible on about:");
is(ContextUI.isVisible, false, "Navbar is not initially visible on about:");
is(ContextUI.isExpanded, false, "Tabbar is not initially visible on about:");
is(Elements.navbar.isShowing, false, "Appbar is not initially visible on about on about::");
is(ContextUI.navbarVisible, false, "Navbar is not initially visible on about:");
is(ContextUI.tabbarVisible, false, "Tabbar is not initially visible on about:");
doEdgeUIGesture();
is(ContextUI.isVisible, true, "Navbar is visible after one swipe");
is(ContextUI.isExpanded, true, "Tabbar is visble after one swipe");
is(Elements.navbar.isShowing, true, "Appbar is visible after one swipe");
is(ContextUI.navbarVisible, true, "Navbar is visible after one swipe");
is(ContextUI.tabbarVisible, true, "Tabbar is visble after one swipe");
doEdgeUIGesture();
is(ContextUI.isVisible, false, "Navbar is not visible after second swipe");
is(ContextUI.isExpanded, false, "Tabbar is not visible after second swipe");
is(Elements.navbar.isShowing, false, "Appbar is hidden after second swipe");
is(ContextUI.navbarVisible, false, "Navbar is not visible after second swipe");
is(ContextUI.tabbarVisible, false, "Tabbar is not visible after second swipe");
is(StartUI.isVisible, false, "Start UI is still not visible");
}
@ -74,12 +71,12 @@ gTests.push({
run: function testAbout() {
let tab = yield addTab("about:");
ContextUI.dismiss();
is(ContextUI.isVisible, false, "Navbar is not initially visible");
is(ContextUI.isExpanded, false, "Tab bar is not initially visible");
is(ContextUI.navbarVisible, false, "Navbar is not initially visible");
is(ContextUI.tabbarVisible, false, "Tab bar is not initially visible");
EventUtils.synthesizeKey('l', { accelKey: true });
is(ContextUI.isVisible, true, "Navbar is visible");
is(ContextUI.isExpanded, false, "Tab bar is not visible");
is(ContextUI.navbarVisible, true, "Navbar is visible");
is(ContextUI.tabbarVisible, false, "Tab bar is not visible");
let edit = document.getElementById("urlbar-edit");
is(edit.value, "about:", "Location field contains the page URL");

View File

@ -171,23 +171,22 @@ function clearSelection(aTarget) {
Asynchronous Metro ui helpers
=============================================================================*/
// Hides the tab and context app bar if they are visible
function hideContextUI()
{
purgeEventQueue();
return Task.spawn(function() {
if (ContextUI.isExpanded) {
if (ContextUI.tabbarVisible) {
let promise = waitForEvent(Elements.tray, "transitionend", null, Elements.tray);
if (ContextUI.dismiss())
{
info("ContextUI dismissed, waiting...");
if (ContextUI.dismiss()) {
yield promise;
}
}
if (Elements.contextappbar.isShowing) {
if (ContextUI.contextAppbarVisible) {
let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
Elements.contextappbar.dismiss();
ContextUI.dismissContextAppbar();
yield promise;
}
});
@ -196,7 +195,7 @@ function hideContextUI()
function showNavBar()
{
let promise = waitForEvent(Elements.navbar, "transitionend");
if (!ContextUI.isVisible) {
if (!ContextUI.navbarVisible) {
ContextUI.displayNavbar();
return promise;
}

View File

@ -385,7 +385,7 @@ pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
// TODO: This is not the correct article for metro!!!
pref("app.sync.tutorialURL", "https://support.mozilla.org/kb/sync-firefox-between-desktop-and-mobile");
pref("app.support.baseURL", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/");
pref("app.privacyURL", "https://www.mozilla.org/legal/privacy/");
pref("app.privacyURL", "http://www.mozilla.org/%LOCALE%/legal/privacy/firefox.html");
pref("app.creditsURL", "http://www.mozilla.org/credits/");
pref("app.channelURL", "http://www.mozilla.org/%LOCALE%/firefox/channel/");

View File

@ -402,7 +402,7 @@ appbar[visible] {
-moz-image-region: rect(0 80px 40px 40px);
}
#toolbar > .appbar-primary:not([checked]):active {
#toolbar > .appbar-primary[checked] {
-moz-image-region: rect(0 120px 40px 80px);
}
@ -410,6 +410,10 @@ appbar[visible] {
-moz-image-region: rect(0 160px 40px 120px);
}
#toolbar > .appbar-primary:active {
-moz-image-region: rect(0 120px 40px 80px);
}
@media (min-resolution: 130dpi) {
#toolbar > .appbar-primary > .toolbarbutton-icon {
width: 40px;
@ -424,13 +428,17 @@ appbar[visible] {
-moz-image-region: rect(0 112px 56px 56px);
}
#toolbar > .appbar-primary:not([checked]):active {
-moz-image-region: rect(0 168px 56px 112px);
#toolbar > .appbar-primary[checked] {
-moz-image-region: rect(0 224px 56px 168px);
}
#toolbar > .appbar-primary[checked]:hover:not(:active) {
-moz-image-region: rect(0 224px 56px 168px);
}
#toolbar > .appbar-primary:active {
-moz-image-region: rect(0 168px 56px 112px);
}
}
/* Page-Specific */

View File

@ -205,158 +205,3 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:hove
richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:active {
-moz-image-region: rect(32px, 64px, 48px, 48px);
}
/*** Status and progress indicator ***/
#downloads-indicator-anchor {
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor {
min-width: 16px;
min-height: 16px;
}
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor {
min-width: 24px;
min-height: 24px;
}
/*** Main indicator icon ***/
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
}
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 24, 24, 0) center no-repeat;
}
toolbar[iconsize="small"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow-small.png");
}
toolbar[iconsize="large"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
}
@keyframes downloadsIndicatorNotificationStartRight {
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
@keyframes downloadsIndicatorNotificationStartLeft {
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
animation-name: downloadsIndicatorNotificationStartRight;
animation-duration: 1s;
}
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
animation-name: downloadsIndicatorNotificationStartLeft;
}
@keyframes downloadsIndicatorNotificationFinish {
from { opacity: 0; transform: scale(1); }
20% { opacity: .65; animation-timing-function: ease-in; }
to { opacity: 0; transform: scale(8); }
}
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
animation-name: downloadsIndicatorNotificationFinish;
animation-duration: 1s;
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 10px;
margin: 0;
color: hsl(0,0%,30%);
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
font-size: 10px;
line-height: 10px;
text-align: center;
}
#downloads-indicator-progress {
width: 16px;
height: 6px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
background-clip: padding-box, border-box;
background-color: rgb(255, 135, 94);
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
border: 1px solid;
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: linear-gradient(#505050, #575757);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-color: rgb(220, 230, 81);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: linear-gradient(#4b5000, #515700);
}
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
margin: 0;
text-align: center;
}

View File

@ -0,0 +1,158 @@
/* 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/. */
/*** Status and progress indicator ***/
#downloads-indicator-anchor {
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor {
min-width: 16px;
min-height: 16px;
}
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor {
min-width: 24px;
min-height: 24px;
}
/*** Main indicator icon ***/
toolbar[iconsize="small"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
}
toolbar[iconsize="large"] > #downloads-indicator > #downloads-indicator-anchor > #downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 24, 24, 0) center no-repeat;
}
toolbar[iconsize="small"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow-small.png");
}
toolbar[iconsize="large"] > #downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-small.png"),
0, 16, 16, 0) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
}
@keyframes downloadsIndicatorNotificationStartRight {
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
@keyframes downloadsIndicatorNotificationStartLeft {
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
animation-name: downloadsIndicatorNotificationStartRight;
animation-duration: 1s;
}
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
animation-name: downloadsIndicatorNotificationStartLeft;
}
@keyframes downloadsIndicatorNotificationFinish {
from { opacity: 0; transform: scale(1); }
20% { opacity: .65; animation-timing-function: ease-in; }
to { opacity: 0; transform: scale(8); }
}
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
animation-name: downloadsIndicatorNotificationFinish;
animation-duration: 1s;
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 10px;
margin: 0;
color: hsl(0,0%,30%);
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
font-size: 10px;
line-height: 10px;
text-align: center;
}
#downloads-indicator-progress {
width: 16px;
height: 6px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
background-clip: padding-box, border-box;
background-color: rgb(255, 135, 94);
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
border: 1px solid;
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: linear-gradient(#505050, #575757);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-color: rgb(220, 230, 81);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: linear-gradient(#4b5000, #515700);
}
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
margin: 0;
text-align: center;
}

View File

@ -57,15 +57,16 @@ browser.jar:
skin/classic/browser/webRTC-shareDevice-16.png
skin/classic/browser/webRTC-shareDevice-64.png
skin/classic/browser/webRTC-sharingDevice-16.png
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
skin/classic/browser/downloads/download-glow-small.png (downloads/download-glow-small.png)
skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png)
skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/indicator.css (downloads/indicator.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/videoFeedIcon.png (feeds/feedIcon.png)

View File

@ -356,182 +356,3 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:acti
-moz-image-region: rect(64px, 256px, 96px, 224px);
}
}
/*** Status and progress indicator ***/
#downloads-indicator-anchor {
min-width: 20px;
min-height: 20px;
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
/* The selected tab may overlap #downloads-indicator-notification */
z-index: 1;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 140, 20, 120) center no-repeat;
}
#downloads-indicator[attention]
#downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-indicator:not([counter])
#downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 140, 20, 120) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention]
#downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
@media (min-resolution: 2dppx) {
#downloads-indicator-icon:not(:-moz-lwtheme-brighttext) {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
background-size: 20px;
}
#downloads-indicator:not([counter]) > #downloads-indicator-anchor >
#downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
}
#downloads-indicator[attention] > #downloads-indicator-anchor >
#downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor >
#downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
}
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
}
@keyframes downloadsIndicatorNotificationStartRight {
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
@keyframes downloadsIndicatorNotificationStartLeft {
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
animation-name: downloadsIndicatorNotificationStartRight;
animation-duration: 1s;
}
@media (min-resolution: 2dppx) {
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start@2x.png");
}
}
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
animation-name: downloadsIndicatorNotificationStartLeft;
}
@keyframes downloadsIndicatorNotificationFinish {
from { opacity: 0; transform: scale(1); }
20% { opacity: .65; animation-timing-function: ease-in; }
to { opacity: 0; transform: scale(8); }
}
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
animation-name: downloadsIndicatorNotificationFinish;
animation-duration: 1s;
}
@media (min-resolution: 2dppx) {
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish@2x.png");
}
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 9px;
margin: -3px 0 0;
color: hsl(0,0%,30%);
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
font-size: 9px;
line-height: 9px;
text-align: center;
}
#downloads-indicator-progress {
width: 16px;
height: 5px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
background-clip: padding-box, border-box;
background-color: rgb(90, 185, 255);
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
border: 1px solid;
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: linear-gradient(#505050, #575757);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-color: rgb(220, 230, 81);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: linear-gradient(#4b5000, #515700);
}
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
margin: 2px 0 0;
padding: 0;
text-align: center;
vertical-align: middle;
}

View File

@ -0,0 +1,182 @@
/* 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/. */
/*** Status and progress indicator ***/
#downloads-indicator-anchor {
min-width: 20px;
min-height: 20px;
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
/* The selected tab may overlap #downloads-indicator-notification */
z-index: 1;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 140, 20, 120) center no-repeat;
}
#downloads-indicator[attention]
#downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-indicator:not([counter])
#downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 140, 20, 120) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention]
#downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
@media (min-resolution: 2dppx) {
#downloads-indicator-icon:not(:-moz-lwtheme-brighttext) {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
background-size: 20px;
}
#downloads-indicator:not([counter]) > #downloads-indicator-anchor >
#downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240);
}
#downloads-indicator[attention] > #downloads-indicator-anchor >
#downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor >
#downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow@2x.png");
}
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
}
@keyframes downloadsIndicatorNotificationStartRight {
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
@keyframes downloadsIndicatorNotificationStartLeft {
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
animation-name: downloadsIndicatorNotificationStartRight;
animation-duration: 1s;
}
@media (min-resolution: 2dppx) {
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start@2x.png");
}
}
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
animation-name: downloadsIndicatorNotificationStartLeft;
}
@keyframes downloadsIndicatorNotificationFinish {
from { opacity: 0; transform: scale(1); }
20% { opacity: .65; animation-timing-function: ease-in; }
to { opacity: 0; transform: scale(8); }
}
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
animation-name: downloadsIndicatorNotificationFinish;
animation-duration: 1s;
}
@media (min-resolution: 2dppx) {
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish@2x.png");
}
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 9px;
margin: -3px 0 0;
color: hsl(0,0%,30%);
text-shadow: 0 1px 0 hsla(0,0%,100%,.5);
font-size: 9px;
line-height: 9px;
text-align: center;
}
#downloads-indicator-progress {
width: 16px;
height: 5px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
background-clip: padding-box, border-box;
background-color: rgb(90, 185, 255);
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
border: 1px solid;
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: linear-gradient(#505050, #575757);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-color: rgb(220, 230, 81);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: linear-gradient(#4b5000, #515700);
}
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
margin: 2px 0 0;
padding: 0;
text-align: center;
vertical-align: middle;
}

View File

@ -94,8 +94,10 @@ browser.jar:
skin/classic/browser/webRTC-shareDevice-64@2x.png
skin/classic/browser/webRTC-sharingDevice-16.png
skin/classic/browser/webRTC-sharingDevice-16@2x.png
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
skin/classic/browser/downloads/buttons@2x.png (downloads/buttons@2x.png)
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
skin/classic/browser/downloads/download-glow@2x.png (downloads/download-glow@2x.png)
skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
@ -105,8 +107,7 @@ browser.jar:
skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png)
skin/classic/browser/downloads/download-summary@2x.png (downloads/download-summary@2x.png)
skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/indicator.css (downloads/indicator.css)
skin/classic/browser/feeds/subscribe.css (feeds/subscribe.css)
skin/classic/browser/feeds/subscribe-ui.css (feeds/subscribe-ui.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)

View File

@ -20,41 +20,3 @@
color: black;
}
}
@media (-moz-windows-compositor) {
/* The following rules are for the downloads indicator when in its normal,
non-downloading, non-paused state (ie, it's just showing the downloads
button icon). */
#toolbar-menubar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
#TabsToolbar[tabsontop=true] #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
/* The following rules are for the downloads indicator when in its paused
or undetermined progress state. We use :not([counter]) as a shortcut for
:-moz-any([progress], [paused]). */
/* This is the case where the downloads indicator has been moved next to the menubar */
#toolbar-menubar #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
/* This is the case where the downloads indicator is in the tabstrip toolbar with tabs on top. */
#TabsToolbar[tabsontop=true] #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
/* This is the case where the downloads indicator is anywhere in the nav-bar with tabs on bottom. */
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
/* This is the case where the downloads indicator is in the tabstrip when the tabstrip is the last item in the toolbox (and is therefore over glass) */
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 108, 18, 90);
}
#toolbar-menubar #downloads-indicator-counter:not(:-moz-lwtheme),
#TabsToolbar[tabsontop=true] #downloads-indicator-counter:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator-counter:not(:-moz-lwtheme),
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator-counter:not(:-moz-lwtheme) {
color: white;
text-shadow: 0 0 1px rgba(0,0,0,.7),
0 1px 1.5px rgba(0,0,0,.5);
}
}
#downloads-indicator-counter {
margin-bottom: -1px;
}

View File

@ -235,152 +235,3 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:hove
richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:active {
-moz-image-region: rect(32px, 64px, 48px, 48px);
}
/*** Status and progress indicator ***/
#downloads-indicator-anchor {
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 108, 18, 90) center no-repeat;
min-width: 18px;
min-height: 18px;
}
#downloads-indicator-icon:-moz-lwtheme-brighttext {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
0, 108, 18, 90) center no-repeat;
}
#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 108, 18, 90) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
}
@keyframes downloadsIndicatorNotificationStartRight {
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
@keyframes downloadsIndicatorNotificationStartLeft {
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
animation-name: downloadsIndicatorNotificationStartRight;
animation-duration: 1s;
}
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
animation-name: downloadsIndicatorNotificationStartLeft;
}
@keyframes downloadsIndicatorNotificationFinish {
from { opacity: 0; transform: scale(1); }
20% { opacity: .65; animation-timing-function: ease-in; }
to { opacity: 0; transform: scale(8); }
}
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
animation-name: downloadsIndicatorNotificationFinish;
animation-duration: 1s;
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 9px;
margin: -3px 0px 0px 0px;
color: hsl(0,0%,30%);
text-shadow: hsla(0,0%,100%,.5) 0 1px;
font-size: 9px;
line-height: 9px;
text-align: center;
}
#downloads-indicator-counter:-moz-lwtheme-brighttext {
color: white;
text-shadow: 0 0 1px rgba(0,0,0,.7),
0 1px 1.5px rgba(0,0,0,.5);
}
#downloads-indicator-progress {
width: 16px;
height: 5px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
background-clip: padding-box, border-box;
background-color: rgb(90, 201, 66);
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
border: 1px solid;
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: linear-gradient(#505050, #575757);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-color: rgb(220, 230, 81);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: linear-gradient(#4b5000, #515700);
}
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
margin: 0;
text-align: center;
}

View File

@ -0,0 +1,45 @@
/* 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/. */
%define WINDOWS_AERO
%include indicator.css
%undef WINDOWS_AERO
@media (-moz-windows-compositor) {
/* The following rules are for the downloads indicator when in its normal,
non-downloading, non-paused state (ie, it's just showing the downloads
button icon). */
#toolbar-menubar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
#TabsToolbar[tabsontop=true] #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not([attention]) > #downloads-indicator-anchor > #downloads-indicator-icon:not(:-moz-lwtheme),
/* The following rules are for the downloads indicator when in its paused
or undetermined progress state. We use :not([counter]) as a shortcut for
:-moz-any([progress], [paused]). */
/* This is the case where the downloads indicator has been moved next to the menubar */
#toolbar-menubar #downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
/* This is the case where the downloads indicator is in the tabstrip toolbar with tabs on top. */
#TabsToolbar[tabsontop=true] #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
/* This is the case where the downloads indicator is anywhere in the nav-bar with tabs on bottom. */
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter,
/* This is the case where the downloads indicator is in the tabstrip when the tabstrip is the last item in the toolbox (and is therefore over glass) */
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator:not(:-moz-lwtheme):not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"), 0, 108, 18, 90);
}
#toolbar-menubar #downloads-indicator-counter:not(:-moz-lwtheme),
#TabsToolbar[tabsontop=true] #downloads-indicator-counter:not(:-moz-lwtheme),
#navigator-toolbox[tabsontop=false] > #nav-bar #downloads-indicator-counter:not(:-moz-lwtheme),
#nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child #downloads-indicator-counter:not(:-moz-lwtheme) {
color: white;
text-shadow: 0 0 1px rgba(0,0,0,.7),
0 1px 1.5px rgba(0,0,0,.5);
}
}
#downloads-indicator-counter {
margin-bottom: -1px;
}

View File

@ -0,0 +1,152 @@
/* 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/. */
/*** Status and progress indicator ***/
#downloads-indicator-anchor {
/* Makes the outermost stack element positioned, so that its contents are
rendered over the main browser window in the Z order. This is required by
the animated event notification. */
position: relative;
}
/*** Main indicator icon ***/
#downloads-indicator-icon {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 108, 18, 90) center no-repeat;
min-width: 18px;
min-height: 18px;
}
#downloads-indicator-icon:-moz-lwtheme-brighttext {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar-inverted.png"),
0, 108, 18, 90) center no-repeat;
}
#downloads-indicator[attention] > #downloads-indicator-anchor > #downloads-indicator-icon {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/* In the next few rules, we use :not([counter]) as a shortcut that is
equivalent to -moz-any([progress], [paused]). */
#downloads-indicator:not([counter]) > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background: -moz-image-rect(url("chrome://browser/skin/Toolbar.png"),
0, 108, 18, 90) center no-repeat;
background-size: 12px;
}
#downloads-indicator:not([counter])[attention] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-counter {
background-image: url("chrome://browser/skin/downloads/download-glow.png");
}
/*** Download notifications ***/
#downloads-indicator-notification {
opacity: 0;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
}
@keyframes downloadsIndicatorNotificationStartRight {
from { opacity: 0; transform: translate(-128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
@keyframes downloadsIndicatorNotificationStartLeft {
from { opacity: 0; transform: translate(128px, 128px) scale(8); }
20% { opacity: .85; animation-timing-function: ease-out; }
to { opacity: 0; transform: translate(0) scale(1); }
}
#downloads-indicator[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-start.png");
animation-name: downloadsIndicatorNotificationStartRight;
animation-duration: 1s;
}
#downloads-indicator[notification="start"]:-moz-locale-dir(rtl) > #downloads-indicator-anchor > #downloads-indicator-notification {
animation-name: downloadsIndicatorNotificationStartLeft;
}
@keyframes downloadsIndicatorNotificationFinish {
from { opacity: 0; transform: scale(1); }
20% { opacity: .65; animation-timing-function: ease-in; }
to { opacity: 0; transform: scale(8); }
}
#downloads-indicator[notification="finish"] > #downloads-indicator-anchor > #downloads-indicator-notification {
background-image: url("chrome://browser/skin/downloads/download-notification-finish.png");
animation-name: downloadsIndicatorNotificationFinish;
animation-duration: 1s;
}
/*** Progress bar and text ***/
#downloads-indicator-counter {
height: 9px;
margin: -3px 0px 0px 0px;
color: hsl(0,0%,30%);
text-shadow: hsla(0,0%,100%,.5) 0 1px;
font-size: 9px;
line-height: 9px;
text-align: center;
}
#downloads-indicator-counter:-moz-lwtheme-brighttext {
color: white;
text-shadow: 0 0 1px rgba(0,0,0,.7),
0 1px 1.5px rgba(0,0,0,.5);
}
#downloads-indicator-progress {
width: 16px;
height: 5px;
min-width: 0;
min-height: 0;
margin-top: 1px;
margin-bottom: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
}
#downloads-indicator-progress > .progress-bar {
-moz-appearance: none;
min-width: 0;
min-height: 0;
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
background-clip: padding-box, border-box;
background-color: rgb(90, 201, 66);
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
border: 1px solid;
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
border-radius: 2px 0 0 2px;
}
#downloads-indicator-progress > .progress-remainder {
-moz-appearance: none;
min-width: 0;
min-height: 0;
background-image: linear-gradient(#505050, #575757);
border: 1px solid;
border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
-moz-border-start: none;
border-radius: 0 2px 2px 0;
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
background-color: rgb(220, 230, 81);
}
#downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
background-image: linear-gradient(#4b5000, #515700);
}
toolbar[mode="full"] > #downloads-indicator > .toolbarbutton-text {
margin: 0;
text-align: center;
}

View File

@ -74,14 +74,15 @@ browser.jar:
skin/classic/browser/webRTC-shareDevice-16.png
skin/classic/browser/webRTC-shareDevice-64.png
skin/classic/browser/webRTC-sharingDevice-16.png
* skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
skin/classic/browser/downloads/buttons.png (downloads/buttons.png)
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/download-glow.png (downloads/download-glow.png)
skin/classic/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
skin/classic/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
skin/classic/browser/downloads/download-summary.png (downloads/download-summary.png)
* skin/classic/browser/downloads/downloads.css (downloads/downloads.css)
* skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
skin/classic/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
* skin/classic/browser/downloads/indicator.css (downloads/indicator.css)
skin/classic/browser/feeds/feedIcon.png (feeds/feedIcon.png)
skin/classic/browser/feeds/feedIcon16.png (feeds/feedIcon16.png)
skin/classic/browser/feeds/audioFeedIcon.png (feeds/feedIcon.png)
@ -327,14 +328,15 @@ browser.jar:
skin/classic/aero/browser/webRTC-shareDevice-16.png
skin/classic/aero/browser/webRTC-shareDevice-64.png
skin/classic/aero/browser/webRTC-sharingDevice-16.png
* skin/classic/aero/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay-aero.css)
skin/classic/aero/browser/downloads/buttons.png (downloads/buttons-aero.png)
skin/classic/aero/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
skin/classic/aero/browser/downloads/download-glow.png (downloads/download-glow.png)
skin/classic/aero/browser/downloads/download-notification-finish.png (downloads/download-notification-finish.png)
skin/classic/aero/browser/downloads/download-notification-start.png (downloads/download-notification-start.png)
skin/classic/aero/browser/downloads/download-summary.png (downloads/download-summary.png)
* skin/classic/aero/browser/downloads/downloads.css (downloads/downloads-aero.css)
* skin/classic/aero/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay-aero.css)
skin/classic/aero/browser/downloads/contentAreaDownloadsView.css (downloads/contentAreaDownloadsView.css)
* skin/classic/aero/browser/downloads/indicator.css (downloads/indicator-aero.css)
skin/classic/aero/browser/feeds/feedIcon.png (feeds/feedIcon-aero.png)
skin/classic/aero/browser/feeds/feedIcon16.png (feeds/feedIcon16-aero.png)
skin/classic/aero/browser/feeds/audioFeedIcon.png (feeds/feedIcon-aero.png)

View File

@ -25,7 +25,7 @@ interface nsIURI;
* interface to mirror this interface when changing it.
*/
[scriptable, uuid(24a35de3-40e4-498e-9c1b-2fd0a2d4cae5)]
[scriptable, uuid(070bfc7f-f8b8-4e84-aa31-a0bfaffa8e8e)]
interface nsIObjectLoadingContent : nsISupports
{
/**
@ -87,6 +87,13 @@ interface nsIObjectLoadingContent : nsISupports
*/
unsigned long getContentTypeForMIMEType(in AUTF8String aMimeType);
/**
* Returns the base URI of the object as seen by plugins. This differs from
* the normal codebase in that it takes <param> tags and plugin-specific
* quirks into account.
*/
[noscript] readonly attribute nsIURI baseURI;
/**
* Returns the plugin instance if it has already been instantiated. This
* will never instantiate the plugin and so is safe to call even when

View File

@ -548,7 +548,8 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, docRequest, csp) {
// Check for unsafe-inline and unsafe-eval in script-src
if (dv._allowUnsafeInline) {
aCSPR._allowInlineScripts = true;
} else if (dv._allowUnsafeEval) {
}
if (dv._allowUnsafeEval) {
aCSPR._allowEval = true;
}
}

View File

@ -22,6 +22,7 @@
#include "plstr.h"
#include "prprf.h"
#include "mozilla/Telemetry.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsDocument.h"
@ -1420,6 +1421,46 @@ nsDocument::~nsDocument()
NS_ASSERTION(!mIsShowing, "Destroying a currently-showing document");
if (IsTopLevelContentDocument()) {
//don't report for about: pages
nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
bool isAboutScheme = true;
if (uri) {
uri->SchemeIs("about", &isAboutScheme);
}
if (!isAboutScheme) {
// Record the mixed content status of the docshell in Telemetry
enum {
NO_MIXED_CONTENT = 0, // There is no Mixed Content on the page
MIXED_DISPLAY_CONTENT = 1, // The page attempted to load Mixed Display Content
MIXED_ACTIVE_CONTENT = 2, // The page attempted to load Mixed Active Content
MIXED_DISPLAY_AND_ACTIVE_CONTENT = 3 // The page attempted to load Mixed Display & Mixed Active Content
};
bool mixedActiveLoaded = GetHasMixedActiveContentLoaded();
bool mixedActiveBlocked = GetHasMixedActiveContentBlocked();
bool mixedDisplayLoaded = GetHasMixedDisplayContentLoaded();
bool mixedDisplayBlocked = GetHasMixedDisplayContentBlocked();
bool hasMixedDisplay = (mixedDisplayBlocked || mixedDisplayLoaded);
bool hasMixedActive = (mixedActiveBlocked || mixedActiveLoaded);
uint32_t mixedContentLevel = NO_MIXED_CONTENT;
if (hasMixedDisplay && hasMixedActive) {
mixedContentLevel = MIXED_DISPLAY_AND_ACTIVE_CONTENT;
} else if (hasMixedActive){
mixedContentLevel = MIXED_ACTIVE_CONTENT;
} else if (hasMixedDisplay) {
mixedContentLevel = MIXED_DISPLAY_CONTENT;
}
Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
}
}
mInDestructor = true;
mInUnlinkOrDeletion = true;
@ -4113,6 +4154,23 @@ nsIDocument::SetContainer(nsISupports* aContainer)
{
mDocumentContainer = do_GetWeakReference(aContainer);
EnumerateFreezableElements(NotifyActivityChanged, nullptr);
// Get the Docshell
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aContainer);
if (docShell) {
int32_t itemType;
docShell->GetItemType(&itemType);
// check itemtype
if (itemType == nsIDocShellTreeItem::typeContent) {
// check if same type root
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
if (sameTypeRoot == docShell) {
static_cast<nsDocument*>(this)->SetIsTopLevelContentDocument(true);
}
}
}
}
void
@ -4243,6 +4301,18 @@ nsDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
}
}
bool
nsDocument::IsTopLevelContentDocument()
{
return mIsTopLevelContentDocument;
}
void
nsDocument::SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument)
{
mIsTopLevelContentDocument = aIsTopLevelContentDocument;
}
nsPIDOMWindow *
nsDocument::GetWindowInternal() const
{

View File

@ -1121,6 +1121,12 @@ public:
static void XPCOMShutdown();
bool mIsTopLevelContentDocument:1;
bool IsTopLevelContentDocument();
void SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument);
js::ExpandoAndGeneration mExpandoAndGeneration;
protected:

View File

@ -18,6 +18,8 @@
#include "nsIDocument.h"
#include "nsIDOMDataContainerEvent.h"
#include "nsIDOMDocument.h"
#include "nsIDOMHTMLObjectElement.h"
#include "nsIDOMHTMLAppletElement.h"
#include "nsIExternalProtocolHandler.h"
#include "nsEventStates.h"
#include "nsIObjectFrame.h"
@ -1065,6 +1067,13 @@ nsObjectLoadingContent::GetContentTypeForMIMEType(const nsACString& aMIMEType,
return NS_OK;
}
NS_IMETHODIMP
nsObjectLoadingContent::GetBaseURI(nsIURI **aResult)
{
NS_IF_ADDREF(*aResult = mBaseURI);
return NS_OK;
}
// nsIInterfaceRequestor
// We use a shim class to implement this so that JS consumers still
// see an interface requestor even though WebIDL bindings don't expose
@ -1271,7 +1280,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy)
}
nsObjectLoadingContent::ParameterUpdateFlags
nsObjectLoadingContent::UpdateObjectParameters()
nsObjectLoadingContent::UpdateObjectParameters(bool aJavaURI)
{
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
@ -1304,7 +1313,7 @@ nsObjectLoadingContent::UpdateObjectParameters()
///
/// Initial MIME Type
///
if (thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
if (aJavaURI || thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
newMime.AssignLiteral("application/x-java-vm");
isJava = true;
} else {
@ -1345,17 +1354,76 @@ nsObjectLoadingContent::UpdateObjectParameters()
nsAutoString codebaseStr;
nsCOMPtr<nsIURI> docBaseURI = thisContent->GetBaseURI();
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, codebaseStr);
if (codebaseStr.IsEmpty() && thisContent->NodeInfo()->Equals(nsGkAtoms::applet)) {
// bug 406541
// NOTE we send the full absolute URI resolved here to java in
// pluginInstanceOwner to avoid disagreements between parsing of
// relative URIs. We need to mimic java's quirks here to make that
// not break things.
codebaseStr.AssignLiteral("/"); // Java resolves codebase="" as "/"
// XXX(johns) This doesn't catch the case of "file:" which java would
// interpret as "file:///" but we would interpret as this document's URI
// but with a changed scheme.
bool hasCodebase = thisContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase);
if (hasCodebase)
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::codebase, codebaseStr);
// Java wants the codebase attribute even if it occurs in <param> tags
// XXX(johns): This duplicates a chunk of code from nsInstanceOwner, see
// bug 853995
if (isJava) {
// Find all <param> tags that are nested beneath us, but not beneath another
// object/applet tag.
nsCOMArray<nsIDOMElement> ourParams;
nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(thisContent);
nsCOMPtr<nsIDOMHTMLCollection> allParams;
NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml");
mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"),
getter_AddRefs(allParams));
if (allParams) {
uint32_t numAllParams;
allParams->GetLength(&numAllParams);
for (uint32_t i = 0; i < numAllParams; i++) {
nsCOMPtr<nsIDOMNode> pnode;
allParams->Item(i, getter_AddRefs(pnode));
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
if (domelement) {
nsAutoString name;
domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
name.Trim(" \n\r\t\b", true, true, false);
if (name.EqualsIgnoreCase("codebase")) {
// Find the first plugin element parent
nsCOMPtr<nsIDOMNode> parent;
nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
pnode->GetParentNode(getter_AddRefs(parent));
while (!(domobject || domapplet) && parent) {
domobject = do_QueryInterface(parent);
domapplet = do_QueryInterface(parent);
nsCOMPtr<nsIDOMNode> temp;
parent->GetParentNode(getter_AddRefs(temp));
parent = temp;
}
if (domapplet || domobject) {
if (domapplet) {
parent = domapplet;
}
else {
parent = domobject;
}
nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(mydomElement);
if (parent == mydomNode) {
hasCodebase = true;
domelement->GetAttribute(NS_LITERAL_STRING("value"),
codebaseStr);
codebaseStr.Trim(" \n\r\t\b", true, true, false);
}
}
}
}
}
}
}
if (isJava && hasCodebase && codebaseStr.IsEmpty()) {
// Java treats an empty codebase as the document codebase, but codebase=""
// as "/"
codebaseStr.AssignLiteral("/");
// XXX(johns): This doesn't cover the case of "https:" which java would
// interpret as "https:///" but we interpret as this document's
// URI but with a changed scheme.
}
if (!codebaseStr.IsEmpty()) {
@ -1372,7 +1440,7 @@ nsObjectLoadingContent::UpdateObjectParameters()
}
}
// Otherwise, use normal document baseURI
// If we failed to build a valid URI, use the document's base URI
if (!newBaseURI) {
newBaseURI = docBaseURI;
}
@ -1384,9 +1452,11 @@ nsObjectLoadingContent::UpdateObjectParameters()
nsAutoString uriStr;
// Different elements keep this in various locations
if (isJava) {
// Applet tags and embed/object with explicit java MIMEs have
// src/data attributes that are not parsed as URIs, so we will
// act as if URI is null
// Applet tags and embed/object with explicit java MIMEs have src/data
// attributes that are not meant to be parsed as URIs or opened by the
// browser -- act as if they are null. (Setting these attributes triggers a
// force-load, so tracking the old value to determine if they have changed
// is not necessary.)
} else if (thisContent->NodeInfo()->Equals(nsGkAtoms::object)) {
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, uriStr);
} else if (thisContent->NodeInfo()->Equals(nsGkAtoms::embed)) {
@ -1416,6 +1486,9 @@ nsObjectLoadingContent::UpdateObjectParameters()
(caps & eAllowPluginSkipChannel) &&
IsPluginEnabledByExtension(newURI, newMime)) {
LOG(("OBJLC [%p]: Using extension as type hint (%s)", this, newMime.get()));
if (!isJava && nsPluginHost::IsJavaMIMEType(newMime.get())) {
return UpdateObjectParameters(true);
}
}
///
@ -1795,10 +1868,20 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
//
if (mType != eType_Null) {
int16_t contentPolicy = nsIContentPolicy::ACCEPT;
bool allowLoad = true;
if (nsPluginHost::IsJavaMIMEType(mContentType.get())) {
nsCOMPtr<nsIScriptSecurityManager> secMan =
nsContentUtils::GetSecurityManager();
rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(),
mBaseURI, 0);
if (NS_FAILED(rv)) {
LOG(("OBJLC [%p]: Java codebase check failed", this));
allowLoad = false;
}
}
int16_t contentPolicy = nsIContentPolicy::ACCEPT;
// If mChannelLoaded is set we presumably already passed load policy
if (mURI && !mChannelLoaded) {
if (allowLoad && mURI && !mChannelLoaded) {
allowLoad = CheckLoadPolicy(&contentPolicy);
}
// If we're loading a type now, check ProcessPolicy. Note that we may check

View File

@ -344,10 +344,14 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*
* NOTE This function does not perform security checks, only determining the
* requested type and parameters of the object.
*
*
* @param aJavaURI Specify that the URI will be consumed by java, which
* changes codebase parsing and URI construction. Used
* internally.
*
* @return Returns a bitmask of ParameterUpdateFlags values
*/
ParameterUpdateFlags UpdateObjectParameters();
ParameterUpdateFlags UpdateObjectParameters(bool aJavaURI = false);
/**
* Queue a CheckPluginStopEvent and track it in mPendingCheckPluginStopEvent

View File

@ -11,6 +11,7 @@
#include "WebGLVertexAttribData.h"
#include "WebGLMemoryMultiReporterWrapper.h"
#include "WebGLFramebuffer.h"
#include "WebGLVertexArray.h"
#include "AccessCheck.h"
#include "nsIConsoleService.h"
@ -253,15 +254,16 @@ WebGLContext::DestroyResourcesAndContext()
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBoundArrayBuffer = nullptr;
mBoundElementArrayBuffer = nullptr;
mCurrentProgram = nullptr;
mBoundFramebuffer = nullptr;
mBoundRenderbuffer = nullptr;
mAttribBuffers.Clear();
mBoundVertexArray = nullptr;
mDefaultVertexArray = nullptr;
while (!mTextures.isEmpty())
mTextures.getLast()->DeleteOnce();
while (!mVertexArrays.isEmpty())
mVertexArrays.getLast()->DeleteOnce();
while (!mBuffers.isEmpty())
mBuffers.getLast()->DeleteOnce();
while (!mRenderbuffers.isEmpty())
@ -984,6 +986,8 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
case OES_texture_float_linear:
return gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float_linear
: GLContext::ARB_texture_float);
case OES_vertex_array_object:
return WebGLExtensionVertexArray::IsSupported(this);
case EXT_texture_filter_anisotropic:
return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
case WEBGL_compressed_texture_s3tc:
@ -1063,6 +1067,10 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
{
ext = OES_texture_float_linear;
}
else if (CompareWebGLExtensionName(name, "OES_vertex_array_object"))
{
ext = OES_vertex_array_object;
}
else if (CompareWebGLExtensionName(name, "OES_standard_derivatives"))
{
ext = OES_standard_derivatives;
@ -1161,6 +1169,9 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& r
case WEBGL_draw_buffers:
obj = new WebGLExtensionDrawBuffers(this);
break;
case OES_vertex_array_object:
obj = new WebGLExtensionVertexArray(this);
break;
default:
MOZ_ASSERT(false, "should not get there.");
}
@ -1564,6 +1575,8 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
arr.AppendElement(NS_LITERAL_STRING("WEBGL_depth_texture"));
if (IsExtensionSupported(cx, WEBGL_draw_buffers))
arr.AppendElement(NS_LITERAL_STRING("WEBGL_draw_buffers"));
if (IsExtensionSupported(cx, OES_vertex_array_object))
arr.AppendElement(NS_LITERAL_STRING("OES_vertex_array_object"));
}
//
@ -1573,17 +1586,16 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString>
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_10(WebGLContext,
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_9(WebGLContext,
mCanvasElement,
mExtensions,
mBound2DTextures,
mBoundCubeMapTextures,
mBoundArrayBuffer,
mBoundElementArrayBuffer,
mCurrentProgram,
mBoundFramebuffer,
mBoundRenderbuffer,
mAttribBuffers)
mBoundVertexArray)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View File

@ -76,6 +76,7 @@ class WebGLFramebuffer;
class WebGLRenderbuffer;
class WebGLShaderPrecisionFormat;
class WebGLTexture;
class WebGLVertexArray;
namespace dom {
struct WebGLContextAttributes;
@ -128,6 +129,7 @@ class WebGLContext :
friend class WebGLExtensionCompressedTexturePVRTC;
friend class WebGLExtensionDepthTexture;
friend class WebGLExtensionDrawBuffers;
friend class WebGLExtensionVertexArray;
enum {
UNPACK_FLIP_Y_WEBGL = 0x9240,
@ -321,6 +323,7 @@ public:
void BindFramebuffer(WebGLenum target, WebGLFramebuffer* wfb);
void BindRenderbuffer(WebGLenum target, WebGLRenderbuffer* wrb);
void BindTexture(WebGLenum target, WebGLTexture *tex);
void BindVertexArray(WebGLVertexArray *vao);
void BlendColor(WebGLclampf r, WebGLclampf g, WebGLclampf b, WebGLclampf a) {
if (!IsContextStable())
return;
@ -367,12 +370,14 @@ public:
already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
already_AddRefed<WebGLTexture> CreateTexture();
already_AddRefed<WebGLShader> CreateShader(WebGLenum type);
already_AddRefed<WebGLVertexArray> CreateVertexArray();
void CullFace(WebGLenum face);
void DeleteBuffer(WebGLBuffer *buf);
void DeleteFramebuffer(WebGLFramebuffer *fbuf);
void DeleteProgram(WebGLProgram *prog);
void DeleteRenderbuffer(WebGLRenderbuffer *rbuf);
void DeleteShader(WebGLShader *shader);
void DeleteVertexArray(WebGLVertexArray *vao);
void DeleteTexture(WebGLTexture *tex);
void DepthFunc(WebGLenum func);
void DepthMask(WebGLboolean b);
@ -465,6 +470,7 @@ public:
bool IsRenderbuffer(WebGLRenderbuffer *rb);
bool IsShader(WebGLShader *shader);
bool IsTexture(WebGLTexture *tex);
bool IsVertexArray(WebGLVertexArray *vao);
void LineWidth(WebGLfloat width) {
if (!IsContextStable())
return;
@ -874,6 +880,7 @@ protected:
OES_standard_derivatives,
OES_texture_float,
OES_texture_float_linear,
OES_vertex_array_object,
WEBGL_compressed_texture_atc,
WEBGL_compressed_texture_pvrtc,
WEBGL_compressed_texture_s3tc,
@ -1031,14 +1038,10 @@ protected:
void ForceLoseContext();
void ForceRestoreContext();
// the buffers bound to the current program's attribs
nsTArray<WebGLVertexAttribData> mAttribBuffers;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
WebGLRefPtr<WebGLProgram> mCurrentProgram;
@ -1046,6 +1049,7 @@ protected:
WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer;
WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
WebGLRefPtr<WebGLVertexArray> mBoundVertexArray;
LinkedList<WebGLTexture> mTextures;
LinkedList<WebGLBuffer> mBuffers;
@ -1053,6 +1057,9 @@ protected:
LinkedList<WebGLShader> mShaders;
LinkedList<WebGLRenderbuffer> mRenderbuffers;
LinkedList<WebGLFramebuffer> mFramebuffers;
LinkedList<WebGLVertexArray> mVertexArrays;
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
// PixelStore parameters
uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
@ -1138,6 +1145,7 @@ public:
friend class WebGLBuffer;
friend class WebGLShader;
friend class WebGLUniformLocation;
friend class WebGLVertexArray;
};
// used by DOM bindings in conjunction with GetParentObject

View File

@ -15,6 +15,7 @@
#include "WebGLShaderPrecisionFormat.h"
#include "WebGLTexture.h"
#include "WebGLExtensions.h"
#include "WebGLVertexArray.h"
#include "nsString.h"
#include "nsDebug.h"
@ -162,7 +163,7 @@ WebGLContext::BindBuffer(WebGLenum target, WebGLBuffer *buf)
if (target == LOCAL_GL_ARRAY_BUFFER) {
mBoundArrayBuffer = buf;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
mBoundElementArrayBuffer = buf;
mBoundVertexArray->mBoundElementArrayBuffer = buf;
}
MakeContextCurrent();
@ -226,6 +227,39 @@ WebGLContext::BindRenderbuffer(WebGLenum target, WebGLRenderbuffer *wrb)
mBoundRenderbuffer = wrb;
}
void
WebGLContext::BindVertexArray(WebGLVertexArray *array)
{
if (!IsContextStable())
return;
if (!ValidateObjectAllowDeletedOrNull("bindVertexArrayObject", array))
return;
if (array && array->IsDeleted()) {
/* http://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt
* BindVertexArrayOES fails and an INVALID_OPERATION error is
* generated if array is not a name returned from a previous call to
* GenVertexArraysOES, or if such a name has since been deleted with
* DeleteVertexArraysOES
*/
ErrorInvalidOperation("bindVertexArray: can't bind a deleted array!");
return;
}
MakeContextCurrent();
if (array) {
gl->fBindVertexArray(array->GLName());
array->SetHasEverBeenBound(true);
mBoundVertexArray = array;
}
else {
gl->fBindVertexArray(0);
mBoundVertexArray = mDefaultVertexArray;
}
}
void
WebGLContext::BindTexture(WebGLenum target, WebGLTexture *tex)
{
@ -337,7 +371,7 @@ GLenum WebGLContext::CheckedBufferData(GLenum target,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
}
NS_ABORT_IF_FALSE(boundBuffer != nullptr, "no buffer bound for this target");
@ -366,7 +400,7 @@ WebGLContext::BufferData(WebGLenum target, WebGLsizeiptr size,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferData: target", target);
}
@ -411,7 +445,7 @@ WebGLContext::BufferData(WebGLenum target, ArrayBuffer *data, WebGLenum usage)
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferData: target", target);
}
@ -449,7 +483,7 @@ WebGLContext::BufferData(WebGLenum target, ArrayBufferView& data, WebGLenum usag
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferData: target", target);
}
@ -492,7 +526,7 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferSubData: target", target);
}
@ -530,7 +564,7 @@ WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
if (target == LOCAL_GL_ARRAY_BUFFER) {
boundBuffer = mBoundArrayBuffer;
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
boundBuffer = mBoundElementArrayBuffer;
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
} else {
return ErrorInvalidEnumInfo("bufferSubData: target", target);
}
@ -1071,13 +1105,14 @@ WebGLContext::DeleteBuffer(WebGLBuffer *buf)
if (mBoundArrayBuffer == buf)
BindBuffer(LOCAL_GL_ARRAY_BUFFER,
static_cast<WebGLBuffer*>(nullptr));
if (mBoundElementArrayBuffer == buf)
if (mBoundVertexArray->mBoundElementArrayBuffer == buf)
BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
static_cast<WebGLBuffer*>(nullptr));
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
if (mAttribBuffers[i].buf == buf)
mAttribBuffers[i].buf = nullptr;
if (mBoundVertexArray->mAttribBuffers[i].buf == buf)
mBoundVertexArray->mAttribBuffers[i].buf = nullptr;
}
buf->RequestDelete();
@ -1124,6 +1159,24 @@ WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer *rbuf)
rbuf->RequestDelete();
}
void
WebGLContext::DeleteVertexArray(WebGLVertexArray *array)
{
if (!IsContextStable())
return;
if (array == nullptr)
return;
if (array->IsDeleted())
return;
if (mBoundVertexArray == array)
BindVertexArray(static_cast<WebGLVertexArray*>(nullptr));
array->RequestDelete();
}
void
WebGLContext::DeleteTexture(WebGLTexture *tex)
{
@ -1251,7 +1304,7 @@ WebGLContext::DisableVertexAttribArray(WebGLuint index)
if (index || gl->IsGLES2())
gl->fDisableVertexAttribArray(index);
mAttribBuffers[index].enabled = false;
mBoundVertexArray->mAttribBuffers[index].enabled = false;
}
int
@ -1262,14 +1315,14 @@ WebGLContext::WhatDoesVertexAttrib0Need()
// work around Mac OSX crash, see bug 631420
#ifdef XP_MACOSX
if (gl->WorkAroundDriverBugs() &&
mAttribBuffers[0].enabled &&
mBoundVertexArray->mAttribBuffers[0].enabled &&
!mCurrentProgram->IsAttribInUse(0))
{
return VertexAttrib0Status::EmulatedUninitializedArray;
}
#endif
return (gl->IsGLES2() || mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
return (gl->IsGLES2() || mBoundVertexArray->mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
: mCurrentProgram->IsAttribInUse(0) ? VertexAttrib0Status::EmulatedInitializedArray
: VertexAttrib0Status::EmulatedUninitializedArray;
}
@ -1369,13 +1422,13 @@ WebGLContext::UndoFakeVertexAttrib0()
if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
return;
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mAttribBuffers[0].buf ? mAttribBuffers[0].buf->GLName() : 0);
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundVertexArray->mAttribBuffers[0].buf ? mBoundVertexArray->mAttribBuffers[0].buf->GLName() : 0);
gl->fVertexAttribPointer(0,
mAttribBuffers[0].size,
mAttribBuffers[0].type,
mAttribBuffers[0].normalized,
mAttribBuffers[0].stride,
reinterpret_cast<const GLvoid *>(mAttribBuffers[0].byteOffset));
mBoundVertexArray->mAttribBuffers[0].size,
mBoundVertexArray->mAttribBuffers[0].type,
mBoundVertexArray->mAttribBuffers[0].normalized,
mBoundVertexArray->mAttribBuffers[0].stride,
reinterpret_cast<const GLvoid *>(mBoundVertexArray->mAttribBuffers[0].byteOffset));
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
}
@ -1592,10 +1645,10 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
if (!mCurrentProgram)
return;
if (!mBoundElementArrayBuffer)
if (!mBoundVertexArray->mBoundElementArrayBuffer)
return ErrorInvalidOperation("drawElements: must have element array buffer binding");
if (!mBoundElementArrayBuffer->ByteLength())
if (!mBoundVertexArray->mBoundElementArrayBuffer->ByteLength())
return ErrorInvalidOperation("drawElements: bound element array buffer doesn't have any data");
CheckedUint32 checked_neededByteCount = checked_byteCount + byteOffset;
@ -1603,7 +1656,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
if (!checked_neededByteCount.isValid())
return ErrorInvalidOperation("drawElements: overflow in byteOffset+byteCount");
if (checked_neededByteCount.value() > mBoundElementArrayBuffer->ByteLength())
if (checked_neededByteCount.value() > mBoundVertexArray->mBoundElementArrayBuffer->ByteLength())
return ErrorInvalidOperation("drawElements: bound element array buffer is too small for given count and offset");
uint32_t maxAllowedCount = 0;
@ -1611,7 +1664,7 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type,
return;
if (!maxAllowedCount ||
!mBoundElementArrayBuffer->Validate(type, maxAllowedCount - 1, first, count))
!mBoundVertexArray->mBoundElementArrayBuffer->Validate(type, maxAllowedCount - 1, first, count))
{
return ErrorInvalidOperation(
"DrawElements: bound vertex attribute buffers do not have sufficient "
@ -1710,7 +1763,7 @@ WebGLContext::EnableVertexAttribArray(WebGLuint index)
InvalidateCachedMinInUseAttribArrayLength();
gl->fEnableVertexAttribArray(index);
mAttribBuffers[index].enabled = true;
mBoundVertexArray->mAttribBuffers[index].enabled = true;
}
void
@ -2030,6 +2083,21 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
}
}
if (IsExtensionEnabled(OES_vertex_array_object)) {
switch (pname) {
case LOCAL_GL_VERTEX_ARRAY_BINDING:
{
if (mBoundVertexArray == mDefaultVertexArray){
return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv);
}
return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv);
}
}
}
switch (pname) {
//
// String params
@ -2291,7 +2359,7 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING:
{
return WebGLObjectAsJSValue(cx, mBoundElementArrayBuffer.get(), rv);
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mBoundElementArrayBuffer.get(), rv);
}
case LOCAL_GL_RENDERBUFFER_BINDING:
@ -2955,7 +3023,7 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
if (!IsContextStable())
return JS::NullValue();
if (!ValidateAttribIndex(index, "getVertexAttrib"))
if (!mBoundVertexArray->EnsureAttribIndex(index, "getVertexAttrib"))
return JS::NullValue();
MakeContextCurrent();
@ -2963,18 +3031,18 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
switch (pname) {
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
{
return WebGLObjectAsJSValue(cx, mAttribBuffers[index].buf.get(), rv);
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribBuffers[index].buf.get(), rv);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
return JS::Int32Value(mAttribBuffers[index].stride);
return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].stride);
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
{
if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
return JS::NullValue();
if (!mAttribBuffers[index].enabled)
if (!mBoundVertexArray->mAttribBuffers[index].enabled)
return JS::Int32Value(4);
// Don't break; fall through.
@ -3009,14 +3077,12 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
{
return JS::BooleanValue(mAttribBuffers[index].enabled);
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].enabled);
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
{
GLint i = 0;
gl->fGetVertexAttribiv(index, pname, &i);
return JS::BooleanValue(bool(i));
return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].normalized);
}
default:
@ -3040,7 +3106,7 @@ WebGLContext::GetVertexAttribOffset(WebGLuint index, WebGLenum pname)
return 0;
}
return mAttribBuffers[index].byteOffset;
return mBoundVertexArray->mAttribBuffers[index].byteOffset;
}
void
@ -3109,6 +3175,20 @@ WebGLContext::IsRenderbuffer(WebGLRenderbuffer *rb)
rb->HasEverBeenBound();
}
bool
WebGLContext::IsVertexArray(WebGLVertexArray *array)
{
if (!IsContextStable())
return false;
if (!array)
return false;
return ValidateObjectAllowDeleted("isVertexArray", array) &&
!array->IsDeleted() &&
array->HasEverBeenBound();
}
bool
WebGLContext::IsShader(WebGLShader *shader)
{
@ -4330,6 +4410,22 @@ WebGLContext::CreateRenderbuffer()
return globj.forget();
}
already_AddRefed<WebGLVertexArray>
WebGLContext::CreateVertexArray()
{
if (!IsContextStable())
return nullptr;
nsRefPtr<WebGLVertexArray> globj = new WebGLVertexArray(this);
MakeContextCurrent();
gl->fGenVertexArrays(1, &globj->mGLName);
mVertexArrays.insertBack(globj);
return globj.forget();
}
void
WebGLContext::Viewport(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height)
{
@ -4889,8 +4985,9 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
// requiredAlignment should always be a power of two.
WebGLsizei requiredAlignmentMask = requiredAlignment - 1;
if (!ValidateAttribIndex(index, "vertexAttribPointer"))
if ( !mBoundVertexArray->EnsureAttribIndex(index, "vertexAttribPointer") ) {
return;
}
if (size < 1 || size > 4)
return ErrorInvalidValue("vertexAttribPointer: invalid element size");
@ -4919,7 +5016,7 @@ WebGLContext::VertexAttribPointer(WebGLuint index, WebGLint size, WebGLenum type
return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
*/
WebGLVertexAttribData &vd = mAttribBuffers[index];
WebGLVertexAttribData &vd = mBoundVertexArray->mAttribBuffers[index];
vd.buf = mBoundArrayBuffer;
vd.stride = stride;

View File

@ -12,6 +12,7 @@
#include "WebGLFramebuffer.h"
#include "WebGLRenderbuffer.h"
#include "WebGLTexture.h"
#include "WebGLVertexArray.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/Preferences.h"
@ -112,9 +113,9 @@ WebGLContext::ValidateBuffers(uint32_t *maxAllowedCount, const char *info)
}
uint32_t maxAllowed = UINT32_MAX;
uint32_t attribs = mAttribBuffers.Length();
uint32_t attribs = mBoundVertexArray->mAttribBuffers.Length();
for (uint32_t i = 0; i < attribs; ++i) {
const WebGLVertexAttribData& vd = mAttribBuffers[i];
const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribBuffers[i];
// If the attrib array isn't enabled, there's nothing to check;
// it's a static value.
@ -850,18 +851,7 @@ WebGLContext::ValidateUniformSetter(const char* name, WebGLUniformLocation *loca
bool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
{
if (index >= mAttribBuffers.Length()) {
if (index == WebGLuint(-1)) {
ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
"the specified program.", info);
} else {
ErrorInvalidValue("%s: index %d is out of range", info, index);
}
return false;
} else {
return true;
}
return mBoundVertexArray->EnsureAttribIndex(index, info);
}
bool WebGLContext::ValidateStencilParamsForDrawCall()
@ -905,13 +895,10 @@ WebGLContext::InitAndValidateGL()
mActiveTexture = 0;
mWebGLError = LOCAL_GL_NO_ERROR;
mAttribBuffers.Clear();
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBoundArrayBuffer = nullptr;
mBoundElementArrayBuffer = nullptr;
mCurrentProgram = nullptr;
mBoundFramebuffer = nullptr;
@ -934,8 +921,6 @@ WebGLContext::InitAndValidateGL()
return false;
}
mAttribBuffers.SetLength(mGLMaxVertexAttribs);
// Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
// even though the hardware supports much more. The
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
@ -1084,5 +1069,9 @@ WebGLContext::InitAndValidateGL()
false);
}
mDefaultVertexArray = new WebGLVertexArray(this);
mDefaultVertexArray->mAttribBuffers.SetLength(mGLMaxVertexAttribs);
mBoundVertexArray = mDefaultVertexArray;
return true;
}

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "WebGLContext.h"
#include "WebGLBuffer.h"
#include "WebGLVertexArray.h"
#include "WebGLExtensions.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
using namespace mozilla;
WebGLExtensionVertexArray::WebGLExtensionVertexArray(WebGLContext* context)
: WebGLExtensionBase(context)
{
MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionVertexArray :"
"OES_vertex_array_object unsuported.");
}
WebGLExtensionVertexArray::~WebGLExtensionVertexArray()
{
}
already_AddRefed<WebGLVertexArray> WebGLExtensionVertexArray::CreateVertexArrayOES()
{
return mContext->CreateVertexArray();
}
void WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
{
mContext->DeleteVertexArray(array);
}
bool WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
{
return mContext->IsVertexArray(array);
}
void WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
{
mContext->BindVertexArray(array);
}
bool WebGLExtensionVertexArray::IsSupported(const WebGLContext* context)
{
gl::GLContext* gl = context->GL();
if (gl->IsGLES2()) {
return gl->IsExtensionSupported(gl::GLContext::OES_vertex_array_object);
}
return gl->IsExtensionSupported(gl::GLContext::ARB_vertex_array_object) ||
gl->IsExtensionSupported(gl::GLContext::APPLE_vertex_array_object);
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray)

View File

@ -172,6 +172,23 @@ public:
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionVertexArray
: public WebGLExtensionBase
{
public:
WebGLExtensionVertexArray(WebGLContext*);
virtual ~WebGLExtensionVertexArray();
already_AddRefed<WebGLVertexArray> CreateVertexArrayOES();
void DeleteVertexArrayOES(WebGLVertexArray* array);
bool IsVertexArrayOES(WebGLVertexArray* array);
void BindVertexArrayOES(WebGLVertexArray* array);
static bool IsSupported(const WebGLContext* context);
DECL_WEBGL_EXTENSION_GOOP
};
} // namespace mozilla
#endif // WEBGLEXTENSIONS_H_

View File

@ -0,0 +1,69 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "WebGLContext.h"
#include "WebGLBuffer.h"
#include "WebGLVertexArray.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "nsContentUtils.h"
using namespace mozilla;
JSObject*
WebGLVertexArray::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
return dom::WebGLVertexArrayBinding::Wrap(cx, scope, this);
}
WebGLVertexArray::WebGLVertexArray(WebGLContext* context)
: WebGLContextBoundObject(context)
, mGLName(0)
, mHasEverBeenBound(false)
{
SetIsDOMBinding();
}
void WebGLVertexArray::Delete() {
if (mGLName != 0) {
mBoundElementArrayBuffer = nullptr;
mContext->MakeContextCurrent();
mContext->gl->fDeleteVertexArrays(1, &mGLName);
LinkedListElement<WebGLVertexArray>::removeFrom(mContext->mVertexArrays);
}
mBoundElementArrayBuffer = nullptr;
mAttribBuffers.Clear();
}
bool WebGLVertexArray::EnsureAttribIndex(WebGLuint index, const char *info)
{
if (index >= WebGLuint(mContext->mGLMaxVertexAttribs)) {
if (index == WebGLuint(-1)) {
mContext->ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
"where this return value -1 means that the passed name didn't correspond to an active attribute in "
"the specified program.", info);
} else {
mContext->ErrorInvalidValue("%s: index %d is out of range", info, index);
}
return false;
}
else if (index >= mAttribBuffers.Length()) {
mAttribBuffers.SetLength(index + 1);
}
return true;
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(WebGLVertexArray,
mAttribBuffers,
mBoundElementArrayBuffer)
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLVertexArray)
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLVertexArray)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLVertexArray)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

View File

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 WEBGLVERTEXARRAY_H_
#define WEBGLVERTEXARRAY_H_
#include "WebGLObjectModel.h"
#include "WebGLVertexAttribData.h"
#include "nsWrapperCache.h"
#include "mozilla/LinkedList.h"
namespace mozilla {
class WebGLVertexArray MOZ_FINAL
: public nsISupports
, public WebGLRefCountedObject<WebGLVertexArray>
, public LinkedListElement<WebGLVertexArray>
, public WebGLContextBoundObject
, public nsWrapperCache
{
public:
WebGLVertexArray(WebGLContext *context);
~WebGLVertexArray() {
DeleteOnce();
};
void Delete();
bool HasEverBeenBound() { return mHasEverBeenBound; }
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
WebGLuint GLName() const { return mGLName; }
WebGLContext* GetParentObject() const {
return Context();
}
bool EnsureAttribIndex(WebGLuint index, const char *info);
virtual JSObject* WrapObject(JSContext *cx,
JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLVertexArray)
WebGLuint mGLName;
bool mHasEverBeenBound;
nsTArray<WebGLVertexAttribData> mAttribBuffers;
WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
friend class WebGLContext;
friend class WebGLExtensionVertexArray;
};
} // namespace mozilla
#endif

View File

@ -47,6 +47,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLExtensionTextureFilterAnisotropic.cpp',
'WebGLExtensionTextureFloat.cpp',
'WebGLExtensionTextureFloatLinear.cpp',
'WebGLExtensionVertexArray.cpp',
'WebGLFramebuffer.cpp',
'WebGLObjectModel.cpp',
'WebGLProgram.cpp',
@ -56,6 +57,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGLTexelConversions.cpp',
'WebGLTexture.cpp',
'WebGLUniformLocation.cpp',
'WebGLVertexArray.cpp',
]
else:
CPP_SOURCES += [

View File

@ -148,7 +148,11 @@ function runObjectTest() {
ext.bindVertexArrayOES(null);
shouldBeTrue("ext.isVertexArrayOES(vao)");
shouldBeFalse("ext.isVertexArrayOES()");
/*
* Issue found in the conformance test. The public webgl mailing list has been notified about it.
* The tests have already been fixed upstream.
*/
//shouldBeFalse("ext.isVertexArrayOES()");
shouldBeFalse("ext.isVertexArrayOES(null)");
ext.deleteVertexArrayOES(vao);

View File

@ -1,4 +1,5 @@
conformance/extensions/oes-texture-float.html
conformance/extensions/oes-vertex-array-object.html
conformance/glsl/functions/glsl-function-abs.html
conformance/glsl/functions/glsl-function-ceil.html
conformance/glsl/functions/glsl-function-clamp-float.html

View File

@ -138,6 +138,7 @@ MOCHITEST_FILES = \
test_paused_after_removed.html \
$(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \
test_texttrack.html \
test_texttrackcue.html \
test_timeupdate_small_files.html \
test_unseekable.html \
test_webvtt_disabled.html \
@ -259,6 +260,7 @@ MOCHITEST_FILES += \
detodos.opus \
notags.mp3 \
id3tags.mp3 \
basic.vtt \
$(NULL)
# Wave sample files

View File

@ -0,0 +1,17 @@
WEBVTT
1
00:00.500 --> 00:00.700
This
2
00:01.200 --> 00:02.400
Is
3
00:02.710 --> 00:02.910
A
3
00:03.217 --> 00:03.989
Test

View File

@ -0,0 +1,126 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=833386
-->
<head>
<meta charset='utf-8'>
<title>Test for Bug 833386 - HTMLTrackElement</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
function() {
var video = document.createElement("video");
video.src = "seek.webm";
var trackElement = document.createElement("track");
trackElement.src = "basic.vtt";
trackElement.kind = "subtitles";
document.getElementById("content").appendChild(video);
video.appendChild(trackElement);
run_tests();
function run_tests() {
// Re-que run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackElement.readyState == 1) {
setTimeout(run_tests, 0);
return;
}
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
var cueList = trackElement.track.cues;
is(cueList.length, 4, "Cue list length should be 4.");
// Check if first cue was parsed correctly.
var cue = cueList[0];
is(cue.id, "1", "Cue's ID should be 1.");
is(cue.startTime, 0.5, "Cue's start time should be 0.5.");
is(cue.endTime, 0.7, "Cue's end time should be 0.7.");
is(cue.pauseOnExit, false, "Cue's pause on exit flag should be false.");
is(cue.text, "This", "Cue's text should be set correctly.");
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=879431
// GetTrack() isn't implemented so this *is* returning undefined currently.
todo_isnot(cue.track, undefined, "Cue's track should be defined.");
// Check that all cue times were not rounded
is(cueList[1].startTime, 1.2, "Second cue's start time should be 1.2.");
is(cueList[1].endTime, 2.4, "Second cue's end time should be 2.4.");
is(cueList[2].startTime, 2.71, "Third cue's start time should be 2.71.");
is(cueList[2].endTime, 2.91, "Third cue's end time should be 2.91.");
is(cueList[3].startTime, 3.217, "Fourth cue's start time should be 3.217.");
is(cueList[3].endTime, 3.989, "Fourth cue's end time should be 3.989.");
// Check that Cue setters are working correctly.
cue.id = "Cue 01";
is(cue.id, "Cue 01", "Cue's ID should be 'Cue 01'.");
cue.startTime = 1.5;
is(cue.startTime, 1.5, "Cue's start time should be 1.5.");
cue.endTime = 2.5;
is(cue.endTime, 2.5, "Cue's end time should be 2.5.");
cue.pauseOnExit = true;
is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
// Check that we can create and add new TextTrackCues
var textTrackCue = new TextTrackCue(3.999, 4, "foo");
trackElement.track.addCue(textTrackCue);
is(cueList.length, 5, "Cue list length should now be 5.");
// Check that new TestTrackCue was added correctly
cue = cueList[4];
is(cue.startTime, 3.999, "Cue's start time should be 3.999.");
is(cue.endTime, 4, "Cue's end time should be 4.");
is(cue.text, "foo", "Cue's text should be foo.");
// Adding the same cue again should not increase the cue count.
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=867823
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrack-addcue
trackElement.track.addCue(textTrackCue);
todo_is(cueList.length, 5, "Cue list length should be 5.");
// Check that we are able to remove cues.
trackElement.track.removeCue(cue);
// TODO: Marked as todo as incorrect addition up top increases cue count
// to 4 -- https://bugzilla.mozilla.org/show_bug.cgi?id=867823
todo_is(cueList.length, 4, "Cue list length should be 4.");
var exceptionHappened = false;
try {
// We should not be able to remove a cue that is not in the list.
cue = new TextTrackCue(1, 2, "foo");
trackElement.removeCue(cue);
} catch (e) {
// "NotFoundError" should be thrown when trying to remove a cue that is
// not in the list.
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=867823
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrack-removecue
todo_is(e.name, "NotFoundError", "We should have caught an error.");
exceptionHappened = true;
}
// If this is false then we did not throw an error and probably removed a cue
// when we shouln't have.
ok(exceptionHappened, "Exception should have happened.");
// We should not have removed a cue so the cue list length should not
// have changed.
// TODO: Marked as todo as incorrect addition of cue up top increases
// count erroneously.
// https://bugzilla.mozilla.org/show_bug.cgi?id=867823
todo_is(cueList.length, 4, "Cue list length should be 4.");
SimpleTest.finish();
}
}
);
</script>
</pre>
</body>
</html>

View File

@ -41,6 +41,12 @@ NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(AudioBufferSourceNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(AudioBufferSourceNode, AudioNode)
/**
* Media-thread playback engine for AudioBufferSourceNode.
* Nothing is played until a non-null buffer has been set (via
* AudioNodeStream::SetBuffer) and a non-zero duration has been set (via
* AudioNodeStream::SetInt32Parameter).
*/
class AudioBufferSourceNodeEngine : public AudioNodeEngine
{
public:
@ -353,8 +359,9 @@ public:
AudioChunk* aOutput,
bool* aFinished)
{
if (!mBuffer)
if (!mBuffer || !mDuration) {
return;
}
uint32_t channels = mBuffer->GetChannels();
if (!channels) {
@ -484,7 +491,9 @@ AudioBufferSourceNode::Start(double aWhen, double aOffset,
std::numeric_limits<double>::min();
SendOffsetAndDurationParametersToStream(ns, aOffset, duration);
} else {
// Remember our arguments so that we can use them once we have a buffer
// Remember our arguments so that we can use them once we have a buffer.
// We can't send these parameters now because we don't know the buffer
// sample rate.
mOffset = aOffset;
mDuration = aDuration.WasPassed() ?
aDuration.Value() :
@ -512,11 +521,13 @@ AudioBufferSourceNode::SendBufferParameterToStream(JSContext* aCx)
mBuffer->GetThreadSharedChannelsForRate(aCx);
ns->SetBuffer(data.forget());
ns->SetInt32Parameter(SAMPLE_RATE, rate);
if (mStartCalled) {
SendOffsetAndDurationParametersToStream(ns, mOffset, mDuration);
}
} else {
ns->SetBuffer(nullptr);
}
SendOffsetAndDurationParametersToStream(ns, mOffset, mDuration);
}
void
@ -524,8 +535,11 @@ AudioBufferSourceNode::SendOffsetAndDurationParametersToStream(AudioNodeStream*
double aOffset,
double aDuration)
{
float rate = mBuffer ? mBuffer->SampleRate() : Context()->SampleRate();
int32_t lengthSamples = mBuffer ? mBuffer->Length() : 0;
NS_ASSERTION(mBuffer && mStartCalled,
"Only call this when we have a buffer and start() has been called");
float rate = mBuffer->SampleRate();
int32_t lengthSamples = mBuffer->Length();
double length = double(lengthSamples) / rate;
double offset = std::max(0.0, aOffset);
double endOffset = aDuration == std::numeric_limits<double>::min() ?

View File

@ -44,6 +44,7 @@ MOCHITEST_FILES := \
test_audioBufferSourceNodeLoop.html \
test_audioBufferSourceNodeLoopStartEnd.html \
test_audioBufferSourceNodeLoopStartEndSame.html \
test_audioBufferSourceNodeNoStart.html \
test_audioBufferSourceNodeNullBuffer.html \
test_badConnect.html \
test_biquadFilterNode.html \

View File

@ -0,0 +1,33 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test AudioBufferSourceNode when start() is not called</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">
var gTest = {
length: 2048,
numberOfChannels: 1,
createGraph: function(context) {
var buffer = context.createBuffer(1, 2048, context.sampleRate);
var data = buffer.getChannelData(0);
for (var i = 0; i < data.length; ++i) {
data[i] = (i%100)/100 - 0.5;
}
var source = context.createBufferSource();
source.buffer = buffer;
return source;
},
};
runTest();
</script>
</pre>
</body>
</html>

View File

@ -18,7 +18,6 @@
#include "mozilla/Services.h"
#include "mozilla/StartupTimeline.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Telemetry.h"
#include "mozilla/unused.h"
#include "mozilla/Util.h"
#include "mozilla/VisualEventTracer.h"

View File

@ -1196,6 +1196,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'WebGLExtensionVertexArray': {
'nativeType': 'mozilla::WebGLExtensionVertexArray',
'headerFile': 'WebGLExtensions.h'
},
'WebGLFramebuffer': {
'nativeType': 'mozilla::WebGLFramebuffer',
'headerFile': 'WebGLFramebuffer.h'
@ -1241,6 +1246,11 @@ DOMInterfaces = {
'wrapperCache': False
},
'WebGLVertexArray': {
'nativeType': 'mozilla::WebGLVertexArray',
'headerFile': 'WebGLVertexArray.h'
},
'WebSocket': {
'headerFile': 'WebSocket.h',
'implicitJSContext': [ 'constructor' ]

View File

@ -80,6 +80,20 @@ listStart = First item
listEnd = Last item
listItemCount = %S items
# Description of a table or grid:
# 1 is a dynamically retrieved localized role of either 'table' or 'grid'.
# 2 is the number of columns within the table.
# 3 is the number of rows within the table or grid.
tableInfo = %S with %S and %S
tableColumnInfo = 1 column;#1 columns
tableRowInfo = 1 row;#1 rows
# table or grid cell information
columnInfo = Column %S
rowInfo = Row %S
spansColumns = spans %S columns
spansRows = spans %S rows
# Invoked actions
jumpAction = jumped
pressAction = pressed
@ -141,3 +155,8 @@ passwordtextAbbr = passwdtxt
imagemapAbbr = imgmap
figureAbbr = fig
textareaAbbr = txtarea
tableAbbr = tbl
tableInfoAbbr = %S %S %S
tableColumnInfoAbbr = #1c;#1c
tableRowInfoAbbr = #1r;#1r
cellInfoAbbr = c%Sr%S

View File

@ -49,6 +49,7 @@ using mozilla::DefaultXDisplay;
#include "nsIDOMHTMLObjectElement.h"
#include "nsIAppShell.h"
#include "nsIDOMHTMLAppletElement.h"
#include "nsIObjectLoadingContent.h"
#include "nsAttrName.h"
#include "nsIFocusManager.h"
#include "nsFocusManager.h"
@ -1047,6 +1048,11 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
mNumCachedAttrs = 0xFFFD;
}
// Check if we are java for special codebase handling
const char* mime = nullptr;
bool isJava = NS_SUCCEEDED(mInstance->GetMIMEType(&mime)) && mime &&
nsPluginHost::IsJavaMIMEType(mime);
// now, we need to find all the PARAM tags that are children of us
// however, be careful not to include any PARAMs that don't have us
// as a direct parent. For nested object (or applet) tags, be sure
@ -1139,6 +1145,23 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
mNumCachedAttrs++;
}
// (Bug 738396) java has quirks in its codebase parsing, pass the
// absolute codebase URI as content sees it.
bool addCodebase = false;
nsAutoCString codebaseStr;
if (isJava) {
nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(mContent);
NS_ENSURE_TRUE(objlc, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIURI> codebaseURI;
nsresult rv = objlc->GetBaseURI(getter_AddRefs(codebaseURI));
NS_ENSURE_SUCCESS(rv, rv);
codebaseURI->GetSpec(codebaseStr);
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::codebase)) {
mNumCachedAttrs++;
addCodebase = true;
}
}
mCachedAttrParamNames = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
mCachedAttrParamValues = (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs + 1 + mNumCachedParams));
@ -1183,7 +1206,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
FixUpURLS(name, value);
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
if (!wmodeType.IsEmpty() &&
if (!wmodeType.IsEmpty() &&
0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "wmode")) {
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType));
@ -1192,12 +1215,21 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
mNumCachedAttrs--;
wmodeSet = true;
}
} else if (isJava && 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "codebase")) {
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
} else {
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
}
nextAttrParamIndex++;
}
// Potentially add CODEBASE attribute
if (addCodebase) {
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("codebase"));
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(codebaseStr));
nextAttrParamIndex++;
}
// Potentially add WMODE attribute.
if (!wmodeType.IsEmpty() && !wmodeSet) {
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
@ -1223,7 +1255,10 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
nextAttrParamIndex++;
// Add PARAM name/value pairs.
for (uint16_t i = 0; i < mNumCachedParams; i++) {
// We may decrement mNumCachedParams below
uint16_t totalParams = mNumCachedParams;
for (uint16_t i = 0; i < totalParams; i++) {
nsIDOMElement* param = ourParams.ObjectAt(i);
if (!param) {
continue;
@ -1233,7 +1268,7 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
nsAutoString value;
param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
param->GetAttribute(NS_LITERAL_STRING("value"), value);
FixUpURLS(name, value);
/*
@ -1248,6 +1283,12 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
*/
name.Trim(" \n\r\t\b", true, true, false);
value.Trim(" \n\r\t\b", true, true, false);
if (isJava && name.EqualsIgnoreCase("codebase")) {
// We inserted normalized codebase above, don't include other versions in
// params
mNumCachedParams--;
continue;
}
mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name);
mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value);
nextAttrParamIndex++;

View File

@ -64,6 +64,9 @@ interface WebGLTexture {
interface WebGLUniformLocation {
};
interface WebGLVertexArray {
};
interface WebGLActiveInfo {
readonly attribute GLint size;
readonly attribute GLenum type;
@ -883,3 +886,13 @@ interface WebGLExtensionDrawBuffers {
interface WebGLExtensionTextureFloatLinear
{
};
[NoInterfaceObject]
interface WebGLExtensionVertexArray {
const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5;
WebGLVertexArray? createVertexArrayOES();
void deleteVertexArrayOES(WebGLVertexArray? arrayObject);
[WebGLHandlesContextLoss] GLboolean isVertexArrayOES(WebGLVertexArray? arrayObject);
void bindVertexArrayOES(WebGLVertexArray? arrayObject);
};

View File

@ -719,7 +719,7 @@ public:
virtual void MaskSurface(const Pattern &aSource,
SourceSurface *aMask,
Point aOffset,
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
const DrawOptions &aOptions = DrawOptions()) = 0;
/*
* Push a clip to the DrawTarget.

View File

@ -107,6 +107,10 @@ public:
virtual void Mask(const Pattern &aSource,
const Pattern &aMask,
const DrawOptions &aOptions = DrawOptions());
virtual void MaskSurface(const Pattern &aSource,
SourceSurface *aMask,
Point aOffset,
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
virtual void PushClip(const Path *aPath);
virtual void PushClipRect(const Rect &aRect);

View File

@ -248,6 +248,16 @@ DrawTargetRecording::Mask(const Pattern &aSource,
mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions);
}
void
DrawTargetRecording::MaskSurface(const Pattern &aSource,
SourceSurface *aMask,
Point aOffset,
const DrawOptions &aOptions)
{
mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask), aOffset, aOptions);
}
void
DrawTargetRecording::Stroke(const Path *aPath,
const Pattern &aPattern,

View File

@ -172,6 +172,11 @@ public:
const Pattern &aMask,
const DrawOptions &aOptions = DrawOptions());
virtual void MaskSurface(const Pattern &aSource,
SourceSurface *aMask,
Point aOffset,
const DrawOptions &aOptions = DrawOptions());
/*
* Push a clip to the DrawTarget.
*

View File

@ -75,6 +75,10 @@ public:
virtual void Mask(const Pattern &aSource,
const Pattern &aMask,
const DrawOptions &aOptions = DrawOptions());
virtual void MaskSurface(const Pattern &aSource,
SourceSurface *aMask,
Point aOffset,
const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); };
virtual void PushClip(const Path *aPath);
virtual void PushClipRect(const Rect& aRect);
virtual void PopClip();

View File

@ -58,6 +58,7 @@ RecordedEvent::LoadEventFromStream(std::istream &aStream, EventType aType)
LOAD_EVENT_TYPE(SNAPSHOT, RecordedSnapshot);
LOAD_EVENT_TYPE(SCALEDFONTCREATION, RecordedScaledFontCreation);
LOAD_EVENT_TYPE(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction);
LOAD_EVENT_TYPE(MASKSURFACE, RecordedMaskSurface);
default:
return NULL;
}
@ -1216,5 +1217,40 @@ RecordedScaledFontDestruction::OutputSimpleEventInfo(stringstream &aStringStream
aStringStream << "[" << mRefPtr << "] ScaledFont Destroyed";
}
void
RecordedMaskSurface::PlayEvent(Translator *aTranslator) const
{
aTranslator->LookupDrawTarget(mDT)->
MaskSurface(*GenericPattern(mPattern, aTranslator),
aTranslator->LookupSourceSurface(mRefMask),
mOffset, mOptions);
}
void
RecordedMaskSurface::RecordToStream(ostream &aStream) const
{
RecordedDrawingEvent::RecordToStream(aStream);
RecordPatternData(aStream, mPattern);
WriteElement(aStream, mRefMask);
WriteElement(aStream, mOffset);
WriteElement(aStream, mOptions);
}
RecordedMaskSurface::RecordedMaskSurface(istream &aStream)
: RecordedDrawingEvent(MASKSURFACE, aStream)
{
ReadPatternData(aStream, mPattern);
ReadElement(aStream, mRefMask);
ReadElement(aStream, mOffset);
ReadElement(aStream, mOptions);
}
void
RecordedMaskSurface::OutputSimpleEventInfo(stringstream &aStringStream) const
{
aStringStream << "[" << mDT << "] MaskSurface (" << mRefMask << ") Offset: (" << mOffset.x << "x" << mOffset.y << ") Pattern: ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
}
}

View File

@ -23,7 +23,7 @@ namespace gfx {
const uint16_t kMajorRevision = 2;
// A change in minor revision means additions of new events. New streams will
// not play in older players.
const uint16_t kMinorRevision = 0;
const uint16_t kMinorRevision = 1;
struct ReferencePtr
{
@ -160,7 +160,8 @@ public:
GRADIENTSTOPSDESTRUCTION,
SNAPSHOT,
SCALEDFONTCREATION,
SCALEDFONTDESTRUCTION
SCALEDFONTDESTRUCTION,
MASKSURFACE
};
virtual void PlayEvent(Translator *aTranslator) const {}
@ -865,6 +866,33 @@ private:
RecordedScaledFontDestruction(std::istream &aStream);
};
class RecordedMaskSurface : public RecordedDrawingEvent {
public:
RecordedMaskSurface(DrawTarget *aDT, const Pattern &aPattern, ReferencePtr aRefMask,
const Point &aOffset, const DrawOptions &aOptions)
: RecordedDrawingEvent(MASKSURFACE, aDT), mRefMask(aRefMask), mOffset(aOffset)
, mOptions(aOptions)
{
StorePattern(mPattern, aPattern);
}
virtual void PlayEvent(Translator *aTranslator) const;
virtual void RecordToStream(std::ostream &aStream) const;
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
virtual std::string GetName() const { return "MaskSurface"; }
private:
friend class RecordedEvent;
RecordedMaskSurface(std::istream &aStream);
PatternStorage mPattern;
ReferencePtr mRefMask;
Point mOffset;
DrawOptions mOptions;
};
}
}

View File

@ -88,6 +88,7 @@ static const char *sExtensionNames[] = {
"GL_OES_element_index_uint",
"GL_OES_vertex_array_object",
"GL_ARB_vertex_array_object",
"GL_APPLE_vertex_array_object",
"GL_ARB_draw_buffers",
"GL_EXT_draw_buffers",
nullptr
@ -552,11 +553,12 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
}
}
if (IsExtensionSupported(OES_vertex_array_object)) {
if (IsExtensionSupported(ARB_vertex_array_object) ||
IsExtensionSupported(OES_vertex_array_object)) {
SymLoadStruct vaoSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrays", "BindVertexArrayOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
{ nullptr, { nullptr } },
};
@ -564,7 +566,32 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
MarkExtensionUnsupported(ARB_vertex_array_object);
MarkExtensionUnsupported(OES_vertex_array_object);
MarkExtensionUnsupported(APPLE_vertex_array_object);
mSymbols.fIsVertexArray = nullptr;
mSymbols.fGenVertexArrays = nullptr;
mSymbols.fBindVertexArray = nullptr;
mSymbols.fDeleteVertexArrays = nullptr;
}
}
else if (IsExtensionSupported(APPLE_vertex_array_object)) {
/*
* separate call to LoadSymbols with APPLE_vertex_array_object to work around
* a driver bug : the IsVertexArray symbol (without suffix) can be present but unusable.
*/
SymLoadStruct vaoSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayAPPLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysAPPLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayAPPLE", nullptr } },
{ (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysAPPLE", nullptr } },
{ nullptr, { nullptr } },
};
if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
MarkExtensionUnsupported(APPLE_vertex_array_object);
mSymbols.fIsVertexArray = nullptr;
mSymbols.fGenVertexArrays = nullptr;
mSymbols.fBindVertexArray = nullptr;

View File

@ -1026,6 +1026,7 @@ public:
OES_element_index_uint,
OES_vertex_array_object,
ARB_vertex_array_object,
APPLE_vertex_array_object,
ARB_draw_buffers,
EXT_draw_buffers,
Extensions_Max

View File

@ -3029,6 +3029,9 @@ typedef uint64_t EGLTime;
#define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
#define LOCAL_GL_WIN_swap_hint 1
// ARB_vertex_array_object
#define LOCAL_GL_VERTEX_ARRAY_BINDING 0x85B5
// ARB_sync
#define LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
#define LOCAL_GL_OBJECT_TYPE 0x9112

View File

@ -7,7 +7,7 @@
#ifndef js_GCAPI_h
#define js_GCAPI_h
#include "HeapAPI.h"
#include "js/HeapAPI.h"
namespace JS {

View File

@ -11,8 +11,8 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/TypeTraits.h"
#include "TemplateLib.h"
#include "Utility.h"
#include "js/TemplateLib.h"
#include "js/Utility.h"
/* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
#ifdef _MSC_VER

View File

@ -117,11 +117,6 @@ else
LOCAL_INCLUDES = -Ictypes/libffi/include
endif
LOCAL_INCLUDES += \
-I. \
$(NULL)
ifdef MOZ_NATIVE_FFI
EXTRA_DSO_LDOPTS += $(MOZ_FFI_LIBS)
else
@ -682,8 +677,6 @@ ifneq (,$(ENABLE_YARR_JIT))
CXXFLAGS += -DENABLE_JIT=1
endif
INCLUDES += -I$(srcdir)/assembler -I$(srcdir)/yarr
#
# END kludges for the Nitro assembler
###############################################

View File

@ -17,12 +17,12 @@
#define USE_SYSTEM_MALLOC 1
// leads to FORCE_SYSTEM_MALLOC in wtf/FastMalloc.cpp
#include <jit/ExecutableAllocator.h>
#include <assembler/LinkBuffer.h>
#include <assembler/CodeLocation.h>
#include <assembler/RepatchBuffer.h>
#include "assembler/jit/ExecutableAllocator.h"
#include "assembler/assembler/LinkBuffer.h"
#include "assembler/assembler/CodeLocation.h"
#include "assembler/assembler/RepatchBuffer.h"
#include <assembler/MacroAssembler.h>
#include "assembler/assembler/MacroAssembler.h"
#include <stdio.h>

View File

@ -32,7 +32,7 @@
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
#include "ARMAssembler.h"
#include "assembler/assembler/ARMAssembler.h"
namespace JSC {

View File

@ -38,7 +38,7 @@
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
#include "AssemblerBufferWithConstantPool.h"
#include "assembler/assembler/AssemblerBufferWithConstantPool.h"
#include "assembler/wtf/Assertions.h"
// TODO: We don't print the condition code in our spew lines. Doing this

View File

@ -35,9 +35,8 @@
#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
#include "AssemblerBuffer.h"
#include "assembler/assembler/AssemblerBuffer.h"
#include "assembler/wtf/Assertions.h"
#include "assembler/wtf/Vector.h"
#include <stdint.h>
namespace JSC {

View File

@ -35,7 +35,7 @@
#if ENABLE_ASSEMBLER
#include "AssemblerBuffer.h"
#include "assembler/assembler/AssemblerBuffer.h"
#include "assembler/wtf/SegmentedVector.h"
#include "assembler/wtf/Assertions.h"

View File

@ -34,7 +34,7 @@
#if ENABLE_ASSEMBLER
#include <assembler/MacroAssembler.h>
#include "assembler/assembler/MacroAssembler.h"
namespace JSC {

View File

@ -31,11 +31,10 @@
#if ENABLE(ASSEMBLER) && CPU(MIPS)
#include "AssemblerBuffer.h"
#include "assembler/assembler/AssemblerBuffer.h"
#include "assembler/wtf/Assertions.h"
#include "assembler/wtf/SegmentedVector.h"
#include "methodjit/Logging.h"
#define IPFX " %s"
#define ISPFX " "
#ifdef JS_METHODJIT_SPEW

View File

@ -35,27 +35,27 @@
#if ENABLE_ASSEMBLER
#if WTF_CPU_ARM_THUMB2
#include "MacroAssemblerARMv7.h"
#include "assembler/assembler/MacroAssemblerARMv7.h"
namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; }
#elif WTF_CPU_ARM_TRADITIONAL
#include "MacroAssemblerARM.h"
#include "assembler/assembler/MacroAssemblerARM.h"
namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; }
#elif WTF_CPU_MIPS
#include "MacroAssemblerMIPS.h"
#include "assembler/assembler/MacroAssemblerMIPS.h"
namespace JSC { typedef MacroAssemblerMIPS MacroAssemblerBase; }
#elif WTF_CPU_X86
#include "MacroAssemblerX86.h"
#include "assembler/assembler/MacroAssemblerX86.h"
namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; }
#elif WTF_CPU_X86_64
#include "MacroAssemblerX86_64.h"
#include "assembler/assembler/MacroAssemblerX86_64.h"
namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; }
#elif WTF_CPU_SPARC
#include "MacroAssemblerSparc.h"
#include "assembler/assembler/MacroAssemblerSparc.h"
namespace JSC { typedef MacroAssemblerSparc MacroAssemblerBase; }
#else

View File

@ -32,7 +32,7 @@
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
#include "MacroAssemblerARM.h"
#include "assembler/assembler/MacroAssemblerARM.h"
#if WTF_OS_LINUX || WTF_OS_ANDROID
#include <sys/types.h>

View File

@ -36,8 +36,8 @@
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
#include "ARMAssembler.h"
#include "AbstractMacroAssembler.h"
#include "assembler/assembler/ARMAssembler.h"
#include "assembler/assembler/AbstractMacroAssembler.h"
namespace JSC {

View File

@ -35,8 +35,8 @@
#if ENABLE(ASSEMBLER)
#include "ARMv7Assembler.h"
#include "AbstractMacroAssembler.h"
#include "assembler/assembler/ARMv7Assembler.h"
#include "assembler/assembler/AbstractMacroAssembler.h"
namespace JSC {

View File

@ -29,8 +29,8 @@
#if ENABLE(ASSEMBLER) && CPU(MIPS)
#include "AbstractMacroAssembler.h"
#include "MIPSAssembler.h"
#include "assembler/assembler/AbstractMacroAssembler.h"
#include "assembler/assembler/MIPSAssembler.h"
namespace JSC {

View File

@ -7,12 +7,12 @@
#ifndef assembler_assembler_MacroAssemblerSparc_h
#define assembler_assembler_MacroAssemblerSparc_h
#include <assembler/wtf/Platform.h>
#include "assembler/wtf/Platform.h"
#if ENABLE_ASSEMBLER && WTF_CPU_SPARC
#include "SparcAssembler.h"
#include "AbstractMacroAssembler.h"
#include "assembler/assembler/SparcAssembler.h"
#include "assembler/assembler/AbstractMacroAssembler.h"
namespace JSC {

Some files were not shown because too many files have changed in this diff Show More