This commit is contained in:
Wes Kocher 2014-03-12 21:22:36 -07:00
Родитель 16d23501e7 7312341e00
Коммит e0a2166785
175 изменённых файлов: 6285 добавлений и 2345 удалений

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

@ -409,6 +409,14 @@ XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx,
}
}
}
nsAutoString name;
Name(name);
if (name != mCachedName) {
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
mCachedName = name;
}
}
////////////////////////////////////////////////////////////////////////////////

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

@ -106,6 +106,7 @@ protected:
// XULTreeItemAccessibleBase
mutable AccessibleHashtable mAccessibleCache;
nsString mCachedName;
};

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

@ -92,6 +92,7 @@
case kShowElm:
aNode.style.display = "block";
break;
default:
return INVOKER_ACTION_FAILED;

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

@ -97,6 +97,26 @@
}
}
/**
* Check name changed a11y event for a row.
*/
function rowNameChangeChecker(aMsg, aRow)
{
this.type = EVENT_NAME_CHANGE;
function targetGetter()
{
var acc = getAccessible(gTree);
return acc.getChildAt(aRow + 1);
}
Object.defineProperty(this, "target", { get: targetGetter });
this.getID = function getID()
{
return aMsg + "name changed";
}
}
////////////////////////////////////////////////////////////////////////////
// Invokers
@ -221,9 +241,10 @@
this.eventSeq =
[
new nameChangeChecker("invalidateColumn: ", 1, 0),
new nameChangeChecker("invalidateColumn: ", 1, 1),
new treeInvalidatedChecker("invalidateColumn", 1, 1, null, null)
new nameChangeChecker("invalidateRow: ", 1, 0),
new nameChangeChecker("invalidateRow: ", 1, 1),
new rowNameChangeChecker("invalidateRow: ", 1),
new treeInvalidatedChecker("invalidateRow", 1, 1, null, null)
];
this.getID = function invalidateRow_getID()
@ -277,11 +298,16 @@
href="https://bugzilla.mozilla.org/show_bug.cgi?id=308564"
title="No accessibility events when data in a tree row changes.">
Mozilla Bug 308564
</a>
</a><br/>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=739524"
title="replace TreeViewChanged DOM event on direct call from XUL tree.">
Mozilla Bug 739524
</a><br/>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=743568"
title="Thunderbird message list tree emitting incorrect focus signals after message deleted.">
Mozilla Bug 743568
</a>
<p id="display"></p>
<div id="content" style="display: none">

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

@ -15,4 +15,5 @@ support-files =
[test_output.html]
[test_tables.html]
[test_touch_adapter.html]
skip-if = true # disabled for a number of intermitten failures: Bug 982326
[test_traversal.html]

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

@ -293,7 +293,7 @@
accesskey="&keywordfield.accesskey;"
oncommand="AddKeywordForSearchField();"/>
<menuitem id="context-searchselect"
oncommand="BrowserSearch.loadSearchFromContext(getBrowserSelection());"/>
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms);"/>
<menuitem id="context-shareselect"
label="&shareSelectCmd.label;"
accesskey="&shareSelectCmd.accesskey;"

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

@ -32,7 +32,7 @@ nsContextMenu.prototype = {
this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
Ci.nsIPrefLocalizedString).data;
} catch (e) { }
this.isTextSelected = this.isTextSelection();
this.isContentSelected = this.isContentSelection();
this.onPlainTextLink = false;
@ -268,19 +268,22 @@ nsContextMenu.prototype = {
},
initMiscItems: function CM_initMiscItems() {
var isTextSelected = this.isTextSelected;
// Use "Bookmark This Link" if on a link.
this.showItem("context-bookmarkpage",
!(this.isContentSelected || this.onTextInput || this.onLink ||
this.onImage || this.onVideo || this.onAudio || this.onSocial));
this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink &&
!this.onSocial) || this.onPlainTextLink);
this.showItem("context-searchselect", isTextSelected);
this.showItem("context-keywordfield",
this.onTextInput && this.onKeywordField);
this.showItem("frame", this.inFrame);
let showSearchSelect = (this.isTextSelected || this.onLink) && !this.onImage;
this.showItem("context-searchselect", showSearchSelect);
if (showSearchSelect) {
this.formatSearchContextItem();
}
// srcdoc cannot be opened separately due to concerns about web
// content with about:srcdoc in location bar masquerading as trusted
// chrome/addon content.
@ -292,7 +295,7 @@ nsContextMenu.prototype = {
this.showItem("context-bookmarkframe", !this.inSrcdocFrame);
this.showItem("open-frame-sep", !this.inSrcdocFrame);
this.showItem("frame-sep", this.inFrame && isTextSelected);
this.showItem("frame-sep", this.inFrame && this.isTextSelected);
// Hide menu entries for images, show otherwise
if (this.inFrame) {
@ -540,6 +543,8 @@ nsContextMenu.prototype = {
this.isDesignMode = false;
this.onCTPPlugin = false;
this.canSpellCheck = false;
this.textSelected = getBrowserSelection();
this.isTextSelected = this.textSelected.length != 0;
// Remember the node that was clicked.
this.target = aNode;
@ -1442,39 +1447,6 @@ nsContextMenu.prototype = {
return text;
},
// Get selected text. Only display the first 15 chars.
isTextSelection: function() {
// Get 16 characters, so that we can trim the selection if it's greater
// than 15 chars
var selectedText = getBrowserSelection(16);
if (!selectedText)
return false;
if (selectedText.length > 15)
selectedText = selectedText.substr(0,15) + this.ellipsis;
// Use the current engine if the search bar is visible, the default
// engine otherwise.
var engineName = "";
var ss = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService);
if (isElementVisible(BrowserSearch.searchBar))
engineName = ss.currentEngine.name;
else
engineName = ss.defaultEngine.name;
// format "Search <engine> for <selection>" string to show in menu
var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearch",
[engineName,
selectedText]);
document.getElementById("context-searchselect").label = menuLabel;
document.getElementById("context-searchselect").accessKey =
gNavigatorBundle.getString("contextMenuSearch.accesskey");
return true;
},
// Returns true if anything is selected.
isContentSelection: function() {
return !document.commandDispatcher.focusedWindow.getSelection().isCollapsed;
@ -1688,5 +1660,34 @@ nsContextMenu.prototype = {
if (this.onImage)
return this.mediaURL;
return "";
},
// Formats the 'Search <engine> for "<selection or link text>"' context menu.
formatSearchContextItem: function() {
var menuItem = document.getElementById("context-searchselect");
var selectedText = this.onLink ? this.linkText() : this.textSelected;
// Store searchTerms in context menu item so we know what to search onclick
menuItem.searchTerms = selectedText;
if (selectedText.length > 15)
selectedText = selectedText.substr(0,15) + this.ellipsis;
// Use the current engine if the search bar is visible, the default
// engine otherwise.
var engineName = "";
var ss = Cc["@mozilla.org/browser/search-service;1"].
getService(Ci.nsIBrowserSearchService);
if (isElementVisible(BrowserSearch.searchBar))
engineName = ss.currentEngine.name;
else
engineName = ss.defaultEngine.name;
// format "Search <engine> for <selection>" string to show in menu
var menuLabel = gNavigatorBundle.getFormattedString("contextMenuSearch",
[engineName,
selectedText]);
menuItem.label = menuLabel;
menuItem.accessKey = gNavigatorBundle.getString("contextMenuSearch.accesskey");
}
};

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

@ -9,6 +9,7 @@ support-files =
browser_bug479408_sample.html
browser_bug678392-1.html
browser_bug678392-2.html
browser_bug970746.xhtml
browser_registerProtocolHandler_notification.html
browser_star_hsts.sjs
browser_tab_dragdrop2_frame1.xul
@ -202,6 +203,7 @@ skip-if = os == "mac" # Intermittent failures, bug 925225
[browser_bug882977.js]
[browser_bug902156.js]
[browser_bug906190.js]
[browser_bug970746.js]
[browser_canonizeURL.js]
[browser_contentAreaClick.js]
[browser_contextSearchTabPosition.js]

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

@ -0,0 +1,104 @@
/* Make sure context menu includes option to search hyperlink text on search engine */
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
let doc = gBrowser.contentDocument;
let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
let ellipsis = "\u2026";
// Tests if the "Search <engine> for '<some terms>'" context menu item is shown for the
// given query string of an element. Tests to make sure label includes the proper search terms.
//
// Options:
//
// id: The id of the element to test.
// isSelected: Flag to enable selection (text hilight) the contents of the element
// shouldBeShown: The display state of the menu item
// expectedLabelContents: The menu item label should contain a portion of this string.
// Will only be tested if shouldBeShown is true.
let testElement = function(opts) {
let element = doc.getElementById(opts.id);
document.popupNode = element;
let selection = content.getSelection();
selection.removeAllRanges();
if(opts.isSelected) {
selection.selectAllChildren(element);
}
let contextMenu = new nsContextMenu(contentAreaContextMenu);
let menuItem = document.getElementById("context-searchselect");
is(document.getElementById("context-searchselect").hidden, !opts.shouldBeShown, "search context menu item is shown for '#" + opts.id + "' and selected is '" + opts.isSelected + "'");
if(opts.shouldBeShown) {
ok(menuItem.label.contains(opts.expectedLabelContents), "Menu item text '" + menuItem.label + "' contains the correct search terms '" + opts.expectedLabelContents + "'");
}
}
testElement({
id: "link",
isSelected: true,
shouldBeShown: true,
expectedLabelContents: "I'm a link!",
});
testElement({
id: "link",
isSelected: false,
shouldBeShown: true,
expectedLabelContents: "I'm a link!",
});
testElement({
id: "longLink",
isSelected: true,
shouldBeShown: true,
expectedLabelContents: "I'm a really lo" + ellipsis,
});
testElement({
id: "longLink",
isSelected: false,
shouldBeShown: true,
expectedLabelContents: "I'm a really lo" + ellipsis,
});
testElement({
id: "plainText",
isSelected: true,
shouldBeShown: true,
expectedLabelContents: "Right clicking " + ellipsis,
});
testElement({
id: "plainText",
isSelected: false,
shouldBeShown: false,
});
testElement({
id: "mixedContent",
isSelected: true,
shouldBeShown: true,
expectedLabelContents: "I'm some text, " + ellipsis,
});
testElement({
id: "mixedContent",
isSelected: false,
shouldBeShown: false,
});
// cleanup
document.popupNode = null;
gBrowser.removeCurrentTab();
finish();
}, true);
content.location = "http://mochi.test:8888/browser/browser/base/content/test/general/browser_bug970746.xhtml";
}

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

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<a href="http://mozilla.org" id="link">I'm a link!</a>
<a href="http://mozilla.org" id="longLink">I'm a really long link and I should be truncated.</a>
<span id="plainText">
Right clicking me when I'm selected should show the menu item.
</span>
<span id="mixedContent">
I'm some text, and <a href="http://mozilla.org">I'm a link!</a>
</span>
</body>
</html>

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

@ -118,7 +118,8 @@ function runTest(testNum) {
"---", null,
"context-bookmarklink", true,
"context-savelink", true,
"context-copylink", true
"context-copylink", true,
"context-searchselect", true
].concat(inspectItems));
} else {
checkContextMenu(["context-openlinkintab", true,
@ -126,7 +127,8 @@ function runTest(testNum) {
"---", null,
"context-bookmarklink", true,
"context-savelink", true,
"context-copylink", true
"context-copylink", true,
"context-searchselect", true
].concat(inspectItems));
}
closeContextMenu();
@ -135,7 +137,9 @@ function runTest(testNum) {
case 4:
// Context menu for text mailto-link
checkContextMenu(["context-copyemail", true].concat(inspectItems));
checkContextMenu(["context-copyemail", true,
"context-searchselect", true
].concat(inspectItems));
closeContextMenu();
openContextMenuFor(img); // Invoke context menu for next test.
break;

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

@ -28,7 +28,9 @@ pref("app.update.checkInstallTime.days", 2);
// Search codes belong only in builds with official branding
pref("browser.search.param.yahoo-fr", "");
pref("browser.search.param.yahoo-fr-metro", "");
pref("browser.search.param.yahoo-fr-cjkt", ""); // now unused
pref("browser.search.param.yahoo-fr-ja", "");
pref("browser.search.param.yahoo-f-CN", "");
#ifdef MOZ_METRO
pref("browser.search.param.yahoo-fr-metro", "");
#endif

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

@ -25,7 +25,9 @@ pref("app.update.checkInstallTime.days", 2);
// Search codes belong only in builds with official branding
pref("browser.search.param.yahoo-fr", "");
pref("browser.search.param.yahoo-fr-metro", "");
pref("browser.search.param.yahoo-fr-cjkt", ""); // now unused
pref("browser.search.param.yahoo-fr-ja", "");
pref("browser.search.param.yahoo-f-CN", "");
#ifdef MOZ_METRO
pref("browser.search.param.yahoo-fr-metro", "");
#endif

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

@ -24,8 +24,10 @@ pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/notes")
pref("app.update.checkInstallTime.days", 63);
pref("browser.search.param.ms-pc", "MOZI");
pref("browser.search.param.ms-pc-metro", "MOZW");
pref("browser.search.param.yahoo-fr", "moz35");
pref("browser.search.param.yahoo-fr-metro", "mozilla_metro_search");
pref("browser.search.param.yahoo-fr-cjkt", "moz35"); // now unused
pref("browser.search.param.yahoo-fr-ja", "mozff");
#ifdef MOZ_METRO
pref("browser.search.param.ms-pc-metro", "MOZW");
pref("browser.search.param.yahoo-fr-metro", "mozilla_metro_search");
#endif

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

@ -25,7 +25,9 @@ pref("app.update.checkInstallTime.days", 2);
// Search codes belong only in builds with official branding
pref("browser.search.param.yahoo-fr", "");
pref("browser.search.param.yahoo-fr-metro", "");
pref("browser.search.param.yahoo-fr-cjkt", ""); // now unused
pref("browser.search.param.yahoo-fr-ja", "");
pref("browser.search.param.yahoo-f-CN", "");
#ifdef MOZ_METRO
pref("browser.search.param.yahoo-fr-metro", "");
#endif

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

@ -167,7 +167,7 @@ DistributionCustomizer.prototype = {
, index: index
, feedURI: this._makeURI(items[iid]["feedLink"])
, siteURI: this._makeURI(items[iid]["siteLink"])
});
}).then(null, Cu.reportError);
break;
case "bookmark":

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

@ -251,24 +251,20 @@ var BookmarkPropertiesPanel = {
case "folder":
this._itemType = BOOKMARK_FOLDER;
PlacesUtils.livemarks.getLivemark(
{ id: this._itemId },
(function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
this._itemType = LIVEMARK_CONTAINER;
this._feedURI = aLivemark.feedURI;
this._siteURI = aLivemark.siteURI;
this._fillEditProperties();
PlacesUtils.livemarks.getLivemark({ id: this._itemId })
.then(aLivemark => {
this._itemType = LIVEMARK_CONTAINER;
this._feedURI = aLivemark.feedURI;
this._siteURI = aLivemark.siteURI;
this._fillEditProperties();
let acceptButton = document.documentElement.getButton("accept");
acceptButton.disabled = !this._inputIsValid();
let acceptButton = document.documentElement.getButton("accept");
acceptButton.disabled = !this._inputIsValid();
let newHeight = window.outerHeight +
this._element("descriptionField").boxObject.height;
window.resizeTo(window.outerWidth, newHeight);
}
}).bind(this)
);
let newHeight = window.outerHeight +
this._element("descriptionField").boxObject.height;
window.resizeTo(window.outerWidth, newHeight);
}, () => undefined);
break;
}

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

@ -317,21 +317,17 @@ PlacesViewBase.prototype = {
element.setAttribute("hostContainer", "true");
}
else if (itemId != -1) {
PlacesUtils.livemarks.getLivemark(
{ id: itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
element.setAttribute("livemark", "true");
PlacesUtils.livemarks.getLivemark({ id: itemId })
.then(aLivemark => {
element.setAttribute("livemark", "true");
#ifdef XP_MACOSX
// OS X native menubar doesn't track list-style-images since
// it doesn't have a frame (bug 733415). Thus enforce updating.
element.setAttribute("image", "");
element.removeAttribute("image");
// OS X native menubar doesn't track list-style-images since
// it doesn't have a frame (bug 733415). Thus enforce updating.
element.setAttribute("image", "");
element.removeAttribute("image");
#endif
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
}
}.bind(this)
);
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
}, () => undefined);
}
let popup = document.createElement("menupopup");
@ -509,16 +505,12 @@ PlacesViewBase.prototype = {
#endif
}
PlacesUtils.livemarks.getLivemark(
{ id: aPlacesNode.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
// Controller will use this to build the meta data for the node.
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
this.invalidateContainer(aPlacesNode);
}
}.bind(this)
);
PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId })
.then(aLivemark => {
// Controller will use this to build the meta data for the node.
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
this.invalidateContainer(aPlacesNode);
}, () => undefined);
}
},
@ -647,26 +639,23 @@ PlacesViewBase.prototype = {
return;
}
PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
let shouldInvalidate =
!this.controller.hasCachedLivemarkInfo(aPlacesNode);
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
if (aNewState == Ci.nsINavHistoryContainerResultNode.STATE_OPENED) {
aLivemark.registerForUpdates(aPlacesNode, this);
// Prioritize the current livemark.
aLivemark.reload();
PlacesUtils.livemarks.reloadLivemarks();
if (shouldInvalidate)
this.invalidateContainer(aPlacesNode);
}
else {
aLivemark.unregisterForUpdates(aPlacesNode);
}
PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId })
.then(aLivemark => {
let shouldInvalidate =
!this.controller.hasCachedLivemarkInfo(aPlacesNode);
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
if (aNewState == Ci.nsINavHistoryContainerResultNode.STATE_OPENED) {
aLivemark.registerForUpdates(aPlacesNode, this);
// Prioritize the current livemark.
aLivemark.reload();
PlacesUtils.livemarks.reloadLivemarks();
if (shouldInvalidate)
this.invalidateContainer(aPlacesNode);
}
}.bind(this)
);
else {
aLivemark.unregisterForUpdates(aPlacesNode);
}
}, () => undefined);
}
}
},
@ -678,10 +667,10 @@ PlacesViewBase.prototype = {
if (aPopup._startMarker.nextSibling == aPopup._endMarker)
this._setLivemarkStatusMenuItem(aPopup, Ci.mozILivemark.STATUS_LOADING);
PlacesUtils.livemarks.getLivemark({ id: aPopup._placesNode.itemId },
function (aStatus, aLivemark) {
PlacesUtils.livemarks.getLivemark({ id: aPopup._placesNode.itemId })
.then(aLivemark => {
let placesNode = aPopup._placesNode;
if (!Components.isSuccessCode(aStatus) || !placesNode.containerOpen)
if (!placesNode.containerOpen)
return;
if (aLivemark.status != Ci.mozILivemark.STATUS_LOADING)
@ -698,8 +687,7 @@ PlacesViewBase.prototype = {
else
this._getDOMNodeForPlacesNode(child).removeAttribute("visited");
}
}.bind(this)
);
}, Components.utils.reportError);
},
invalidateContainer: function PVB_invalidateContainer(aPlacesNode) {
@ -1008,15 +996,11 @@ PlacesToolbar.prototype = {
button.setAttribute("tagContainer", "true");
}
else if (PlacesUtils.nodeIsFolder(aChild)) {
PlacesUtils.livemarks.getLivemark(
{ id: aChild.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
button.setAttribute("livemark", "true");
this.controller.cacheLivemarkInfo(aChild, aLivemark);
}
}.bind(this)
);
PlacesUtils.livemarks.getLivemark({ id: aChild.itemId })
.then(aLivemark => {
button.setAttribute("livemark", "true");
this.controller.cacheLivemarkInfo(aChild, aLivemark);
}, () => undefined);
}
let popup = document.createElement("menupopup");
@ -1268,15 +1252,11 @@ PlacesToolbar.prototype = {
if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
elt.setAttribute("livemark", true);
PlacesUtils.livemarks.getLivemark(
{ id: aPlacesNode.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
this.invalidateContainer(aPlacesNode);
}
}.bind(this)
);
PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId })
.then(aLivemark => {
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
this.invalidateContainer(aPlacesNode);
}, Components.utils.reportError);
}
}
else {
@ -1840,15 +1820,11 @@ PlacesPanelMenuView.prototype = {
button.setAttribute("tagContainer", "true");
}
else if (PlacesUtils.nodeIsFolder(aChild)) {
PlacesUtils.livemarks.getLivemark(
{ id: aChild.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
button.setAttribute("livemark", "true");
this.controller.cacheLivemarkInfo(aChild, aLivemark);
}
}.bind(this)
);
PlacesUtils.livemarks.getLivemark({ id: aChild.itemId })
.then(aLivemark => {
button.setAttribute("livemark", "true");
this.controller.cacheLivemarkInfo(aChild, aLivemark);
}, () => undefined);
}
}
else if (PlacesUtils.nodeIsURI(aChild)) {
@ -1912,15 +1888,11 @@ PlacesPanelMenuView.prototype = {
if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
elt.setAttribute("livemark", true);
PlacesUtils.livemarks.getLivemark(
{ id: aPlacesNode.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
this.invalidateContainer(aPlacesNode);
}
}.bind(this)
);
PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId })
.then(aLivemark => {
this.controller.cacheLivemarkInfo(aPlacesNode, aLivemark);
this.invalidateContainer(aPlacesNode);
}, Components.utils.reportError);
}
},

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

@ -694,14 +694,10 @@ PlacesController.prototype = {
var selectedNode = this._view.selectedNode;
if (selectedNode) {
let itemId = selectedNode.itemId;
PlacesUtils.livemarks.getLivemark(
{ id: itemId },
(function(aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
aLivemark.reload(true);
}
}).bind(this)
);
PlacesUtils.livemarks.getLivemark({ id: itemId })
.then(aLivemark => {
aLivemark.reload(true);
}, Components.utils.reportError);
}
},

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

@ -147,17 +147,13 @@ var gEditItemOverlay = {
else {
this._uri = null;
this._isLivemark = false;
PlacesUtils.livemarks.getLivemark(
{id: this._itemId },
(function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
this._isLivemark = true;
this._initTextField("feedLocationField", aLivemark.feedURI.spec, true);
this._initTextField("siteLocationField", aLivemark.siteURI ? aLivemark.siteURI.spec : "", true);
this._showHideRows();
}
}).bind(this)
);
PlacesUtils.livemarks.getLivemark({id: this._itemId })
.then(aLivemark => {
this._isLivemark = true;
this._initTextField("feedLocationField", aLivemark.feedURI.spec, true);
this._initTextField("siteLocationField", aLivemark.siteURI ? aLivemark.siteURI.spec : "", true);
this._showHideRows();
}, () => undefined);
}
// folder picker

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

@ -326,10 +326,13 @@ var PlacesOrganizer = {
},
openFlatContainer: function PO_openFlatContainerFlatContainer(aContainer) {
if (aContainer.itemId != -1)
if (aContainer.itemId != -1) {
PlacesUtils.asContainer(this._places.selectedNode).containerOpen = true;
this._places.selectItems([aContainer.itemId], false);
else if (PlacesUtils.nodeIsQuery(aContainer))
}
else if (PlacesUtils.nodeIsQuery(aContainer)) {
this._places.selectPlaceURI(aContainer.uri);
}
},
/**

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

@ -786,11 +786,11 @@ PlacesTreeView.prototype = {
},
_populateLivemarkContainer: function PTV__populateLivemarkContainer(aNode) {
PlacesUtils.livemarks.getLivemark({ id: aNode.itemId },
function (aStatus, aLivemark) {
PlacesUtils.livemarks.getLivemark({ id: aNode.itemId })
.then(aLivemark => {
let placesNode = aNode;
// Need to check containerOpen since getLivemark is async.
if (!Components.isSuccessCode(aStatus) || !placesNode.containerOpen)
if (!placesNode.containerOpen)
return;
let children = aLivemark.getNodesForContainer(placesNode);
@ -798,7 +798,7 @@ PlacesTreeView.prototype = {
let child = children[i];
this.nodeInserted(placesNode, child, i);
}
}.bind(this));
}, Components.utils.reportError);
},
nodeTitleChanged: function PTV_nodeTitleChanged(aNode, aNewTitle) {
@ -847,19 +847,15 @@ PlacesTreeView.prototype = {
this._invalidateCellValue(aNode, this.COLUMN_TYPE_DESCRIPTION);
}
else if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
PlacesUtils.livemarks.getLivemark(
{ id: aNode.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
this._controller.cacheLivemarkInfo(aNode, aLivemark);
let properties = this._cellProperties.get(aNode);
this._cellProperties.set(aNode, properties += " livemark ");
PlacesUtils.livemarks.getLivemark({ id: aNode.itemId })
.then(aLivemark => {
this._controller.cacheLivemarkInfo(aNode, aLivemark);
let properties = this._cellProperties.get(aNode);
this._cellProperties.set(aNode, properties += " livemark ");
// The livemark attribute is set as a cell property on the title cell.
this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
}
}.bind(this)
);
// The livemark attribute is set as a cell property on the title cell.
this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
}, Components.utils.reportError);
}
},
@ -883,26 +879,23 @@ PlacesTreeView.prototype = {
return;
}
PlacesUtils.livemarks.getLivemark({ id: aNode.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
let shouldInvalidate =
!this._controller.hasCachedLivemarkInfo(aNode);
this._controller.cacheLivemarkInfo(aNode, aLivemark);
if (aNewState == Components.interfaces.nsINavHistoryContainerResultNode.STATE_OPENED) {
aLivemark.registerForUpdates(aNode, this);
// Prioritize the current livemark.
aLivemark.reload();
PlacesUtils.livemarks.reloadLivemarks();
if (shouldInvalidate)
this.invalidateContainer(aNode);
}
else {
aLivemark.unregisterForUpdates(aNode);
}
PlacesUtils.livemarks.getLivemark({ id: aNode.itemId })
.then(aLivemark => {
let shouldInvalidate =
!this._controller.hasCachedLivemarkInfo(aNode);
this._controller.cacheLivemarkInfo(aNode, aLivemark);
if (aNewState == Components.interfaces.nsINavHistoryContainerResultNode.STATE_OPENED) {
aLivemark.registerForUpdates(aNode, this);
// Prioritize the current livemark.
aLivemark.reload();
PlacesUtils.livemarks.reloadLivemarks();
if (shouldInvalidate)
this.invalidateContainer(aNode);
}
}.bind(this)
);
else {
aLivemark.unregisterForUpdates(aNode);
}
}, () => undefined);
}
},
@ -1174,17 +1167,13 @@ PlacesTreeView.prototype = {
properties += " livemark";
}
else {
PlacesUtils.livemarks.getLivemark(
{ id: node.itemId },
function (aStatus, aLivemark) {
if (Components.isSuccessCode(aStatus)) {
this._controller.cacheLivemarkInfo(node, aLivemark);
properties += " livemark";
// The livemark attribute is set as a cell property on the title cell.
this._invalidateCellValue(node, this.COLUMN_TYPE_TITLE);
}
}.bind(this)
);
PlacesUtils.livemarks.getLivemark({ id: node.itemId })
.then(aLivemark => {
this._controller.cacheLivemarkInfo(node, aLivemark);
properties += " livemark";
// The livemark attribute is set as a cell property on the title cell.
this._invalidateCellValue(node, this.COLUMN_TYPE_TITLE);
}, () => undefined);
}
}

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

@ -47,3 +47,4 @@ skip-if = true
[browser_library_left_pane_select_hierarchy.js]
[browser_435851_copy_query.js]
[browser_toolbarbutton_menu_context.js]
[browser_library_openFlatContainer.js]

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

@ -0,0 +1,42 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* Test opening a flat container in the right pane even if its parent in the
* left pane is closed.
*/
add_task(function* () {
let folder = PlacesUtils.bookmarks
.createFolder(PlacesUtils.unfiledBookmarksFolderId,
"Folder",
PlacesUtils.bookmarks.DEFAULT_INDEX);
let bookmark = PlacesUtils.bookmarks
.insertBookmark(folder, NetUtil.newURI("http://example.com/"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"Bookmark");
let library = yield promiseLibrary("AllBookmarks");
registerCleanupFunction(function () {
library.close();
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
});
// Select unfiled later, to ensure it's closed.
library.PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks");
ok(!library.PlacesOrganizer._places.selectedNode.containerOpen,
"Unfiled container is closed");
let folderNode = library.ContentTree.view.view.nodeForTreeIndex(0);
is(folderNode.itemId, folder,
"Found the expected folder in the right pane");
// Select the folder node in the right pane.
library.ContentTree.view.selectNode(folderNode);
synthesizeClickOnSelectedTreeCell(library.ContentTree.view,
{ clickCount: 2 });
is(library.ContentTree.view.view.nodeForTreeIndex(0).itemId, bookmark,
"Found the expected bookmark in the right pane");
});

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

@ -119,27 +119,6 @@ function test() {
}, true);
}
function synthesizeClickOnSelectedTreeCell(aTree) {
let tbo = aTree.treeBoxObject;
is(tbo.view.selection.count, 1,
"The test node should be successfully selected");
// Get selection rowID.
let min = {}, max = {};
tbo.view.selection.getRangeAt(0, min, max);
let rowID = min.value;
tbo.ensureRowIsVisible(rowID);
// Calculate the click coordinates.
let x = {}, y = {}, width = {}, height = {};
tbo.getCoordsForCellItem(rowID, aTree.columns[0], "text",
x, y, width, height);
x = x.value + width.value / 2;
y = y.value + height.value / 2;
// Simulate the click.
EventUtils.synthesizeMouse(aTree.body, x, y, {},
aTree.ownerDocument.defaultView);
}
function changeSidebarDirection(aDirection) {
sidebar.contentDocument.documentElement.style.direction = aDirection;
}

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

@ -1,7 +1,11 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
// We need to cache this before test runs...
let cachedLeftPaneFolderIdGetter;
@ -182,6 +186,22 @@ function addVisits(aPlaceInfo, aWindow, aCallback, aStack) {
);
}
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
function synthesizeClickOnSelectedTreeCell(aTree, aOptions) {
let tbo = aTree.treeBoxObject;
if (tbo.view.selection.count != 1)
throw new Error("The test node should be successfully selected");
// Get selection rowID.
let min = {}, max = {};
tbo.view.selection.getRangeAt(0, min, max);
let rowID = min.value;
tbo.ensureRowIsVisible(rowID);
// Calculate the click coordinates.
let x = {}, y = {}, width = {}, height = {};
tbo.getCoordsForCellItem(rowID, aTree.columns[0], "text",
x, y, width, height);
x = x.value + width.value / 2;
y = y.value + height.value / 2;
// Simulate the click.
EventUtils.synthesizeMouse(aTree.body, x, y, aOptions || {},
aTree.ownerDocument.defaultView);
}

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

@ -11,8 +11,8 @@ Services.prefs.setBoolPref("devtools.debugger.log", true);
let gProcess;
function test() {
// Windows XP test slaves are terribly slow at this test.
requestLongerTimeout(4);
// Windows XP and 8.1 test slaves are terribly slow at this test.
requestLongerTimeout(5);
initChromeDebugger(aOnClose).then(aProcess => {
gProcess = aProcess;

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

@ -217,10 +217,14 @@ toolbarbutton[sdk-button="true"][cui-areatype="menu-panel"] > .toolbarbutton-ico
-moz-box-orient: vertical;
width: calc(@menuPanelButtonWidth@ - 2px);
height: calc(49px + 2.2em);
margin-top: 3px; /* Hack needed to get type=menu-button to properly align vertically. */
border: 0;
}
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-text,
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-multiline-text {
margin-top: 2px; /* Hack needed to get the label of type=menu-button aligned with other buttons */
}
.panel-customization-placeholder-child {
margin: 6px 0 0;
padding: 2px 6px;

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

@ -57,7 +57,7 @@ robocop_FILES := \
$(NULL)
robocop-deps := $(notdir $(robocop_FILES))
MOCHITEST_ROBOCOP_FILES := \
ROBOCOP_FILES := \
$(wildcard $(TESTPATH)/*.html) \
$(wildcard $(TESTPATH)/*.jpg) \
$(wildcard $(TESTPATH)/*.sjs) \
@ -67,6 +67,9 @@ MOCHITEST_ROBOCOP_FILES := \
$(wildcard $(TESTPATH)/*.swf) \
$(NULL)
ROBOCOP_DEST = $(DEPTH)/_tests/testing/mochitest/tests/robocop/
INSTALL_TARGETS += ROBOCOP
GARBAGE += \
AndroidManifest.xml \
$(robocop-deps) \

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

@ -73,8 +73,14 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
_DEPRECATED_VARIABLES := \
ANDROID_RESFILES \
MOCHITEST_FILES_PARTS \
MOCHITEST_A11Y_FILES \
MOCHITEST_BROWSER_FILES \
MOCHITEST_BROWSER_FILES_PARTS \
MOCHITEST_CHROME_FILES \
MOCHITEST_FILES \
MOCHITEST_FILES_PARTS \
MOCHITEST_METRO_FILES \
MOCHITEST_ROBOCOP_FILES \
SHORT_LIBNAME \
$(NULL)

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

@ -1,52 +0,0 @@
# -*- makefile -*-
# vim:set ts=8 sw=8 sts=8 noet:
#
# 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 INCLUDED_TESTS_MOCHITEST_MK #{
# $1- test directory name
# $2- optional: if passed dot used to flatten directory hierarchy copy
# else- relativesrcdir
mochitestdir = \
$(strip \
$(if $(2),$(DEPTH)/_tests/testing/mochitest/$1/. \
,$(DEPTH)/_tests/testing/mochitest/$1/$(relativesrcdir) \
))
ifdef MOCHITEST_FILES
MOCHITEST_DEST := $(call mochitestdir,tests)
INSTALL_TARGETS += MOCHITEST
endif
ifdef MOCHITEST_CHROME_FILES
MOCHITEST_CHROME_DEST := $(call mochitestdir,chrome)
INSTALL_TARGETS += MOCHITEST_CHROME
endif
ifdef MOCHITEST_BROWSER_FILES
MOCHITEST_BROWSER_DEST := $(call mochitestdir,browser)
INSTALL_TARGETS += MOCHITEST_BROWSER
endif
ifdef MOCHITEST_A11Y_FILES
MOCHITEST_A11Y_DEST := $(call mochitestdir,a11y)
INSTALL_TARGETS += MOCHITEST_A11Y
endif
ifdef MOCHITEST_METRO_FILES
MOCHITEST_METRO_DEST := $(call mochitestdir,metro)
INSTALL_TARGETS += MOCHITEST_METRO
endif
ifdef MOCHITEST_ROBOCOP_FILES
MOCHITEST_ROBOCOP_DEST := $(call mochitestdir,tests/robocop,flat_hierarchy)
INSTALL_TARGETS += MOCHITEST_ROBOCOP
endif
INCLUDED_TESTS_MOCHITEST_MK := 1
endif #} INCLUDED_TESTS_MOCHITEST_MK

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

@ -99,10 +99,6 @@ ifdef ENABLE_TESTS
# locally against non-current test code.
DIRS += $(TEST_DIRS)
ifndef INCLUDED_TESTS_MOCHITEST_MK #{
include $(topsrcdir)/config/makefiles/mochitest.mk
endif #}
ifdef CPP_UNIT_TESTS
ifdef COMPILE_ENVIRONMENT
@ -1635,12 +1631,6 @@ FREEZE_VARIABLES = \
TIERS \
EXTRA_COMPONENTS \
EXTRA_PP_COMPONENTS \
MOCHITEST_FILES \
MOCHITEST_CHROME_FILES \
MOCHITEST_BROWSER_FILES \
MOCHITEST_A11Y_FILES \
MOCHITEST_METRO_FILES \
MOCHITEST_ROBOCOP_FILES \
$(NULL)
$(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))

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

@ -1964,6 +1964,7 @@ GK_ATOM(genConInitializerProperty, "QuoteNodeProperty")
GK_ATOM(labelMouseDownPtProperty, "LabelMouseDownPtProperty")
GK_ATOM(baseURIProperty, "baseURIProperty")
GK_ATOM(lockedStyleStates, "lockedStyleStates")
GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
// Languages for lang-specific transforms
GK_ATOM(Japanese, "ja")

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

@ -241,6 +241,16 @@ public:
MOZ_ASSERT(aTarget);
}
nsSimplePluginEvent(nsIContent* aTarget,
nsIDocument* aDocument,
const nsAString& aEvent)
: mTarget(aTarget)
, mDocument(aDocument)
, mEvent(aEvent)
{
MOZ_ASSERT(aTarget && aDocument);
}
~nsSimplePluginEvent() {}
NS_IMETHOD Run();
@ -703,7 +713,7 @@ nsObjectLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
nsIDocument* ownerDoc = thisContent->OwnerDoc();
ownerDoc->RemovePlugin(this);
if (mType == eType_Plugin && mInstanceOwner) {
if (mType == eType_Plugin && (mInstanceOwner || mInstantiating)) {
// we'll let the plugin continue to run at least until we get back to
// the event loop. If we get back to the event loop and the node
// has still not been added back to the document then we tear down the
@ -744,7 +754,7 @@ nsObjectLoadingContent::~nsObjectLoadingContent()
NS_NOTREACHED("Should not be tearing down frame loaders at this point");
mFrameLoader->Destroy();
}
if (mInstanceOwner) {
if (mInstanceOwner || mInstantiating) {
// This is especially bad as delayed stop will try to hold on to this
// object...
NS_NOTREACHED("Should not be tearing down a plugin at this point!");
@ -772,7 +782,7 @@ nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent *>(this));
nsIDocument* doc = thisContent->GetCurrentDoc();
nsCOMPtr<nsIDocument> doc = thisContent->GetCurrentDoc();
if (!doc || !InActiveDocument(thisContent)) {
NS_ERROR("Shouldn't be calling "
"InstantiatePluginInstance without an active document");
@ -894,8 +904,10 @@ nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
}
}
nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(thisContent,
NS_LITERAL_STRING("PluginInstantiated"));
nsCOMPtr<nsIRunnable> ev = \
new nsSimplePluginEvent(thisContent,
doc,
NS_LITERAL_STRING("PluginInstantiated"));
NS_DispatchToCurrentThread(ev);
return NS_OK;
@ -909,7 +921,7 @@ nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged()
// If we have a plugin we want to queue an event to stop it unless we are
// moved into an active document before returning to the event loop.
if (mInstanceOwner)
if (mInstanceOwner || mInstantiating)
QueueCheckPluginStopEvent();
}
@ -1073,8 +1085,10 @@ nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
// Lost our frame. If we aren't going to be getting a new frame, e.g. we've
// become display:none, we'll want to stop the plugin. Queue a
// CheckPluginStopEvent
if (mInstanceOwner) {
mInstanceOwner->SetFrame(nullptr);
if (mInstanceOwner || mInstantiating) {
if (mInstanceOwner) {
mInstanceOwner->SetFrame(nullptr);
}
QueueCheckPluginStopEvent();
}
return NS_OK;
@ -2826,6 +2840,10 @@ nsObjectLoadingContent::StopPluginInstance()
mPendingInstantiateEvent = nullptr;
mPendingCheckPluginStopEvent = nullptr;
// If we're currently instantiating, clearing this will cause
// InstantiatePluginInstance's re-entrance check to destroy the created plugin
mInstantiating = false;
if (!mInstanceOwner) {
return NS_OK;
}

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

@ -1006,6 +1006,7 @@ nsScriptLoader::FillCompileOptionsForRequest(nsScriptLoadRequest *aRequest,
// aRequest ended up getting script data from, as the script filename.
nsContentUtils::GetWrapperSafeScriptFilename(mDocument, aRequest->mURI, aRequest->mURL);
aOptions->setIntroductionType("scriptElement");
aOptions->setFileAndLine(aRequest->mURL.get(), aRequest->mLineNo);
aOptions->setVersion(JSVersion(aRequest->mJSVersion));
aOptions->setCompileAndGo(JS_IsGlobalObject(aScopeChain));

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

@ -1,2 +1,4 @@
[test_messagemanager_assertpermission.html]
skip-if = buildapp == 'b2g' #b2g(specialpowers.wrap issue, NS_ERROR_XPC_GS_RETURNED_FAILURE) b2g-debug(specialpowers.wrap issue, NS_ERROR_XPC_GS_RETURNED_FAILURE) b2g-desktop(specialpowers.wrap issue, NS_ERROR_XPC_GS_RETURNED_FAILURE)
[test_child_process_shutdown_message.html]
skip-if = buildapp == 'b2g' #b2g(specialpowers.wrap issue, NS_ERROR_XPC_GS_RETURNED_FAILURE) b2g-debug(specialpowers.wrap issue, NS_ERROR_XPC_GS_RETURNED_FAILURE) b2g-desktop(specialpowers.wrap issue, NS_ERROR_XPC_GS_RETURNED_FAILURE)

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

@ -544,7 +544,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #needs plugin support # b2g(
[test_classList.html]
# This test fails on the Mac for some reason
[test_copyimage.html]
skip-if = toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows'
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows' #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_copypaste.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
[test_copypaste.xhtml]

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

@ -475,15 +475,15 @@ skip-if = buildapp == 'b2g'
skip-if = appname == "seamonkey" # See bug 598252
[test_buffered.html]
skip-if = toolkit == 'android' || os == "win" # See bug 832768 and 864682
skip-if = toolkit == 'android' || os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682, b2g(assertion failures)
[test_bug465498.html]
skip-if = os == "win" # See bug 832768 and 864682
skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 832768 and 864682
[test_bug493187.html]
skip-if = os == "win" || (buildapp=='b2g'&&debug) # See bug 707777, #b2g-emulator-debug - process crash
skip-if = os == "win" || (buildapp=='b2g'&&debug) || (toolkit == 'gonk' && !debug) # See bug 707777, #b2g-emulator-debug - process crash
[test_media_selection.html]
skip-if = os == "win" # See bug 897843
skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 897843, b2g(timed out)
[test_seek.html]
skip-if = toolkit == 'android' || os == "win" # See bug 832678, 795271, and 857424 # android(bug 845162) androidx86(bug 845162)
skip-if = toolkit == 'android' || os == "win" || (toolkit == 'gonk' && !debug) # See bug 832678, 795271, and 857424 # android(bug 845162) androidx86(bug 845162)
# The tests below contain backend-specific tests. Write backend independent
# tests rather than adding to this list.

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

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) #b2g-debug(bug 916135) b2g-desktop(bug 916135)
support-files =
audio-expected.wav
audio-mono-expected-2.wav

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

@ -2643,7 +2643,8 @@ nsXULPrototypeScript::Compile(const char16_t* aText,
// Ok, compile it to create a prototype script object!
NS_ENSURE_TRUE(JSVersion(mLangVersion) != JSVERSION_UNKNOWN, NS_OK);
JS::CompileOptions options(cx);
options.setFileAndLine(urlspec.get(), aLineNo)
options.setIntroductionType("scriptElement")
.setFileAndLine(urlspec.get(), aLineNo)
.setVersion(JSVersion(mLangVersion));
// If the script was inline, tell the JS parser to save source for
// Function.prototype.toSource(). If it's out of line, we retrieve the

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

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = buildapp == 'b2g' #tests that use xul
[test_bug486990.xul]
skip-if = toolkit == 'android' #TIMED_OUT

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

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = toolkit=='gonk' #b2g(bug 972927, nearly perma-fail) b2g-debug(bug 972927, nearly perma-fail)
support-files =
file_app.sjs
file_app.template.html

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

@ -3,7 +3,7 @@
# so we don't run that test on platforms which don't support OOP tests.
# OOP tests don't work on native-fennec (bug 774939).
# Bug 960345 - Disabled on OSX debug for frequent crashes.
skip-if = os == "android" || (toolkit == "cocoa" && debug)
skip-if = os == "android" || (toolkit == "cocoa" && debug) || (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
support-files =
browserElement_OpenMixedProcess.js
file_browserElement_OpenMixedProcess.html
@ -11,15 +11,19 @@ support-files =
[test_browserElement_inproc_ErrorSecurity.html]
skip-if = toolkit=='gonk'
[test_browserElement_inproc_OpenMixedProcess.html]
skip-if = toolkit=='gonk'
skip-if = toolkit=='gonk' || (toolkit == 'gonk' && !debug)
[test_browserElement_oop_Alert.html]
[test_browserElement_oop_AlertInFrame.html]
[test_browserElement_oop_AppFramePermission.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_AppWindowNamespace.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_Auth.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_BackForward.html]
[test_browserElement_oop_BadScreenshot.html]
[test_browserElement_oop_BrowserWindowNamespace.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_BrowserWindowResize.html]
[test_browserElement_oop_Close.html]
[test_browserElement_oop_CookiesNotThirdParty.html]
@ -27,20 +31,28 @@ skip-if = toolkit=='gonk'
[test_browserElement_oop_DataURI.html]
[test_browserElement_oop_DocumentFirstPaint.html]
[test_browserElement_oop_ErrorSecurity.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_FirstPaint.html]
[test_browserElement_oop_ForwardName.html]
[test_browserElement_oop_FrameWrongURI.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_GetScreenshot.html]
[test_browserElement_oop_GetScreenshotDppx.html]
[test_browserElement_oop_Iconchange.html]
[test_browserElement_oop_LoadEvents.html]
[test_browserElement_oop_Metachange.html]
[test_browserElement_oop_OpenMixedProcess.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_OpenNamed.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_OpenWindow.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_OpenWindowDifferentOrigin.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_OpenWindowInFrame.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_OpenWindowRejected.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_Opensearch.html]
[test_browserElement_oop_PromptCheck.html]
[test_browserElement_oop_PromptConfirm.html]
@ -50,7 +62,7 @@ skip-if = toolkit=='gonk'
[test_browserElement_oop_RemoveBrowserElement.html]
[test_browserElement_oop_ScrollEvent.html]
[test_browserElement_oop_SecurityChange.html]
skip-if = toolkit == 'android' #TIMED_OUT, bug 766586
skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) #TIMED_OUT, bug 766586
[test_browserElement_oop_SendEvent.html]
[test_browserElement_oop_SetInputMethodActive.html]
[test_browserElement_oop_SetVisible.html]
@ -58,6 +70,7 @@ skip-if = toolkit == 'android' #TIMED_OUT, bug 766586
[test_browserElement_oop_SetVisibleFrames2.html]
[test_browserElement_oop_Stop.html]
[test_browserElement_oop_TargetBlank.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_TargetTop.html]
[test_browserElement_oop_Titlechange.html]
[test_browserElement_oop_TopBarrier.html]

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

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
support-files =
../../../browser/base/content/test/general/audio.ogg
../../../content/media/test/short-video.ogv

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

@ -1,6 +1,6 @@
[DEFAULT]
# Good luck running these tests on anything but desktop Linux.
skip-if = toolkit != "gtk2"
skip-if = toolkit != "gtk2" || (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
# Note: ../browserElementTestHelpers.js makes all tests in this directory OOP,
# because testing the process-priority manager without OOP frames does not make

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

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = toolkit=='gonk' #b2g(bug 974270, frequent failures) b2g-debug(bug 974270, frequent failures)
support-files =
file_app_install.html
file_readonly.html

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

@ -10,17 +10,19 @@ support-files =
[conformancetest/test_event.html]
[conformancetest/test_runtest.html]
skip-if = toolkit == 'android'
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #b2g(takes too long) b2g-debug(takes too long) b2g-desktop(takes too long)
[selecttest/test_Document-open.html]
[selecttest/test_addRange.html]
skip-if = toolkit == 'android' #bug 775227
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(bug 775227) b2g(oom?, bug 775227) b2g-debug(oom?, bug 775227) b2g-desktop(oom?, bug 775227)
[selecttest/test_collapse.html]
[selecttest/test_collapseToStartEnd.html]
[selecttest/test_deleteFromDocument.html]
[selecttest/test_extend.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure; time out)
[selecttest/test_getRangeAt.html]
[selecttest/test_getSelection.html]
[selecttest/test_interfaces.html]
[selecttest/test_isCollapsed.html]
[selecttest/test_removeAllRanges.html]
[selecttest/test_selectAllChildren.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)

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

@ -57,211 +57,414 @@ support-files =
webgl/common.js
[dom/collections/test_HTMLCollection-empty-name.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/errors/test_DOMException-constants.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/errors/test_exceptions.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_Event-constants.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_Event-constructors.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_Event-defaultPrevented.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_Event-initEvent.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_Event-propagation.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_Event-type.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_EventTarget-addEventListener.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_EventTarget-dispatchEvent.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_EventTarget-removeEventListener.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/events/test_ProgressEvent.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/lists/test_DOMTokenList-stringifier.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_CharacterData-appendData.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_CharacterData-deleteData.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_CharacterData-insertData.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_CharacterData-remove.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_CharacterData-replaceData.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Comment-constructor.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_DOMImplementation-createDocument.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_DOMImplementation-createDocumentType.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_DOMImplementation-createHTMLDocument.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_DOMImplementation-hasFeature.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-adoptNode.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createComment.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createElement-namespace.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createElement.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createElementNS.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createEvent.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createProcessingInstruction-literal-1.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createProcessingInstruction-literal-2.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createProcessingInstruction.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createProcessingInstruction.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-createTreeWalker.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-getElementById.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-getElementsByTagName.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-getElementsByTagNameNS.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Document-importNode.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_DocumentType-remove.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Element-children.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Element-getElementsByClassName.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Element-remove.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Element-removeAttributeNS.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Element-tagName.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-appendChild.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-cloneNode.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-compareDocumentPosition.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-constants.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-contains.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-contains.xml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-insertBefore.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-isEqualNode.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-lookupPrefix.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-nodeName.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-nodeName.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-normalize.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-parentElement.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-parentNode.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-properties.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-removeChild.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_Node-replaceChild.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_attributes.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_case.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-01.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-02.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-03.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-04.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-05.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-06.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-07.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-08.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-09.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-10.xml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-11.xml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-12.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-13.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-14.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-15.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-16.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-17.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/nodes/test_getElementsByClassName-18.htm]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-attributes.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-cloneContents.html]
skip-if = buildapp == 'b2g'
[dom/ranges/test_Range-cloneRange.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-collapse.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-commonAncestorContainer-2.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-commonAncestorContainer.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-compareBoundaryPoints.html]
skip-if = buildapp == 'b2g' #b2g(times out, bug 862196) b2g-debug(times out, bug 862196) b2g-desktop(times out, bug 862196)
[dom/ranges/test_Range-comparePoint-2.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-comparePoint.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-deleteContents.html]
skip-if = buildapp == 'b2g'
[dom/ranges/test_Range-detach.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-extractContents.html]
skip-if = buildapp == 'b2g'
[dom/ranges/test_Range-insertNode.html]
skip-if = buildapp == 'b2g' #b2g(oom?, bug 775227) b2g-debug(oom?, bug 775227) b2g-desktop(oom?, bug 775227)
[dom/ranges/test_Range-intersectsNode-binding.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-intersectsNode.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-isPointInRange.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-mutations.html]
skip-if = buildapp == 'b2g' #Test timed out.
[dom/ranges/test_Range-selectNode.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/ranges/test_Range-set.html]
skip-if = buildapp == 'b2g'
[dom/ranges/test_Range-surroundContents.html]
skip-if = buildapp == 'b2g'
[dom/test_historical.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/test_interface-objects.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/test_interfaces.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[dom/traversal/test_NodeFilter-constants.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[domxpath/test_evaluator-constructor.html]
[html/browsers/browsing-the-web/read-media/test_pageload-image.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/browsers/browsing-the-web/read-media/test_pageload-video.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/browsers/the-window-object/named-access-on-the-window-object/test_window-null-names.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/browsers/the-window-object/test_window-indexed-properties-strict.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/browsers/the-window-object/test_window-indexed-properties.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/browsers/the-window-object/test_window-named-properties.html]
skip-if = true # bug 859075
skip-if = true || (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure) bug 859075
[html/browsers/the-window-object/test_window-properties.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/browsers/the-window-object/test_window-prototype-chain.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-case.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-case.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-id.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-id.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-namespace.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-namespace.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-newelements.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-newelements.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-null-undef.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-null-undef.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-param.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-param.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-same.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_Document.getElementsByClassName-null-undef.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_Element.getElementsByClassName-null-undef.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.body-getter.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.body-setter-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.embeds-document.plugins-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.getElementsByClassName-same.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.head-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.head-02.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.images.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.title-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.title-02.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.title-03.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.title-04.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.title-05.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.title-06.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_document.title-07.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_nameditem-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_nameditem-02.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_nameditem-03.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_nameditem-04.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_nameditem-05.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/documents/dta/test_nameditem-06.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_classlist-nonstring.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_dataset-delete.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_dataset-enumeration.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_dataset-get.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_dataset-prototype.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_dataset-set.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_dataset.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_document-dir.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_id-attribute.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/dom/elements/global-attributes/test_id-name.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/obsolete/implreq/oeaaa/test_document-color-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/obsolete/implreq/oeaaa/test_document-color-02.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/obsolete/implreq/oeaaa/test_document-color-03.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/obsolete/implreq/oeaaa/test_document-color-04.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/obsolete/implreq/oeaaa/test_heading-obsolete-attributes-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/obsolete/implreq/oeaaa/test_script-IDL-event-htmlfor.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/document-metadata/the-title-element/test_title.text-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/document-metadata/the-title-element/test_title.text-02.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/document-metadata/the-title-element/test_title.text-03.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/document-metadata/the-title-element/test_title.text-04.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-form-element/test_form-elements-interfaces-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-form-element/test_form-elements-matches.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-form-element/test_form-elements-nameditem-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-form-element/test_form-elements-nameditem-02.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-form-element/test_form-nameditem.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-option-element/test_option-text-backslash.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-option-element/test_option-text-recurse.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-option-element/test_option-text-spaces.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-select-element/test_select-named-getter.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/forms/the-select-element/test_select-remove.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-for-event.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-for-event.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-for-onload.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-language-type.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-languages-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-languages-02.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-noembed-noframes-iframe.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-onload-string.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-text.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/scripting-1/the-script-element/test_script-text.xhtml]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/tabular-data/the-table-element/test_createTBody.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/tabular-data/the-table-element/test_insertRow-method-01.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/tabular-data/the-table-element/test_insertRow-method-02.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/tabular-data/the-table-element/test_tBodies.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/tabular-data/the-table-element/test_table-insertRow.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/tabular-data/the-table-element/test_table-rows.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/semantics/text-level-semantics/the-time-element/test_001.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/atob/test_base64.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/scripting/events/test_body-onload.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/scripting/events/test_event-handler-javascript.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/scripting/events/test_event-handler-spec-example.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/scripting/processing-model-2/test_window-onerror-parse-error.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/scripting/processing-model-2/test_window-onerror-runtime-error-throw.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/scripting/processing-model-2/test_window-onerror-runtime-error.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[html/webappapis/timers/test_evil-spec-example.html]
skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
[js/builtins/test_Array.DefineOwnProperty.html]
[js/builtins/test_Array.prototype.join-order.html]
[js/builtins/test_Math.max.html]
@ -271,14 +474,14 @@ skip-if = true # bug 859075
[microdata/microdata-dom-api/test_001.html]
[typedarrays/test_constructors.html]
[webgl/test_bufferSubData.html]
skip-if = toolkit == 'android' #WebGL
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_compressedTexImage2D.html]
skip-if = toolkit == 'android' #WebGL
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_compressedTexSubImage2D.html]
skip-if = toolkit == 'android' #WebGL
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_texImage2D.html]
skip-if = toolkit == 'android' #WebGL
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_texSubImage2D.html]
skip-if = toolkit == 'android' #WebGL
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)
[webgl/test_uniformMatrixNfv.html]
skip-if = toolkit == 'android' #WebGL
skip-if = (toolkit == 'android') || (buildapp == 'b2g') #android(WebGL)

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

@ -47,7 +47,7 @@ using class mozilla::WidgetTouchEvent from "ipc/nsGUIEventIPC.h";
using struct mozilla::dom::RemoteDOMEvent from "mozilla/dom/TabMessageUtils.h";
using mozilla::dom::ScreenOrientation from "mozilla/dom/ScreenOrientation.h";
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
using mozilla::CSSIntPoint from "Units.h";
using mozilla::CSSPoint from "Units.h";
using mozilla::CSSToScreenScale from "Units.h";
namespace mozilla {
@ -366,21 +366,21 @@ child:
* the scroll offset. This message is expected to round-trip back to
* ZoomToRect() with a rect indicating where we should zoom to.
*/
HandleDoubleTap(CSSIntPoint point, ScrollableLayerGuid aGuid);
HandleDoubleTap(CSSPoint point, ScrollableLayerGuid aGuid);
/**
* Requests handling of a single tap. |point| is in CSS pixels, relative to
* the scroll offset. This message is expected to send a "mousedown" and
* "mouseup" series of events at this point.
*/
HandleSingleTap(CSSIntPoint point, ScrollableLayerGuid aGuid);
HandleSingleTap(CSSPoint point, ScrollableLayerGuid aGuid);
/**
* Requests handling of a long tap. |point| is in CSS pixels, relative to
* the scroll offset. This message is expected to send a "contextmenu"
* events at this point.
*/
HandleLongTap(CSSIntPoint point, ScrollableLayerGuid aGuid);
HandleLongTap(CSSPoint point, ScrollableLayerGuid aGuid);
/**
* Requests handling of releasing a long tap. |aPoint| is in CSS pixels,
@ -389,7 +389,7 @@ child:
* this message is expected to generate a "mousedown" and "mouseup"
* series of events
*/
HandleLongTapUp(CSSIntPoint point, ScrollableLayerGuid aGuid);
HandleLongTapUp(CSSPoint point, ScrollableLayerGuid aGuid);
/**
* Notifies the child that the parent has begun or finished transforming

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

@ -661,7 +661,7 @@ TabChild::HandlePossibleViewportChange()
// Force a repaint with these metrics. This, among other things, sets the
// displayport, so we start with async painting.
ProcessUpdateFrame(metrics);
mLastRootMetrics = ProcessUpdateFrame(metrics);
if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) {
// If the CSS viewport is narrower than the screen (i.e. width <= device-width)
@ -832,7 +832,7 @@ TabChild::SetChromeFlags(uint32_t aChromeFlags)
NS_IMETHODIMP
TabChild::DestroyBrowserWindow()
{
NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild");
NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild");
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -1477,7 +1477,9 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
if (aFrameMetrics.mIsRoot) {
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
if (APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) {
return ProcessUpdateFrame(aFrameMetrics);
mLastRootMetrics = ProcessUpdateFrame(aFrameMetrics);
APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, mLastRootMetrics);
return true;
}
} else {
// aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
@ -1487,6 +1489,7 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
if (content) {
FrameMetrics newSubFrameMetrics(aFrameMetrics);
APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
APZCCallbackHelper::UpdateCallbackTransform(aFrameMetrics, newSubFrameMetrics);
return true;
}
}
@ -1494,7 +1497,8 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
// We've recieved a message that is out of date and we want to ignore.
// However we can't reply without painting so we reply by painting the
// exact same thing as we did before.
return ProcessUpdateFrame(mLastRootMetrics);
mLastRootMetrics = ProcessUpdateFrame(mLastRootMetrics);
return true;
}
bool
@ -1505,11 +1509,11 @@ TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
return true;
}
bool
FrameMetrics
TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
{
if (!mGlobal || !mTabChildGlobal) {
return true;
return aFrameMetrics;
}
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
@ -1549,22 +1553,20 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
data.AppendLiteral(" }");
DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
mLastRootMetrics = newMetrics;
return true;
return newMetrics;
}
bool
TabChild::RecvHandleDoubleTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (!mGlobal || !mTabChildGlobal) {
return true;
}
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
nsCString data;
data += nsPrintfCString("{ \"x\" : %d", aPoint.x);
data += nsPrintfCString(", \"y\" : %d", aPoint.y);
data += nsPrintfCString("{ \"x\" : %f", point.x);
data += nsPrintfCString(", \"y\" : %f", point.y);
data += nsPrintfCString(" }");
DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
@ -1573,13 +1575,13 @@ TabChild::RecvHandleDoubleTap(const CSSIntPoint& aPoint, const ScrollableLayerGu
}
bool
TabChild::RecvHandleSingleTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (!mGlobal || !mTabChildGlobal) {
return true;
}
LayoutDevicePoint currentPoint = CSSPoint(aPoint) * mWidget->GetDefaultScale();;
LayoutDevicePoint currentPoint = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();;
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
@ -1598,14 +1600,16 @@ TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
}
bool
TabChild::RecvHandleLongTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (!mGlobal || !mTabChildGlobal) {
return true;
}
mContextMenuHandled =
DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"), aPoint, 2, 1, 0, false,
DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid),
2, 1, 0, false,
nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
SendContentReceivedTouch(aGuid, mContextMenuHandled);
@ -1614,7 +1618,7 @@ TabChild::RecvHandleLongTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid
}
bool
TabChild::RecvHandleLongTapUp(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
TabChild::RecvHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (mContextMenuHandled) {
mContextMenuHandled = false;
@ -1857,6 +1861,10 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
const ScrollableLayerGuid& aGuid)
{
WidgetTouchEvent localEvent(aEvent);
for (size_t i = 0; i < localEvent.touches.Length(); i++) {
aEvent.touches[i]->mRefPoint = APZCCallbackHelper::ApplyCallbackTransform(aEvent.touches[i]->mRefPoint, aGuid, mWidget->GetDefaultScale());
}
nsEventStatus status = DispatchWidgetEvent(localEvent);
if (!IsAsyncPanZoomEnabled()) {

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

@ -218,13 +218,13 @@ public:
virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration) MOZ_OVERRIDE;
virtual bool RecvHandleDoubleTap(const CSSIntPoint& aPoint,
virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
virtual bool RecvHandleSingleTap(const CSSIntPoint& aPoint,
virtual bool RecvHandleSingleTap(const CSSPoint& aPoint,
const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
virtual bool RecvHandleLongTap(const CSSIntPoint& aPoint,
virtual bool RecvHandleLongTap(const CSSPoint& aPoint,
const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
virtual bool RecvHandleLongTapUp(const CSSIntPoint& aPoint,
virtual bool RecvHandleLongTapUp(const CSSPoint& aPoint,
const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
virtual bool RecvNotifyTransformBegin(const ViewID& aViewId) MOZ_OVERRIDE;
virtual bool RecvNotifyTransformEnd(const ViewID& aViewId) MOZ_OVERRIDE;
@ -417,7 +417,7 @@ private:
bool InitRenderingState();
void DestroyWindow();
void SetProcessNameToAppName();
bool ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
FrameMetrics ProcessUpdateFrame(const FrameMetrics& aFrameMetrics);
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
void DoFakeShow();

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

@ -516,7 +516,7 @@ TabParent::AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScr
}
}
void TabParent::HandleDoubleTap(const CSSIntPoint& aPoint,
void TabParent::HandleDoubleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid &aGuid)
{
@ -525,7 +525,7 @@ void TabParent::HandleDoubleTap(const CSSIntPoint& aPoint,
}
}
void TabParent::HandleSingleTap(const CSSIntPoint& aPoint,
void TabParent::HandleSingleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid &aGuid)
{
@ -535,7 +535,7 @@ void TabParent::HandleSingleTap(const CSSIntPoint& aPoint,
}
}
void TabParent::HandleLongTap(const CSSIntPoint& aPoint,
void TabParent::HandleLongTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid &aGuid)
{
@ -544,7 +544,7 @@ void TabParent::HandleLongTap(const CSSIntPoint& aPoint,
}
}
void TabParent::HandleLongTapUp(const CSSIntPoint& aPoint,
void TabParent::HandleLongTapUp(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid &aGuid)
{
@ -721,7 +721,7 @@ bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event)
return PBrowserParent::SendRealMouseEvent(event);
}
CSSIntPoint TabParent::AdjustTapToChildWidget(const CSSIntPoint& aPoint)
CSSPoint TabParent::AdjustTapToChildWidget(const CSSPoint& aPoint)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
@ -735,12 +735,12 @@ CSSIntPoint TabParent::AdjustTapToChildWidget(const CSSIntPoint& aPoint)
}
nsPresContext* presContext = doc->GetShell()->GetPresContext();
return CSSIntPoint(
aPoint.x + presContext->DevPixelsToIntCSSPixels(mChildProcessOffsetAtTouchStart.x),
aPoint.y + presContext->DevPixelsToIntCSSPixels(mChildProcessOffsetAtTouchStart.y));
return aPoint + CSSPoint(
presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.x),
presContext->DevPixelsToFloatCSSPixels(mChildProcessOffsetAtTouchStart.y));
}
bool TabParent::SendHandleSingleTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
bool TabParent::SendHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;
@ -749,7 +749,7 @@ bool TabParent::SendHandleSingleTap(const CSSIntPoint& aPoint, const ScrollableL
return PBrowserParent::SendHandleSingleTap(AdjustTapToChildWidget(aPoint), aGuid);
}
bool TabParent::SendHandleLongTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;
@ -758,7 +758,7 @@ bool TabParent::SendHandleLongTap(const CSSIntPoint& aPoint, const ScrollableLay
return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aGuid);
}
bool TabParent::SendHandleLongTapUp(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
bool TabParent::SendHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;
@ -767,7 +767,7 @@ bool TabParent::SendHandleLongTapUp(const CSSIntPoint& aPoint, const ScrollableL
return PBrowserParent::SendHandleLongTapUp(AdjustTapToChildWidget(aPoint), aGuid);
}
bool TabParent::SendHandleDoubleTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid)
bool TabParent::SendHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;

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

@ -198,16 +198,16 @@ public:
void UpdateDimensions(const nsRect& rect, const nsIntSize& size);
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
void AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration);
void HandleDoubleTap(const CSSIntPoint& aPoint,
void HandleDoubleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid);
void HandleSingleTap(const CSSIntPoint& aPoint,
void HandleSingleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid);
void HandleLongTap(const CSSIntPoint& aPoint,
void HandleLongTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid);
void HandleLongTapUp(const CSSIntPoint& aPoint,
void HandleLongTapUp(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid);
void NotifyTransformBegin(ViewID aViewId);
@ -229,10 +229,10 @@ public:
bool SendMouseWheelEvent(mozilla::WidgetWheelEvent& event);
bool SendRealKeyEvent(mozilla::WidgetKeyboardEvent& event);
bool SendRealTouchEvent(WidgetTouchEvent& event);
bool SendHandleSingleTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid);
bool SendHandleLongTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid);
bool SendHandleLongTapUp(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid);
bool SendHandleDoubleTap(const CSSIntPoint& aPoint, const ScrollableLayerGuid& aGuid);
bool SendHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid);
bool SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid);
bool SendHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid);
bool SendHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid);
virtual PDocumentRendererParent*
AllocPDocumentRendererParent(const nsRect& documentRect,
@ -360,7 +360,7 @@ private:
nsRefPtr<ContentParent> mManager;
void TryCacheDPIAndScale();
CSSIntPoint AdjustTapToChildWidget(const CSSIntPoint& aPoint);
CSSPoint AdjustTapToChildWidget(const CSSPoint& aPoint);
// When true, we create a pan/zoom controller for our frame and
// notify it of input events targeting us.

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

@ -21,4 +21,4 @@ disabled = disabled until bug 859593 is fixed
[test_keyboard.html]
skip-if = buildapp != 'b2g'
[test_wifi-manage.html]
skip-if = buildapp != 'b2g'
skip-if = (buildapp != 'b2g') || (buildapp == 'b2g' && toolkit != 'gonk') #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)

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

@ -1566,13 +1566,7 @@ bool nsPluginHost::IsJavaMIMEType(const char* aType)
(0 == PL_strncasecmp(aType, "application/x-java-applet",
sizeof("application/x-java-applet") - 1)) ||
(0 == PL_strncasecmp(aType, "application/x-java-bean",
sizeof("application/x-java-bean") - 1))
#ifdef DEBUG
// Emulate java handling for the npjavatest plugin
|| (0 == PL_strncasecmp(aType, "application/x-java-test",
sizeof("application/x-java-test") - 1))
#endif
);
sizeof("application/x-java-bean") - 1)));
}
// Check whether or not a tag is a live, valid tag, and that it's loaded.

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

@ -1682,7 +1682,8 @@ nsPluginInstanceOwner::ProcessMouseDown(nsIDOMEvent* aMouseEvent)
return NS_OK;
}
nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent)
nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
bool aAllowPropagate)
{
#if !defined(XP_MACOSX)
if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow))
@ -1699,7 +1700,9 @@ nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent)
nsEventStatus rv = ProcessEvent(*mouseEvent);
if (nsEventStatus_eConsumeNoDefault == rv) {
aMouseEvent->PreventDefault();
aMouseEvent->StopPropagation();
if (!aAllowPropagate) {
aMouseEvent->StopPropagation();
}
}
if (mouseEvent->message == NS_MOUSE_BUTTON_UP) {
mLastMouseDownButtonType = -1;
@ -1741,8 +1744,10 @@ nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
}
return DispatchMouseToPlugin(aEvent);
}
if (eventType.EqualsLiteral("mousemove") ||
eventType.EqualsLiteral("click") ||
if (eventType.EqualsLiteral("mousemove")) {
return DispatchMouseToPlugin(aEvent, true);
}
if (eventType.EqualsLiteral("click") ||
eventType.EqualsLiteral("dblclick") ||
eventType.EqualsLiteral("mouseover") ||
eventType.EqualsLiteral("mouseout")) {

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

@ -365,7 +365,8 @@ private:
nsRefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
bool aAllowPropagate = false);
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
int mLastMouseDownButtonType;

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

@ -169,8 +169,9 @@ PluginModuleChild::Init(const std::string& aPluginFilename,
#if defined(MOZ_X11) || defined(OS_MACOSX)
nsPluginInfo info = nsPluginInfo();
if (NS_FAILED(pluginFile.GetPluginInfo(info, &mLibrary)))
if (NS_FAILED(pluginFile.GetPluginInfo(info, &mLibrary))) {
return false;
}
#if defined(MOZ_X11)
NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
@ -181,6 +182,8 @@ PluginModuleChild::Init(const std::string& aPluginFilename,
mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
#endif
pluginFile.FreePluginInfo(info);
if (!mLibrary)
#endif
{

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

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #b2g-desktop(tests that use plugins)
support-files =
307-xo-redirect.sjs
crashing_subpage.html

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

@ -1,11 +1,11 @@
/* ***** BEGIN LICENSE BLOCK *****
*
*
* Copyright (c) 2008, Mozilla Corporation
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
@ -14,7 +14,7 @@
* * Neither the name of the Mozilla Corporation nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -25,11 +25,11 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Contributor(s):
* Dave Townsend <dtownsend@oxymoronical.com>
* Josh Aas <josh@mozilla.com>
*
*
* ***** END LICENSE BLOCK ***** */
#include "nptest.h"
@ -389,7 +389,7 @@ static void initializeIdentifiers()
NPN_GetStringIdentifiers(sPluginPropertyIdentifierNames,
ARRAY_LENGTH(sPluginPropertyIdentifierNames), sPluginPropertyIdentifiers);
sIdentifiersInitialized = true;
sIdentifiersInitialized = true;
// Check whether nullptr is handled in NPN_GetStringIdentifiers
NPIdentifier IDList[2];
@ -431,7 +431,7 @@ static void sendBufferToFrame(NPP instance)
if (!instanceData->npnNewStream) outbuf = "data:text/html,";
const char* buf = reinterpret_cast<char *>(instanceData->streamBuf);
int32_t bufsize = instanceData->streamBufSize;
if (instanceData->streamMode == NP_ASFILE ||
if (instanceData->streamMode == NP_ASFILE ||
instanceData->streamMode == NP_ASFILEONLY) {
buf = reinterpret_cast<char *>(instanceData->fileBuf);
bufsize = instanceData->fileBufSize;
@ -445,24 +445,24 @@ static void sendBufferToFrame(NPP instance)
else {
outbuf.append("Error: no data in buffer");
}
if (instanceData->npnNewStream &&
instanceData->err.str().length() == 0) {
char typeHTML[] = "text/html";
NPStream* stream;
printf("calling NPN_NewStream...");
NPError err = NPN_NewStream(instance, typeHTML,
NPError err = NPN_NewStream(instance, typeHTML,
instanceData->frame.c_str(), &stream);
printf("return value %d\n", err);
if (err != NPERR_NO_ERROR) {
instanceData->err << "NPN_NewStream returned " << err;
return;
}
int32_t bytesToWrite = outbuf.length();
int32_t bytesWritten = 0;
while ((bytesToWrite - bytesWritten) > 0) {
int32_t numBytes = (bytesToWrite - bytesWritten) <
int32_t numBytes = (bytesToWrite - bytesWritten) <
instanceData->streamChunkSize ?
bytesToWrite - bytesWritten : instanceData->streamChunkSize;
int32_t written = NPN_Write(instance, stream,
@ -503,7 +503,7 @@ static void sendBufferToFrame(NPP instance)
}
}
NPError err = NPN_GetURL(instance, outbuf.c_str(),
NPError err = NPN_GetURL(instance, outbuf.c_str(),
instanceData->frame.c_str());
if (err != NPERR_NO_ERROR) {
instanceData->err << "NPN_GetURL returned " << err;
@ -523,7 +523,7 @@ static void XPSleep(unsigned int seconds)
TestFunction
getFuncFromString(const char* funcname)
{
FunctionTable funcTable[] =
FunctionTable funcTable[] =
{
{ FUNCTION_NPP_NEWSTREAM, "npp_newstream" },
{ FUNCTION_NPP_WRITEREADY, "npp_writeready" },
@ -856,7 +856,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
for (int i = 0; i < argc; i++) {
if (strcmp(argn[i], "drawmode") == 0) {
if (strcmp(argv[i], "solid") == 0)
scriptableObject->drawMode = DM_SOLID_COLOR;
scriptableObject->drawMode = DM_SOLID_COLOR;
}
else if (strcmp(argn[i], "color") == 0) {
scriptableObject->drawColor = parseHexColor(argv[i], strlen(argv[i]));
@ -1034,7 +1034,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
NPN_ReleaseObject(o);
o = nullptr;
}
// Set a property on NPNVWindowNPObject
err = NPN_GetValue(instance, NPNVWindowNPObject, &o);
if (err == NPERR_NO_ERROR) {
@ -1053,7 +1053,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
}
}
else if (instanceData->testFunction == FUNCTION_NPP_GETURLNOTIFY) {
NPError err = NPN_GetURLNotify(instance, instanceData->testUrl.c_str(),
NPError err = NPN_GetURLNotify(instance, instanceData->testUrl.c_str(),
nullptr, static_cast<void*>(&kNotifyData));
if (err != NPERR_NO_ERROR) {
instanceData->err << "NPN_GetURLNotify returned " << err;
@ -1178,7 +1178,7 @@ NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable,
{
printf("NPP_NewStream\n");
InstanceData* instanceData = (InstanceData*)(instance->pdata);
if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM &&
instanceData->failureCode) {
instanceData->err << SUCCESS_STRING;
@ -1257,20 +1257,20 @@ NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
return NPERR_GENERIC_ERROR;
}
if (strcmp(reinterpret_cast<char *>(instanceData->fileBuf),
if (strcmp(reinterpret_cast<char *>(instanceData->fileBuf),
reinterpret_cast<char *>(instanceData->streamBuf))) {
instanceData->err <<
"Error: data passed to NPP_Write and NPP_StreamAsFile differed";
}
}
if (instanceData->frame.length() > 0 &&
if (instanceData->frame.length() > 0 &&
instanceData->testFunction != FUNCTION_NPP_GETURLNOTIFY &&
instanceData->testFunction != FUNCTION_NPP_POSTURL) {
sendBufferToFrame(instance);
}
if (instanceData->testFunction == FUNCTION_NPP_POSTURL) {
NPError err = NPN_PostURL(instance, instanceData->testUrl.c_str(),
instanceData->postMode == POSTMODE_FRAME ? instanceData->frame.c_str() : nullptr,
NPError err = NPN_PostURL(instance, instanceData->testUrl.c_str(),
instanceData->postMode == POSTMODE_FRAME ? instanceData->frame.c_str() : nullptr,
instanceData->streamBufSize,
reinterpret_cast<char *>(instanceData->streamBuf), false);
if (err != NPERR_NO_ERROR)
@ -1288,7 +1288,7 @@ NPP_WriteReady(NPP instance, NPStream* stream)
if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) {
instanceData->err << "NPP_WriteReady called";
}
// temporarily disabled per bug 519870
//if (instanceData->writeReadyCount == 1) {
// return 0;
@ -1318,7 +1318,7 @@ NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buf
return len;
}
if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM) {
instanceData->err << "NPP_Write called";
}
@ -1354,7 +1354,7 @@ NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buf
NPN_DestroyStream(instance, stream, NPRES_USER_BREAK);
}
else if (instanceData->streamMode == NP_SEEK &&
stream->end != 0 &&
stream->end != 0 &&
stream->end == ((uint32_t)instanceData->streamBufSize + len)) {
// If the complete stream has been written, and we're doing a seek test,
// then call NPN_RequestRead.
@ -1373,7 +1373,7 @@ NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buf
char* streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
if (offset + len <= instanceData->streamBufSize) {
if (memcmp(buffer, streamBuf + offset, len)) {
instanceData->err <<
instanceData->err <<
"Error: data written from NPN_RequestRead doesn't match";
}
else {
@ -1402,8 +1402,8 @@ NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buf
streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
}
else {
instanceData->streamBuf =
realloc(reinterpret_cast<char *>(instanceData->streamBuf),
instanceData->streamBuf =
realloc(reinterpret_cast<char *>(instanceData->streamBuf),
instanceData->streamBufSize + len + 1);
streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
}
@ -1813,14 +1813,14 @@ NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
}
NPError
NPN_PostURLNotify(NPP instance, const char* url,
const char* target, uint32_t len,
NPN_PostURLNotify(NPP instance, const char* url,
const char* target, uint32_t len,
const char* buf, NPBool file, void* notifyData)
{
return sBrowserFuncs->posturlnotify(instance, url, target, len, buf, file, notifyData);
}
NPError
NPError
NPN_PostURL(NPP instance, const char *url,
const char *target, uint32_t len,
const char *buf, NPBool file)
@ -1835,8 +1835,8 @@ NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason)
}
NPError
NPN_NewStream(NPP instance,
NPMIMEType type,
NPN_NewStream(NPP instance,
NPMIMEType type,
const char* target,
NPStream** stream)
{
@ -1858,7 +1858,7 @@ NPN_Enumerate(NPP instance,
NPIdentifier **identifiers,
uint32_t *identifierCount)
{
return sBrowserFuncs->enumerate(instance, npobj, identifiers,
return sBrowserFuncs->enumerate(instance, npobj, identifiers,
identifierCount);
}
@ -1999,7 +1999,7 @@ scriptableInvoke(NPObject* npobj, NPIdentifier name, const NPVariant* args, uint
}
return false;
}
for (int i = 0; i < int(ARRAY_LENGTH(sPluginMethodIdentifiers)); i++) {
if (name == sPluginMethodIdentifiers[i])
return sPluginMethodFunctions[i](npobj, args, argCount, result);
@ -2048,7 +2048,9 @@ scriptableInvokeDefault(NPObject* npobj, const NPVariant* args, uint32_t argCoun
value << ";other";
}
}
STRINGZ_TO_NPVARIANT(NPN_StrDup(value.str().c_str()), *result);
char *outval = NPN_StrDup(value.str().c_str());
STRINGZ_TO_NPVARIANT(outval, *result);
return true;
}
@ -2056,16 +2058,21 @@ bool
scriptableHasProperty(NPObject* npobj, NPIdentifier name)
{
if (NPN_IdentifierIsString(name)) {
if (NPN_GetStringIdentifier(NPN_UTF8FromIdentifier(name)) != name)
NPUTF8 *asUTF8 = NPN_UTF8FromIdentifier(name);
if (NPN_GetStringIdentifier(asUTF8) != name) {
Crash();
}
NPN_MemFree(asUTF8);
}
else {
if (NPN_GetIntIdentifier(NPN_IntFromIdentifier(name)) != name)
if (NPN_GetIntIdentifier(NPN_IntFromIdentifier(name)) != name) {
Crash();
}
}
for (int i = 0; i < int(ARRAY_LENGTH(sPluginPropertyIdentifiers)); i++) {
if (name == sPluginPropertyIdentifiers[i])
if (name == sPluginPropertyIdentifiers[i]) {
return true;
}
}
return false;
}
@ -2141,7 +2148,7 @@ compareVariants(NPP instance, const NPVariant* var1, const NPVariant* var2)
" expected " << var2->type;
return false;
}
switch (var1->type) {
case NPVariantType_Int32: {
int32_t result = NPVARIANT_TO_INT32(*var1);
@ -2184,8 +2191,8 @@ compareVariants(NPP instance, const NPVariant* var1, const NPVariant* var2)
const NPString* expected = &NPVARIANT_TO_STRING(*var2);
if (strcmp(result->UTF8Characters, expected->UTF8Characters) ||
strlen(result->UTF8Characters) != strlen(expected->UTF8Characters)) {
id->err << "Variant values don't match; got " <<
result->UTF8Characters << " expected " <<
id->err << "Variant values don't match; got " <<
result->UTF8Characters << " expected " <<
expected->UTF8Characters;
success = false;
}
@ -2221,7 +2228,7 @@ compareVariants(NPP instance, const NPVariant* var1, const NPVariant* var2)
success = false;
}
else {
success = compareVariants(instance, &resultVariant,
success = compareVariants(instance, &resultVariant,
&expectedVariant);
NPN_ReleaseVariantValue(&expectedVariant);
}
@ -2235,7 +2242,7 @@ compareVariants(NPP instance, const NPVariant* var1, const NPVariant* var2)
id->err << "Unknown variant type";
success = false;
}
return success;
}
@ -2246,7 +2253,7 @@ throwExceptionNextInvoke(NPObject* npobj, const NPVariant* args, uint32_t argCou
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
id->throwOnNextInvoke = true;
BOOLEAN_TO_NPVARIANT(true, *result);
return true;
return true;
}
static bool
@ -2254,7 +2261,7 @@ npnInvokeDefaultTest(NPObject* npobj, const NPVariant* args, uint32_t argCount,
{
bool success = false;
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
NPObject* windowObject;
NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
if (!windowObject)
@ -2271,7 +2278,7 @@ npnInvokeDefaultTest(NPObject* npobj, const NPVariant* args, uint32_t argCount,
NPObject* selfObject = NPVARIANT_TO_OBJECT(objectVariant);
if (selfObject != nullptr) {
NPVariant resultVariant;
if (NPN_InvokeDefault(npp, selfObject, argCount > 1 ? &args[1] : nullptr,
if (NPN_InvokeDefault(npp, selfObject, argCount > 1 ? &args[1] : nullptr,
argCount - 1, &resultVariant)) {
*result = resultVariant;
success = true;
@ -2297,18 +2304,18 @@ npnInvokeTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVaria
NPIdentifier function = variantToIdentifier(args[0]);
if (!function)
return false;
NPObject* windowObject;
NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
if (!windowObject)
return false;
NPVariant invokeResult;
bool invokeReturn = NPN_Invoke(npp, windowObject, function,
argCount > 2 ? &args[2] : nullptr, argCount - 2, &invokeResult);
bool compareResult = compareVariants(npp, &invokeResult, &args[1]);
NPN_ReleaseObject(windowObject);
NPN_ReleaseVariantValue(&invokeResult);
BOOLEAN_TO_NPVARIANT(invokeReturn && compareResult, *result);
@ -2320,10 +2327,10 @@ npnEvaluateTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVar
{
bool success = false;
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
if (argCount != 1)
return false;
if (!NPVARIANT_IS_STRING(args[0]))
return false;
@ -2331,9 +2338,9 @@ npnEvaluateTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVar
NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
if (!windowObject)
return false;
success = NPN_Evaluate(npp, windowObject, (NPString*)&NPVARIANT_TO_STRING(args[0]), result);
NPN_ReleaseObject(windowObject);
return success;
}
@ -2580,10 +2587,13 @@ getError(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* r
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
if (id->err.str().length() == 0)
STRINGZ_TO_NPVARIANT(NPN_StrDup(SUCCESS_STRING), *result);
else
STRINGZ_TO_NPVARIANT(NPN_StrDup(id->err.str().c_str()), *result);
if (id->err.str().length() == 0) {
char *outval = NPN_StrDup(SUCCESS_STRING);
STRINGZ_TO_NPVARIANT(outval, *result);
} else {
char *outval = NPN_StrDup(id->err.str().c_str());
STRINGZ_TO_NPVARIANT(outval, *result);
}
return true;
}
@ -2663,7 +2673,7 @@ convertPointY(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVaria
double resultX, resultY;
NPN_ConvertPoint(npp, sourceX, sourceY, (NPCoordinateSpace)sourceSpace, &resultX, &resultY, (NPCoordinateSpace)destSpace);
DOUBLE_TO_NPVARIANT(resultY, *result);
return true;
}
@ -2906,7 +2916,9 @@ static bool getJavaCodebase(NPObject* npobj, const NPVariant* args, uint32_t arg
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
STRINGZ_TO_NPVARIANT(NPN_StrDup(id->javaCodebase.c_str()), *result);
char *outval = NPN_StrDup(id->javaCodebase.c_str());
STRINGZ_TO_NPVARIANT(outval, *result);
return true;
}
@ -2954,12 +2966,12 @@ static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t
// caller is responsible for freeing return buffer
static char* URLForInstanceWindow(NPP instance) {
char *outString = nullptr;
NPObject* windowObject = nullptr;
NPError err = NPN_GetValue(instance, NPNVWindowNPObject, &windowObject);
if (err != NPERR_NO_ERROR || !windowObject)
return nullptr;
NPIdentifier locationIdentifier = NPN_GetStringIdentifier("location");
NPVariant locationVariant;
if (NPN_GetProperty(instance, windowObject, locationIdentifier, &locationVariant)) {
@ -2977,13 +2989,13 @@ static char* URLForInstanceWindow(NPP instance) {
}
}
NPN_ReleaseVariantValue(&hrefVariant);
}
}
}
NPN_ReleaseVariantValue(&locationVariant);
}
NPN_ReleaseObject(windowObject);
return outString;
}
@ -2995,15 +3007,15 @@ setCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant*
if (!NPVARIANT_IS_STRING(args[0]))
return false;
const NPString* cookie = &NPVARIANT_TO_STRING(args[0]);
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
char* url = URLForInstanceWindow(npp);
if (!url)
return false;
NPError err = NPN_SetValueForURL(npp, NPNURLVCookie, url, cookie->UTF8Characters, cookie->UTF8Length);
free(url);
return (err == NPERR_NO_ERROR);
}
@ -3012,9 +3024,9 @@ getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant*
{
if (argCount != 0)
return false;
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
char* url = URLForInstanceWindow(npp);
if (!url)
return false;
@ -3024,7 +3036,7 @@ getCookie(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant*
free(url);
if (err != NPERR_NO_ERROR || !cookie)
return false;
STRINGZ_TO_NPVARIANT(cookie, *result);
return true;
}
@ -3051,18 +3063,18 @@ getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant
char* username = nullptr;
char* password = nullptr;
uint32_t ulen = 0, plen = 0;
NPError err = NPN_GetAuthenticationInfo(npp,
protocol->UTF8Characters,
host->UTF8Characters,
port,
scheme->UTF8Characters,
NPError err = NPN_GetAuthenticationInfo(npp,
protocol->UTF8Characters,
host->UTF8Characters,
port,
scheme->UTF8Characters,
realm->UTF8Characters,
&username,
&ulen,
&password,
&username,
&ulen,
&password,
&plen);
if (err != NPERR_NO_ERROR) {
return false;
}
@ -3077,7 +3089,7 @@ getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant
NPN_MemFree(username);
NPN_MemFree(password);
return true;
}
@ -3105,7 +3117,7 @@ static void timerCallback(NPP npp, uint32_t timerID)
}
NPN_ReleaseObject(windowObject);
if (event.timerIdSchedule > -1) {
id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback);
}
@ -3128,9 +3140,9 @@ timerTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant*
id->timerTestResult = true;
timerEvent event = timerEvents[currentTimerEventCount];
id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback);
return id->timerID[event.timerIdSchedule] != 0;
}
@ -3171,7 +3183,7 @@ asyncCallback(void* cookie)
id->asyncCallbackResult = false;
#endif
break;
// async callback triggered from different thread
default:
NPObject* windowObject;
@ -3197,11 +3209,11 @@ asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPV
return false;
const NPString* argstr = &NPVARIANT_TO_STRING(args[0]);
id->asyncTestScriptCallback = argstr->UTF8Characters;
id->asyncTestPhase = 0;
id->asyncCallbackResult = true;
NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
return true;
}
@ -3287,7 +3299,7 @@ checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount,
return false;
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
NPObject* localFunc =
NPN_CreateObject(npp, const_cast<NPClass*>(&kGCRaceClass));
@ -3310,7 +3322,7 @@ hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
busyHang = NPVARIANT_TO_BOOLEAN(args[0]);
}
if (busyHang) {
if (busyHang) {
const time_t start = std::time(nullptr);
while ((std::time(nullptr) - start) < 100000) {
volatile int dummy = 0;
@ -3660,7 +3672,7 @@ bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount,
return false;
NPObject* ctor = NPVARIANT_TO_OBJECT(args[0]);
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
return NPN_Construct(npp, ctor, args + 1, argCount - 1, result);
@ -3693,12 +3705,12 @@ bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount,
const char* flagsEnd = strchr(siteEnd + 1, ':');
*((char*) flagsEnd) = '\0';
*((char*) next) = '\0';
siteData data;
data.site = string(iterator);
data.flags = atoi(siteEnd + 1);
data.age = atoi(flagsEnd + 1);
sSitesWithData->push_back(data);
if (next == end)
@ -3728,7 +3740,9 @@ bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
STRINGZ_TO_NPVARIANT(NPN_StrDup(id->lastKeyText.c_str()), *result);
char *outval = NPN_StrDup(id->lastKeyText.c_str());
STRINGZ_TO_NPVARIANT(outval, *result);
return true;
}
@ -3756,7 +3770,7 @@ bool getMouseUpEventCount(NPObject* npobj, const NPVariant* args, uint32_t argCo
if (argCount != 0) {
return false;
}
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
INT32_TO_NPVARIANT(id->mouseUpEventCount, *result);

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

@ -185,11 +185,10 @@ public:
NS_IMPL_CYCLE_COLLECTION_CLASS(Promise)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Promise)
tmp->MaybeReportRejected();
tmp->MaybeReportRejectedOnce();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveCallbacks);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectCallbacks);
tmp->mResult = JS::UndefinedValue();
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -229,8 +228,7 @@ Promise::Promise(nsIGlobalObject* aGlobal)
Promise::~Promise()
{
MaybeReportRejected();
mResult = JS::UndefinedValue();
MaybeReportRejectedOnce();
mozilla::DropJSObjects(this);
}
@ -822,6 +820,9 @@ Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
if (aRejectCallback) {
mHadRejectCallback = true;
mRejectCallbacks.AppendElement(aRejectCallback);
// Now that there is a callback, we don't need to report anymore.
RemoveFeature();
}
// If promise's state is resolved, queue a task to process our resolve
@ -1058,9 +1059,47 @@ Promise::RunResolveTask(JS::Handle<JS::Value> aValue,
SetResult(aValue);
SetState(aState);
// If the Promise was rejected, and there is no reject handler already setup,
// watch for thread shutdown.
if (aState == PromiseState::Rejected &&
!mHadRejectCallback &&
!NS_IsMainThread()) {
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
mFeature = new PromiseReportRejectFeature(this);
if (NS_WARN_IF(!worker->AddFeature(worker->GetJSContext(), mFeature))) {
// Worker is shutting down, report rejection immediately since it is
// unlikely that reject callbacks will be added after this point.
MaybeReportRejected();
}
}
RunTask();
}
void
Promise::RemoveFeature()
{
if (mFeature) {
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->RemoveFeature(worker->GetJSContext(), mFeature);
mFeature = nullptr;
}
}
bool
PromiseReportRejectFeature::Notify(JSContext* aCx, workers::Status aStatus)
{
MOZ_ASSERT(aStatus > workers::Running);
mPromise->MaybeReportRejectedOnce();
// After this point, `this` has been deleted by RemoveFeature!
return true;
}
bool
Promise::ArgumentToJSValue(const nsAString& aArgument,
JSContext* aCx,

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

@ -18,6 +18,8 @@
#include "nsAutoPtr.h"
#include "js/TypeDecls.h"
#include "mozilla/dom/workers/bindings/WorkerFeature.h"
class nsIGlobalObject;
namespace mozilla {
@ -28,6 +30,23 @@ class PromiseCallback;
class PromiseInit;
class PromiseNativeHandler;
class Promise;
class PromiseReportRejectFeature : public workers::WorkerFeature
{
// The Promise that owns this feature.
Promise* mPromise;
public:
PromiseReportRejectFeature(Promise* aPromise)
: mPromise(aPromise)
{
MOZ_ASSERT(mPromise);
}
virtual bool
Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE;
};
class Promise MOZ_FINAL : public nsISupports,
public nsWrapperCache
{
@ -35,6 +54,7 @@ class Promise MOZ_FINAL : public nsISupports,
friend class PromiseResolverMixin;
friend class PromiseResolverTask;
friend class PromiseTask;
friend class PromiseReportRejectFeature;
friend class RejectPromiseCallback;
friend class ResolvePromiseCallback;
friend class WorkerPromiseResolverTask;
@ -157,8 +177,15 @@ private:
// If we have been rejected and our mResult is a JS exception,
// report it to the error console.
// Use MaybeReportRejectedOnce() for actual calls.
void MaybeReportRejected();
void MaybeReportRejectedOnce() {
MaybeReportRejected();
RemoveFeature();
mResult = JS::UndefinedValue();
}
void MaybeResolveInternal(JSContext* aCx,
JS::Handle<JS::Value> aValue,
PromiseTaskSync aSync = AsyncTask);
@ -271,6 +298,8 @@ private:
void HandleException(JSContext* aCx);
void RemoveFeature();
nsRefPtr<nsIGlobalObject> mGlobal;
nsTArray<nsRefPtr<PromiseCallback> > mResolveCallbacks;
@ -282,6 +311,12 @@ private:
bool mHadRejectCallback;
bool mResolvePending;
// If a rejected promise on a worker has no reject callbacks attached, it
// needs to know when the worker is shutting down, to report the error on the
// console before the worker's context is deleted. This feature is used for
// that purpose.
nsAutoPtr<PromiseReportRejectFeature> mFeature;
};
} // namespace dom

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

@ -310,15 +310,17 @@ gfxMemorySharedReadLock::GetReadCount()
gfxShmSharedReadLock::gfxShmSharedReadLock(ISurfaceAllocator* aAllocator)
: mAllocator(aAllocator)
, mAllocSuccess(false)
{
MOZ_COUNT_CTOR(gfxShmSharedReadLock);
MOZ_ASSERT(mAllocator);
if (mAllocator) {
#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
if (mAllocator->AllocUnsafeShmem(MOZ_ALIGN_WORD(sizeof(ShmReadLockInfo)),
mozilla::ipc::SharedMemory::TYPE_BASIC, &mShmem)) {
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
info->readCount = 1;
mAllocSuccess = true;
}
}
}
@ -331,13 +333,18 @@ gfxShmSharedReadLock::~gfxShmSharedReadLock()
int32_t
gfxShmSharedReadLock::ReadLock() {
NS_ASSERT_OWNINGTHREAD(gfxShmSharedReadLock);
if (!mAllocSuccess) {
return 0;
}
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
return PR_ATOMIC_INCREMENT(&info->readCount);
}
int32_t
gfxShmSharedReadLock::ReadUnlock() {
if (!mAllocSuccess) {
return 0;
}
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
int32_t readCount = PR_ATOMIC_DECREMENT(&info->readCount);
NS_ASSERTION(readCount >= 0, "ReadUnlock called without a ReadLock.");
@ -350,7 +357,9 @@ gfxShmSharedReadLock::ReadUnlock() {
int32_t
gfxShmSharedReadLock::GetReadCount() {
NS_ASSERT_OWNINGTHREAD(gfxShmSharedReadLock);
if (!mAllocSuccess) {
return 0;
}
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
return info->readCount;
}
@ -514,6 +523,9 @@ TileClient::GetBackBuffer(const nsIntRegion& aDirtyRegion, TextureClientPool *aP
} else {
mBackLock = new gfxShmSharedReadLock(mManager->AsShadowForwarder());
}
MOZ_ASSERT(mBackLock->IsValid());
*aCreatedTextureClient = true;
mInvalidBack = nsIntRect(0, 0, TILEDLAYERBUFFER_TILE_SIZE, TILEDLAYERBUFFER_TILE_SIZE);
}

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

@ -55,6 +55,7 @@ public:
virtual int32_t ReadLock() = 0;
virtual int32_t ReadUnlock() = 0;
virtual int32_t GetReadCount() = 0;
virtual bool IsValid() const = 0;
enum gfxSharedReadLockType {
TYPE_MEMORY,
@ -80,6 +81,8 @@ public:
virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_MEMORY; }
virtual bool IsValid() const MOZ_OVERRIDE { return true; };
private:
int32_t mReadCount;
};
@ -101,6 +104,8 @@ public:
virtual int32_t GetReadCount() MOZ_OVERRIDE;
virtual bool IsValid() const MOZ_OVERRIDE { return mAllocSuccess; };
virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_SHMEM; }
mozilla::ipc::Shmem& GetShmem() { return mShmem; }
@ -116,6 +121,7 @@ private:
gfxShmSharedReadLock(ISurfaceAllocator* aAllocator, const mozilla::ipc::Shmem& aShmem)
: mAllocator(aAllocator)
, mShmem(aShmem)
, mAllocSuccess(true)
{
MOZ_COUNT_CTOR(gfxShmSharedReadLock);
}
@ -128,6 +134,7 @@ private:
RefPtr<ISurfaceAllocator> mAllocator;
mozilla::ipc::Shmem mShmem;
bool mAllocSuccess;
};
/**
@ -170,14 +177,18 @@ struct TileClient
void ReadUnlock()
{
NS_ASSERTION(mFrontLock != nullptr, "ReadUnlock with no gfxSharedReadLock");
mFrontLock->ReadUnlock();
MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock");
if (mFrontLock) {
mFrontLock->ReadUnlock();
}
}
void ReadLock()
{
NS_ASSERTION(mFrontLock != nullptr, "ReadLock with no gfxSharedReadLock");
mFrontLock->ReadLock();
MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock");
if (mFrontLock) {
mFrontLock->ReadLock();
}
}
void Release()

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

@ -904,7 +904,7 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
}
bool
AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSIntPoint* aOut)
AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut)
{
APZCTreeManager* treeManagerLocal = mTreeManager;
if (treeManagerLocal) {
@ -917,8 +917,7 @@ AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSIntPoint* a
LayoutDevicePoint layoutPoint = LayoutDevicePoint(result.x, result.y);
{ // scoped lock to access mFrameMetrics
ReentrantMonitorAutoEnter lock(mMonitor);
CSSPoint cssPoint = layoutPoint / mFrameMetrics.mDevPixelsPerCSSPixel;
*aOut = gfx::RoundedToInt(cssPoint);
*aOut = layoutPoint / mFrameMetrics.mDevPixelsPerCSSPixel;
}
return true;
}
@ -930,7 +929,7 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent)
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
CSSIntPoint geckoScreenPoint;
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
SetState(WAITING_CONTENT_RESPONSE);
SetContentResponseTimer();
@ -946,7 +945,7 @@ nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEven
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
CSSIntPoint geckoScreenPoint;
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
controller->HandleLongTapUp(geckoScreenPoint, modifiers, GetGuid());
return nsEventStatus_eConsumeNoDefault;
@ -962,7 +961,7 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven
// sending event to content
if (controller && !mZoomConstraints.mAllowDoubleTapZoom) {
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
CSSIntPoint geckoScreenPoint;
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
// Because this may be being running as part of APZCTreeManager::ReceiveInputEvent,
// calling controller->HandleSingleTap directly might mean that content receives
@ -984,7 +983,7 @@ nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
CSSIntPoint geckoScreenPoint;
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
// See comment in OnSingleTapUp as to why we do this in PostDelayedTask.
controller->PostDelayedTask(
@ -1003,7 +1002,7 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent)
if (controller) {
if (mZoomConstraints.mAllowDoubleTapZoom) {
int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
CSSIntPoint geckoScreenPoint;
CSSPoint geckoScreenPoint;
if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
controller->HandleDoubleTap(geckoScreenPoint, modifiers, GetGuid());
}
@ -1685,7 +1684,8 @@ gfx3DMatrix AsyncPanZoomController::GetNontransientAsyncTransform() {
gfx3DMatrix AsyncPanZoomController::GetTransformToLastDispatchedPaint() {
ReentrantMonitorAutoEnter lock(mMonitor);
CSSPoint scrollChange = mLastContentPaintMetrics.mScrollOffset - mLastDispatchedPaintMetrics.mScrollOffset;
LayerPoint scrollChange = (mLastContentPaintMetrics.mScrollOffset - mLastDispatchedPaintMetrics.mScrollOffset)
* mLastContentPaintMetrics.LayersPixelsPerCSSPixel();
float zoomChange = mLastContentPaintMetrics.mZoom.scale / mLastDispatchedPaintMetrics.mZoom.scale;
return gfx3DMatrix::Translation(scrollChange.x, scrollChange.y, 0) *
gfx3DMatrix::ScalingMatrix(zoomChange, zoomChange, 1);

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

@ -601,12 +601,12 @@ private:
void SetState(PanZoomState aState);
/**
* Convert ScreenPoint relative to this APZC to CSSIntPoint relative
* Convert ScreenPoint relative to this APZC to CSSPoint relative
* to the parent document. This excludes the transient compositor transform.
* NOTE: This must be converted to CSSIntPoint relative to the child
* NOTE: This must be converted to CSSPoint relative to the child
* document before sending over IPC.
*/
bool ConvertToGecko(const ScreenPoint& aPoint, CSSIntPoint* aOut);
bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut);
/**
* Internal helpers for checking general state of this apzc.

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

@ -8,7 +8,7 @@
#define mozilla_layers_GeckoContentController_h
#include "FrameMetrics.h" // for FrameMetrics, etc
#include "Units.h" // for CSSIntPoint, CSSRect, etc
#include "Units.h" // for CSSPoint, CSSRect, etc
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "nsISupportsImpl.h"
@ -42,7 +42,7 @@ public:
* AsyncPanZoomController::ZoomToRect with the dimensions that we want to zoom
* to.
*/
virtual void HandleDoubleTap(const CSSIntPoint& aPoint,
virtual void HandleDoubleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) = 0;
@ -51,7 +51,7 @@ public:
* current scroll offset. This should simulate and send to content a mouse
* button down, then mouse button up at |aPoint|.
*/
virtual void HandleSingleTap(const CSSIntPoint& aPoint,
virtual void HandleSingleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) = 0;
@ -59,7 +59,7 @@ public:
* Requests handling a long tap. |aPoint| is in CSS pixels, relative to the
* current scroll offset.
*/
virtual void HandleLongTap(const CSSIntPoint& aPoint,
virtual void HandleLongTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) = 0;
@ -68,7 +68,7 @@ public:
* relative to the current scroll offset. HandleLongTapUp will always be
* preceeded by HandleLongTap
*/
virtual void HandleLongTapUp(const CSSIntPoint& aPoint,
virtual void HandleLongTapUp(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) = 0;

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

@ -10,7 +10,7 @@
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "mozilla/layers/APZCTreeManager.h" // for APZCTreeManager
#include "base/task.h" // for CancelableTask, etc
#include "mozilla/Preferences.h" // for Preferences
#include "gfxPrefs.h" // for gfxPrefs
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/mozalloc.h" // for operator new
#include "nsDebug.h" // for NS_WARN_IF_FALSE
@ -85,7 +85,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEve
mAsyncPanZoomController->PostDelayedTask(
mLongTapTimeoutTask,
Preferences::GetInt("ui.click_hold_context_menus.delay", 500));
gfxPrefs::UiClickHoldContextMenusDelay());
}
} else if (length == 2) {
// Another finger has been added; it can't be a tap anymore.

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

@ -137,72 +137,6 @@ DrawQuads(GLContext *aGLContext,
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
#ifdef MOZ_WIDGET_GONK
CompositorOGLGonkBackendSpecificData::CompositorOGLGonkBackendSpecificData(CompositorOGL* aCompositor)
: mCompositor(aCompositor)
{
}
CompositorOGLGonkBackendSpecificData::~CompositorOGLGonkBackendSpecificData()
{
// Delete all textures by calling EndFrame twice
gl()->MakeCurrent();
EndFrame();
EndFrame();
}
GLContext*
CompositorOGLGonkBackendSpecificData::gl() const
{
return mCompositor->gl();
}
GLuint
CompositorOGLGonkBackendSpecificData::GetTexture()
{
GLuint texture = 0;
if (!mUnusedTextures.IsEmpty()) {
// Try to reuse one from the unused pile first
texture = mUnusedTextures[0];
mUnusedTextures.RemoveElementAt(0);
} else if (gl()->MakeCurrent()) {
// There isn't one to reuse, create one.
gl()->fGenTextures(1, &texture);
}
if (texture) {
mCreatedTextures.AppendElement(texture);
}
return texture;
}
void
CompositorOGLGonkBackendSpecificData::EndFrame()
{
gl()->MakeCurrent();
// Some platforms have issues unlocking Gralloc buffers even when they're
// rebound.
if (gfxPrefs::OverzealousGrallocUnlocking()) {
mUnusedTextures.AppendElements(mCreatedTextures);
mCreatedTextures.Clear();
}
// Delete unused textures
for (size_t i = 0; i < mUnusedTextures.Length(); i++) {
GLuint texture = mUnusedTextures[i];
gl()->fDeleteTextures(1, &texture);
}
mUnusedTextures.Clear();
// Move all created textures into the unused pile
mUnusedTextures.AppendElements(mCreatedTextures);
mCreatedTextures.Clear();
}
#endif
CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
int aSurfaceHeight, bool aUseExternalSurfaceSize)
: mWidget(aWidget)
@ -246,38 +180,18 @@ CompositorOGL::CreateContext()
return context.forget();
}
GLuint
CompositorOGL::GetTemporaryTexture(GLenum aTextureUnit)
{
size_t index = aTextureUnit - LOCAL_GL_TEXTURE0;
// lazily grow the array of temporary textures
if (mTextures.Length() <= index) {
size_t prevLength = mTextures.Length();
mTextures.SetLength(index + 1);
for(unsigned int i = prevLength; i <= index; ++i) {
mTextures[i] = 0;
}
}
// lazily initialize the temporary textures
if (!mTextures[index]) {
if (!gl()->MakeCurrent()) {
return 0;
}
gl()->fGenTextures(1, &mTextures[index]);
}
return mTextures[index];
}
void
CompositorOGL::Destroy()
{
if (gl() && gl()->MakeCurrent()) {
if (mTextures.Length() > 0) {
gl()->fDeleteTextures(mTextures.Length(), &mTextures[0]);
}
mVBOs.Flush(gl());
}
mTextures.SetLength(0);
if (mTexturePool) {
mTexturePool->Clear();
mTexturePool = nullptr;
}
if (!mDestroyed) {
mDestroyed = true;
CleanupResources();
@ -1366,11 +1280,9 @@ CompositorOGL::EndFrame()
mCurrentRenderTarget = nullptr;
#ifdef MOZ_WIDGET_GONK
if (mCompositorBackendSpecificData) {
static_cast<CompositorOGLGonkBackendSpecificData*>(mCompositorBackendSpecificData.get())->EndFrame();
if (mTexturePool) {
mTexturePool->EndFrame();
}
#endif
mGLContext->SwapBuffers();
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
@ -1480,17 +1392,6 @@ CompositorOGL::Resume()
return true;
}
#ifdef MOZ_WIDGET_GONK
CompositorBackendSpecificData*
CompositorOGL::GetCompositorBackendSpecificData()
{
if (!mCompositorBackendSpecificData) {
mCompositorBackendSpecificData = new CompositorOGLGonkBackendSpecificData(this);
}
return mCompositorBackendSpecificData;
}
#endif
TemporaryRef<DataTextureSource>
CompositorOGL::CreateDataTextureSource(TextureFlags aFlags)
{
@ -1593,5 +1494,120 @@ CompositorOGL::BindAndDrawQuad(ShaderProgramOGL *aProg,
aFlipped, aDrawMode);
}
GLuint
CompositorOGL::GetTemporaryTexture(GLenum aUnit)
{
if (!mTexturePool) {
#ifdef MOZ_WIDGET_GONK
mTexturePool = new PerFrameTexturePoolOGL(gl());
#else
mTexturePool = new PerUnitTexturePoolOGL(gl());
#endif
}
return mTexturePool->GetTexture(aUnit);
}
GLuint
PerUnitTexturePoolOGL::GetTexture(GLenum aTextureUnit)
{
size_t index = aTextureUnit - LOCAL_GL_TEXTURE0;
// lazily grow the array of temporary textures
if (mTextures.Length() <= index) {
size_t prevLength = mTextures.Length();
mTextures.SetLength(index + 1);
for(unsigned int i = prevLength; i <= index; ++i) {
mTextures[i] = 0;
}
}
// lazily initialize the temporary textures
if (!mTextures[index]) {
if (!mGL->MakeCurrent()) {
return 0;
}
mGL->fGenTextures(1, &mTextures[index]);
}
return mTextures[index];
}
void
PerUnitTexturePoolOGL::DestroyTextures()
{
if (mGL && mGL->MakeCurrent()) {
if (mTextures.Length() > 0) {
mGL->fDeleteTextures(mTextures.Length(), &mTextures[0]);
}
}
mTextures.SetLength(0);
}
void
PerFrameTexturePoolOGL::DestroyTextures()
{
if (!mGL->MakeCurrent()) {
return;
}
if (mUnusedTextures.Length() > 0) {
mGL->fDeleteTextures(mUnusedTextures.Length(), &mUnusedTextures[0]);
mUnusedTextures.Clear();
}
if (mCreatedTextures.Length() > 0) {
mGL->fDeleteTextures(mCreatedTextures.Length(), &mCreatedTextures[0]);
mCreatedTextures.Clear();
}
}
GLuint
PerFrameTexturePoolOGL::GetTexture(GLenum)
{
GLuint texture = 0;
if (!mUnusedTextures.IsEmpty()) {
// Try to reuse one from the unused pile first
texture = mUnusedTextures[0];
mUnusedTextures.RemoveElementAt(0);
} else if (mGL->MakeCurrent()) {
// There isn't one to reuse, create one.
mGL->fGenTextures(1, &texture);
}
if (texture) {
mCreatedTextures.AppendElement(texture);
}
return texture;
}
void
PerFrameTexturePoolOGL::EndFrame()
{
if (!mGL->MakeCurrent()) {
// this means the context got destroyed underneith us somehow, and the driver
// already has destroyed the textures.
mCreatedTextures.Clear();
mUnusedTextures.Clear();
return;
}
// Some platforms have issues unlocking Gralloc buffers even when they're
// rebound.
if (gfxPrefs::OverzealousGrallocUnlocking()) {
mUnusedTextures.AppendElements(mCreatedTextures);
mCreatedTextures.Clear();
}
// Delete unused textures
for (size_t i = 0; i < mUnusedTextures.Length(); i++) {
GLuint texture = mUnusedTextures[i];
mGL->fDeleteTextures(1, &texture);
}
mUnusedTextures.Clear();
// Move all created textures into the unused pile
mUnusedTextures.AppendElements(mCreatedTextures);
mCreatedTextures.Clear();
}
} /* layers */
} /* mozilla */

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

@ -55,6 +55,99 @@ class TextureSource;
struct Effect;
struct EffectChain;
/**
* Interface for pools of temporary gl textures for the compositor.
* The textures are fully owned by the pool, so the latter is responsible
* calling fDeleteTextures accordingly.
* Users of GetTexture receive a texture that is only valid for the duration
* of the current frame.
* This is primarily intended for direct texturing APIs that need to attach
* shared objects (such as an EGLImage) to a gl texture.
*/
class CompositorTexturePoolOGL : public RefCounted<CompositorTexturePoolOGL>
{
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositorTexturePoolOGL)
virtual ~CompositorTexturePoolOGL() {}
virtual void Clear() = 0;
virtual GLuint GetTexture(GLenum aUnit) = 0;
virtual void EndFrame() = 0;
};
/**
* Agressively reuses textures. One gl texture per texture unit in total.
* So far this hasn't shown the best results on b2g.
*/
class PerUnitTexturePoolOGL : public CompositorTexturePoolOGL
{
public:
PerUnitTexturePoolOGL(gl::GLContext* aGL)
: mGL(aGL)
{}
virtual ~PerUnitTexturePoolOGL()
{
DestroyTextures();
}
virtual void Clear() MOZ_OVERRIDE
{
DestroyTextures();
}
virtual GLuint GetTexture(GLenum aUnit) MOZ_OVERRIDE;
virtual void EndFrame() MOZ_OVERRIDE {}
protected:
void DestroyTextures();
nsTArray<GLuint> mTextures;
RefPtr<gl::GLContext> mGL;
};
/**
* Reuse gl textures from a pool of textures that haven't yet been
* used during the current frame.
* All the textures that are not used at the end of a frame are
* deleted.
* This strategy seems to work well with gralloc textures because destroying
* unused textures which are bound to gralloc buffers let drivers know that it
* can unlock the gralloc buffers.
*/
class PerFrameTexturePoolOGL : public CompositorTexturePoolOGL
{
public:
PerFrameTexturePoolOGL(gl::GLContext* aGL)
: mGL(aGL)
{}
virtual ~PerFrameTexturePoolOGL()
{
DestroyTextures();
}
virtual void Clear() MOZ_OVERRIDE
{
DestroyTextures();
}
virtual GLuint GetTexture(GLenum aUnit) MOZ_OVERRIDE;
virtual void EndFrame() MOZ_OVERRIDE;
protected:
void DestroyTextures();
RefPtr<gl::GLContext> mGL;
nsTArray<GLuint> mCreatedTextures;
nsTArray<GLuint> mUnusedTextures;
};
class CompositorOGL : public Compositor
{
typedef mozilla::gl::GLContext GLContext;
@ -162,10 +255,6 @@ public:
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
#ifdef MOZ_WIDGET_GONK
virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() MOZ_OVERRIDE;
#endif
GLContext* gl() const { return mGLContext; }
gfx::SurfaceFormat GetFBOFormat() const {
return gfx::SurfaceFormat::R8G8B8A8;
@ -309,43 +398,17 @@ private:
*/
GLint FlipY(GLint y) const { return mHeight - y; }
bool mDestroyed;
RefPtr<CompositorTexturePoolOGL> mTexturePool;
// Textures used for direct texturing of buffers like gralloc.
// The index of the texture in this array must correspond to the texture unit.
nsTArray<GLuint> mTextures;
bool mDestroyed;
/**
* Height of the OpenGL context's primary framebuffer in pixels. Used by
* FlipY for the y-flipping calculation.
*/
GLint mHeight;
#ifdef MOZ_WIDGET_GONK
RefPtr<CompositorBackendSpecificData> mCompositorBackendSpecificData;
#endif
};
#ifdef MOZ_WIDGET_GONK
class CompositorOGLGonkBackendSpecificData : public CompositorBackendSpecificData
{
public:
CompositorOGLGonkBackendSpecificData(CompositorOGL* aCompositor);
virtual ~CompositorOGLGonkBackendSpecificData();
GLuint GetTexture();
void EndFrame();
private:
gl::GLContext* gl() const;
RefPtr<CompositorOGL> mCompositor;
nsTArray<GLuint> mCreatedTextures;
nsTArray<GLuint> mUnusedTextures;
};
#endif
}
}

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

@ -93,7 +93,6 @@ GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL* aCompositor,
, mGraphicBuffer(aGraphicBuffer)
, mEGLImage(0)
, mFormat(aFormat)
, mNeedsReset(true)
{
MOZ_ASSERT(mGraphicBuffer.get());
}
@ -107,14 +106,6 @@ GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
void
GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit)
{
/*
* The job of this function is to ensure that the texture is tied to the
* android::GraphicBuffer, so that texturing will source the GraphicBuffer.
*
* To this effect we create an EGLImage wrapping this GraphicBuffer,
* using EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
* texture using fEGLImageTargetTexture2D.
*/
MOZ_ASSERT(gl());
if (!IsValid()) {
return;
@ -127,29 +118,22 @@ GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit)
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(textureTarget, tex);
if (mCompositableBackendData) {
// There are two paths for locking/unlocking - if mCompositableBackendData is
// set, we use the texture on there, otherwise we use
// CompositorBackendSpecificData from the compositor and bind the EGLImage
// only in Lock().
if (!mEGLImage) {
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
}
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
}
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
}
void GrallocTextureSourceOGL::Lock()
{
if (mCompositableBackendData) return;
/*
* The job of this function is to ensure that the texture is tied to the
* android::GraphicBuffer, so that texturing will source the GraphicBuffer.
*
* To this effect we create an EGLImage wrapping this GraphicBuffer,
* using EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
* texture using fEGLImageTargetTexture2D.
*/
MOZ_ASSERT(IsValid());
CompositorOGLGonkBackendSpecificData* backendData =
static_cast<CompositorOGLGonkBackendSpecificData*>(mCompositor->GetCompositorBackendSpecificData());
mTexture = backendData->GetTexture();
mTexture = mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
GLuint textureTarget = GetTextureTarget();
@ -165,7 +149,7 @@ void GrallocTextureSourceOGL::Lock()
bool
GrallocTextureSourceOGL::IsValid() const
{
return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mCompositableBackendData);
return !!gl() && !!mGraphicBuffer.get();
}
gl::GLContext*
@ -205,51 +189,6 @@ GrallocTextureSourceOGL::GetFormat() const {
return mFormat;
}
void
GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
{
if (!aBackendData) {
mCompositableBackendData = nullptr;
DeallocateDeviceData();
return;
}
if (mCompositableBackendData != aBackendData) {
mNeedsReset = true;
}
if (!mNeedsReset) {
// Update binding to the EGLImage
gl()->MakeCurrent();
GLuint tex = GetGLTexture();
GLuint textureTarget = GetTextureTarget();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(textureTarget, tex);
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
return;
}
mCompositableBackendData = aBackendData;
if (!mCompositor) {
return;
}
// delete old EGLImage
DeallocateDeviceData();
gl()->MakeCurrent();
GLuint tex = GetGLTexture();
GLuint textureTarget = GetTextureTarget();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(textureTarget, tex);
// create new EGLImage
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
mNeedsReset = false;
}
gfx::IntSize
GrallocTextureSourceOGL::GetSize() const
{
@ -418,11 +357,6 @@ GrallocTextureSourceOGL::GetAsSurface() {
GLuint
GrallocTextureSourceOGL::GetGLTexture()
{
if (mCompositableBackendData) {
mCompositableBackendData->SetCompositor(mCompositor);
return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
}
return mTexture;
}

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

@ -45,8 +45,6 @@ public:
return LOCAL_GL_CLAMP_TO_EDGE;
}
virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE;
void DeallocateDeviceData();
gl::GLContext* gl() const;
@ -70,7 +68,6 @@ protected:
EGLImage mEGLImage;
GLuint mTexture;
gfx::SurfaceFormat mFormat;
bool mNeedsReset;
};
class GrallocTextureHostOGL : public TextureHost

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

@ -155,12 +155,10 @@ WrapMode(gl::GLContext *aGl, bool aAllowRepeat)
}
CompositableDataGonkOGL::CompositableDataGonkOGL()
: mTexture(0)
{
}
CompositableDataGonkOGL::~CompositableDataGonkOGL()
{
DeleteTextureIfPresent();
}
gl::GLContext*
@ -177,28 +175,6 @@ void CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor)
void CompositableDataGonkOGL::ClearData()
{
CompositableBackendSpecificData::ClearData();
DeleteTextureIfPresent();
}
GLuint CompositableDataGonkOGL::GetTexture()
{
if (!mTexture) {
if (gl()->MakeCurrent()) {
gl()->fGenTextures(1, &mTexture);
}
}
return mTexture;
}
void
CompositableDataGonkOGL::DeleteTextureIfPresent()
{
if (mTexture) {
if (gl()->MakeCurrent()) {
gl()->fDeleteTextures(1, &mTexture);
}
mTexture = 0;
}
}
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 17
@ -731,19 +707,6 @@ TextureImageDeprecatedTextureHostOGL::UpdateImpl(const SurfaceDescriptor& aImage
return;
}
#ifdef MOZ_WIDGET_GONK
if (mCompositableBackendData) {
// on gonk, this class is used as a fallback from gralloc buffer.
// There is a case this class is used with GrallocDeprecatedTextureHostOGL
// under same CompositableHost. if it happens, a gralloc buffer of
// GrallocDeprecatedTextureHostOGL needs to be unbounded from a texture,
// when the gralloc buffer is not rendered.
// Establish the unbound by deleting the texture.
// See Bug 916264.
static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->DeleteTextureIfPresent();
}
#endif
AutoOpenSurface surf(OPEN_READ_ONLY, aImage);
gfx::IntSize size = surf.Size();
TextureImage::ImageFormat format = surf.ImageFormat();
@ -1196,7 +1159,7 @@ GLuint
GrallocDeprecatedTextureHostOGL::GetGLTexture()
{
mCompositableBackendData->SetCompositor(mCompositor);
return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
return mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
}
#endif // MOZ_WIDGET_GONK

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

@ -72,12 +72,9 @@ public:
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual void ClearData() MOZ_OVERRIDE;
GLuint GetTexture();
void DeleteTextureIfPresent();
gl::GLContext* gl() const;
protected:
RefPtr<CompositorOGL> mCompositor;
GLuint mTexture;
};
/*

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

@ -54,10 +54,10 @@ class MockContentController : public GeckoContentController {
public:
MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration));
MOCK_METHOD3(HandleDoubleTap, void(const CSSIntPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleSingleTap, void(const CSSIntPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleLongTap, void(const CSSIntPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleLongTapUp, void(const CSSIntPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleDoubleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleSingleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleLongTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(HandleLongTapUp, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&));
MOCK_METHOD3(SendAsyncScrollDOMEvent, void(bool aIsRoot, const CSSRect &aContentRect, const CSSSize &aScrollableSize));
MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs));
};
@ -686,7 +686,7 @@ TEST_F(AsyncPanZoomControllerTester, OverScrollPanning) {
EXPECT_EQ(pointOut, ScreenPoint(0, 90));
}
TEST(AsyncPanZoomController, ShortPress) {
TEST_F(AsyncPanZoomControllerTester, ShortPress) {
nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
@ -704,13 +704,13 @@ TEST(AsyncPanZoomController, ShortPress) {
// touchdown is fully processed. The ordering here is important.
mcc->CheckHasDelayedTask();
EXPECT_CALL(*mcc, HandleSingleTap(CSSIntPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
mcc->RunDelayedTask();
apzc->Destroy();
}
TEST(AsyncPanZoomController, MediumPress) {
TEST_F(AsyncPanZoomControllerTester, MediumPress) {
nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
@ -728,7 +728,7 @@ TEST(AsyncPanZoomController, MediumPress) {
// touchdown is fully processed. The ordering here is important.
mcc->CheckHasDelayedTask();
EXPECT_CALL(*mcc, HandleSingleTap(CSSIntPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
mcc->RunDelayedTask();
apzc->Destroy();
@ -761,11 +761,11 @@ DoLongPressTest(bool aShouldUseTouchAction, uint32_t aBehavior) {
InSequence s;
EXPECT_CALL(check, Call("preHandleLongTap"));
EXPECT_CALL(*mcc, HandleLongTap(CSSIntPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
EXPECT_CALL(check, Call("preHandleLongTapUp"));
EXPECT_CALL(*mcc, HandleLongTapUp(CSSIntPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTapUp"));
}
@ -791,7 +791,7 @@ DoLongPressTest(bool aShouldUseTouchAction, uint32_t aBehavior) {
apzc->Destroy();
}
TEST(AsyncPanZoomController, LongPressPreventDefault) {
TEST_F(AsyncPanZoomControllerTester, LongPressPreventDefault) {
// We have to initialize both an integer time and TimeStamp time because
// TimeStamp doesn't have any ToXXX() functions for converting back to
// primitives.
@ -824,7 +824,7 @@ TEST(AsyncPanZoomController, LongPressPreventDefault) {
InSequence s;
EXPECT_CALL(check, Call("preHandleLongTap"));
EXPECT_CALL(*mcc, HandleLongTap(CSSIntPoint(touchX, touchStartY), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid())).Times(1);
EXPECT_CALL(check, Call("postHandleLongTap"));
}
@ -866,11 +866,11 @@ TEST(AsyncPanZoomController, LongPressPreventDefault) {
apzc->Destroy();
}
TEST(AsyncPanZoomController, LongPress) {
TEST_F(AsyncPanZoomControllerTester, LongPress) {
DoLongPressTest(false, mozilla::layers::AllowedTouchBehavior::NONE);
}
TEST(AsyncPanZoomController, LongPressPanAndZoom) {
TEST_F(AsyncPanZoomControllerTester, LongPressPanAndZoom) {
DoLongPressTest(true, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN
| mozilla::layers::AllowedTouchBehavior::ZOOM);

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

@ -178,6 +178,8 @@ private:
DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);
DECL_GFX_PREF(Live, "ui.click_hold_context_menus.delay", UiClickHoldContextMenusDelay, int32_t, 500);
DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false);
public:

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

@ -0,0 +1,39 @@
function testReduce() {
function sum(a, b) {
var r = a + b;
}
var array = build(8 * 0X0aaec , function() { return 1; });
var parResult = array.reducePar(sum);
}
for (var ix = 0; ix < 3; ++ix) {
testReduce();
}
function build(n, f) {
var result = [];
for (var i = 0; i < n; i++)
result.push(f(i));
return result;
}
function seq_scan(array, f) {
for (var i = 1; i < array.length; i++) {
}
}
function assertAlmostEq(v1, v2) {
if (e1 instanceof Array && e2 instanceof Array) {
for (prop in e1) {
if (e1.hasOwnProperty(prop)) { }
}
}
}
function assertEqArray(a, b) {
for (var i = 0, l = a.length; i < l; i++) {
try { } catch (e) { }
}
}
function assertParallelExecWillRecover(opFunction) {
assertParallelExecSucceeds(
function(m) {},
function(r) {}
);
}

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

@ -506,8 +506,9 @@ jit::FinishOffThreadBuilder(IonBuilder *builder)
{
ExecutionMode executionMode = builder->info().executionMode();
// Clear the recompiling flag if it would have failed.
if (builder->script()->hasIonScript())
// Clear the recompiling flag of the old ionScript, since we continue to
// use the old ionScript if recompiling fails.
if (executionMode == SequentialExecution && builder->script()->hasIonScript())
builder->script()->ionScript()->clearRecompiling();
// Clean up if compilation did not succeed.

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

@ -539,7 +539,7 @@ public:
}
}
virtual void HandleDoubleTap(const CSSIntPoint& aPoint,
virtual void HandleDoubleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
{
@ -558,7 +558,7 @@ public:
}
}
virtual void HandleSingleTap(const CSSIntPoint& aPoint,
virtual void HandleSingleTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
{
@ -577,7 +577,7 @@ public:
}
}
virtual void HandleLongTap(const CSSIntPoint& aPoint,
virtual void HandleLongTap(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
{
@ -596,7 +596,7 @@ public:
}
}
virtual void HandleLongTapUp(const CSSIntPoint& aPoint,
virtual void HandleLongTapUp(const CSSPoint& aPoint,
int32_t aModifiers,
const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
{

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

@ -141,7 +141,7 @@ HTTP(..) == bug533251.html bug533251-ref.html
HTTP(..) == font-familiy-whitespace-1.html font-familiy-whitespace-1-ref.html
HTTP(..) != font-familiy-whitespace-1.html font-familiy-whitespace-1-notref.html
skip-if(B2G) fails-if(Android) HTTP(..) == ivs-1.html ivs-1-ref.html # bug 773482
skip-if(B2G) HTTP(..) == ivs-1.html ivs-1-ref.html # bug 773482
skip-if(B2G) HTTP(..) == missing-names.html missing-names-ref.html # bug 773482

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

@ -20,6 +20,8 @@ css_properties.js: host_ListCSSProperties$(HOST_BIN_SUFFIX) css_properties_like_
./host_ListCSSProperties$(HOST_BIN_SUFFIX) > $@
cat $(srcdir)/css_properties_like_longhand.js >> $@
GARBAGE += css_properties.jsm
MOCHITEST_FILES += css_properties.js
GARBAGE += css_properties.js
TEST_FILES := css_properties.js
TEST_DEST = $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
INSTALL_TARGETS += TEST
endif

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

@ -1,4 +1,5 @@
[DEFAULT]
skip-if = buildapp == 'b2g'
[test_bug386386.html]
[test_bug394800.xhtml]

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

@ -827,17 +827,15 @@ pref("browser.snippets.syncPromo.enabled", true);
#ifdef MOZ_ANDROID_SYNTHAPKS
// The URL of the APK factory from which we obtain APKs for webapps.
// This currently points to the development server.
pref("browser.webapps.apkFactoryUrl", "http://dapk.net/application.apk");
pref("browser.webapps.apkFactoryUrl", "https://controller.apk.firefox.com/application.apk");
// How frequently to check for webapp updates, in seconds (86400 is daily).
pref("browser.webapps.updateInterval", 86400);
// The URL of the service that checks for updates.
// This currently points to the development server.
// To test updates, set this to http://apk-update-checker.paas.allizom.org,
// which is a test server that always reports all apps as having updates.
pref("browser.webapps.updateCheckUrl", "http://dapk.net/app_updates");
pref("browser.webapps.updateCheckUrl", "https://controller.apk.firefox.com/app_updates");
#endif
@ -848,3 +846,7 @@ pref("home.sync.updateMode", 0);
// How frequently to check if we should sync home provider data.
pref("home.sync.checkIntervalSecs", 3600);
#ifdef NIGHTLY_BUILD
pref("devtools.debugger.remote-enabled", true);
#endif

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

@ -42,7 +42,6 @@ import org.mozilla.gecko.home.SearchEngine;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.preferences.GeckoPreferences;
import org.mozilla.gecko.prompts.Prompt;
import org.mozilla.gecko.prompts.PromptListItem;
import org.mozilla.gecko.sync.setup.SyncAccounts;
import org.mozilla.gecko.toolbar.AutocompleteHandler;
import org.mozilla.gecko.toolbar.BrowserToolbar;
@ -1447,7 +1446,7 @@ abstract public class BrowserApp extends GeckoApp
// If we failed to load a favicon, we use the default favicon instead.
Tabs.getInstance()
.updateFaviconForURL(pageUrl,
(favicon == null) ? Favicons.sDefaultFavicon : favicon);
(favicon == null) ? Favicons.defaultFavicon : favicon);
}
};
@ -1694,16 +1693,22 @@ abstract public class BrowserApp extends GeckoApp
mHomePager = (HomePager) homePagerStub.inflate();
final HomeBanner homeBanner = (HomeBanner) findViewById(R.id.home_banner);
mHomePager.setBanner(homeBanner);
// Remove the banner from the view hierarchy if it is dismissed.
homeBanner.setOnDismissListener(new HomeBanner.OnDismissListener() {
@Override
public void onDismiss() {
mHomePager.setBanner(null);
mHomePagerContainer.removeView(homeBanner);
}
});
// Never show the home banner in guest mode.
if (GeckoProfile.get(this).inGuestMode()) {
mHomePagerContainer.removeView(homeBanner);
} else {
mHomePager.setBanner(homeBanner);
// Remove the banner from the view hierarchy if it is dismissed.
homeBanner.setOnDismissListener(new HomeBanner.OnDismissListener() {
@Override
public void onDismiss() {
mHomePager.setBanner(null);
mHomePagerContainer.removeView(homeBanner);
}
});
}
}
mHomePagerContainer.setVisibility(View.VISIBLE);

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

@ -1121,10 +1121,13 @@ public class GeckoAppShell
/**
* Given the inputs to <code>getOpenURIIntent</code>, plus an optional
* package name and class name, create and fire an intent to open the
* provided URI.
* provided URI. If a class name is specified but a package name is not,
* we will default to using the current fennec package.
*
* @param targetURI the string spec of the URI to open.
* @param mimeType an optional MIME type string.
* @param packageName an optional app package name.
* @param className an optional intent class name.
* @param action an Android action specifier, such as
* <code>Intent.ACTION_SEND</code>.
* @param title the title to use in <code>ACTION_SEND</code> intents.
@ -1145,8 +1148,13 @@ public class GeckoAppShell
return false;
}
if (packageName.length() > 0 && className.length() > 0) {
intent.setClassName(packageName, className);
if (!TextUtils.isEmpty(className)) {
if (!TextUtils.isEmpty(packageName)) {
intent.setClassName(packageName, className);
} else {
// Default to using the fennec app context.
intent.setClassName(context, className);
}
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

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

@ -13,7 +13,6 @@ import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.favicons.cache.FaviconCache;
import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.util.GeckoJarReader;
import org.mozilla.gecko.util.NonEvictingLruCache;
import org.mozilla.gecko.util.ThreadUtils;
@ -29,12 +28,9 @@ import android.util.SparseArray;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class Favicons {
private static final String LOGTAG = "GeckoFavicons";
@ -53,25 +49,25 @@ public class Favicons {
public static final int FLAG_PERSIST = 2;
public static final int FLAG_SCALE = 4;
protected static Context sContext;
protected static Context context;
// The default Favicon to show if no other can be found.
public static Bitmap sDefaultFavicon;
public static Bitmap defaultFavicon;
// The density-adjusted default Favicon dimensions.
public static int sDefaultFaviconSize;
public static int defaultFaviconSize;
// The density-adjusted maximum Favicon dimensions.
public static int sLargestFaviconSize;
public static int largestFaviconSize;
private static final SparseArray<LoadFaviconTask> sLoadTasks = new SparseArray<LoadFaviconTask>();
private static final SparseArray<LoadFaviconTask> loadTasks = new SparseArray<LoadFaviconTask>();
// Cache to hold mappings between page URLs and Favicon URLs. Used to avoid going to the DB when
// doing so is not necessary.
private static final NonEvictingLruCache<String, String> sPageURLMappings = new NonEvictingLruCache<String, String>(NUM_PAGE_URL_MAPPINGS_TO_STORE);
private static final NonEvictingLruCache<String, String> pageURLMappings = new NonEvictingLruCache<String, String>(NUM_PAGE_URL_MAPPINGS_TO_STORE);
public static String getFaviconURLForPageURLFromCache(String pageURL) {
return sPageURLMappings.get(pageURL);
return pageURLMappings.get(pageURL);
}
/**
@ -79,10 +75,10 @@ public class Favicons {
* Useful for short-circuiting local database access.
*/
public static void putFaviconURLForPageURLInCache(String pageURL, String faviconURL) {
sPageURLMappings.put(pageURL, faviconURL);
pageURLMappings.put(pageURL, faviconURL);
}
private static FaviconCache sFaviconsCache;
private static FaviconCache faviconsCache;
/**
* Returns either NOT_LOADING, or LOADED if the onFaviconLoaded call could
@ -117,7 +113,7 @@ public class Favicons {
* Returns null otherwise.
*/
public static Bitmap getSizedFaviconForPageFromCache(final String pageURL, int targetSize) {
final String faviconURL = sPageURLMappings.get(pageURL);
final String faviconURL = pageURLMappings.get(pageURL);
if (faviconURL == null) {
return null;
}
@ -143,7 +139,7 @@ public class Favicons {
// Do we know the favicon URL for this page already?
String cacheURL = faviconURL;
if (cacheURL == null) {
cacheURL = sPageURLMappings.get(pageURL);
cacheURL = pageURLMappings.get(pageURL);
}
// If there's no favicon URL given, try and hit the cache with the default one.
@ -153,7 +149,7 @@ public class Favicons {
// If it's something we can't even figure out a default URL for, just give up.
if (cacheURL == null) {
return dispatchResult(pageURL, null, sDefaultFavicon, listener);
return dispatchResult(pageURL, null, defaultFavicon, listener);
}
Bitmap cachedIcon = getSizedFaviconFromCache(cacheURL, targetSize);
@ -162,8 +158,8 @@ public class Favicons {
}
// Check if favicon has failed.
if (sFaviconsCache.isFailedFavicon(cacheURL)) {
return dispatchResult(pageURL, cacheURL, sDefaultFavicon, listener);
if (faviconsCache.isFailedFavicon(cacheURL)) {
return dispatchResult(pageURL, cacheURL, defaultFavicon, listener);
}
// Failing that, try and get one from the database or internet.
@ -181,7 +177,7 @@ public class Favicons {
* null if no applicable Favicon exists in the cache.
*/
public static Bitmap getSizedFaviconFromCache(String faviconURL, int targetSize) {
return sFaviconsCache.getFaviconForDimensions(faviconURL, targetSize);
return faviconsCache.getFaviconForDimensions(faviconURL, targetSize);
}
/**
@ -201,10 +197,10 @@ public class Favicons {
public static int getSizedFaviconForPageFromLocal(final String pageURL, final int targetSize, final OnFaviconLoadedListener callback) {
// Firstly, try extremely hard to cheat.
// Have we cached this favicon URL? If we did, we can consult the memcache right away.
String targetURL = sPageURLMappings.get(pageURL);
String targetURL = pageURLMappings.get(pageURL);
if (targetURL != null) {
// Check if favicon has failed.
if (sFaviconsCache.isFailedFavicon(targetURL)) {
if (faviconsCache.isFailedFavicon(targetURL)) {
return dispatchResult(pageURL, targetURL, null, callback);
}
@ -219,15 +215,15 @@ public class Favicons {
// No joy using in-memory resources. Go to background thread and ask the database.
LoadFaviconTask task = new LoadFaviconTask(ThreadUtils.getBackgroundHandler(), pageURL, targetURL, 0, callback, targetSize, true);
int taskId = task.getId();
synchronized(sLoadTasks) {
sLoadTasks.put(taskId, task);
synchronized(loadTasks) {
loadTasks.put(taskId, task);
}
task.execute();
return taskId;
}
public static int getSizedFaviconForPageFromLocal(final String pageURL, final OnFaviconLoadedListener callback) {
return getSizedFaviconForPageFromLocal(pageURL, sDefaultFaviconSize, callback);
return getSizedFaviconForPageFromLocal(pageURL, defaultFaviconSize, callback);
}
/**
@ -250,7 +246,7 @@ public class Favicons {
}
}
targetURL = BrowserDB.getFaviconUrlForHistoryUrl(sContext.getContentResolver(), pageURL);
targetURL = BrowserDB.getFaviconUrlForHistoryUrl(context.getContentResolver(), pageURL);
if (targetURL == null) {
// Nothing in the history database. Fall back to the default URL and hope for the best.
targetURL = guessDefaultFaviconURL(pageURL);
@ -286,8 +282,8 @@ public class Favicons {
LoadFaviconTask task = new LoadFaviconTask(ThreadUtils.getBackgroundHandler(), pageUrl, faviconUrl, flags, listener, targetSize, false);
int taskId = task.getId();
synchronized(sLoadTasks) {
sLoadTasks.put(taskId, task);
synchronized(loadTasks) {
loadTasks.put(taskId, task);
}
task.execute();
@ -296,7 +292,7 @@ public class Favicons {
}
public static void putFaviconInMemCache(String pageUrl, Bitmap image) {
sFaviconsCache.putSingleFavicon(pageUrl, image);
faviconsCache.putSingleFavicon(pageUrl, image);
}
/**
@ -308,7 +304,7 @@ public class Favicons {
* @param images An iterator over the new favicons to put in the cache.
*/
public static void putFaviconsInMemCache(String pageUrl, Iterator<Bitmap> images, boolean permanently) {
sFaviconsCache.putFavicons(pageUrl, images, permanently);
faviconsCache.putFavicons(pageUrl, images, permanently);
}
public static void putFaviconsInMemCache(String pageUrl, Iterator<Bitmap> images) {
@ -316,12 +312,12 @@ public class Favicons {
}
public static void clearMemCache() {
sFaviconsCache.evictAll();
sPageURLMappings.evictAll();
faviconsCache.evictAll();
pageURLMappings.evictAll();
}
public static void putFaviconInFailedCache(String faviconURL) {
sFaviconsCache.putFailed(faviconURL);
faviconsCache.putFailed(faviconURL);
}
public static boolean cancelFaviconLoad(int taskId) {
@ -330,13 +326,14 @@ public class Favicons {
}
boolean cancelled;
synchronized (sLoadTasks) {
if (sLoadTasks.indexOfKey(taskId) < 0)
synchronized (loadTasks) {
if (loadTasks.indexOfKey(taskId) < 0) {
return false;
}
Log.d(LOGTAG, "Cancelling favicon load (" + taskId + ")");
LoadFaviconTask task = sLoadTasks.get(taskId);
LoadFaviconTask task = loadTasks.get(taskId);
cancelled = task.cancel(false);
}
return cancelled;
@ -346,12 +343,12 @@ public class Favicons {
Log.d(LOGTAG, "Closing Favicons database");
// Cancel any pending tasks
synchronized (sLoadTasks) {
final int count = sLoadTasks.size();
synchronized (loadTasks) {
final int count = loadTasks.size();
for (int i = 0; i < count; i++) {
cancelFaviconLoad(sLoadTasks.keyAt(i));
cancelFaviconLoad(loadTasks.keyAt(i));
}
sLoadTasks.clear();
loadTasks.clear();
}
LoadFaviconTask.closeHTTPClient();
@ -364,7 +361,7 @@ public class Favicons {
* @return The dominant colour of the provided Favicon.
*/
public static int getFaviconColor(String url) {
return sFaviconsCache.getDominantColor(url);
return faviconsCache.getDominantColor(url);
}
/**
@ -376,24 +373,24 @@ public class Favicons {
*/
public static void attachToContext(Context context) throws Exception {
final Resources res = context.getResources();
sContext = context;
Favicons.context = context;
// Decode the default Favicon ready for use.
sDefaultFavicon = BitmapFactory.decodeResource(res, R.drawable.favicon);
if (sDefaultFavicon == null) {
defaultFavicon = BitmapFactory.decodeResource(res, R.drawable.favicon);
if (defaultFavicon == null) {
throw new Exception("Null default favicon was returned from the resources system!");
}
sDefaultFaviconSize = res.getDimensionPixelSize(R.dimen.favicon_bg);
defaultFaviconSize = res.getDimensionPixelSize(R.dimen.favicon_bg);
// Screen-density-adjusted upper limit on favicon size. Favicons larger than this are
// downscaled to this size or discarded.
sLargestFaviconSize = context.getResources().getDimensionPixelSize(R.dimen.favicon_largest_interesting_size);
sFaviconsCache = new FaviconCache(FAVICON_CACHE_SIZE_BYTES, sLargestFaviconSize);
largestFaviconSize = context.getResources().getDimensionPixelSize(R.dimen.favicon_largest_interesting_size);
faviconsCache = new FaviconCache(FAVICON_CACHE_SIZE_BYTES, largestFaviconSize);
// Initialize page mappings for each of our special pages.
for (String url : AboutPages.getDefaultIconPages()) {
sPageURLMappings.putWithoutEviction(url, BUILT_IN_FAVICON_URL);
pageURLMappings.putWithoutEviction(url, BUILT_IN_FAVICON_URL);
}
// Load and cache the built-in favicon in each of its sizes.
@ -453,8 +450,8 @@ public class Favicons {
}
public static void removeLoadTask(int taskId) {
synchronized(sLoadTasks) {
sLoadTasks.delete(taskId);
synchronized(loadTasks) {
loadTasks.delete(taskId);
}
}
@ -464,7 +461,7 @@ public class Favicons {
* @param faviconURL Favicon URL to check for failure.
*/
static boolean isFailedFavicon(String faviconURL) {
return sFaviconsCache.isFailedFavicon(faviconURL);
return faviconsCache.isFailedFavicon(faviconURL);
}
/**

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

@ -22,7 +22,7 @@ import org.mozilla.gecko.favicons.decoders.LoadFaviconResult;
import org.mozilla.gecko.util.GeckoJarReader;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UiAsyncTask;
import static org.mozilla.gecko.favicons.Favicons.sContext;
import static org.mozilla.gecko.favicons.Favicons.context;
import java.io.IOException;
import java.io.InputStream;
@ -53,21 +53,21 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
// by the server.
private static final int DEFAULT_FAVICON_BUFFER_SIZE = 25000;
private static AtomicInteger mNextFaviconLoadId = new AtomicInteger(0);
private int mId;
private String mPageUrl;
private String mFaviconUrl;
private OnFaviconLoadedListener mListener;
private int mFlags;
private static AtomicInteger nextFaviconLoadId = new AtomicInteger(0);
private int id;
private String pageUrl;
private String faviconURL;
private OnFaviconLoadedListener listener;
private int flags;
private final boolean mOnlyFromLocal;
private final boolean onlyFromLocal;
// Assuming square favicons, judging by width only is acceptable.
protected int mTargetWidth;
private LinkedList<LoadFaviconTask> mChainees;
private boolean mIsChaining;
protected int targetWidth;
private LinkedList<LoadFaviconTask> chainees;
private boolean isChaining;
static AndroidHttpClient sHttpClient = AndroidHttpClient.newInstance(GeckoAppShell.getGeckoInterface().getDefaultUAString());
static AndroidHttpClient httpClient = AndroidHttpClient.newInstance(GeckoAppShell.getGeckoInterface().getDefaultUAString());
public LoadFaviconTask(Handler backgroundThreadHandler,
String pageUrl, String faviconUrl, int flags,
@ -76,33 +76,33 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
}
public LoadFaviconTask(Handler backgroundThreadHandler,
String pageUrl, String faviconUrl, int flags,
OnFaviconLoadedListener aListener, int targetSize, boolean fromLocal) {
OnFaviconLoadedListener listener, int targetWidth, boolean onlyFromLocal) {
super(backgroundThreadHandler);
mId = mNextFaviconLoadId.incrementAndGet();
id = nextFaviconLoadId.incrementAndGet();
mPageUrl = pageUrl;
mFaviconUrl = faviconUrl;
mListener = aListener;
mFlags = flags;
mTargetWidth = targetSize;
mOnlyFromLocal = fromLocal;
this.pageUrl = pageUrl;
this.faviconURL = faviconUrl;
this.listener = listener;
this.flags = flags;
this.targetWidth = targetWidth;
this.onlyFromLocal = onlyFromLocal;
}
// Runs in background thread
private LoadFaviconResult loadFaviconFromDb() {
ContentResolver resolver = sContext.getContentResolver();
return BrowserDB.getFaviconForFaviconUrl(resolver, mFaviconUrl);
ContentResolver resolver = context.getContentResolver();
return BrowserDB.getFaviconForFaviconUrl(resolver, faviconURL);
}
// Runs in background thread
private void saveFaviconToDb(final byte[] encodedFavicon) {
if ((mFlags & FLAG_PERSIST) == 0) {
if ((flags & FLAG_PERSIST) == 0) {
return;
}
ContentResolver resolver = sContext.getContentResolver();
BrowserDB.updateFaviconForUrl(resolver, mPageUrl, encodedFavicon, mFaviconUrl);
ContentResolver resolver = context.getContentResolver();
BrowserDB.updateFaviconForUrl(resolver, pageUrl, encodedFavicon, faviconURL);
}
/**
@ -121,7 +121,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
}
HttpGet request = new HttpGet(faviconURI);
HttpResponse response = sHttpClient.execute(request);
HttpResponse response = httpClient.execute(request);
if (response == null) {
return null;
}
@ -172,7 +172,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
if (uri.startsWith("jar:jar:")) {
Log.d(LOGTAG, "Fetching favicon from JAR.");
try {
return GeckoJarReader.getBitmap(sContext.getResources(), uri);
return GeckoJarReader.getBitmap(context.getResources(), uri);
} catch (Exception e) {
// Just about anything could happen here.
Log.w(LOGTAG, "Error fetching favicon from JAR.", e);
@ -287,27 +287,27 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
// Handle the case of malformed favicon URL.
// If favicon is empty, fall back to the stored one.
if (TextUtils.isEmpty(mFaviconUrl)) {
if (TextUtils.isEmpty(faviconURL)) {
// Try to get the favicon URL from the memory cache.
storedFaviconUrl = Favicons.getFaviconURLForPageURLFromCache(mPageUrl);
storedFaviconUrl = Favicons.getFaviconURLForPageURLFromCache(pageUrl);
// If that failed, try to get the URL from the database.
if (storedFaviconUrl == null) {
storedFaviconUrl = Favicons.getFaviconURLForPageURL(mPageUrl);
storedFaviconUrl = Favicons.getFaviconURLForPageURL(pageUrl);
if (storedFaviconUrl != null) {
// If that succeeded, cache the URL loaded from the database in memory.
Favicons.putFaviconURLForPageURLInCache(mPageUrl, storedFaviconUrl);
Favicons.putFaviconURLForPageURLInCache(pageUrl, storedFaviconUrl);
}
}
// If we found a faviconURL - use it.
if (storedFaviconUrl != null) {
mFaviconUrl = storedFaviconUrl;
faviconURL = storedFaviconUrl;
} else {
// If we don't have a stored one, fall back to the default.
mFaviconUrl = Favicons.guessDefaultFaviconURL(mPageUrl);
faviconURL = Favicons.guessDefaultFaviconURL(pageUrl);
if (TextUtils.isEmpty(mFaviconUrl)) {
if (TextUtils.isEmpty(faviconURL)) {
return null;
}
isUsingDefaultURL = true;
@ -316,7 +316,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
// Check if favicon has failed - if so, give up. We need this check because, sometimes, we
// didn't know the real Favicon URL until we asked the database.
if (Favicons.isFailedFavicon(mFaviconUrl)) {
if (Favicons.isFailedFavicon(faviconURL)) {
return null;
}
@ -329,10 +329,10 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
// If there is, just join the queue and wait for it to finish. If not, we carry on.
synchronized(loadsInFlight) {
// Another load of the current Favicon is already underway
LoadFaviconTask existingTask = loadsInFlight.get(mFaviconUrl);
LoadFaviconTask existingTask = loadsInFlight.get(faviconURL);
if (existingTask != null && !existingTask.isCancelled()) {
existingTask.chainTasks(this);
mIsChaining = true;
isChaining = true;
// If we are chaining, we want to keep the first task started to do this job as the one
// in the hashmap so subsequent tasks will add themselves to its chaining list.
@ -341,7 +341,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
// We do not want to update the hashmap if the task has chained - other tasks need to
// chain onto the same parent task.
loadsInFlight.put(mFaviconUrl, this);
loadsInFlight.put(faviconURL, this);
}
if (isCancelled()) {
@ -354,20 +354,20 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
return pushToCacheAndGetResult(loadedBitmaps);
}
if (mOnlyFromLocal || isCancelled()) {
if (onlyFromLocal || isCancelled()) {
return null;
}
// Let's see if it's in a JAR.
image = fetchJARFavicon(mFaviconUrl);
image = fetchJARFavicon(faviconURL);
if (imageIsValid(image)) {
// We don't want to put this into the DB.
Favicons.putFaviconInMemCache(mFaviconUrl, image);
Favicons.putFaviconInMemCache(faviconURL, image);
return image;
}
try {
loadedBitmaps = downloadFavicon(new URI(mFaviconUrl));
loadedBitmaps = downloadFavicon(new URI(faviconURL));
} catch (URISyntaxException e) {
Log.e(LOGTAG, "The provided favicon URL is not valid");
return null;
@ -381,7 +381,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
}
if (isUsingDefaultURL) {
Favicons.putFaviconInFailedCache(mFaviconUrl);
Favicons.putFaviconInFailedCache(faviconURL);
return null;
}
@ -390,16 +390,16 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
}
// If we're not already trying the default URL, try it now.
final String guessed = Favicons.guessDefaultFaviconURL(mPageUrl);
final String guessed = Favicons.guessDefaultFaviconURL(pageUrl);
if (guessed == null) {
Favicons.putFaviconInFailedCache(mFaviconUrl);
Favicons.putFaviconInFailedCache(faviconURL);
return null;
}
image = fetchJARFavicon(guessed);
if (imageIsValid(image)) {
// We don't want to put this into the DB.
Favicons.putFaviconInMemCache(mFaviconUrl, image);
Favicons.putFaviconInMemCache(faviconURL, image);
return image;
}
@ -428,8 +428,8 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
* we are under extreme memory pressure and find ourselves dropping the cache immediately.
*/
private Bitmap pushToCacheAndGetResult(LoadFaviconResult loadedBitmaps) {
Favicons.putFaviconsInMemCache(mFaviconUrl, loadedBitmaps.getBitmaps());
Bitmap result = Favicons.getSizedFaviconFromCache(mFaviconUrl, mTargetWidth);
Favicons.putFaviconsInMemCache(faviconURL, loadedBitmaps.getBitmaps());
Bitmap result = Favicons.getSizedFaviconFromCache(faviconURL, targetWidth);
return result;
}
@ -441,7 +441,7 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
@Override
protected void onPostExecute(Bitmap image) {
if (mIsChaining) {
if (isChaining) {
return;
}
@ -450,10 +450,10 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
synchronized (loadsInFlight) {
// Prevent any other tasks from chaining on this one.
loadsInFlight.remove(mFaviconUrl);
loadsInFlight.remove(faviconURL);
}
// Since any update to mChainees is done while holding the loadsInFlight lock, once we reach
// Since any update to chainees is done while holding the loadsInFlight lock, once we reach
// this point no further updates to that list can possibly take place (As far as other tasks
// are concerned, there is no longer a task to chain from. The above block will have waited
// for any tasks that were adding themselves to the list before reaching this point.)
@ -463,8 +463,8 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
// actually happens outside of the strange situations unit tests create.
// Share the result with all chained tasks.
if (mChainees != null) {
for (LoadFaviconTask t : mChainees) {
if (chainees != null) {
for (LoadFaviconTask t : chainees) {
// In the case that we just decoded multiple favicons, either we're passing the right
// image now, or the call into the cache in processResult will fetch the right one.
t.processResult(image);
@ -473,35 +473,35 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
}
private void processResult(Bitmap image) {
Favicons.removeLoadTask(mId);
Favicons.removeLoadTask(id);
Bitmap scaled = image;
// Notify listeners, scaling if required.
if (mTargetWidth != -1 && image != null && image.getWidth() != mTargetWidth) {
scaled = Favicons.getSizedFaviconFromCache(mFaviconUrl, mTargetWidth);
if (targetWidth != -1 && image != null && image.getWidth() != targetWidth) {
scaled = Favicons.getSizedFaviconFromCache(faviconURL, targetWidth);
}
Favicons.dispatchResult(mPageUrl, mFaviconUrl, scaled, mListener);
Favicons.dispatchResult(pageUrl, faviconURL, scaled, listener);
}
@Override
protected void onCancelled() {
Favicons.removeLoadTask(mId);
Favicons.removeLoadTask(id);
synchronized(loadsInFlight) {
// Only remove from the hashmap if the task there is the one that's being canceled.
// Cancellation of a task that would have chained is not interesting to the hashmap.
final LoadFaviconTask primary = loadsInFlight.get(mFaviconUrl);
final LoadFaviconTask primary = loadsInFlight.get(faviconURL);
if (primary == this) {
loadsInFlight.remove(mFaviconUrl);
loadsInFlight.remove(faviconURL);
return;
}
if (primary == null) {
// This shouldn't happen.
return;
}
if (primary.mChainees != null) {
primary.mChainees.remove(this);
if (primary.chainees != null) {
primary.chainees.remove(this);
}
}
@ -518,15 +518,15 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
* @param aChainee LoadFaviconTask
*/
private void chainTasks(LoadFaviconTask aChainee) {
if (mChainees == null) {
mChainees = new LinkedList<LoadFaviconTask>();
if (chainees == null) {
chainees = new LinkedList<LoadFaviconTask>();
}
mChainees.add(aChainee);
chainees.add(aChainee);
}
int getId() {
return mId;
return id;
}
static void closeHTTPClient() {
@ -534,8 +534,8 @@ public class LoadFaviconTask extends UiAsyncTask<Void, Void, Bitmap> {
// the connection pool, which typically involves closing a connection --
// which counts as network activity.
if (ThreadUtils.isOnBackgroundThread()) {
if (sHttpClient != null) {
sHttpClient.close();
if (httpClient != null) {
httpClient.close();
}
return;
}

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

@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* When a favicon at a particular URL is decoded, it will yield one or more bitmaps.
* While in memory, these bitmaps are stored in a list, sorted in ascending order of size, in a
* FaviconsForURL object.
* The collection of FaviconsForURL objects currently in the cache is stored in mBackingMap, keyed
* The collection of FaviconsForURL objects currently in the cache is stored in backingMap, keyed
* by favicon URL.
*
* A second map exists for permanent cache entries -- ones that are never expired. These entries
@ -59,7 +59,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* as well as the bitmap, a pointer to the encapsulating FaviconsForURL object (Used by the LRU
* culler), the size of the encapsulated image, a flag indicating if this is a primary favicon, and
* a flag indicating if the entry is invalid.
* All FaviconCacheElement objects are tracked in the mOrdering LinkedList. This is used to record
* All FaviconCacheElement objects are tracked in the ordering LinkedList. This is used to record
* LRU information about FaviconCacheElements. In particular, the most recently used FaviconCacheElement
* will be at the start of the list, the least recently used at the end of the list.
*
@ -98,7 +98,7 @@ public class FaviconCache {
private static final int NUM_FAVICON_SIZES = 4;
// Dimensions of the largest favicon to store in the cache. Everything is downscaled to this.
public final int mMaxCachedWidth;
public final int maxCachedWidth;
// Retry failed favicons after 20 minutes.
public static final long FAILURE_RETRY_MILLISECONDS = 1000 * 60 * 20;
@ -107,16 +107,16 @@ public class FaviconCache {
// Since favicons may be container formats holding multiple icons, the underlying type holds a
// sorted list of bitmap payloads in ascending order of size. The underlying type may be queried
// for the least larger payload currently present.
private final ConcurrentHashMap<String, FaviconsForURL> mBackingMap = new ConcurrentHashMap<String, FaviconsForURL>();
private final ConcurrentHashMap<String, FaviconsForURL> backingMap = new ConcurrentHashMap<String, FaviconsForURL>();
// And the same, but never evicted.
private final ConcurrentHashMap<String, FaviconsForURL> mPermanentBackingMap = new ConcurrentHashMap<String, FaviconsForURL>();
private final ConcurrentHashMap<String, FaviconsForURL> permanentBackingMap = new ConcurrentHashMap<String, FaviconsForURL>();
// A linked list used to implement a queue, defining the LRU properties of the cache. Elements
// contained within the various FaviconsForURL objects are held here, the least recently used
// of which at the end of the list. When space needs to be reclaimed, the appropriate bitmap is
// culled.
private final LinkedList<FaviconCacheElement> mOrdering = new LinkedList<FaviconCacheElement>();
private final LinkedList<FaviconCacheElement> ordering = new LinkedList<FaviconCacheElement>();
// The above structures, if used correctly, enable this cache to exhibit LRU semantics across all
// favicon payloads in the system, as well as enabling the dynamic selection from the cache of
@ -124,60 +124,48 @@ public class FaviconCache {
// are provided by the underlying file format).
// Current size, in bytes, of the bitmap data present in the LRU cache.
private final AtomicInteger mCurrentSize = new AtomicInteger(0);
private final AtomicInteger currentSize = new AtomicInteger(0);
// The maximum quantity, in bytes, of bitmap data which may be stored in the cache.
private final int mMaxSizeBytes;
private final int maxSizeBytes;
// Tracks the number of ongoing read operations. Enables the first one in to lock writers out and
// the last one out to let them in.
private final AtomicInteger mOngoingReads = new AtomicInteger(0);
private final AtomicInteger ongoingReads = new AtomicInteger(0);
// Used to ensure transaction fairness - each txn acquires and releases this as the first operation.
// The effect is an orderly, inexpensive ordering enforced on txns to prevent writer starvation.
private final Semaphore mTurnSemaphore = new Semaphore(1);
private final Semaphore turnSemaphore = new Semaphore(1);
// A deviation from the usual MRSW solution - this semaphore is used to guard modification to the
// ordering map. This allows for read transactions to update the most-recently-used value without
// needing to take out the write lock.
private final Semaphore mReorderingSemaphore = new Semaphore(1);
private final Semaphore reorderingSemaphore = new Semaphore(1);
// The semaphore one must acquire in order to perform a write.
private final Semaphore mWriteLock = new Semaphore(1);
private final Semaphore writeLock = new Semaphore(1);
/**
* Called by txns performing only reads as they start. Prevents writer starvation with a turn
* semaphore and locks writers out if this is the first concurrent reader txn starting up.
*/
private void startRead() {
mTurnSemaphore.acquireUninterruptibly();
mTurnSemaphore.release();
turnSemaphore.acquireUninterruptibly();
turnSemaphore.release();
if (mOngoingReads.incrementAndGet() == 1) {
if (ongoingReads.incrementAndGet() == 1) {
// First one in. Wait for writers to finish and lock them out.
mWriteLock.acquireUninterruptibly();
writeLock.acquireUninterruptibly();
}
}
/**
* An alternative to startWrite to be used when in a read transaction and wanting to upgrade it
* to a write transaction. Such a transaction should be terminated with finishWrite.
*/
private void upgradeReadToWrite() {
mTurnSemaphore.acquireUninterruptibly();
if (mOngoingReads.decrementAndGet() == 0) {
mWriteLock.release();
}
mWriteLock.acquireUninterruptibly();
}
/**
* Called by transactions performing only reads as they finish. Ensures that if this is the last
* concluding read transaction then then writers are subsequently allowed in.
*/
private void finishRead() {
if (mOngoingReads.decrementAndGet() == 0) {
mWriteLock.release();
if (ongoingReads.decrementAndGet() == 0) {
writeLock.release();
}
}
@ -186,21 +174,21 @@ public class FaviconCache {
* Upon return, no other txns will be executing concurrently.
*/
private void startWrite() {
mTurnSemaphore.acquireUninterruptibly();
mWriteLock.acquireUninterruptibly();
turnSemaphore.acquireUninterruptibly();
writeLock.acquireUninterruptibly();
}
/**
* Called by a concluding write transaction - unlocks the structure.
*/
private void finishWrite() {
mTurnSemaphore.release();
mWriteLock.release();
turnSemaphore.release();
writeLock.release();
}
public FaviconCache(int maxSize, int maxWidthToCache) {
mMaxSizeBytes = maxSize;
mMaxCachedWidth = maxWidthToCache;
maxSizeBytes = maxSize;
maxCachedWidth = maxWidthToCache;
}
/**
@ -217,57 +205,42 @@ public class FaviconCache {
startRead();
boolean isExpired = false;
boolean isAborting = false;
try {
// If we don't have it in the cache, it certainly isn't a known failure.
// Non-evictable favicons are never failed, so we don't need to
// check mPermanentBackingMap.
if (!mBackingMap.containsKey(faviconURL)) {
// check permanentBackingMap.
if (!backingMap.containsKey(faviconURL)) {
return false;
}
FaviconsForURL container = mBackingMap.get(faviconURL);
FaviconsForURL container = backingMap.get(faviconURL);
// If the has failed flag is not set, it's certainly not a known failure.
if (!container.mHasFailed) {
if (!container.hasFailed) {
return false;
}
final long failureTimestamp = container.mDownloadTimestamp;
final long failureTimestamp = container.downloadTimestamp;
// Calculate elapsed time since the failing download.
final long failureDiff = System.currentTimeMillis() - failureTimestamp;
// If long enough has passed, mark it as no longer a failure.
if (failureDiff > FAILURE_RETRY_MILLISECONDS) {
isExpired = true;
} else {
// If the expiry is still in effect, return. Otherwise, continue and unmark the failure.
if (failureDiff < FAILURE_RETRY_MILLISECONDS) {
return true;
}
} catch (Exception unhandled) {
// Handle any exception thrown and return the locks to a sensible state.
finishRead();
// Flag to prevent finally from doubly-unlocking.
isAborting = true;
Log.e(LOGTAG, "FaviconCache exception!", unhandled);
return true;
} finally {
if (!isAborting) {
if (isExpired) {
// No longer expired.
upgradeReadToWrite();
} else {
finishRead();
}
}
finishRead();
}
startWrite();
// If the entry is no longer failed, remove the record of it from the cache.
try {
recordRemoved(mBackingMap.get(faviconURL));
mBackingMap.remove(faviconURL);
recordRemoved(backingMap.remove(faviconURL));
return false;
} finally {
finishWrite();
@ -282,14 +255,12 @@ public class FaviconCache {
public void putFailed(String faviconURL) {
startWrite();
if (mBackingMap.containsKey(faviconURL)) {
recordRemoved(mBackingMap.get(faviconURL));
try {
FaviconsForURL container = new FaviconsForURL(0, true);
recordRemoved(backingMap.put(faviconURL, container));
} finally {
finishWrite();
}
FaviconsForURL container = new FaviconsForURL(0, true);
mBackingMap.put(faviconURL, container);
finishWrite();
}
/**
@ -309,9 +280,7 @@ public class FaviconCache {
return null;
}
boolean doingWrites = false;
boolean shouldComputeColour = false;
boolean isAborting = false;
boolean wasPermanent = false;
FaviconsForURL container;
final Bitmap newBitmap;
@ -319,9 +288,9 @@ public class FaviconCache {
startRead();
try {
container = mPermanentBackingMap.get(faviconURL);
container = permanentBackingMap.get(faviconURL);
if (container == null) {
container = mBackingMap.get(faviconURL);
container = backingMap.get(faviconURL);
if (container == null) {
// We don't have it!
return null;
@ -338,22 +307,22 @@ public class FaviconCache {
// cacheElementIndex now holds either the index of the next least largest bitmap from
// targetSize, or -1 if targetSize > all bitmaps.
if (cacheElementIndex != -1) {
// If cacheElementIndex is not the sentinel value, then it is a valid index into mFavicons.
cacheElement = container.mFavicons.get(cacheElementIndex);
// If cacheElementIndex is not the sentinel value, then it is a valid index into favicons.
cacheElement = container.favicons.get(cacheElementIndex);
if (cacheElement.mInvalidated) {
if (cacheElement.invalidated) {
return null;
}
// If we found exactly what we wanted - we're done.
if (cacheElement.mImageSize == targetSize) {
setMostRecentlyUsed(cacheElement);
return cacheElement.mFaviconPayload;
if (cacheElement.imageSize == targetSize) {
setMostRecentlyUsedWithinRead(cacheElement);
return cacheElement.faviconPayload;
}
} else {
// We requested an image larger than all primaries. Set the element to start the search
// from to the element beyond the end of the array, so the search runs backwards.
cacheElementIndex = container.mFavicons.size();
cacheElementIndex = container.favicons.size();
}
// We did not find exactly what we wanted, but now have set cacheElementIndex to the index
@ -370,17 +339,12 @@ public class FaviconCache {
if (targetSize == -1) {
// We got the biggest primary, so that's what we'll return.
return cacheElement.mFaviconPayload;
return cacheElement.faviconPayload;
}
// Having got this far, we'll be needing to write the new secondary to the cache, which
// involves us falling through to the next try block. This flag lets us do this (Other
// paths prior to this end in returns.)
doingWrites = true;
// Scaling logic...
Bitmap largestElementBitmap = cacheElement.mFaviconPayload;
int largestSize = cacheElement.mImageSize;
Bitmap largestElementBitmap = cacheElement.faviconPayload;
int largestSize = cacheElement.imageSize;
if (largestSize >= targetSize) {
// The largest we have is larger than the target - downsize to target.
@ -401,24 +365,16 @@ public class FaviconCache {
}
}
} catch (Exception unhandled) {
isAborting = true;
// Handle any exception thrown and return the locks to a sensible state.
finishRead();
// Flag to prevent finally from doubly-unlocking.
Log.e(LOGTAG, "FaviconCache exception!", unhandled);
return null;
} finally {
if (!isAborting) {
if (doingWrites) {
upgradeReadToWrite();
} else {
finishRead();
}
}
finishRead();
}
startWrite();
try {
if (shouldComputeColour) {
// And since we failed, we'll need the dominant colour.
@ -432,8 +388,9 @@ public class FaviconCache {
FaviconCacheElement newElement = container.addSecondary(newBitmap, targetSize);
if (!wasPermanent) {
setMostRecentlyUsed(newElement);
mCurrentSize.addAndGet(newElement.sizeOf());
if (setMostRecentlyUsedWithinWrite(newElement)) {
currentSize.addAndGet(newElement.sizeOf());
}
}
} finally {
finishWrite();
@ -452,19 +409,18 @@ public class FaviconCache {
startRead();
try {
FaviconsForURL element = mPermanentBackingMap.get(key);
FaviconsForURL element = permanentBackingMap.get(key);
if (element == null) {
element = mBackingMap.get(key);
element = backingMap.get(key);
}
if (element == null) {
Log.w(LOGTAG, "Cannot compute dominant color of non-cached favicon. Cache fullness " +
mCurrentSize.get() + '/' + mMaxSizeBytes);
currentSize.get() + '/' + maxSizeBytes);
finishRead();
return 0xFFFFFF;
}
return element.ensureDominantColor();
} finally {
finishRead();
@ -472,8 +428,8 @@ public class FaviconCache {
}
/**
* Remove all payloads stored in the given container from the LRU cache. Must be called while
* holding the write lock.
* Remove all payloads stored in the given container from the LRU cache.
* Must be called while holding the write lock.
*
* @param wasRemoved The container to purge from the cache.
*/
@ -485,40 +441,59 @@ public class FaviconCache {
int sizeRemoved = 0;
for (FaviconCacheElement e : wasRemoved.mFavicons) {
for (FaviconCacheElement e : wasRemoved.favicons) {
sizeRemoved += e.sizeOf();
mOrdering.remove(e);
ordering.remove(e);
}
mCurrentSize.addAndGet(-sizeRemoved);
currentSize.addAndGet(-sizeRemoved);
}
private Bitmap produceCacheableBitmap(Bitmap favicon) {
// Never cache the default Favicon, or the null Favicon.
if (favicon == Favicons.sDefaultFavicon || favicon == null) {
if (favicon == Favicons.defaultFavicon || favicon == null) {
return null;
}
// Some sites serve up insanely huge Favicons (Seen 512x512 ones...)
// While we want to cache nice big icons, we apply a limit based on screen density for the
// sake of space.
if (favicon.getWidth() > mMaxCachedWidth) {
return Bitmap.createScaledBitmap(favicon, mMaxCachedWidth, mMaxCachedWidth, true);
if (favicon.getWidth() > maxCachedWidth) {
return Bitmap.createScaledBitmap(favicon, maxCachedWidth, maxCachedWidth, true);
}
return favicon;
}
/**
* Set an existing element as the most recently used element. May be called from either type of
* transaction.
* Set an existing element as the most recently used element. Intended for use from read transactions. While
* write transactions may safely use this method, it will perform slightly worse than its unsafe counterpart below.
*
* @param element The element that is to become the most recently used one.
* @return true if this element already existed in the list, false otherwise. (Useful for preventing multiple-insertion.)
*/
private void setMostRecentlyUsed(FaviconCacheElement element) {
mReorderingSemaphore.acquireUninterruptibly();
mOrdering.remove(element);
mOrdering.offer(element);
mReorderingSemaphore.release();
private boolean setMostRecentlyUsedWithinRead(FaviconCacheElement element) {
reorderingSemaphore.acquireUninterruptibly();
try {
boolean contained = ordering.remove(element);
ordering.offer(element);
return contained;
} finally {
reorderingSemaphore.release();
}
}
/**
* Functionally equivalent to setMostRecentlyUsedWithinRead, but operates without taking the reordering semaphore.
* Only safe for use when called from a write transaction, or there is a risk of concurrent modification.
*
* @param element The element that is to become the most recently used one.
* @return true if this element already existed in the list, false otherwise. (Useful for preventing multiple-insertion.)
*/
private boolean setMostRecentlyUsedWithinWrite(FaviconCacheElement element) {
boolean contained = ordering.remove(element);
ordering.offer(element);
return contained;
}
/**
@ -546,13 +521,13 @@ public class FaviconCache {
startWrite();
try {
// Set the new element as the most recently used one.
setMostRecentlyUsed(newElement);
setMostRecentlyUsedWithinWrite(newElement);
mCurrentSize.addAndGet(newElement.sizeOf());
currentSize.addAndGet(newElement.sizeOf());
// Update the value in the LruCache...
FaviconsForURL wasRemoved;
wasRemoved = mBackingMap.put(faviconURL, toInsert);
wasRemoved = backingMap.put(faviconURL, toInsert);
recordRemoved(wasRemoved);
} finally {
@ -584,42 +559,23 @@ public class FaviconCache {
sizeGained += newElement.sizeOf();
}
startRead();
boolean abortingRead = false;
// Not using setMostRecentlyUsed, because the elements are known to be new. This can be done
// without taking the write lock, via the magic of the reordering semaphore.
mReorderingSemaphore.acquireUninterruptibly();
try {
if (!permanently) {
for (FaviconCacheElement newElement : toInsert.mFavicons) {
mOrdering.offer(newElement);
}
}
} catch (Exception e) {
abortingRead = true;
mReorderingSemaphore.release();
finishRead();
Log.e(LOGTAG, "Favicon cache exception!", e);
return;
} finally {
if (!abortingRead) {
mReorderingSemaphore.release();
upgradeReadToWrite();
}
}
startWrite();
try {
if (permanently) {
mPermanentBackingMap.put(faviconURL, toInsert);
} else {
mCurrentSize.addAndGet(sizeGained);
// Update the value in the LruCache...
recordRemoved(mBackingMap.put(faviconURL, toInsert));
permanentBackingMap.put(faviconURL, toInsert);
return;
}
for (FaviconCacheElement newElement : toInsert.favicons) {
setMostRecentlyUsedWithinWrite(newElement);
}
// In the event this insertion is being made to a key that already held a value, the subsequent recordRemoved
// call will subtract the size of the old value, preventing double-counting.
currentSize.addAndGet(sizeGained);
// Update the value in the LruCache...
recordRemoved(backingMap.put(faviconURL, toInsert));
} finally {
finishWrite();
}
@ -632,24 +588,24 @@ public class FaviconCache {
* Otherwise, do nothing.
*/
private void cullIfRequired() {
Log.d(LOGTAG, "Favicon cache fullness: " + mCurrentSize.get() + '/' + mMaxSizeBytes);
Log.d(LOGTAG, "Favicon cache fullness: " + currentSize.get() + '/' + maxSizeBytes);
if (mCurrentSize.get() <= mMaxSizeBytes) {
if (currentSize.get() <= maxSizeBytes) {
return;
}
startWrite();
try {
while (mCurrentSize.get() > mMaxSizeBytes) {
while (currentSize.get() > maxSizeBytes) {
// Cull the least recently used element.
FaviconCacheElement victim;
victim = mOrdering.poll();
victim = ordering.poll();
mCurrentSize.addAndGet(-victim.sizeOf());
currentSize.addAndGet(-victim.sizeOf());
victim.onEvictedFromCache();
Log.d(LOGTAG, "After cull: " + mCurrentSize.get() + '/' + mMaxSizeBytes);
Log.d(LOGTAG, "After cull: " + currentSize.get() + '/' + maxSizeBytes);
}
} finally {
finishWrite();
@ -664,9 +620,9 @@ public class FaviconCache {
// Note that we neither clear, nor track the size of, the permanent map.
try {
mCurrentSize.set(0);
mBackingMap.clear();
mOrdering.clear();
currentSize.set(0);
backingMap.clear();
ordering.clear();
} finally {
finishWrite();

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

@ -12,49 +12,49 @@ import android.graphics.Bitmap;
*/
public class FaviconCacheElement implements Comparable<FaviconCacheElement> {
// Was this Favicon computed via scaling another primary Favicon, or is this a primary Favicon?
final boolean mIsPrimary;
final boolean isPrimary;
// The Favicon bitmap.
Bitmap mFaviconPayload;
Bitmap faviconPayload;
// If set, mFaviconPayload is absent. Since the underlying ICO may contain multiple primary
// If set, faviconPayload is absent. Since the underlying ICO may contain multiple primary
// payloads, primary payloads are never truly deleted from the cache, but instead have their
// payload deleted and this flag set on their FaviconCacheElement. That way, the cache always
// has a record of the existence of a primary payload, even if it is no longer in the cache.
// This means that when a request comes in that will be best served using a primary that is in
// the database but no longer cached, we know that it exists and can go get it (Useful when ICO
// support is added).
volatile boolean mInvalidated;
volatile boolean invalidated;
final int mImageSize;
final int imageSize;
// Used for LRU pruning.
final FaviconsForURL mBackpointer;
final FaviconsForURL backpointer;
public FaviconCacheElement(Bitmap payload, boolean isPrimary, int imageSize, FaviconsForURL backpointer) {
mFaviconPayload = payload;
mIsPrimary = isPrimary;
mImageSize = imageSize;
mBackpointer = backpointer;
public FaviconCacheElement(Bitmap payload, boolean primary, int size, FaviconsForURL backpointer) {
this.faviconPayload = payload;
this.isPrimary = primary;
this.imageSize = size;
this.backpointer = backpointer;
}
public FaviconCacheElement(Bitmap payload, boolean isPrimary, FaviconsForURL backpointer) {
mFaviconPayload = payload;
mIsPrimary = isPrimary;
mBackpointer = backpointer;
public FaviconCacheElement(Bitmap faviconPayload, boolean isPrimary, FaviconsForURL backpointer) {
this.faviconPayload = faviconPayload;
this.isPrimary = isPrimary;
this.backpointer = backpointer;
if (payload != null) {
mImageSize = payload.getWidth();
if (faviconPayload != null) {
imageSize = faviconPayload.getWidth();
} else {
mImageSize = 0;
imageSize = 0;
}
}
public int sizeOf() {
if (mInvalidated) {
if (invalidated) {
return 0;
}
return mFaviconPayload.getRowBytes() * mFaviconPayload.getHeight();
return faviconPayload.getRowBytes() * faviconPayload.getHeight();
}
/**
@ -68,20 +68,20 @@ public class FaviconCacheElement implements Comparable<FaviconCacheElement> {
*/
@Override
public int compareTo(FaviconCacheElement another) {
if (mInvalidated && !another.mInvalidated) {
if (invalidated && !another.invalidated) {
return -1;
}
if (!mInvalidated && another.mInvalidated) {
if (!invalidated && another.invalidated) {
return 1;
}
if (mInvalidated) {
if (invalidated) {
return 0;
}
final int w1 = mImageSize;
final int w2 = another.mImageSize;
final int w1 = imageSize;
final int w2 = another.imageSize;
if (w1 > w2) {
return 1;
} else if (w2 > w1) {
@ -96,20 +96,20 @@ public class FaviconCacheElement implements Comparable<FaviconCacheElement> {
* If primary, drop the payload and set invalid. If secondary, just unlink from parent node.
*/
public void onEvictedFromCache() {
if (mIsPrimary) {
if (isPrimary) {
// So we keep a record of which primaries exist in the database for this URL, we
// don't actually delete the entry for primaries. Instead, we delete their payload
// and flag them as invalid. This way, we can later figure out that what a request
// really want is one of the primaries that have been dropped from the cache, and we
// can go get it.
mInvalidated = true;
mFaviconPayload = null;
invalidated = true;
faviconPayload = null;
} else {
// Secondaries don't matter - just delete them.
if (mBackpointer == null) {
if (backpointer == null) {
return;
}
mBackpointer.mFavicons.remove(this);
backpointer.favicons.remove(this);
}
}
}

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

@ -14,21 +14,21 @@ import java.util.Collections;
public class FaviconsForURL {
private static final String LOGTAG = "FaviconForURL";
private volatile int mDominantColor = -1;
private volatile int dominantColor = -1;
final long mDownloadTimestamp;
final ArrayList<FaviconCacheElement> mFavicons;
final long downloadTimestamp;
final ArrayList<FaviconCacheElement> favicons;
public final boolean mHasFailed;
public final boolean hasFailed;
public FaviconsForURL(int size) {
this(size, false);
}
public FaviconsForURL(int size, boolean hasFailed) {
mHasFailed = hasFailed;
mDownloadTimestamp = System.currentTimeMillis();
mFavicons = new ArrayList<FaviconCacheElement>(size);
public FaviconsForURL(int size, boolean failed) {
hasFailed = failed;
downloadTimestamp = System.currentTimeMillis();
favicons = new ArrayList<FaviconCacheElement>(size);
}
public FaviconCacheElement addSecondary(Bitmap favicon, int imageSize) {
@ -42,15 +42,19 @@ public class FaviconsForURL {
private FaviconCacheElement addInternal(Bitmap favicon, boolean isPrimary, int imageSize) {
FaviconCacheElement c = new FaviconCacheElement(favicon, isPrimary, imageSize, this);
int index = Collections.binarySearch(mFavicons, c);
int index = Collections.binarySearch(favicons, c);
// We've already got an equivalent one. We don't care about this new one. This only occurs in certain obscure
// case conditions.
if (index >= 0) {
return favicons.get(index);
}
// binarySearch returns -x - 1 where x is the insertion point of the element. Convert
// this to the actual insertion point..
if (index < 0) {
index++;
index = -index;
}
mFavicons.add(index, c);
index++;
index = -index;
favicons.add(index, c);
return c;
}
@ -66,7 +70,7 @@ public class FaviconsForURL {
// Create a dummy object to hold the target value for comparable.
FaviconCacheElement dummy = new FaviconCacheElement(null, false, targetSize, null);
int index = Collections.binarySearch(mFavicons, dummy);
int index = Collections.binarySearch(favicons, dummy);
// The search routine returns the index of an element equal to dummy, if present.
// Otherwise, it returns -x - 1, where x is the index in the ArrayList where dummy would be
@ -78,11 +82,11 @@ public class FaviconsForURL {
// index is now 'x', as described above.
// The routine will return mFavicons.size() as the index iff dummy is larger than all elements
// The routine will return favicons.size() as the index iff dummy is larger than all elements
// present (So the "index at which it should be inserted" is the index after the end.
// In this case, we set the sentinel value -1 to indicate that we just requested something
// larger than all primaries.
if (index == mFavicons.size()) {
if (index == favicons.size()) {
index = -1;
}
@ -97,19 +101,19 @@ public class FaviconsForURL {
* primary at all (The input index may be a secondary which is larger than the actual available
* primary.)
*
* @param fromIndex The index into mFavicons from which to start the search.
* @param fromIndex The index into favicons from which to start the search.
* @return The FaviconCacheElement of the next valid primary from the given index. If none exists,
* then returns the previous valid primary. If none exists, returns null (Insanity.).
*/
public FaviconCacheElement getNextPrimary(final int fromIndex) {
final int numIcons = mFavicons.size();
final int numIcons = favicons.size();
int searchIndex = fromIndex;
while (searchIndex < numIcons) {
FaviconCacheElement element = mFavicons.get(searchIndex);
FaviconCacheElement element = favicons.get(searchIndex);
if (element.mIsPrimary) {
if (element.mInvalidated) {
if (element.isPrimary) {
if (element.invalidated) {
// We return null here, despite the possible existence of other primaries,
// because we know the most suitable primary for this request exists, but is
// no longer in the cache. By returning null, we cause the caller to load the
@ -124,10 +128,10 @@ public class FaviconsForURL {
// No larger primary available. Let's look for smaller ones...
searchIndex = fromIndex - 1;
while (searchIndex >= 0) {
FaviconCacheElement element = mFavicons.get(searchIndex);
FaviconCacheElement element = favicons.get(searchIndex);
if (element.mIsPrimary) {
if (element.mInvalidated) {
if (element.isPrimary) {
if (element.invalidated) {
return null;
}
return element;
@ -144,17 +148,17 @@ public class FaviconsForURL {
* Ensure the dominant colour field is populated for this favicon.
*/
public int ensureDominantColor() {
if (mDominantColor == -1) {
if (dominantColor == -1) {
// Find a payload, any payload, that is not invalidated.
for (FaviconCacheElement element : mFavicons) {
if (!element.mInvalidated) {
mDominantColor = BitmapUtils.getDominantColor(element.mFaviconPayload);
return mDominantColor;
for (FaviconCacheElement element : favicons) {
if (!element.invalidated) {
dominantColor = BitmapUtils.getDominantColor(element.faviconPayload);
return dominantColor;
}
}
mDominantColor = 0xFFFFFF;
dominantColor = 0xFFFFFF;
}
return mDominantColor;
return dominantColor;
}
}

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

@ -89,14 +89,14 @@ public class FaviconDecoder {
LoadFaviconResult result;
if (isDecodableByAndroid(buffer, offset)) {
result = new LoadFaviconResult();
result.mOffset = offset;
result.mLength = length;
result.mIsICO = false;
result.offset = offset;
result.length = length;
result.isICO = false;
// We assume here that decodeByteArray doesn't hold on to the entire supplied
// buffer -- worst case, each of our buffers will be twice the necessary size.
result.mBitmapsDecoded = new SingleBitmapIterator(BitmapUtils.decodeByteArray(buffer, offset, length));
result.mFaviconBytes = buffer;
result.bitmapsDecoded = new SingleBitmapIterator(BitmapUtils.decodeByteArray(buffer, offset, length));
result.faviconBytes = buffer;
return result;
}
@ -193,10 +193,10 @@ public class FaviconDecoder {
* Iterator to hold a single bitmap.
*/
static class SingleBitmapIterator implements Iterator<Bitmap> {
private Bitmap mBitmap;
private Bitmap bitmap;
public SingleBitmapIterator(Bitmap b) {
mBitmap = b;
bitmap = b;
}
/**
@ -207,22 +207,22 @@ public class FaviconDecoder {
* @return The bitmap carried by this SingleBitmapIterator.
*/
public Bitmap peek() {
return mBitmap;
return bitmap;
}
@Override
public boolean hasNext() {
return mBitmap != null;
return bitmap != null;
}
@Override
public Bitmap next() {
if (mBitmap == null) {
if (bitmap == null) {
throw new NoSuchElementException("Element already returned from SingleBitmapIterator.");
}
Bitmap ret = mBitmap;
mBitmap = null;
Bitmap ret = bitmap;
bitmap = null;
return ret;
}

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

@ -10,7 +10,6 @@ import org.mozilla.gecko.gfx.BitmapUtils;
import android.util.SparseArray;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
@ -79,55 +78,55 @@ public class ICODecoder implements Iterable<Bitmap> {
public static final int ICO_ICONDIRENTRY_LENGTH_BYTES = 16;
// The buffer containing bytes to attempt to decode.
private byte[] mDecodand;
private byte[] decodand;
// The region of the decodand to decode.
private int mOffset;
private int mLen;
private int offset;
private int len;
private IconDirectoryEntry[] mIconDirectory;
private boolean mIsValid;
private boolean mHasDecoded;
private IconDirectoryEntry[] iconDirectory;
private boolean isValid;
private boolean hasDecoded;
public ICODecoder(byte[] buffer, int offset, int len) {
mDecodand = buffer;
mOffset = offset;
mLen = len;
public ICODecoder(byte[] decodand, int offset, int len) {
this.decodand = decodand;
this.offset = offset;
this.len = len;
}
/**
* Decode the Icon Directory for this ICO and store the result in mIconDirectory.
* Decode the Icon Directory for this ICO and store the result in iconDirectory.
*
* @return true if ICO decoding was considered to probably be a success, false if it certainly
* was a failure.
*/
private boolean decodeIconDirectoryAndPossiblyPrune() {
mHasDecoded = true;
hasDecoded = true;
// Fail if the end of the described range is out of bounds.
if (mOffset + mLen > mDecodand.length) {
if (offset + len > decodand.length) {
return false;
}
// Fail if we don't have enough space for the header.
if (mLen < ICO_HEADER_LENGTH_BYTES) {
if (len < ICO_HEADER_LENGTH_BYTES) {
return false;
}
// Check that the reserved fields in the header are indeed zero, and that the type field
// specifies ICO. If not, we've probably been given something that isn't really an ICO.
if (mDecodand[mOffset] != 0 ||
mDecodand[mOffset + 1] != 0 ||
mDecodand[mOffset + 2] != 1 ||
mDecodand[mOffset + 3] != 0) {
if (decodand[offset] != 0 ||
decodand[offset + 1] != 0 ||
decodand[offset + 2] != 1 ||
decodand[offset + 3] != 0) {
return false;
}
// Here, and in many other places, byte values are ANDed with 0xFF. This is because Java
// bytes are signed - to obtain a numerical value of a longer type which holds the unsigned
// interpretation of the byte of interest, we do this.
int numEncodedImages = (mDecodand[mOffset + 4] & 0xFF) |
(mDecodand[mOffset + 5] & 0xFF) << 8;
int numEncodedImages = (decodand[offset + 4] & 0xFF) |
(decodand[offset + 5] & 0xFF) << 8;
// Fail if there are no images or the field is corrupt.
@ -139,12 +138,12 @@ public class ICODecoder implements Iterable<Bitmap> {
// Fail if there is not enough space in the buffer for the stated number of icondir entries,
// let alone the data.
if (mLen < headerAndDirectorySize) {
if (len < headerAndDirectorySize) {
return false;
}
// Put the pointer on the first byte of the first Icon Directory Entry.
int bufferIndex = mOffset + ICO_HEADER_LENGTH_BYTES;
int bufferIndex = offset + ICO_HEADER_LENGTH_BYTES;
// We now iterate over the Icon Directory, decoding each entry as we go. We also need to
// discard all entries except one >= the maximum interesting size.
@ -157,35 +156,35 @@ public class ICODecoder implements Iterable<Bitmap> {
for (int i = 0; i < numEncodedImages; i++, bufferIndex += ICO_ICONDIRENTRY_LENGTH_BYTES) {
// Decode the Icon Directory Entry at this offset.
IconDirectoryEntry newEntry = IconDirectoryEntry.createFromBuffer(mDecodand, mOffset, mLen, bufferIndex);
newEntry.mIndex = i;
IconDirectoryEntry newEntry = IconDirectoryEntry.createFromBuffer(decodand, offset, len, bufferIndex);
newEntry.index = i;
if (newEntry.mIsErroneous) {
if (newEntry.isErroneous) {
continue;
}
if (newEntry.mWidth > Favicons.sLargestFaviconSize) {
if (newEntry.width > Favicons.largestFaviconSize) {
// If we already have a smaller image larger than the maximum size of interest, we
// don't care about the new one which is larger than the smallest image larger than
// the maximum size.
if (newEntry.mWidth >= minimumMaximum) {
if (newEntry.width >= minimumMaximum) {
continue;
}
// Remove the previous minimum-maximum.
preferenceArray.delete(minimumMaximum);
minimumMaximum = newEntry.mWidth;
minimumMaximum = newEntry.width;
}
IconDirectoryEntry oldEntry = preferenceArray.get(newEntry.mWidth);
IconDirectoryEntry oldEntry = preferenceArray.get(newEntry.width);
if (oldEntry == null) {
preferenceArray.put(newEntry.mWidth, newEntry);
preferenceArray.put(newEntry.width, newEntry);
continue;
}
if (oldEntry.compareTo(newEntry) < 0) {
preferenceArray.put(newEntry.mWidth, newEntry);
preferenceArray.put(newEntry.width, newEntry);
}
}
@ -197,24 +196,24 @@ public class ICODecoder implements Iterable<Bitmap> {
}
// Allocate space for the icon directory entries in the decoded directory.
mIconDirectory = new IconDirectoryEntry[count];
iconDirectory = new IconDirectoryEntry[count];
// The size of the data in the buffer that we find useful.
int retainedSpace = ICO_HEADER_LENGTH_BYTES;
for (int i = 0; i < count; i++) {
IconDirectoryEntry e = preferenceArray.valueAt(i);
retainedSpace += ICO_ICONDIRENTRY_LENGTH_BYTES + e.mPayloadSize;
mIconDirectory[i] = e;
retainedSpace += ICO_ICONDIRENTRY_LENGTH_BYTES + e.payloadSize;
iconDirectory[i] = e;
}
mIsValid = true;
isValid = true;
// Set the number of images field in the buffer to reflect the number of retained entries.
mDecodand[mOffset + 4] = (byte) mIconDirectory.length;
mDecodand[mOffset + 5] = (byte) (mIconDirectory.length >>> 8);
decodand[offset + 4] = (byte) iconDirectory.length;
decodand[offset + 5] = (byte) (iconDirectory.length >>> 8);
if ((mLen - retainedSpace) > COMPACT_THRESHOLD) {
if ((len - retainedSpace) > COMPACT_THRESHOLD) {
compactingCopy(retainedSpace);
}
@ -228,19 +227,19 @@ public class ICODecoder implements Iterable<Bitmap> {
byte[] buf = new byte[spaceRetained];
// Copy the header.
System.arraycopy(mDecodand, mOffset, buf, 0, ICO_HEADER_LENGTH_BYTES);
System.arraycopy(decodand, offset, buf, 0, ICO_HEADER_LENGTH_BYTES);
int headerPtr = ICO_HEADER_LENGTH_BYTES;
int payloadPtr = ICO_HEADER_LENGTH_BYTES + (mIconDirectory.length * ICO_ICONDIRENTRY_LENGTH_BYTES);
int payloadPtr = ICO_HEADER_LENGTH_BYTES + (iconDirectory.length * ICO_ICONDIRENTRY_LENGTH_BYTES);
int ind = 0;
for (IconDirectoryEntry entry : mIconDirectory) {
for (IconDirectoryEntry entry : iconDirectory) {
// Copy this entry.
System.arraycopy(mDecodand, mOffset + entry.getOffset(), buf, headerPtr, ICO_ICONDIRENTRY_LENGTH_BYTES);
System.arraycopy(decodand, offset + entry.getOffset(), buf, headerPtr, ICO_ICONDIRENTRY_LENGTH_BYTES);
// Copy its payload.
System.arraycopy(mDecodand, mOffset + entry.mPayloadOffset, buf, payloadPtr, entry.mPayloadSize);
System.arraycopy(decodand, offset + entry.payloadOffset, buf, payloadPtr, entry.payloadSize);
// Update the offset field.
buf[headerPtr + 12] = (byte) payloadPtr;
@ -248,17 +247,17 @@ public class ICODecoder implements Iterable<Bitmap> {
buf[headerPtr + 14] = (byte) (payloadPtr >>> 16);
buf[headerPtr + 15] = (byte) (payloadPtr >>> 24);
entry.mPayloadOffset = payloadPtr;
entry.mIndex = ind;
entry.payloadOffset = payloadPtr;
entry.index = ind;
payloadPtr += entry.mPayloadSize;
payloadPtr += entry.payloadSize;
headerPtr += ICO_ICONDIRENTRY_LENGTH_BYTES;
ind++;
}
mDecodand = buf;
mOffset = 0;
mLen = spaceRetained;
decodand = buf;
offset = 0;
len = spaceRetained;
}
/**
@ -269,16 +268,16 @@ public class ICODecoder implements Iterable<Bitmap> {
* fails.
*/
public Bitmap decodeBitmapAtIndex(int index) {
final IconDirectoryEntry iconDirEntry = mIconDirectory[index];
final IconDirectoryEntry iconDirEntry = iconDirectory[index];
if (iconDirEntry.mPayloadIsPNG) {
if (iconDirEntry.payloadIsPNG) {
// PNG payload. Simply extract it and decode it.
return BitmapUtils.decodeByteArray(mDecodand, mOffset + iconDirEntry.mPayloadOffset, iconDirEntry.mPayloadSize);
return BitmapUtils.decodeByteArray(decodand, offset + iconDirEntry.payloadOffset, iconDirEntry.payloadSize);
}
// The payload is a BMP, so we need to do some magic to get the decoder to do what we want.
// We construct an ICO containing just the image we want, and let Android do the rest.
byte[] decodeTarget = new byte[ICO_HEADER_LENGTH_BYTES + ICO_ICONDIRENTRY_LENGTH_BYTES + iconDirEntry.mPayloadSize];
byte[] decodeTarget = new byte[ICO_HEADER_LENGTH_BYTES + ICO_ICONDIRENTRY_LENGTH_BYTES + iconDirEntry.payloadSize];
// Set the type field in the ICO header.
decodeTarget[2] = 1;
@ -287,11 +286,11 @@ public class ICODecoder implements Iterable<Bitmap> {
decodeTarget[4] = 1;
// Copy the ICONDIRENTRY we need into the new buffer.
System.arraycopy(mDecodand, mOffset + iconDirEntry.getOffset(), decodeTarget, ICO_HEADER_LENGTH_BYTES, ICO_ICONDIRENTRY_LENGTH_BYTES);
System.arraycopy(decodand, offset + iconDirEntry.getOffset(), decodeTarget, ICO_HEADER_LENGTH_BYTES, ICO_ICONDIRENTRY_LENGTH_BYTES);
// Copy the payload into the new buffer.
final int singlePayloadOffset = ICO_HEADER_LENGTH_BYTES + ICO_ICONDIRENTRY_LENGTH_BYTES;
System.arraycopy(mDecodand, mOffset + iconDirEntry.mPayloadOffset, decodeTarget, singlePayloadOffset, iconDirEntry.mPayloadSize);
System.arraycopy(decodand, offset + iconDirEntry.payloadOffset, decodeTarget, singlePayloadOffset, iconDirEntry.payloadSize);
// Update the offset field of the ICONDIRENTRY to make the new ICO valid.
decodeTarget[ICO_HEADER_LENGTH_BYTES + 12] = (byte) singlePayloadOffset;
@ -311,12 +310,12 @@ public class ICODecoder implements Iterable<Bitmap> {
@Override
public ICOIterator iterator() {
// If a previous call to decode concluded this ICO is invalid, abort.
if (mHasDecoded && !mIsValid) {
if (hasDecoded && !isValid) {
return null;
}
// If we've not been decoded before, but now fail to make any sense of the ICO, abort.
if (!mHasDecoded) {
if (!hasDecoded) {
if (!decodeIconDirectoryAndPossiblyPrune()) {
return null;
}
@ -339,11 +338,11 @@ public class ICODecoder implements Iterable<Bitmap> {
LoadFaviconResult result = new LoadFaviconResult();
result.mBitmapsDecoded = bitmaps;
result.mFaviconBytes = mDecodand;
result.mOffset = mOffset;
result.mLength = mLen;
result.mIsICO = true;
result.bitmapsDecoded = bitmaps;
result.faviconBytes = decodand;
result.offset = offset;
result.length = len;
result.isICO = true;
return result;
}
@ -356,12 +355,12 @@ public class ICODecoder implements Iterable<Bitmap> {
@Override
public boolean hasNext() {
return mIndex < mIconDirectory.length;
return mIndex < iconDirectory.length;
}
@Override
public Bitmap next() {
if (mIndex > mIconDirectory.length) {
if (mIndex > iconDirectory.length) {
throw new NoSuchElementException("No more elements in this ICO.");
}
return decodeBitmapAtIndex(mIndex++);
@ -369,10 +368,10 @@ public class ICODecoder implements Iterable<Bitmap> {
@Override
public void remove() {
if (mIconDirectory[mIndex] == null) {
if (iconDirectory[mIndex] == null) {
throw new IllegalStateException("Remove already called for element " + mIndex);
}
mIconDirectory[mIndex] = null;
iconDirectory[mIndex] = null;
}
}
}

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

@ -9,28 +9,28 @@ package org.mozilla.gecko.favicons.decoders;
*/
public class IconDirectoryEntry implements Comparable<IconDirectoryEntry> {
public static int sMaxBPP;
public static int maxBPP;
int mWidth;
int mHeight;
int mPaletteSize;
int mBitsPerPixel;
int mPayloadSize;
int mPayloadOffset;
boolean mPayloadIsPNG;
int width;
int height;
int paletteSize;
int bitsPerPixel;
int payloadSize;
int payloadOffset;
boolean payloadIsPNG;
// Tracks the index in the Icon Directory of this entry. Useful only for pruning.
int mIndex;
boolean mIsErroneous;
int index;
boolean isErroneous;
public IconDirectoryEntry(int width, int height, int paletteSize, int bitsPerPixel, int payloadSize, int payloadOffset, boolean payloadIsPNG) {
mWidth = width;
mHeight = height;
mPaletteSize = paletteSize;
mBitsPerPixel = bitsPerPixel;
mPayloadSize = payloadSize;
mPayloadOffset = payloadOffset;
mPayloadIsPNG = payloadIsPNG;
this.width = width;
this.height = height;
this.paletteSize = paletteSize;
this.bitsPerPixel = bitsPerPixel;
this.payloadSize = payloadSize;
this.payloadOffset = payloadOffset;
this.payloadIsPNG = payloadIsPNG;
}
/**
@ -40,7 +40,7 @@ public class IconDirectoryEntry implements Comparable<IconDirectoryEntry> {
*/
public static IconDirectoryEntry getErroneousEntry() {
IconDirectoryEntry ret = new IconDirectoryEntry(-1, -1, -1, -1, -1, -1, false);
ret.mIsErroneous = true;
ret.isErroneous = true;
return ret;
}
@ -118,63 +118,63 @@ public class IconDirectoryEntry implements Comparable<IconDirectoryEntry> {
* Get the number of bytes from the start of the ICO file to the beginning of this entry.
*/
public int getOffset() {
return ICODecoder.ICO_HEADER_LENGTH_BYTES + (mIndex * ICODecoder.ICO_ICONDIRENTRY_LENGTH_BYTES);
return ICODecoder.ICO_HEADER_LENGTH_BYTES + (index * ICODecoder.ICO_ICONDIRENTRY_LENGTH_BYTES);
}
@Override
public int compareTo(IconDirectoryEntry another) {
if (mWidth > another.mWidth) {
if (width > another.width) {
return 1;
}
if (mWidth < another.mWidth) {
if (width < another.width) {
return -1;
}
// Where both images exceed the max BPP, take the smaller of the two BPP values.
if (mBitsPerPixel >= sMaxBPP && another.mBitsPerPixel >= sMaxBPP) {
if (mBitsPerPixel < another.mBitsPerPixel) {
if (bitsPerPixel >= maxBPP && another.bitsPerPixel >= maxBPP) {
if (bitsPerPixel < another.bitsPerPixel) {
return 1;
}
if (mBitsPerPixel > another.mBitsPerPixel) {
if (bitsPerPixel > another.bitsPerPixel) {
return -1;
}
}
// Otherwise, take the larger of the BPP values.
if (mBitsPerPixel > another.mBitsPerPixel) {
if (bitsPerPixel > another.bitsPerPixel) {
return 1;
}
if (mBitsPerPixel < another.mBitsPerPixel) {
if (bitsPerPixel < another.bitsPerPixel) {
return -1;
}
// Prefer large palettes.
if (mPaletteSize > another.mPaletteSize) {
if (paletteSize > another.paletteSize) {
return 1;
}
if (mPaletteSize < another.mPaletteSize) {
if (paletteSize < another.paletteSize) {
return -1;
}
// Prefer smaller payloads.
if (mPayloadSize < another.mPayloadSize) {
if (payloadSize < another.payloadSize) {
return 1;
}
if (mPayloadSize > another.mPayloadSize) {
if (payloadSize > another.payloadSize) {
return -1;
}
// If all else fails, prefer PNGs over BMPs. They tend to be smaller.
if (mPayloadIsPNG && !another.mPayloadIsPNG) {
if (payloadIsPNG && !another.payloadIsPNG) {
return 1;
}
if (!mPayloadIsPNG && another.mPayloadIsPNG) {
if (!payloadIsPNG && another.payloadIsPNG) {
return -1;
}
@ -182,20 +182,20 @@ public class IconDirectoryEntry implements Comparable<IconDirectoryEntry> {
}
public static void setMaxBPP(int maxBPP) {
sMaxBPP = maxBPP;
IconDirectoryEntry.maxBPP = maxBPP;
}
@Override
public String toString() {
return "IconDirectoryEntry{" +
"\nmWidth=" + mWidth +
", \nmHeight=" + mHeight +
", \nmPaletteSize=" + mPaletteSize +
", \nmBitsPerPixel=" + mBitsPerPixel +
", \nmPayloadSize=" + mPayloadSize +
", \nmPayloadOffset=" + mPayloadOffset +
", \nmPayloadIsPNG=" + mPayloadIsPNG +
", \nmIndex=" + mIndex +
"\nwidth=" + width +
", \nheight=" + height +
", \npaletteSize=" + paletteSize +
", \nbitsPerPixel=" + bitsPerPixel +
", \npayloadSize=" + payloadSize +
", \npayloadOffset=" + payloadOffset +
", \npayloadIsPNG=" + payloadIsPNG +
", \nindex=" + index +
'}';
}
}

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

@ -21,15 +21,15 @@ import java.util.Iterator;
public class LoadFaviconResult {
private static final String LOGTAG = "LoadFaviconResult";
byte[] mFaviconBytes;
int mOffset;
int mLength;
byte[] faviconBytes;
int offset;
int length;
boolean mIsICO;
Iterator<Bitmap> mBitmapsDecoded;
boolean isICO;
Iterator<Bitmap> bitmapsDecoded;
public Iterator<Bitmap> getBitmaps() {
return mBitmapsDecoded;
return bitmapsDecoded;
}
/**
@ -40,17 +40,17 @@ public class LoadFaviconResult {
*/
public byte[] getBytesForDatabaseStorage() {
// Begin by normalising the buffer.
if (mOffset != 0 || mLength != mFaviconBytes.length) {
final byte[] normalised = new byte[mLength];
System.arraycopy(mFaviconBytes, mOffset, normalised, 0, mLength);
mOffset = 0;
mFaviconBytes = normalised;
if (offset != 0 || length != faviconBytes.length) {
final byte[] normalised = new byte[length];
System.arraycopy(faviconBytes, offset, normalised, 0, length);
offset = 0;
faviconBytes = normalised;
}
// For results containing a single image, we re-encode the result as a PNG in an effort to
// save space.
if (!mIsICO) {
Bitmap favicon = ((FaviconDecoder.SingleBitmapIterator) mBitmapsDecoded).peek();
if (!isICO) {
Bitmap favicon = ((FaviconDecoder.SingleBitmapIterator) bitmapsDecoded).peek();
byte[] data = null;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
@ -68,7 +68,7 @@ public class LoadFaviconResult {
// We may instead want to consider re-encoding the entire ICO as a collection of efficiently
// encoded PNGs. This may not be worth the CPU time (Indeed, the encoding of single-image
// favicons may also not be worth the time/space tradeoff.).
return mFaviconBytes;
return faviconBytes;
}
}

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

@ -568,7 +568,7 @@ public class BrowserSearch extends HomeFragment
mSuggestionsOptInPrompt = ((ViewStub) mView.findViewById(R.id.suggestions_opt_in_prompt)).inflate();
TextView promptText = (TextView) mSuggestionsOptInPrompt.findViewById(R.id.suggestions_prompt_title);
promptText.setText(getResources().getString(R.string.suggestions_prompt, mSearchEngines.get(0).name));
promptText.setText(getResources().getString(R.string.suggestions_prompt));
final View yesButton = mSuggestionsOptInPrompt.findViewById(R.id.suggestions_prompt_yes);
final View noButton = mSuggestionsOptInPrompt.findViewById(R.id.suggestions_prompt_no);

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

@ -378,9 +378,7 @@ just addresses the organization to follow, e.g. "This site is run by " -->
from Android">
<!ENTITY bookmarkhistory_import_wait "Please wait...">
<!-- Localization note (suggestions_prompt2): The placeholder &formatS; will be
replaced with the name of the search engine. -->
<!ENTITY suggestions_prompt2 "Would you like to turn on &formatS; search suggestions?">
<!ENTITY suggestions_prompt3 "Would you like to turn on search suggestions?">
<!-- Localization note (suggestion_for_engine): The placeholder &formatS1; will be
replaced with the name of the search engine. The placeholder &formatS2; will be

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

@ -133,13 +133,13 @@ public class SearchEnginePreference extends CustomListPreference {
if (mFaviconView != null) {
desiredWidth = mFaviconView.getWidth();
} else {
// sLargestFaviconSize is initialized when Favicons is attached to a
// largestFaviconSize is initialized when Favicons is attached to a
// context, which occurs during GeckoApp.onCreate. That might not
// ever happen (leaving it at 0), so we fall back.
if (Favicons.sLargestFaviconSize == 0) {
if (Favicons.largestFaviconSize == 0) {
desiredWidth = 128;
} else {
desiredWidth = Favicons.sLargestFaviconSize;
desiredWidth = Favicons.largestFaviconSize;
}
}

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

@ -370,7 +370,7 @@
<string name="updater_apply_select">&updater_apply_select2;</string>
<!-- Search suggestions opt-in -->
<string name="suggestions_prompt">&suggestions_prompt2;</string>
<string name="suggestions_prompt">&suggestions_prompt3;</string>
<string name="suggestion_for_engine">&suggestion_for_engine;</string>

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

@ -70,8 +70,6 @@ skip-if = processor == "x86"
[testPasswordProvider]
# [testPermissions] # see bug 757475
[testPictureLinkContextMenu]
# disabled on Android 2.3; bug 979612
skip-if = android_version == "10"
[testPrefsObserver]
[testPrivateBrowsing]
[testPromptGridInput]

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

@ -13,6 +13,7 @@ Cu.import("resource://gre/modules/Task.jsm");
const TEST_DATASET_ID = "test-dataset-id";
const TEST_URL = "http://test.com";
const TEST_TITLE = "Test";
const PREF_SYNC_CHECK_INTERVAL_SECS = "home.sync.checkIntervalSecs";
const TEST_INTERVAL_SECS = 1;
@ -47,7 +48,7 @@ add_test(function test_periodic_sync() {
add_task(function test_save_and_delete() {
// Use the HomeProvider API to save some data.
let storage = HomeProvider.getStorage(TEST_DATASET_ID);
yield storage.save([{ url: TEST_URL }]);
yield storage.save([{ title: TEST_TITLE, url: TEST_URL }]);
// Peek in the DB to make sure we have the right data.
let db = yield Sqlite.openConnection({ path: DB_PATH });
@ -71,4 +72,61 @@ add_task(function test_save_and_delete() {
db.close();
});
add_task(function test_row_validation() {
// Use the HomeProvider API to save some data.
let storage = HomeProvider.getStorage(TEST_DATASET_ID);
let invalidRows = [
{ url: "url" },
{ title: "title" },
{ description: "description" },
{ image_url: "image_url" }
];
// None of these save calls should save anything
for (let row of invalidRows) {
try {
yield storage.save([row]);
} catch (e if e instanceof HomeProvider.ValidationError) {
// Just catch and ignore validation errors
}
}
// Peek in the DB to make sure we have the right data.
let db = yield Sqlite.openConnection({ path: DB_PATH });
// Make sure no data has been saved.
let result = yield db.execute("SELECT * FROM items");
do_check_eq(result.length, 0);
db.close();
});
add_task(function test_save_transaction() {
// Use the HomeProvider API to save some data.
let storage = HomeProvider.getStorage(TEST_DATASET_ID);
// One valid, one invalid
let rows = [
{ title: TEST_TITLE, url: TEST_URL },
{ image_url: "image_url" }
];
// Try to save all the rows at once
try {
yield storage.save(rows);
} catch (e if e instanceof HomeProvider.ValidationError) {
// Just catch and ignore validation errors
}
// Peek in the DB to make sure we have the right data.
let db = yield Sqlite.openConnection({ path: DB_PATH });
// Make sure no data has been saved.
let result = yield db.execute("SELECT * FROM items");
do_check_eq(result.length, 0);
db.close();
});
run_next_test();

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