Merge mozilla-central into services-central

This commit is contained in:
Gregory Szorc 2012-07-13 17:19:51 -07:00
commit 92d1fbddef
472 changed files with 5586 additions and 3563 deletions

View File

@ -30,7 +30,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable // nsIAccessibleTable
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::)
// Accessible // Accessible
virtual TableAccessible* AsTable() { return this; } virtual TableAccessible* AsTable() { return this; }

View File

@ -95,7 +95,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
// nsIAccessible Table // nsIAccessible Table
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::)
// TableAccessible // TableAccessible
virtual Accessible* Caption(); virtual Accessible* Caption();

View File

@ -65,65 +65,4 @@ protected:
mozilla::a11y::TableAccessible* mTable; mozilla::a11y::TableAccessible* mTable;
}; };
#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \
NS_IMETHOD GetCaption(nsIAccessible** aCaption) \
{ return xpcAccessibleTable::GetCaption(aCaption); } \
NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary) \
{ return xpcAccessibleTable::GetSummary(aSummary); } \
NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32* aColumnCount) \
{ return xpcAccessibleTable::GetColumnCount(aColumnCount); } \
NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32* aRowCount) \
{ return xpcAccessibleTable::GetRowCount(aRowCount); } \
NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible** _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetCellAt(rowIndex, columnIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetCellIndexAt(rowIndex, columnIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetColumnIndexAt(cellIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetRowIndexAt(cellIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM) \
{ return xpcAccessibleTable::GetRowAndColumnIndicesAt(cellIndex, rowIndex, columnIndex); } \
NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetColumnExtentAt(row, column, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetRowExtentAt(row, column, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString& _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetColumnDescription(columnIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString& _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::GetRowDescription(rowIndex, _retval); } \
NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 colIdx, bool* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::IsColumnSelected(colIdx, _retval); } \
NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIdx, bool* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::IsRowSelected(rowIdx, _retval); } \
NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIdx, PRInt32 colIdx, bool* _retval NS_OUTPARAM) \
{ return xpcAccessibleTable::IsCellSelected(rowIdx, colIdx, _retval); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32* aSelectedCellCount) \
{ return xpcAccessibleTable::GetSelectedCellCount(aSelectedCellCount); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32* aSelectedColumnCount) \
{ return xpcAccessibleTable::GetSelectedColumnCount(aSelectedColumnCount); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32* aSelectedRowCount) \
{ return xpcAccessibleTable::GetSelectedRowCount(aSelectedRowCount); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray** aSelectedCells) \
{ return xpcAccessibleTable::GetSelectedCells(aSelectedCells); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32* cellsArraySize NS_OUTPARAM, \
PRInt32** cellsArray NS_OUTPARAM) \
{ return xpcAccessibleTable::GetSelectedCellIndices(cellsArraySize, cellsArray); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32* colsArraySize NS_OUTPARAM, \
PRInt32** colsArray NS_OUTPARAM) \
{ return xpcAccessibleTable::GetSelectedColumnIndices(colsArraySize, colsArray); } \
NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32* rowsArraySize NS_OUTPARAM, \
PRInt32** rowsArray NS_OUTPARAM) \
{ return xpcAccessibleTable::GetSelectedRowIndices(rowsArraySize, rowsArray); } \
NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 aRowIdx) \
{ return xpcAccessibleTable::SelectRow(aRowIdx); } \
NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 aColIdx) \
{ return xpcAccessibleTable::SelectColumn(aColIdx); } \
NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 aColIdx) \
{ return xpcAccessibleTable::UnselectColumn(aColIdx); } \
NS_IMETHOD UnselectRow(PRInt32 aRowIdx) \
{ return xpcAccessibleTable::UnselectRow(aRowIdx); } \
NS_IMETHOD IsProbablyForLayout(bool* aResult) \
{ return xpcAccessibleTable::IsProbablyForLayout(aResult); } \
#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_ #endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_

View File

@ -70,7 +70,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable // nsIAccessibleTable
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::)
// TableAccessible // TableAccessible
virtual PRUint32 ColCount(); virtual PRUint32 ColCount();

View File

@ -28,7 +28,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_ISUPPORTS_INHERITED
// nsIAccessibleTable // nsIAccessibleTable
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::)
// TableAccessible // TableAccessible
virtual PRUint32 ColCount(); virtual PRUint32 ColCount();

View File

@ -53,7 +53,8 @@ let FormAssistant = {
checkbox: true, checkbox: true,
radio: true, radio: true,
reset: true, reset: true,
submit: true submit: true,
image: true
}; };
if (evt.target instanceof HTMLSelectElement) { if (evt.target instanceof HTMLSelectElement) {
@ -156,6 +157,10 @@ let FormAssistant = {
}, },
tryShowIme: function(element) { tryShowIme: function(element) {
if (!element) {
return;
}
// FIXME/bug 729623: work around apparent bug in the IME manager // FIXME/bug 729623: work around apparent bug in the IME manager
// in gecko. // in gecko.
let readonly = element.getAttribute("readonly"); let readonly = element.getAttribute("readonly");

View File

@ -43,6 +43,10 @@ XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
return DebuggerServer; return DebuggerServer;
}); });
function getContentWindow() {
return shell.contentBrowser.contentWindow;
}
// FIXME Bug 707625 // FIXME Bug 707625
// until we have a proper security model, add some rights to // until we have a proper security model, add some rights to
// the pre-installed web applications // the pre-installed web applications

View File

@ -34,7 +34,7 @@ ContentPermissionPrompt.prototype = {
return; return;
let browser = Services.wm.getMostRecentWindow("navigator:browser"); let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.content; let content = browser.getContentWindow();
if (!content) if (!content)
return; return;
@ -42,8 +42,8 @@ ContentPermissionPrompt.prototype = {
content.addEventListener("mozContentEvent", function contentEvent(evt) { content.addEventListener("mozContentEvent", function contentEvent(evt) {
if (evt.detail.id != requestId) if (evt.detail.id != requestId)
return; return;
evt.target.removeEventListener(evt.type, contentEvent);
content.removeEventListener(evt.type, contentEvent);
if (evt.detail.type == "permission-allow") { if (evt.detail.type == "permission-allow") {
request.allow(); request.allow();
return; return;
@ -52,10 +52,15 @@ ContentPermissionPrompt.prototype = {
request.cancel(); request.cancel();
}); });
browser.shell.sendEvent(browser.content, "mozChromeEvent", { let details = {
"type": "permission-prompt", "permission": request.type, "type": "permission-prompt",
"id": requestId, "url": request.uri.spec "permission": request.type,
}); "id": requestId,
"url": request.uri.spec
};
let event = content.document.createEvent("CustomEvent");
event.initCustomEvent("mozChromeEvent", true, true, details);
content.dispatchEvent(event);
}, },
classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"), classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"),

View File

@ -140,6 +140,12 @@ var gPluginHandler = {
self.pluginUnavailable(plugin, event.type); self.pluginUnavailable(plugin, event.type);
break; break;
case "PluginVulnerableUpdatable":
let updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
self.addLinkClickCallback(updateLink, "openPluginUpdatePage");
/* FALLTHRU */
case "PluginVulnerableNoUpdate":
case "PluginClickToPlay": case "PluginClickToPlay":
self._handleClickToPlayEvent(plugin); self._handleClickToPlayEvent(plugin);
break; break;
@ -151,9 +157,10 @@ var gPluginHandler = {
} }
// Hide the in-content UI if it's too big. The crashed plugin handler already did this. // Hide the in-content UI if it's too big. The crashed plugin handler already did this.
if (event.type != "PluginCrashed" && event.type != "PluginClickToPlay") { if (event.type != "PluginCrashed") {
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox"); let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
if (self.isTooSmall(plugin, overlay)) /* overlay might be null, so only operate on it if it exists */
if (overlay != null && self.isTooSmall(plugin, overlay))
overlay.style.visibility = "hidden"; overlay.style.visibility = "hidden";
} }
}, },
@ -224,6 +231,12 @@ var gPluginHandler = {
managePlugins: function (aEvent) { managePlugins: function (aEvent) {
BrowserOpenAddonsMgr("addons://list/plugin"); BrowserOpenAddonsMgr("addons://list/plugin");
}, },
// Callback for user clicking on the link in a click-to-play plugin
// (where the plugin has an update)
openPluginUpdatePage: function (aEvent) {
openURL(Services.urlFormatter.formatURLPref("plugins.update.url"));
},
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
// Callback for user clicking "submit a report" link // Callback for user clicking "submit a report" link
@ -258,15 +271,18 @@ var gPluginHandler = {
objLoadingContent.playPlugin(); objLoadingContent.playPlugin();
return; return;
} else if (pluginsPermission == Ci.nsIPermissionManager.DENY_ACTION) { } else if (pluginsPermission == Ci.nsIPermissionManager.DENY_ACTION) {
overlay.style.visibility = "hidden"; if (overlay)
overlay.style.visibility = "hidden";
return; return;
} }
let overlay = doc.getAnonymousElementByAttribute(aPlugin, "class", "mainBox");
// The overlay is null if the XBL binding is not attached (element is display:none). // The overlay is null if the XBL binding is not attached (element is display:none).
if (overlay) { if (overlay) {
overlay.addEventListener("click", function(aEvent) { overlay.addEventListener("click", function(aEvent) {
if (aEvent.button == 0 && aEvent.isTrusted) // Have to check that the target is a XULElement and not the link
// to update the plugin
if (aEvent.target instanceof XULElement &&
aEvent.button == 0 && aEvent.isTrusted)
gPluginHandler.activateSinglePlugin(aEvent.target.ownerDocument.defaultView.top, aPlugin); gPluginHandler.activateSinglePlugin(aEvent.target.ownerDocument.defaultView.top, aPlugin);
}, true); }, true);
} }

View File

@ -1001,6 +1001,8 @@ var gBrowserInit = {
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true); gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
gBrowser.addEventListener("PluginDisabled", gPluginHandler, true); gBrowser.addEventListener("PluginDisabled", gPluginHandler, true);
gBrowser.addEventListener("PluginClickToPlay", gPluginHandler, true); gBrowser.addEventListener("PluginClickToPlay", gPluginHandler, true);
gBrowser.addEventListener("PluginVulnerableUpdatable", gPluginHandler, true);
gBrowser.addEventListener("PluginVulnerableNoUpdate", gPluginHandler, true);
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true); gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);
#ifdef XP_MACOSX #ifdef XP_MACOSX
gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true); gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true);

View File

@ -517,5 +517,103 @@ function test17() {
var missingNotification = PopupNotifications.getNotification("missing-plugins", gTestBrowser); var missingNotification = PopupNotifications.getNotification("missing-plugins", gTestBrowser);
ok(!missingNotification, "Test 17, Should not have a missing plugin notification"); ok(!missingNotification, "Test 17, Should not have a missing plugin notification");
registerFakeBlocklistService(Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE);
prepareTest(test18a, gTestRoot + "plugin_test.html");
}
const Cr = Components.results;
const Cm = Components.manager;
const Cc = Components.classes;
const gReg = Cm.QueryInterface(Ci.nsIComponentRegistrar);
const gRealBlocklistServiceCID = Cc["@mozilla.org/extensions/blocklist;1"];
const gFakeBlocklistServiceCID = Components.ID("{614b68a0-3c53-4ec0-8146-28cc1e25f8a1}");
var gFactory = null;
function registerFakeBlocklistService(blockState) {
var BlocklistService = {
getPluginBlocklistState: function(plugin, appVersion, toolkitVersion) {
return blockState;
},
classID: gFakeBlocklistServiceCID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBlocklistService])
};
gFactory = {
createInstance: function(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return BlocklistService.QueryInterface(iid);
}
};
gReg.registerFactory(gFakeBlocklistServiceCID,
"Fake Blocklist Service",
"@mozilla.org/extensions/blocklist;1",
gFactory);
}
function unregisterFakeBlocklistService() {
if (gFactory != null ) {
gReg.unregisterFactory(gFakeBlocklistServiceCID, gFactory);
gFactory = null;
// This should restore the original blocklist service:
gReg.registerFactory(gRealBlocklistServiceCID,
"Blocklist Service",
"@mozilla.org/extensions/blocklist;1",
null);
}
}
// Tests a vulnerable, updatable plugin
function test18a() {
var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(clickToPlayNotification, "Test 18a, Should have a click-to-play notification");
var doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "Test 18a, Plugin should not be activated");
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
ok(overlay.style.visibility != "hidden", "Test 18a, Plugin overlay should exist, not be hidden");
var updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
ok(updateLink.style.visibility != "hidden", "Test 18a, Plugin should have an update link");
var tabOpenListener = new TabOpenListener(Services.urlFormatter.formatURLPref("plugins.update.url"), false, false);
tabOpenListener.handleEvent = function(event) {
if (event.type == "TabOpen") {
gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
this.tab = event.originalTarget;
ok(event.target.label == this.url, "Test 18a, Update link should open up the plugin check page");
gBrowser.removeTab(this.tab);
test18b();
}
};
EventUtils.synthesizeMouse(updateLink, 5, 5, {}, gTestBrowser.contentWindow);
}
function test18b() {
unregisterFakeBlocklistService();
registerFakeBlocklistService(Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
prepareTest(test18c, gTestRoot + "plugin_test.html");
}
// Tests a vulnerable plugin with no update
function test18c() {
var clickToPlayNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(clickToPlayNotification, "Test 18c, Should have a click-to-play notification");
var doc = gTestBrowser.contentDocument;
var plugin = doc.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "Test 18c, Plugin should not be activated");
var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
ok(overlay.style.visibility != "hidden", "Test 18c, Plugin overlay should exist, not be hidden");
var updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
ok(updateLink.style.display != "block", "Test 18c, Plugin should not have an update link");
unregisterFakeBlocklistService();
var plugin = get_test_plugin();
plugin.clicktoplay = false;
finishTest(); finishTest();
} }

View File

@ -57,6 +57,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_pause-exceptions.js \ browser_dbg_pause-exceptions.js \
browser_dbg_multiple-windows.js \ browser_dbg_multiple-windows.js \
browser_dbg_menustatus.js \ browser_dbg_menustatus.js \
browser_dbg_bfcache.js \
head.js \ head.js \
$(NULL) $(NULL)

View File

@ -0,0 +1,118 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that the debugger is updated with the correct scripts when moving
* back and forward in the tab.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gScripts = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.contentWindow;
testInitialLoad();
});
}
function testInitialLoad() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
executeSoon(function() {
validateFirstPage();
testLocationChange();
});
});
gDebuggee.firstCall();
}
function testLocationChange()
{
gDebugger.DebuggerController.activeThread.resume(function() {
gDebugger.DebuggerController.client.addOneTimeListener("tabAttached", function(aEvent, aPacket) {
ok(true, "Successfully reattached to the tab again.");
gDebugger.DebuggerController.client.addOneTimeListener("resumed", function(aEvent, aPacket) {
executeSoon(function() {
validateSecondPage();
testBack();
});
});
});
content.location = STACK_URL;
});
}
function testBack()
{
gDebugger.DebuggerController.client.addOneTimeListener("tabAttached", function(aEvent, aPacket) {
ok(true, "Successfully reattached to the tab after going back.");
gDebugger.DebuggerController.client.addOneTimeListener("resumed", function(aEvent, aPacket) {
executeSoon(function() {
validateFirstPage();
testForward();
});
});
});
info("Going back.");
content.history.back();
}
function testForward()
{
gDebugger.DebuggerController.client.addOneTimeListener("tabAttached", function(aEvent, aPacket) {
ok(true, "Successfully reattached to the tab after going forward.");
gDebugger.DebuggerController.client.addOneTimeListener("resumed", function(aEvent, aPacket) {
executeSoon(function() {
validateSecondPage();
closeDebuggerAndFinish();
});
});
});
info("Going forward.");
content.history.forward();
}
function validateFirstPage() {
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gScripts.itemCount, 2, "Found the expected number of scripts.");
let label1 = "test-script-switching-01.js";
let label2 = "test-script-switching-02.js";
ok(gDebugger.DebuggerView.Scripts.containsLabel(label1),
"Found the first script label.");
ok(gDebugger.DebuggerView.Scripts.containsLabel(label2),
"Found the second script label.");
}
function validateSecondPage() {
gScripts = gDebugger.DebuggerView.Scripts._scripts;
is(gScripts.itemCount, 1, "Found the expected number of scripts.");
ok(gDebugger.DebuggerView.Scripts.containsLabel("browser_dbg_stack.html"),
"Found the single script label.");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gScripts = null;
});

View File

@ -509,7 +509,28 @@ class DeviceManager:
success: True success: True
failure: False failure: False
""" """
@staticmethod
def _escapedCommandLine(cmd):
""" Utility function to return escaped and quoted version of command line """
quotedCmd = []
for arg in cmd:
arg.replace('&', '\&')
needsQuoting = False
for char in [ ' ', '(', ')', '"', '&' ]:
if arg.find(char) >= 0:
needsQuoting = True
break
if needsQuoting:
arg = '\'%s\'' % arg
quotedCmd.append(arg)
return " ".join(quotedCmd)
class NetworkTools: class NetworkTools:
def __init__(self): def __init__(self):
pass pass

View File

@ -95,24 +95,13 @@ class DeviceManagerADB(DeviceManager):
# success: <return code> # success: <return code>
# failure: None # failure: None
def shell(self, cmd, outputfile, env=None, cwd=None): def shell(self, cmd, outputfile, env=None, cwd=None):
# need to quote and escape special characters here
for (index, arg) in enumerate(cmd):
arg.replace('&', '\&')
needsQuoting = False
for char in [ ' ', '(', ')', '"', '&' ]:
if arg.find(char):
needsQuoting = True
break
if needsQuoting:
cmd[index] = '\'%s\'' % arg
# This is more complex than you'd think because adb doesn't actually
# return the return code from a process, so we have to capture the output
# to get it
# FIXME: this function buffers all output of the command into memory, # FIXME: this function buffers all output of the command into memory,
# always. :( # always. :(
cmdline = " ".join(cmd) + "; echo $?"
# Getting the return code is more complex than you'd think because adb
# doesn't actually return the return code from a process, so we have to
# capture the output to get it
cmdline = "%s; echo $?" % self._escapedCommandLine(cmd)
# prepend cwd and env to command if necessary # prepend cwd and env to command if necessary
if cwd: if cwd:

View File

@ -260,7 +260,7 @@ class DeviceManagerSUT(DeviceManager):
# success: <return code> # success: <return code>
# failure: None # failure: None
def shell(self, cmd, outputfile, env=None, cwd=None): def shell(self, cmd, outputfile, env=None, cwd=None):
cmdline = subprocess.list2cmdline(cmd) cmdline = self._escapedCommandLine(cmd)
if env: if env:
cmdline = '%s %s' % (self.formatEnvString(env), cmdline) cmdline = '%s %s' % (self.formatEnvString(env), cmdline)

View File

@ -191,7 +191,7 @@ endif
profiledbuild:: profiledbuild::
$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_GENERATE=1 MOZ_PGO_INSTRUMENTED=1 $(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_GENERATE=1 MOZ_PGO_INSTRUMENTED=1
$(MAKE) -C $(PGO_OBJDIR) stage-package MOZ_PGO_INSTRUMENTED=1 $(MAKE) -C $(PGO_OBJDIR) package MOZ_PGO_INSTRUMENTED=1 MOZ_INTERNAL_SIGNING_FORMAT= MOZ_EXTERNAL_SIGNING_FORMAT=
MOZ_PGO_INSTRUMENTED=1 OBJDIR=${PGO_OBJDIR} JARLOG_DIR=${PGO_OBJDIR}/jarlog/en-US $(PROFILE_GEN_SCRIPT) MOZ_PGO_INSTRUMENTED=1 OBJDIR=${PGO_OBJDIR} JARLOG_DIR=${PGO_OBJDIR}/jarlog/en-US $(PROFILE_GEN_SCRIPT)
$(MAKE) -f $(TOPSRCDIR)/client.mk maybe_clobber_profiledbuild $(MAKE) -f $(TOPSRCDIR)/client.mk maybe_clobber_profiledbuild
$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_USE=1 $(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_USE=1

View File

@ -4039,7 +4039,7 @@ MOZ_ZLIB_CHECK([1.2.3])
if test "$MOZ_NATIVE_ZLIB" != 1; then if test "$MOZ_NATIVE_ZLIB" != 1; then
MOZ_ZLIB_CFLAGS= MOZ_ZLIB_CFLAGS=
MOZ_ZLIB_LIBS='$(call EXPAND_LIBNAME_PATH,mozz,'"$_objdir"'/modules/zlib/src)' MOZ_ZLIB_LIBS='$(call EXPAND_LIBNAME_PATH,mozz,'"$MOZ_BUILD_ROOT"'/modules/zlib/src)'
fi fi
if test "$MOZ_LINKER" = 1 -a "$MOZ_NATIVE_ZLIB" != 1; then if test "$MOZ_LINKER" = 1 -a "$MOZ_NATIVE_ZLIB" != 1; then

View File

@ -80,20 +80,6 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
#define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args) #define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
#define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG) #define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
#include "mozilla/Preferences.h"
static bool gClickToPlayPlugins = false;
static void
InitPrefCache()
{
static bool initializedPrefCache = false;
if (!initializedPrefCache) {
mozilla::Preferences::AddBoolVarCache(&gClickToPlayPlugins, "plugins.click_to_play");
}
initializedPrefCache = true;
}
class nsAsyncInstantiateEvent : public nsRunnable { class nsAsyncInstantiateEvent : public nsRunnable {
public: public:
nsObjectLoadingContent *mContent; nsObjectLoadingContent *mContent;
@ -181,6 +167,12 @@ nsPluginErrorEvent::Run()
case ePluginClickToPlay: case ePluginClickToPlay:
type = NS_LITERAL_STRING("PluginClickToPlay"); type = NS_LITERAL_STRING("PluginClickToPlay");
break; break;
case ePluginVulnerableUpdatable:
type = NS_LITERAL_STRING("PluginVulnerableUpdatable");
break;
case ePluginVulnerableNoUpdate:
type = NS_LITERAL_STRING("PluginVulnerableNoUpdate");
break;
case ePluginUnsupported: case ePluginUnsupported:
type = NS_LITERAL_STRING("PluginNotFound"); type = NS_LITERAL_STRING("PluginNotFound");
break; break;
@ -484,7 +476,11 @@ nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMETy
return rv; return rv;
} }
if (!mShouldPlay) { if (!pluginHost->IsPluginClickToPlayForType(aMIMEType.get())) {
mCTPPlayable = true;
}
if (!mCTPPlayable) {
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this)); nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
MOZ_ASSERT(thisContent); MOZ_ASSERT(thisContent);
nsIDocument* ownerDoc = thisContent->OwnerDoc(); nsIDocument* ownerDoc = thisContent->OwnerDoc();
@ -505,12 +501,17 @@ nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMETy
nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv); nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
PRUint32 permission; PRUint32 permission;
rv = permissionManager->TestPermission(topUri, rv = permissionManager->TestPermission(topUri, "plugins", &permission);
"plugins",
&permission);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (permission == nsIPermissionManager::ALLOW_ACTION) {
mShouldPlay = true; PRUint32 state;
rv = pluginHost->GetBlocklistStateForType(aMIMEType.get(), &state);
NS_ENSURE_SUCCESS(rv, rv);
if (permission == nsIPermissionManager::ALLOW_ACTION &&
state != nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE &&
state != nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
mCTPPlayable = true;
} else { } else {
return NS_ERROR_PLUGIN_CLICKTOPLAY; return NS_ERROR_PLUGIN_CLICKTOPLAY;
} }
@ -542,12 +543,9 @@ GetExtensionFromURI(nsIURI* uri, nsCString& ext)
*/ */
bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType) bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
{ {
if (!mShouldPlay) {
return false;
}
nsCAutoString ext; nsCAutoString ext;
GetExtensionFromURI(uri, ext); GetExtensionFromURI(uri, ext);
bool enabled = false;
if (ext.IsEmpty()) { if (ext.IsEmpty()) {
return false; return false;
@ -562,9 +560,18 @@ bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString&
const char* typeFromExt; const char* typeFromExt;
if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) { if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
mimeType = typeFromExt; mimeType = typeFromExt;
return true; enabled = true;
if (!pluginHost->IsPluginClickToPlayForType(mimeType.get())) {
mCTPPlayable = true;
}
}
if (!mCTPPlayable) {
return false;
} else {
return enabled;
} }
return false;
} }
nsresult nsresult
@ -598,13 +605,8 @@ nsObjectLoadingContent::nsObjectLoadingContent()
, mIsStopping(false) , mIsStopping(false)
, mSrcStreamLoading(false) , mSrcStreamLoading(false)
, mFallbackReason(ePluginOtherState) , mFallbackReason(ePluginOtherState)
{ , mCTPPlayable(false)
InitPrefCache(); , mActivated(false) {}
// If plugins.click_to_play is false, plugins should always play
mShouldPlay = !gClickToPlayPlugins;
// If plugins.click_to_play is true, track the activated state of plugins.
mActivated = !gClickToPlayPlugins;
}
nsObjectLoadingContent::~nsObjectLoadingContent() nsObjectLoadingContent::~nsObjectLoadingContent()
{ {
@ -617,10 +619,6 @@ nsObjectLoadingContent::~nsObjectLoadingContent()
nsresult nsresult
nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI) nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI)
{ {
if (!mShouldPlay) {
return NS_ERROR_PLUGIN_CLICKTOPLAY;
}
// Don't do anything if we already have an active instance. // Don't do anything if we already have an active instance.
if (mInstanceOwner) { if (mInstanceOwner) {
return NS_OK; return NS_OK;
@ -665,6 +663,14 @@ nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI*
return rv; return rv;
} }
if (!pluginHost->IsPluginClickToPlayForType(aMimeType)) {
mCTPPlayable = true;
}
if (!mCTPPlayable) {
return NS_ERROR_PLUGIN_CLICKTOPLAY;
}
// If you add early return(s), be sure to balance this call to // If you add early return(s), be sure to balance this call to
// appShell->SuspendNative() with additional call(s) to // appShell->SuspendNative() with additional call(s) to
// appShell->ReturnNative(). // appShell->ReturnNative().
@ -1191,6 +1197,10 @@ nsObjectLoadingContent::ObjectState() const
switch (mFallbackReason) { switch (mFallbackReason) {
case ePluginClickToPlay: case ePluginClickToPlay:
return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY; return NS_EVENT_STATE_TYPE_CLICK_TO_PLAY;
case ePluginVulnerableUpdatable:
return NS_EVENT_STATE_VULNERABLE_UPDATABLE;
case ePluginVulnerableNoUpdate:
return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
case ePluginDisabled: case ePluginDisabled:
state |= NS_EVENT_STATE_HANDLER_DISABLED; state |= NS_EVENT_STATE_HANDLER_DISABLED;
break; break;
@ -1933,8 +1943,10 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
} }
PluginSupportState pluginDisabledState = GetPluginDisabledState(aContentType); PluginSupportState pluginDisabledState = GetPluginDisabledState(aContentType);
if (pluginDisabledState == ePluginClickToPlay) { if (pluginDisabledState == ePluginClickToPlay ||
return ePluginClickToPlay; pluginDisabledState == ePluginVulnerableUpdatable ||
pluginDisabledState == ePluginVulnerableNoUpdate) {
return pluginDisabledState;
} else if (hasAlternateContent) { } else if (hasAlternateContent) {
return ePluginOtherState; return ePluginOtherState;
} else { } else {
@ -1946,12 +1958,28 @@ PluginSupportState
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType) nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
{ {
nsresult rv = IsPluginEnabledForType(aContentType); nsresult rv = IsPluginEnabledForType(aContentType);
if (rv == NS_ERROR_PLUGIN_DISABLED) if (rv == NS_ERROR_PLUGIN_DISABLED) {
return ePluginDisabled; return ePluginDisabled;
if (rv == NS_ERROR_PLUGIN_CLICKTOPLAY) }
if (rv == NS_ERROR_PLUGIN_CLICKTOPLAY) {
PRUint32 state;
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (pluginHost) {
rv = pluginHost->GetBlocklistStateForType(aContentType.get(), &state);
if (NS_SUCCEEDED(rv)) {
if (state == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
return ePluginVulnerableUpdatable;
} else if (state == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
return ePluginVulnerableNoUpdate;
}
}
}
return ePluginClickToPlay; return ePluginClickToPlay;
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED) }
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED) {
return ePluginBlocklisted; return ePluginBlocklisted;
}
return ePluginUnsupported; return ePluginUnsupported;
} }
@ -2213,7 +2241,7 @@ nsObjectLoadingContent::PlayPlugin()
if (!nsContentUtils::IsCallerChrome()) if (!nsContentUtils::IsCallerChrome())
return NS_OK; return NS_OK;
mShouldPlay = true; mCTPPlayable = true;
return LoadObject(mURI, true, mContentType, true); return LoadObject(mURI, true, mContentType, true);
} }

View File

@ -38,7 +38,9 @@ enum PluginSupportState {
ePluginOutdated, // The plugin is considered outdated, but not disabled ePluginOutdated, // The plugin is considered outdated, but not disabled
ePluginOtherState, // Something else (e.g. uninitialized or not a plugin) ePluginOtherState, // Something else (e.g. uninitialized or not a plugin)
ePluginCrashed, ePluginCrashed,
ePluginClickToPlay // The plugin is disabled until the user clicks on it ePluginClickToPlay, // The plugin is disabled until the user clicks on it
ePluginVulnerableUpdatable, // The plugin is vulnerable (update available)
ePluginVulnerableNoUpdate // The plugin is vulnerable (no update available)
}; };
/** /**
@ -372,9 +374,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// it may lose the flag. // it may lose the flag.
bool mNetworkCreated : 1; bool mNetworkCreated : 1;
// Used to keep track of whether or not a plugin should be played. // Used to keep track of if a plugin is blocked by click-to-play.
// This is used for click-to-play plugins. // True indicates the plugin is not click-to-play or it has been clicked by
bool mShouldPlay : 1; // the user.
// False indicates the plugin is click-to-play and has not yet been clicked.
bool mCTPPlayable : 1;
// Used to keep track of whether or not a plugin has been played. // Used to keep track of whether or not a plugin has been played.
// This is used for click-to-play plugins. // This is used for click-to-play plugins.

View File

@ -242,6 +242,10 @@ private:
#define NS_EVENT_STATE_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(38) #define NS_EVENT_STATE_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(38)
// Content is in the sub-suboptimal region. // Content is in the sub-suboptimal region.
#define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(39) #define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(39)
// Handler for click to play plugin (vulnerable w/update)
#define NS_EVENT_STATE_VULNERABLE_UPDATABLE NS_DEFINE_EVENT_STATE_MACRO(40)
// Handler for click to play plugin (vulnerable w/no update)
#define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(41)
/** /**
* NOTE: do not go over 63 without updating nsEventStates::InternalType! * NOTE: do not go over 63 without updating nsEventStates::InternalType!

View File

@ -282,7 +282,9 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
aTypeAtom == nsGkAtoms::ontouchcancel)) { aTypeAtom == nsGkAtoms::ontouchcancel)) {
mMayHaveTouchEventListener = true; mMayHaveTouchEventListener = true;
nsPIDOMWindow* window = GetInnerWindowForTarget(); nsPIDOMWindow* window = GetInnerWindowForTarget();
if (window) // we don't want touchevent listeners added by scrollbars to flip this flag
// so we ignore listeners created with system event flag
if (window && !(aFlags & NS_EVENT_FLAG_SYSTEM_EVENT))
window->SetHasTouchEventListeners(); window->SetHasTouchEventListeners();
} else if (aTypeAtom == nsGkAtoms::onmouseenter || } else if (aTypeAtom == nsGkAtoms::onmouseenter ||
aTypeAtom == nsGkAtoms::onmouseleave) { aTypeAtom == nsGkAtoms::onmouseleave) {

View File

@ -1848,12 +1848,6 @@ nsXBLPrototypeBinding::ReadContentNode(nsIObjectInputStream* aStream,
prototype->mNodeInfo = nodeInfo; prototype->mNodeInfo = nodeInfo;
nsCOMPtr<Element> result;
nsresult rv =
nsXULElement::Create(prototype, aDocument, false, getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
content = result;
nsXULPrototypeAttribute* attrs = nsnull; nsXULPrototypeAttribute* attrs = nsnull;
if (attrCount > 0) { if (attrCount > 0) {
attrs = new nsXULPrototypeAttribute[attrCount]; attrs = new nsXULPrototypeAttribute[attrCount];
@ -1892,6 +1886,12 @@ nsXBLPrototypeBinding::ReadContentNode(nsIObjectInputStream* aStream,
rv = prototype->SetAttrAt(i, val, documentURI); rv = prototype->SetAttrAt(i, val, documentURI);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
nsCOMPtr<Element> result;
nsresult rv =
nsXULElement::Create(prototype, aDocument, false, getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
content = result;
} }
else { else {
#endif #endif

View File

@ -107,6 +107,28 @@ ConsoleAPI.prototype = {
timeEnd: function CA_timeEnd() { timeEnd: function CA_timeEnd() {
self.queueCall("timeEnd", arguments); self.queueCall("timeEnd", arguments);
}, },
profile: function CA_profile() {
// Send a notification picked up by the profiler if installed.
// This must happen right away otherwise we will miss samples
let consoleEvent = {
action: "profile",
arguments: arguments
};
consoleEvent.wrappedJSObject = consoleEvent;
Services.obs.notifyObservers(consoleEvent, "console-api-profiler",
null);
},
profileEnd: function CA_profileEnd() {
// Send a notification picked up by the profiler if installed.
// This must happen right away otherwise we will miss samples
let consoleEvent = {
action: "profileEnd",
arguments: arguments
};
consoleEvent.wrappedJSObject = consoleEvent;
Services.obs.notifyObservers(consoleEvent, "console-api-profiler",
null);
},
__exposedProps__: { __exposedProps__: {
log: "r", log: "r",
info: "r", info: "r",
@ -119,7 +141,9 @@ ConsoleAPI.prototype = {
groupCollapsed: "r", groupCollapsed: "r",
groupEnd: "r", groupEnd: "r",
time: "r", time: "r",
timeEnd: "r" timeEnd: "r",
profile: "r",
profileEnd: "r"
} }
}; };
@ -143,6 +167,8 @@ ConsoleAPI.prototype = {
groupEnd: genPropDesc('groupEnd'), groupEnd: genPropDesc('groupEnd'),
time: genPropDesc('time'), time: genPropDesc('time'),
timeEnd: genPropDesc('timeEnd'), timeEnd: genPropDesc('timeEnd'),
profile: genPropDesc('profile'),
profileEnd: genPropDesc('profileEnd'),
__noSuchMethod__: { enumerable: true, configurable: true, writable: true, __noSuchMethod__: { enumerable: true, configurable: true, writable: true,
value: function() {} }, value: function() {} },
__mozillaConsole__: { value: true } __mozillaConsole__: { value: true }

View File

@ -21,8 +21,7 @@
#define DOM_PROTOTYPE_SLOT (JSCLASS_GLOBAL_SLOT_COUNT + 1) #define DOM_PROTOTYPE_SLOT (JSCLASS_GLOBAL_SLOT_COUNT + 1)
// We use these flag bits for the new bindings. // We use these flag bits for the new bindings.
#define JSCLASS_IS_DOMJSCLASS JSCLASS_USERBIT1 #define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
#define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT2
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {

View File

@ -10,9 +10,8 @@
function testSteps() function testSteps()
{ {
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = grabEventAndContinueHandler; request.onerror = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -51,12 +51,11 @@
function testSteps() function testSteps()
{ {
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
window.addEventListener("indexedDB-addMore", onAddMore, true); window.addEventListener("indexedDB-addMore", onAddMore, true);
window.addEventListener("indexedDB-done", onDone, true); window.addEventListener("indexedDB-done", onDone, true);
let request = indexedDB.open(name, version++, description); let request = indexedDB.open(name, version++);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -13,7 +13,6 @@
function testSteps() function testSteps()
{ {
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreInfo = [ const objectStoreInfo = [
{ name: "1", options: { keyPath: null } }, { name: "1", options: { keyPath: null } },
{ name: "2", options: { keyPath: null, autoIncrement: true } }, { name: "2", options: { keyPath: null, autoIncrement: true } },
@ -31,7 +30,7 @@
{ name: undefined } { name: undefined }
]; ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -13,7 +13,6 @@
function testSteps() function testSteps()
{ {
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
@ -35,7 +34,7 @@
expectedFileIds: [9, 9, 10, 11, 11, 9, 9] } expectedFileIds: [9, 9, 10, 11, 11, 9, 9] }
]; ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,8 +15,8 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const databaseInfo = [ const databaseInfo = [
{ name: window.location.pathname + "1", description: "Test Database 1" }, { name: window.location.pathname + "1" },
{ name: window.location.pathname + "2", description: "Test Database 2" } { name: window.location.pathname + "2" }
]; ];
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
@ -25,7 +25,7 @@
let databases = []; let databases = [];
for each (let info in databaseInfo) { for each (let info in databaseInfo) {
let request = indexedDB.open(info.name, 1, info.description); let request = indexedDB.open(info.name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
@ -24,7 +23,7 @@
const fileData3 = { key: 3, file: getRandomFile("random3.bin", 130000) }; const fileData3 = { key: 3, file: getRandomFile("random3.bin", 130000) };
{ {
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
@ -67,7 +66,7 @@
ok(hasFileInfo(name, 3), "Correct ref count"); ok(hasFileInfo(name, 3), "Correct ref count");
{ {
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
@ -25,7 +24,7 @@
const fileData = { key: 1, file: getRandomFile("random.bin", 100000) }; const fileData = { key: 1, file: getRandomFile("random.bin", 100000) };
{ {
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
@ -25,7 +24,7 @@
const objectData1 = { key: 1, object: { foo: blob, bar: blob } }; const objectData1 = { key: 1, object: { foo: blob, bar: blob } };
const objectData2 = { key: 2, object: { foo: file, bar: file } }; const objectData2 = { key: 2, object: { foo: file, bar: file } };
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
const blobData = { key: 1, blob: getRandomBlob(10000) }; const blobData = { key: 1, blob: getRandomBlob(10000) };
const fileData = { key: 2, file: getRandomFile("random.bin", 100000) }; const fileData = { key: 2, file: getRandomFile("random.bin", 100000) };
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -16,14 +16,13 @@
const DEFAULT_QUOTA_MB = 50; const DEFAULT_QUOTA_MB = 50;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
const testData = { key: 0, value: {} }; const testData = { key: 0, value: {} };
const fileData = { key: 1, file: null }; const fileData = { key: 1, file: null };
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -13,7 +13,6 @@
function testSteps() function testSteps()
{ {
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
@ -23,7 +22,7 @@
blobData.blobs[i] = getRandomBlob(i); blobData.blobs[i] = getRandomBlob(i);
} }
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
const fileData = { key: 1, file: getRandomFile("random.bin", 100000) }; const fileData = { key: 1, file: getRandomFile("random.bin", 100000) };
{ {
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
@ -72,7 +71,7 @@
is(getFileRefCount(name, 1), 0, "Correct ref count"); is(getFileRefCount(name, 1), 0, "Correct ref count");
{ {
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
const fileData = { key: 1, file: getRandomFile("random.bin", 100000) }; const fileData = { key: 1, file: getRandomFile("random.bin", 100000) };
{ {
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreInfo = [ const objectStoreInfo = [
{ name: "Blobs", options: { } }, { name: "Blobs", options: { } },
@ -24,7 +23,7 @@
const fileData = { key: 1, file: getRandomFile("random.bin", 100000) }; const fileData = { key: 1, file: getRandomFile("random.bin", 100000) };
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
const fileData = { key: 1, file: getRandomFile("random.bin", 100000) }; const fileData = { key: 1, file: getRandomFile("random.bin", 100000) };
{ {
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -16,9 +16,8 @@
const DEFAULT_QUOTA_MB = 50; const DEFAULT_QUOTA_MB = 50;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,8 +15,8 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const databaseInfo = [ const databaseInfo = [
{ name: window.location.pathname + "1", description: "Test Database 1" }, { name: window.location.pathname + "1" },
{ name: window.location.pathname + "2", description: "Test Database 2" } { name: window.location.pathname + "2" }
]; ];
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
@ -25,7 +25,7 @@
let databases = []; let databases = [];
for each (let info in databaseInfo) { for each (let info in databaseInfo) {
let request = indexedDB.open(info.name, 1, info.description); let request = indexedDB.open(info.name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,13 +15,12 @@
const READ_WRITE = IDBTransaction.READ_WRITE; const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs"; const objectStoreName = "Blobs";
const testFile = getRandomFile("random.bin", 100000); const testFile = getRandomFile("random.bin", 100000);
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -13,10 +13,9 @@
function testSteps() function testSteps()
{ {
const name = window.location.pathname; const name = window.location.pathname;
const description = "My Test Database";
const osName = "foo"; const osName = "foo";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,10 +8,9 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const entryCount = 1000; const entryCount = 1000;
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const START_DATA = "hi"; const START_DATA = "hi";
const END_DATA = "bye"; const END_DATA = "bye";
const objectStoreInfo = [ const objectStoreInfo = [
@ -27,7 +26,7 @@ function testSteps()
let info = objectStoreInfo[i]; let info = objectStoreInfo[i];
ok(true, "1"); ok(true, "1");
request = indexedDB.open(name, i + 1, description); request = indexedDB.open(name, i + 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
event = yield; event = yield;

View File

@ -8,13 +8,12 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const keys = [1, -1, 0, 10, 2000, "q", "z", "two", "b", "a"]; const keys = [1, -1, 0, 10, 2000, "q", "z", "two", "b", "a"];
const sortedKeys = [-1, 0, 1, 10, 2000, "a", "b", "q", "two", "z"]; const sortedKeys = [-1, 0, 1, 10, 2000, "a", "b", "q", "two", "z"];
is(keys.length, sortedKeys.length, "Good key setup"); is(keys.length, sortedKeys.length, "Good key setup");
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,10 +8,9 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "Objects"; const objectStoreName = "Objects";
var request = indexedDB.open(name, 1, description); var request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
var event = yield; var event = yield;

View File

@ -8,11 +8,10 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const values = [ "a", "1", 1, "foo", 300, true, false, 4.5, null ]; const values = [ "a", "1", 1, "foo", 300, true, false, 4.5, null ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,11 +8,10 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStore = { name: "Objects", const objectStore = { name: "Objects",
options: { keyPath: "id", autoIncrement: true } }; options: { keyPath: "id", autoIncrement: true } };
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;
@ -26,7 +25,7 @@ function testSteps()
continueToNextStep(); continueToNextStep();
yield; yield;
request = indexedDB.open(name, 1, description); request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
event = yield; event = yield;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People"; const objectStoreName = "People";
const objectStoreData = [ const objectStoreData = [
@ -52,7 +51,7 @@ function testSteps()
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } } { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
]; ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People"; const objectStoreName = "People";
const objectStoreData = [ const objectStoreData = [
@ -52,7 +51,7 @@ function testSteps()
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } } { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
]; ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? this.window ? window.location.pathname : "Splendid Test" : "Splendid Test"; const name = this.window ? this.window ? window.location.pathname : "Splendid Test" : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People"; const objectStoreName = "People";
@ -53,7 +52,7 @@ function testSteps()
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } } { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
]; ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People"; const objectStoreName = "People";
@ -39,7 +38,7 @@ function testSteps()
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } } { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
]; ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStores = [ const objectStores = [
{ name: "a", autoIncrement: false }, { name: "a", autoIncrement: false },
@ -22,7 +21,7 @@ function testSteps()
var j = 0; var j = 0;
for (let i in objectStores) { for (let i in objectStores) {
let request = indexedDB.open(name, ++j, description); let request = indexedDB.open(name, ++j);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;
@ -55,7 +54,7 @@ function testSteps()
executeSoon(function() { testGenerator.next(); }); executeSoon(function() { testGenerator.next(); });
yield; yield;
let request = indexedDB.open(name, j, description); let request = indexedDB.open(name, j);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -9,9 +9,8 @@ function testSteps()
{ {
const IDBObjectStore = Components.interfaces.nsIIDBObjectStore; const IDBObjectStore = Components.interfaces.nsIIDBObjectStore;
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
var request = indexedDB.open(name, 1, description); var request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
var event = yield; var event = yield;

View File

@ -9,7 +9,6 @@ function testSteps()
{ {
const IDBObjectStore = Components.interfaces.nsIIDBObjectStore; const IDBObjectStore = Components.interfaces.nsIIDBObjectStore;
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
var data = [ var data = [
{ name: "inline key; key generator", { name: "inline key; key generator",
@ -41,7 +40,7 @@ function testSteps()
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
let test = data[i]; let test = data[i];
let request = indexedDB.open(name, i+1, description); let request = indexedDB.open(name, i+1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -9,10 +9,9 @@ function testSteps()
{ {
const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore; const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "Objects"; const objectStoreName = "Objects";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,10 +8,9 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStores = [ "foo", "bar" ]; const objectStores = [ "foo", "bar" ];
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,13 +8,12 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "Objects"; const objectStoreName = "Objects";
let testString = { key: 0, value: "testString" }; let testString = { key: 0, value: "testString" };
let testInt = { key: 1, value: 1002 }; let testInt = { key: 1, value: 1002 };
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,13 +8,12 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "Objects"; const objectStoreName = "Objects";
let testString = { value: "testString" }; let testString = { value: "testString" };
let testInt = { value: 1002 }; let testInt = { value: 1002 };
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -10,10 +10,9 @@ function testSteps()
const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore; const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const indexName = "My Test Index"; const indexName = "My Test Index";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -10,10 +10,9 @@ function testSteps()
const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore; const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "Objects"; const objectStoreName = "Objects";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;
@ -42,7 +41,7 @@ function testSteps()
db.close(); db.close();
let request = indexedDB.open(name, 2, description); let request = indexedDB.open(name, 2);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;
@ -86,7 +85,7 @@ function testSteps()
db.close(); db.close();
let request = indexedDB.open(name, 3, description); let request = indexedDB.open(name, 3);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
is(request.readyState, "pending", "Correct readyState"); is(request.readyState, "pending", "Correct readyState");
request.onerror = errorHandler; request.onerror = errorHandler;

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
let event = yield; let event = yield;
@ -30,7 +29,7 @@ function testSteps()
for (let i = 0; i < versions.length; i++) { for (let i = 0; i < versions.length; i++) {
let version = versions[i]; let version = versions[i];
let request = indexedDB.open(name, version, description); let request = indexedDB.open(name, version);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield; let event = yield;

View File

@ -8,10 +8,9 @@ var testGenerator = testSteps();
function testSteps() function testSteps()
{ {
const name = this.window ? window.location.pathname : "Splendid Test"; const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
// Open a datbase for the first time. // Open a datbase for the first time.
let request = indexedDB.open(name, 1, description); let request = indexedDB.open(name, 1);
// Sanity checks // Sanity checks
ok(request instanceof IDBRequest, "Request should be an IDBRequest"); ok(request instanceof IDBRequest, "Request should be an IDBRequest");
@ -46,7 +45,7 @@ function testSteps()
}, false); }, false);
// Open the database again and trigger an upgrade that should succeed // Open the database again and trigger an upgrade that should succeed
request = indexedDB.open(name, 2, description); request = indexedDB.open(name, 2);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = errorHandler; request.onsuccess = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler; request.onupgradeneeded = grabEventAndContinueHandler;
@ -84,7 +83,7 @@ function testSteps()
}, false); }, false);
// Test opening the existing version again // Test opening the existing version again
request = indexedDB.open(name, 2, description); request = indexedDB.open(name, 2);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler; request.onsuccess = grabEventAndContinueHandler;
if (SpecialPowers.isMainProcess()) { if (SpecialPowers.isMainProcess()) {
@ -98,7 +97,7 @@ function testSteps()
db3 = event.target.result; db3 = event.target.result;
// Test an upgrade that should fail // Test an upgrade that should fail
request = indexedDB.open(name, 3, description); request = indexedDB.open(name, 3);
request.onerror = errorHandler; request.onerror = errorHandler;
request.onsuccess = errorHandler; request.onsuccess = errorHandler;
request.onupgradeneeded = errorHandler; request.onupgradeneeded = errorHandler;

View File

@ -98,6 +98,15 @@ CrashReporterParent::GenerateHangCrashReport(const AnnotationTable* processNotes
return true; return true;
} }
bool
CrashReporterParent::GenerateCrashReportForMinidump(nsIFile* minidump,
const AnnotationTable* processNotes)
{
if (!CrashReporter::GetIDFromMinidump(minidump, mChildDumpID))
return false;
return GenerateChildData(processNotes);
}
bool bool
CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes) CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes)
{ {

View File

@ -49,6 +49,10 @@ public:
bool bool
GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes); GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
bool
GenerateCrashReportForMinidump(nsIFile* minidump,
const AnnotationTable* processNotes);
/* Instantiate a new crash reporter actor from a given parent that manages /* Instantiate a new crash reporter actor from a given parent that manages
the protocol. the protocol.
*/ */
@ -135,7 +139,7 @@ CrashReporterParent::GenerateCrashReport(Toplevel* t,
const AnnotationTable* processNotes) const AnnotationTable* processNotes)
{ {
nsCOMPtr<nsIFile> crashDump; nsCOMPtr<nsIFile> crashDump;
if (t->TakeMinidump(getter_AddRefs(crashDump)) && if (t->TakeMinidump(getter_AddRefs(crashDump), NULL) &&
CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) { CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) {
return GenerateChildData(processNotes); return GenerateChildData(processNotes);
} }

View File

@ -5,7 +5,7 @@
#include "nsISupports.idl" #include "nsISupports.idl"
[scriptable, uuid(88e03453-a773-47ba-9d84-14f672ac99e2)] [scriptable, uuid(a361a7e7-7f8d-4b68-91e9-30ae096460d4)]
interface nsIPluginTag : nsISupports interface nsIPluginTag : nsISupports
{ {
readonly attribute AUTF8String description; readonly attribute AUTF8String description;
@ -15,4 +15,5 @@ interface nsIPluginTag : nsISupports
readonly attribute AUTF8String name; readonly attribute AUTF8String name;
attribute boolean disabled; attribute boolean disabled;
attribute boolean blocklisted; attribute boolean blocklisted;
attribute boolean clicktoplay;
}; };

View File

@ -342,8 +342,10 @@ nsPluginHost::nsPluginHost()
Preferences::GetBool("plugin.override_internal_types", false); Preferences::GetBool("plugin.override_internal_types", false);
mPluginsDisabled = Preferences::GetBool("plugin.disable", false); mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
mPluginsClickToPlay = Preferences::GetBool("plugins.click_to_play", false);
Preferences::AddStrongObserver(this, "plugin.disable"); Preferences::AddStrongObserver(this, "plugin.disable");
Preferences::AddStrongObserver(this, "plugins.click_to_play");
nsCOMPtr<nsIObserverService> obsService = nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService(); mozilla::services::GetObserverService();
@ -1294,6 +1296,36 @@ nsPluginHost::IsPluginEnabledForType(const char* aMimeType)
return NS_OK; return NS_OK;
} }
bool
nsPluginHost::IsPluginClickToPlayForType(const char* aMimeType)
{
nsPluginTag *plugin = FindPluginForType(aMimeType, true);
if (plugin &&
(plugin->HasFlag(NS_PLUGIN_FLAG_CLICKTOPLAY) || mPluginsClickToPlay)) {
return true;
}
else {
return false;
}
}
nsresult
nsPluginHost::GetBlocklistStateForType(const char *aMimeType, PRUint32 *aState)
{
nsPluginTag *plugin = FindPluginForType(aMimeType, true);
if (plugin) {
nsCOMPtr<nsIBlocklistService> blocklist = do_GetService("@mozilla.org/extensions/blocklist;1");
if (blocklist) {
// The EmptyString()s are so we use the currently running application
// and toolkit versions
return blocklist->GetPluginBlocklistState(plugin, EmptyString(),
EmptyString(), aState);
}
}
return NS_ERROR_FAILURE;
}
// check comma delimitered extensions // check comma delimitered extensions
static int CompareExtensions(const char *aExtensionList, const char *aExtension) static int CompareExtensions(const char *aExtensionList, const char *aExtension)
@ -2074,19 +2106,32 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
EmptyString(), &state); EmptyString(), &state);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
// If the blocklist says so then block the plugin. If the blocklist says // If the blocklist says so, block the plugin.
// it is risky and we have never seen this plugin before then disable it // If the blocklist says it is risky and we have never seen this
if (state == nsIBlocklistService::STATE_BLOCKED) // plugin before, then disable it.
pluginTag->Mark(NS_PLUGIN_FLAG_BLOCKLISTED); // If the blocklist says this is an outdated plugin, warn about
else if (state == nsIBlocklistService::STATE_SOFTBLOCKED && !seenBefore) // outdated plugins.
enabled = false; // If the blocklist says the plugin is one of the click-to-play
else if (state == nsIBlocklistService::STATE_OUTDATED && !seenBefore) // states, set the click-to-play flag.
warnOutdated = true; if (state == nsIBlocklistService::STATE_BLOCKED) {
pluginTag->Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
}
if (state == nsIBlocklistService::STATE_SOFTBLOCKED && !seenBefore) {
enabled = false;
}
if (state == nsIBlocklistService::STATE_OUTDATED && !seenBefore) {
warnOutdated = true;
}
if (state == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE ||
state == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
pluginTag->Mark(NS_PLUGIN_FLAG_CLICKTOPLAY);
}
} }
} }
if (!enabled) if (!enabled) {
pluginTag->UnMark(NS_PLUGIN_FLAG_ENABLED); pluginTag->UnMark(NS_PLUGIN_FLAG_ENABLED);
}
// Plugin unloading is tag-based. If we created a new tag and loaded // Plugin unloading is tag-based. If we created a new tag and loaded
// the library in the process then we want to attempt to unload it here. // the library in the process then we want to attempt to unload it here.
@ -3302,6 +3347,7 @@ NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
} }
if (!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { if (!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
mPluginsDisabled = Preferences::GetBool("plugin.disable", false); mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
mPluginsClickToPlay = Preferences::GetBool("plugins.click_to_play", false);
// Unload or load plugins as needed // Unload or load plugins as needed
if (mPluginsDisabled) { if (mPluginsDisabled) {
UnloadPlugins(); UnloadPlugins();

View File

@ -85,6 +85,8 @@ public:
nsIPluginInstanceOwner *aOwner); nsIPluginInstanceOwner *aOwner);
nsresult IsPluginEnabledForType(const char* aMimeType); nsresult IsPluginEnabledForType(const char* aMimeType);
nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType); nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
bool IsPluginClickToPlayForType(const char *aMimeType);
nsresult GetBlocklistStateForType(const char *aMimeType, PRUint32 *state);
nsresult GetPluginCount(PRUint32* aPluginCount); nsresult GetPluginCount(PRUint32* aPluginCount);
nsresult GetPlugins(PRUint32 aPluginCount, nsIDOMPlugin** aPluginArray); nsresult GetPlugins(PRUint32 aPluginCount, nsIDOMPlugin** aPluginArray);
@ -281,6 +283,8 @@ private:
// set by pref plugin.disable // set by pref plugin.disable
bool mPluginsDisabled; bool mPluginsDisabled;
// set by pref plugins.click_to_play
bool mPluginsClickToPlay;
// Any instances in this array will have valid plugin objects via GetPlugin(). // Any instances in this array will have valid plugin objects via GetPlugin().
// When removing an instance it might not die - be sure to null out it's plugin. // When removing an instance it might not die - be sure to null out it's plugin.

View File

@ -320,6 +320,30 @@ nsPluginTag::SetBlocklisted(bool aBlocklisted)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsPluginTag::GetClicktoplay(bool *aClicktoplay)
{
*aClicktoplay = HasFlag(NS_PLUGIN_FLAG_CLICKTOPLAY);
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::SetClicktoplay(bool aClicktoplay)
{
if (HasFlag(NS_PLUGIN_FLAG_CLICKTOPLAY) == aClicktoplay) {
return NS_OK;
}
if (aClicktoplay) {
Mark(NS_PLUGIN_FLAG_CLICKTOPLAY);
} else {
UnMark(NS_PLUGIN_FLAG_CLICKTOPLAY);
}
mPluginHost->UpdatePluginInfo(nsnull);
return NS_OK;
}
void nsPluginTag::Mark(PRUint32 mask) void nsPluginTag::Mark(PRUint32 mask)
{ {
bool wasEnabled = IsEnabled(); bool wasEnabled = IsEnabled();

View File

@ -27,6 +27,7 @@ struct nsPluginInfo;
#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache #define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache
// no longer used 0x0008 // reuse only if regenerating pluginreg.dat // no longer used 0x0008 // reuse only if regenerating pluginreg.dat
#define NS_PLUGIN_FLAG_BLOCKLISTED 0x0010 // this is a blocklisted plugin #define NS_PLUGIN_FLAG_BLOCKLISTED 0x0010 // this is a blocklisted plugin
#define NS_PLUGIN_FLAG_CLICKTOPLAY 0x0020 // this is a click-to-play plugin
// A linked-list of plugin information that is used for instantiating plugins // A linked-list of plugin information that is used for instantiating plugins
// and reflecting plugin information into JavaScript. // and reflecting plugin information into JavaScript.

View File

@ -27,9 +27,6 @@
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsCRT.h" #include "nsCRT.h"
#ifdef MOZ_CRASHREPORTER
#include "mozilla/dom/CrashReporterParent.h"
#endif
#include "nsNPAPIPlugin.h" #include "nsNPAPIPlugin.h"
#include "nsIFile.h" #include "nsIFile.h"
@ -49,6 +46,12 @@ using namespace mozilla;
using namespace mozilla::plugins; using namespace mozilla::plugins;
using namespace mozilla::plugins::parent; using namespace mozilla::plugins::parent;
#ifdef MOZ_CRASHREPORTER
#include "mozilla/dom/CrashReporterParent.h"
using namespace CrashReporter;
#endif
static const char kChildTimeoutPref[] = "dom.ipc.plugins.timeoutSecs"; static const char kChildTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
static const char kParentTimeoutPref[] = "dom.ipc.plugins.parentTimeoutSecs"; static const char kParentTimeoutPref[] = "dom.ipc.plugins.parentTimeoutSecs";
static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs"; static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
@ -133,9 +136,9 @@ PluginModuleParent::~PluginModuleParent()
#ifdef MOZ_CRASHREPORTER_INJECTOR #ifdef MOZ_CRASHREPORTER_INJECTOR
if (mFlashProcess1) if (mFlashProcess1)
CrashReporter::UnregisterInjectorCallback(mFlashProcess1); UnregisterInjectorCallback(mFlashProcess1);
if (mFlashProcess2) if (mFlashProcess2)
CrashReporter::UnregisterInjectorCallback(mFlashProcess2); UnregisterInjectorCallback(mFlashProcess2);
#endif #endif
Preferences::UnregisterCallback(TimeoutChanged, kChildTimeoutPref, this); Preferences::UnregisterCallback(TimeoutChanged, kChildTimeoutPref, this);
@ -144,7 +147,7 @@ PluginModuleParent::~PluginModuleParent()
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
void void
PluginModuleParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes) PluginModuleParent::WriteExtraDataForMinidump(AnnotationTable& notes)
{ {
typedef nsDependentCString CS; typedef nsDependentCString CS;
@ -200,19 +203,17 @@ bool
PluginModuleParent::ShouldContinueFromReplyTimeout() PluginModuleParent::ShouldContinueFromReplyTimeout()
{ {
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
if (mPluginDumpID.IsEmpty()) { CrashReporterParent* crashReporter = CrashReporter();
CrashReporterParent* crashReporter = CrashReporter(); if (crashReporter->GeneratePairedMinidump(this)) {
if (crashReporter->GeneratePairedMinidump(this)) { mBrowserDumpID = crashReporter->ParentDumpID();
mBrowserDumpID = crashReporter->ParentDumpID(); mPluginDumpID = crashReporter->ChildDumpID();
mPluginDumpID = crashReporter->ChildDumpID(); PLUGIN_LOG_DEBUG(
PLUGIN_LOG_DEBUG( ("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
("generated paired browser/plugin minidumps: %s/%s (ID=%s)", NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
NS_ConvertUTF16toUTF8(mBrowserDumpID).get(), NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
NS_ConvertUTF16toUTF8(mPluginDumpID).get(), NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
NS_ConvertUTF16toUTF8(crashReporter->HangID()).get())); } else {
} else { NS_WARNING("failed to capture paired minidumps from hang");
NS_WARNING("failed to capture paired minidumps from hang");
}
} }
#endif #endif
@ -237,33 +238,99 @@ PluginModuleParent::CrashReporter()
} }
#endif #endif
#ifdef MOZ_CRASHREPORTER
static void
RemoveMinidump(nsIFile* minidump)
{
if (!minidump)
return;
minidump->Remove(false);
nsCOMPtr<nsIFile> extraFile;
if (GetExtraFileForMinidump(minidump,
getter_AddRefs(extraFile))) {
extraFile->Remove(true);
}
}
void
PluginModuleParent::ProcessFirstMinidump()
{
CrashReporterParent* crashReporter = CrashReporter();
if (!crashReporter)
return;
AnnotationTable notes;
notes.Init(4);
WriteExtraDataForMinidump(notes);
if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
crashReporter->GenerateHangCrashReport(&notes);
return;
}
PRUint32 sequence = PR_UINT32_MAX;
nsCOMPtr<nsIFile> dumpFile;
nsCAutoString flashProcessType;
TakeMinidump(getter_AddRefs(dumpFile), &sequence);
#ifdef MOZ_CRASHREPORTER_INJECTOR
nsCOMPtr<nsIFile> childDumpFile;
PRUint32 childSequence;
if (mFlashProcess1 &&
TakeMinidumpForChild(mFlashProcess1,
getter_AddRefs(childDumpFile),
&childSequence)) {
if (childSequence < sequence) {
RemoveMinidump(dumpFile);
dumpFile = childDumpFile;
sequence = childSequence;
flashProcessType.AssignLiteral("Broker");
}
else {
RemoveMinidump(childDumpFile);
}
}
if (mFlashProcess2 &&
TakeMinidumpForChild(mFlashProcess2,
getter_AddRefs(childDumpFile),
&childSequence)) {
if (childSequence < sequence) {
RemoveMinidump(dumpFile);
dumpFile = childDumpFile;
sequence = childSequence;
flashProcessType.AssignLiteral("Sandbox");
}
else {
RemoveMinidump(childDumpFile);
}
}
#endif
if (!dumpFile) {
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
return;
}
PLUGIN_LOG_DEBUG(("got child minidump: %s",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
GetIDFromMinidump(dumpFile, mPluginDumpID);
if (!flashProcessType.IsEmpty()) {
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"), flashProcessType);
}
crashReporter->GenerateCrashReportForMinidump(dumpFile, &notes);
}
#endif
void void
PluginModuleParent::ActorDestroy(ActorDestroyReason why) PluginModuleParent::ActorDestroy(ActorDestroyReason why)
{ {
switch (why) { switch (why) {
case AbnormalShutdown: { case AbnormalShutdown: {
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
CrashReporterParent* crashReporter = CrashReporter(); ProcessFirstMinidump();
CrashReporter::AnnotationTable notes;
notes.Init(4);
WriteExtraDataForMinidump(notes);
if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
crashReporter->GenerateHangCrashReport(&notes);
}
else if (!mPluginDumpID.IsEmpty()) {
// Nothing to do, we've already written this minidump in
// PluginModuleParent::OnCrash
}
else if (crashReporter->GenerateCrashReport(this, &notes)) {
mPluginDumpID = crashReporter->ChildDumpID();
PLUGIN_LOG_DEBUG(("got child minidump: %s",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
}
else {
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
}
#endif #endif
mShutdown = true; mShutdown = true;
@ -1248,33 +1315,8 @@ PluginModuleParent::InitializeInjector()
} }
void void
PluginModuleParent::OnCrash(DWORD processID, const nsAString& aDumpID) PluginModuleParent::OnCrash(DWORD processID)
{ {
if (!mPluginDumpID.IsEmpty()) {
// One process has already crashed: we assume that the first-to-crash
// is the interesting one
return;
}
mPluginDumpID = aDumpID;
CrashReporter::AnnotationTable notes;
notes.Init(4);
WriteExtraDataForMinidump(notes);
notes.Put(NS_LITERAL_CSTRING("ProcessType"), NS_LITERAL_CSTRING("plugin"));
if (processID == mFlashProcess1) {
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"),
NS_LITERAL_CSTRING("Broker"));
}
else if (processID == mFlashProcess2) {
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"),
NS_LITERAL_CSTRING("Sandbox"));
}
else {
NS_ERROR("Got minidump for Flash process neither broker nor sandbox.");
}
CrashReporter::AppendExtraData(aDumpID, notes);
GetIPCChannel()->CloseWithError(); GetIPCChannel()->CloseWithError();
KillProcess(OtherProcess(), 1, false); KillProcess(OtherProcess(), 1, false);
} }

View File

@ -288,6 +288,7 @@ private:
CrashReporterParent* CrashReporter(); CrashReporterParent* CrashReporter();
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
void ProcessFirstMinidump();
void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes); void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
#endif #endif
void CleanupFromTimeout(); void CleanupFromTimeout();
@ -319,7 +320,7 @@ private:
#ifdef MOZ_CRASHREPORTER_INJECTOR #ifdef MOZ_CRASHREPORTER_INJECTOR
void InitializeInjector(); void InitializeInjector();
NS_OVERRIDE void OnCrash(DWORD processID, const nsAString& aDumpID); NS_OVERRIDE void OnCrash(DWORD processID);
DWORD mFlashProcess1; DWORD mFlashProcess1;
DWORD mFlashProcess2; DWORD mFlashProcess2;

View File

@ -32,6 +32,8 @@ function doTest() {
"groupEnd": "function", "groupEnd": "function",
"time": "function", "time": "function",
"timeEnd": "function", "timeEnd": "function",
"profile": "function",
"profileEnd": "function",
"__noSuchMethod__": "function" "__noSuchMethod__": "function"
}; };

View File

@ -236,9 +236,14 @@ var WifiManager = (function() {
function scanCommand(forceActive, callback) { function scanCommand(forceActive, callback) {
if (forceActive && !scanModeActive) { if (forceActive && !scanModeActive) {
doSetScanModeCommand(true, function(ok) { // Note: we ignore errors from doSetScanMode.
ok && doBooleanCommand("SCAN", "OK", function(ok) { doSetScanModeCommand(true, function(ignore) {
ok && doSetScanModeCommand(false, callback); doBooleanCommand("SCAN", "OK", function(ok) {
doSetScanModeCommand(false, function(ignore) {
// The result of scanCommand is the result of the actual SCAN
// request.
callback(ok);
});
}); });
}); });
return; return;
@ -603,7 +608,7 @@ var WifiManager = (function() {
} }
manager.start = function() { manager.start = function() {
debug("detected SDK version " + sdkVersion); debug("detected SDK version " + sdkVersion + " and device " + device);
// If we reconnected to an already-running supplicant, then manager.state // If we reconnected to an already-running supplicant, then manager.state
// will have already been updated to the supplicant's state. Otherwise, we // will have already been updated to the supplicant's state. Otherwise, we

View File

@ -29,13 +29,13 @@ nsSelectionState::DoTraverse(nsCycleCollectionTraversalCallback &cb)
{ {
for (PRUint32 i = 0, iEnd = mArray.Length(); i < iEnd; ++i) for (PRUint32 i = 0, iEnd = mArray.Length(); i < iEnd; ++i)
{ {
nsRangeStore &item = mArray[i]; nsRangeStore* item = mArray[i];
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"selection state mArray[i].startNode"); "selection state mArray[i].startNode");
cb.NoteXPCOMChild(item.startNode); cb.NoteXPCOMChild(item->startNode);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"selection state mArray[i].endNode"); "selection state mArray[i].endNode");
cb.NoteXPCOMChild(item.endNode); cb.NoteXPCOMChild(item->endNode);
} }
} }
@ -53,6 +53,7 @@ nsSelectionState::SaveSelection(nsISelection *aSel)
for (i=0; i<count; i++) for (i=0; i<count; i++)
{ {
mArray.AppendElement(); mArray.AppendElement();
mArray[i] = new nsRangeStore();
} }
} }
@ -71,7 +72,7 @@ nsSelectionState::SaveSelection(nsISelection *aSel)
{ {
nsCOMPtr<nsIDOMRange> range; nsCOMPtr<nsIDOMRange> range;
res = aSel->GetRangeAt(i, getter_AddRefs(range)); res = aSel->GetRangeAt(i, getter_AddRefs(range));
mArray[i].StoreRange(range); mArray[i]->StoreRange(range);
} }
return res; return res;
@ -91,7 +92,7 @@ nsSelectionState::RestoreSelection(nsISelection *aSel)
for (i=0; i<arrayCount; i++) for (i=0; i<arrayCount; i++)
{ {
nsRefPtr<nsRange> range; nsRefPtr<nsRange> range;
mArray[i].GetRange(getter_AddRefs(range)); mArray[i]->GetRange(getter_AddRefs(range));
NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
res = aSel->AddRange(range); res = aSel->AddRange(range);
@ -106,7 +107,7 @@ nsSelectionState::IsCollapsed()
{ {
if (1 != mArray.Length()) return false; if (1 != mArray.Length()) return false;
nsRefPtr<nsRange> range; nsRefPtr<nsRange> range;
mArray[0].GetRange(getter_AddRefs(range)); mArray[0]->GetRange(getter_AddRefs(range));
NS_ENSURE_TRUE(range, false); NS_ENSURE_TRUE(range, false);
bool bIsCollapsed = false; bool bIsCollapsed = false;
range->GetCollapsed(&bIsCollapsed); range->GetCollapsed(&bIsCollapsed);
@ -124,8 +125,8 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
for (i=0; i<myCount; i++) for (i=0; i<myCount; i++)
{ {
nsRefPtr<nsRange> myRange, itsRange; nsRefPtr<nsRange> myRange, itsRange;
mArray[i].GetRange(getter_AddRefs(myRange)); mArray[i]->GetRange(getter_AddRefs(myRange));
aSelState->mArray[i].GetRange(getter_AddRefs(itsRange)); aSelState->mArray[i]->GetRange(getter_AddRefs(itsRange));
NS_ENSURE_TRUE(myRange && itsRange, false); NS_ENSURE_TRUE(myRange && itsRange, false);
PRInt16 compResult; PRInt16 compResult;
@ -190,7 +191,7 @@ nsRangeUpdater::RegisterSelectionState(nsSelectionState &aSelState)
for (i=0; i<theCount; i++) for (i=0; i<theCount; i++)
{ {
RegisterRangeItem(&aSelState.mArray[i]); RegisterRangeItem(aSelState.mArray[i]);
} }
return NS_OK; return NS_OK;
@ -204,7 +205,7 @@ nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState)
for (i=0; i<theCount; i++) for (i=0; i<theCount; i++)
{ {
DropRangeItem(&aSelState.mArray[i]); DropRangeItem(aSelState.mArray[i]);
} }
return NS_OK; return NS_OK;

View File

@ -30,6 +30,8 @@ struct nsRangeStore
~nsRangeStore(); ~nsRangeStore();
nsresult StoreRange(nsIDOMRange *aRange); nsresult StoreRange(nsIDOMRange *aRange);
nsresult GetRange(nsRange** outRange); nsresult GetRange(nsRange** outRange);
NS_INLINE_DECL_REFCOUNTING(nsRangeStore)
nsCOMPtr<nsIDOMNode> startNode; nsCOMPtr<nsIDOMNode> startNode;
PRInt32 startOffset; PRInt32 startOffset;
@ -55,7 +57,7 @@ class nsSelectionState
void MakeEmpty(); void MakeEmpty();
bool IsEmpty(); bool IsEmpty();
protected: protected:
nsTArray<nsRangeStore> mArray; nsTArray<nsRefPtr<nsRangeStore> > mArray;
friend class nsRangeUpdater; friend class nsRangeUpdater;
}; };
@ -99,7 +101,7 @@ class nsRangeUpdater
nsresult WillMoveNode(); nsresult WillMoveNode();
nsresult DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset); nsresult DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset);
protected: protected:
nsTArray<nsRangeStore*> mArray; nsTArray<nsRefPtr<nsRangeStore> > mArray;
bool mLock; bool mLock;
}; };
@ -115,25 +117,26 @@ class NS_STACK_CLASS nsAutoTrackDOMPoint
nsRangeUpdater &mRU; nsRangeUpdater &mRU;
nsCOMPtr<nsIDOMNode> *mNode; nsCOMPtr<nsIDOMNode> *mNode;
PRInt32 *mOffset; PRInt32 *mOffset;
nsRangeStore mRangeItem; nsRefPtr<nsRangeStore> mRangeItem;
public: public:
nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, nsCOMPtr<nsIDOMNode> *aNode, PRInt32 *aOffset) : nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, nsCOMPtr<nsIDOMNode> *aNode, PRInt32 *aOffset) :
mRU(aRangeUpdater) mRU(aRangeUpdater)
,mNode(aNode) ,mNode(aNode)
,mOffset(aOffset) ,mOffset(aOffset)
{ {
mRangeItem.startNode = *mNode; mRangeItem = new nsRangeStore();
mRangeItem.endNode = *mNode; mRangeItem->startNode = *mNode;
mRangeItem.startOffset = *mOffset; mRangeItem->endNode = *mNode;
mRangeItem.endOffset = *mOffset; mRangeItem->startOffset = *mOffset;
mRU.RegisterRangeItem(&mRangeItem); mRangeItem->endOffset = *mOffset;
mRU.RegisterRangeItem(mRangeItem);
} }
~nsAutoTrackDOMPoint() ~nsAutoTrackDOMPoint()
{ {
mRU.DropRangeItem(&mRangeItem); mRU.DropRangeItem(mRangeItem);
*mNode = mRangeItem.startNode; *mNode = mRangeItem->startNode;
*mOffset = mRangeItem.startOffset; *mOffset = mRangeItem->startOffset;
} }
}; };

View File

@ -184,6 +184,7 @@ mDocChangeRange(nsnull)
mCachedStyles[16] = StyleCache(nsEditProperty::cssBackgroundColor, EmptyString(), EmptyString()); mCachedStyles[16] = StyleCache(nsEditProperty::cssBackgroundColor, EmptyString(), EmptyString());
mCachedStyles[17] = StyleCache(nsEditProperty::sub, EmptyString(), EmptyString()); mCachedStyles[17] = StyleCache(nsEditProperty::sub, EmptyString(), EmptyString());
mCachedStyles[18] = StyleCache(nsEditProperty::sup, EmptyString(), EmptyString()); mCachedStyles[18] = StyleCache(nsEditProperty::sup, EmptyString(), EmptyString());
mRangeItem = new nsRangeStore();
} }
nsHTMLEditRules::~nsHTMLEditRules() nsHTMLEditRules::~nsHTMLEditRules()
@ -287,17 +288,17 @@ nsHTMLEditRules::BeforeEdit(nsEditor::OperationID action,
PRInt32 selOffset; PRInt32 selOffset;
res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selStartNode), &selOffset); res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selStartNode), &selOffset);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
mRangeItem.startNode = selStartNode; mRangeItem->startNode = selStartNode;
mRangeItem.startOffset = selOffset; mRangeItem->startOffset = selOffset;
// get the selection end location // get the selection end location
res = mHTMLEditor->GetEndNodeAndOffset(selection, getter_AddRefs(selEndNode), &selOffset); res = mHTMLEditor->GetEndNodeAndOffset(selection, getter_AddRefs(selEndNode), &selOffset);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
mRangeItem.endNode = selEndNode; mRangeItem->endNode = selEndNode;
mRangeItem.endOffset = selOffset; mRangeItem->endOffset = selOffset;
// register this range with range updater to track this as we perturb the doc // register this range with range updater to track this as we perturb the doc
(mHTMLEditor->mRangeUpdater).RegisterRangeItem(&mRangeItem); (mHTMLEditor->mRangeUpdater).RegisterRangeItem(mRangeItem);
// clear deletion state bool // clear deletion state bool
mDidDeleteSelection = false; mDidDeleteSelection = false;
@ -361,7 +362,7 @@ nsHTMLEditRules::AfterEdit(nsEditor::OperationID action,
res = AfterEditInner(action, aDirection); res = AfterEditInner(action, aDirection);
// free up selectionState range item // free up selectionState range item
(mHTMLEditor->mRangeUpdater).DropRangeItem(&mRangeItem); (mHTMLEditor->mRangeUpdater).DropRangeItem(mRangeItem);
// Reset the contenteditable count to its previous value // Reset the contenteditable count to its previous value
if (mRestoreContentEditableCount) { if (mRestoreContentEditableCount) {
@ -453,11 +454,13 @@ nsHTMLEditRules::AfterEditInner(nsEditor::OperationID action,
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
// also do this for original selection endpoints. // also do this for original selection endpoints.
nsWSRunObject(mHTMLEditor, mRangeItem.startNode, mRangeItem.startOffset).AdjustWhitespace(); nsWSRunObject(mHTMLEditor, mRangeItem->startNode,
mRangeItem->startOffset).AdjustWhitespace();
// we only need to handle old selection endpoint if it was different from start // we only need to handle old selection endpoint if it was different from start
if ((mRangeItem.startNode != mRangeItem.endNode) || (mRangeItem.startOffset != mRangeItem.endOffset)) if (mRangeItem->startNode != mRangeItem->endNode ||
{ mRangeItem->startOffset != mRangeItem->endOffset) {
nsWSRunObject(mHTMLEditor, mRangeItem.endNode, mRangeItem.endOffset).AdjustWhitespace(); nsWSRunObject(mHTMLEditor, mRangeItem->endNode,
mRangeItem->endOffset).AdjustWhitespace();
} }
} }
@ -494,7 +497,8 @@ nsHTMLEditRules::AfterEditInner(nsEditor::OperationID action,
} }
res = mHTMLEditor->HandleInlineSpellCheck(action, selection, res = mHTMLEditor->HandleInlineSpellCheck(action, selection,
mRangeItem.startNode, mRangeItem.startOffset, mRangeItem->startNode,
mRangeItem->startOffset,
rangeStartParent, rangeStartOffset, rangeStartParent, rangeStartOffset,
rangeEndParent, rangeEndOffset); rangeEndParent, rangeEndOffset);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
@ -5572,7 +5576,7 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray<nsIDOMRange>& inArrayOfRanges,
if (!aDontTouchContent) if (!aDontTouchContent)
{ {
nsAutoTArray<nsRangeStore, 16> rangeItemArray; nsTArray<nsRefPtr<nsRangeStore> > rangeItemArray;
if (!rangeItemArray.AppendElements(rangeCount)) { if (!rangeItemArray.AppendElements(rangeCount)) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -5584,21 +5588,21 @@ nsHTMLEditRules::GetNodesForOperation(nsCOMArray<nsIDOMRange>& inArrayOfRanges,
for (i = 0; i < rangeCount; i++) for (i = 0; i < rangeCount; i++)
{ {
opRange = inArrayOfRanges[0]; opRange = inArrayOfRanges[0];
nsRangeStore *item = rangeItemArray.Elements() + i; rangeItemArray[i] = new nsRangeStore();
item->StoreRange(opRange); rangeItemArray[i]->StoreRange(opRange);
mHTMLEditor->mRangeUpdater.RegisterRangeItem(item); mHTMLEditor->mRangeUpdater.RegisterRangeItem(rangeItemArray[i]);
inArrayOfRanges.RemoveObjectAt(0); inArrayOfRanges.RemoveObjectAt(0);
} }
// now bust up inlines. Safe to start at rangeCount-1, since we // now bust up inlines. Safe to start at rangeCount-1, since we
// asserted we have enough items above. // asserted we have enough items above.
for (i = rangeCount-1; i >= 0 && NS_SUCCEEDED(res); i--) for (i = rangeCount-1; i >= 0 && NS_SUCCEEDED(res); i--)
{ {
res = BustUpInlinesAtRangeEndpoints(rangeItemArray[i]); res = BustUpInlinesAtRangeEndpoints(*rangeItemArray[i]);
} }
// then unregister the ranges // then unregister the ranges
for (i = 0; i < rangeCount; i++) for (i = 0; i < rangeCount; i++)
{ {
nsRangeStore *item = rangeItemArray.Elements() + i; nsRangeStore* item = rangeItemArray[i];
mHTMLEditor->mRangeUpdater.DropRangeItem(item); mHTMLEditor->mRangeUpdater.DropRangeItem(item);
nsRefPtr<nsRange> range; nsRefPtr<nsRange> range;
nsresult res2 = item->GetRange(getter_AddRefs(range)); nsresult res2 = item->GetRange(getter_AddRefs(range));

View File

@ -293,7 +293,7 @@ protected:
nsRefPtr<nsRange> mUtilRange; nsRefPtr<nsRange> mUtilRange;
PRUint32 mJoinOffset; // need to remember an int across willJoin/didJoin... PRUint32 mJoinOffset; // need to remember an int across willJoin/didJoin...
nsCOMPtr<nsIDOMNode> mNewBlock; nsCOMPtr<nsIDOMNode> mNewBlock;
nsRangeStore mRangeItem; nsRefPtr<nsRangeStore> mRangeItem;
StyleCache mCachedStyles[SIZE_STYLE_TABLE]; StyleCache mCachedStyles[SIZE_STYLE_TABLE];
}; };

View File

@ -648,7 +648,8 @@ nsTextEditRules::WillInsertText(nsEditor::OperationID aAction,
mTimer = do_CreateInstance("@mozilla.org/timer;1", &res); mTimer = do_CreateInstance("@mozilla.org/timer;1", &res);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
mTimer->InitWithCallback(this, 600, nsITimer::TYPE_ONE_SHOT); mTimer->InitWithCallback(this, LookAndFeel::GetPasswordMaskDelay(),
nsITimer::TYPE_ONE_SHOT);
} }
else else
{ {

View File

@ -19,6 +19,7 @@
#include "nsAppDirectoryServiceDefs.h" #include "nsAppDirectoryServiceDefs.h"
#include "prprf.h" #include "prprf.h"
#include "mozilla/storage.h" #include "mozilla/storage.h"
#include "mozilla/Attributes.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
@ -115,7 +116,7 @@ nsHostEntry::nsHostEntry(const nsHostEntry& toCopy)
* Note: Once the callback has been called this DeleteFromMozHostListener cannot * Note: Once the callback has been called this DeleteFromMozHostListener cannot
* be reused. * be reused.
*/ */
class CloseDatabaseListener : public mozIStorageCompletionCallback class CloseDatabaseListener MOZ_FINAL : public mozIStorageCompletionCallback
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
@ -164,7 +165,7 @@ CloseDatabaseListener::Complete()
* Note: Once the callback has been called this DeleteFromMozHostListener cannot * Note: Once the callback has been called this DeleteFromMozHostListener cannot
* be reused. * be reused.
*/ */
class DeleteFromMozHostListener : public mozIStorageStatementCallback class DeleteFromMozHostListener MOZ_FINAL : public mozIStorageStatementCallback
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS

View File

@ -140,6 +140,14 @@ EXPORTS_mozilla/layers += ShadowLayerUtilsD3D10.h
DEFINES += -DMOZ_ENABLE_D3D10_LAYER DEFINES += -DMOZ_ENABLE_D3D10_LAYER
endif endif
# NB: Gralloc is available on other platforms that use the android GL
# libraries, but only Gonk is able to use it reliably because Gecko
# has full system permissions there.
ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
EXPORTS_mozilla/layers += ShadowLayerUtilsGralloc.h
CPPSRCS += ShadowLayerUtilsGralloc.cpp
endif
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk

View File

@ -171,6 +171,16 @@ protected:
return tmp.forget(); return tmp.forget();
} }
/**
* Set the buffer only. This is intended to be used with the
* shadow-layer Open/CloseDescriptor interface, to ensure we don't
* accidentally touch a buffer when it's not mapped.
*/
void SetBuffer(gfxASurface* aBuffer)
{
mBuffer = aBuffer;
}
/** /**
* Get a context at the specified resolution for updating |aBounds|, * Get a context at the specified resolution for updating |aBounds|,
* which must be contained within a single quadrant. * which must be contained within a single quadrant.

View File

@ -10,8 +10,8 @@
using namespace mozilla::gfx; using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
static bool static bool
IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion) IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion)
@ -47,10 +47,10 @@ BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
// Pull out the mask surface and transform here, because the mask // Pull out the mask surface and transform here, because the mask
// is internal to basic layers // is internal to basic layers
gfxMatrix maskTransform; AutoMaskData mask;
if (nsRefPtr<gfxASurface> maskSurface = if (GetMaskData(aMaskLayer, &mask)) {
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) { DrawBufferWithRotation(aTarget, aOpacity,
DrawBufferWithRotation(aTarget, aOpacity, maskSurface, &maskTransform); mask.GetSurface(), &mask.GetTransform());
} else { } else {
DrawBufferWithRotation(aTarget, aOpacity); DrawBufferWithRotation(aTarget, aOpacity);
} }

View File

@ -58,6 +58,27 @@ public:
gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation, gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
const nsIntRegion& aUpdateRegion); const nsIntRegion& aUpdateRegion);
/**
* When BasicThebesLayerBuffer is used with layers that hold
* SurfaceDescriptor, this buffer only has a valid gfxASurface in
* the scope of an AutoOpenSurface for that SurfaceDescriptor. That
* is, it's sort of a "virtual buffer" that's only mapped an
* unmapped within the scope of AutoOpenSurface. None of the
* underlying buffer attributes (rect, rotation) are affected by
* mapping/unmapping.
*
* These helpers just exist to provide more descriptive names of the
* map/unmap process.
*/
void MapBuffer(gfxASurface* aBuffer)
{
SetBuffer(aBuffer);
}
void UnmapBuffer()
{
SetBuffer(nsnull);
}
private: private:
BasicThebesLayerBuffer(gfxASurface* aBuffer, BasicThebesLayerBuffer(gfxASurface* aBuffer,
const nsIntRect& aRect, const nsIntPoint& aRotation) const nsIntRect& aRect, const nsIntPoint& aRotation)
@ -87,18 +108,25 @@ public:
MOZ_COUNT_DTOR(ShadowThebesLayerBuffer); MOZ_COUNT_DTOR(ShadowThebesLayerBuffer);
} }
void Swap(gfxASurface* aNewBuffer, /**
const nsIntRect& aNewRect, const nsIntPoint& aNewRotation, * Swap in the old "virtual buffer" (see above) attributes in aNew*
gfxASurface** aOldBuffer, * and return the old ones in aOld*.
*
* Swap() must only be called when the buffer is in its "unmapped"
* state, that is the underlying gfxASurface is not available. It
* is expected that the owner of this buffer holds an unmapped
* SurfaceDescriptor as the backing storage for this buffer. That's
* why no gfxASurface or SurfaceDescriptor parameters appear here.
*/
void Swap(const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
nsIntRect* aOldRect, nsIntPoint* aOldRotation) nsIntRect* aOldRect, nsIntPoint* aOldRotation)
{ {
*aOldRect = BufferRect(); *aOldRect = BufferRect();
*aOldRotation = BufferRotation(); *aOldRotation = BufferRotation();
nsRefPtr<gfxASurface> oldBuffer; nsRefPtr<gfxASurface> oldBuffer;
oldBuffer = SetBuffer(aNewBuffer, oldBuffer = SetBuffer(nsnull, aNewRect, aNewRotation);
aNewRect, aNewRotation); MOZ_ASSERT(!oldBuffer);
oldBuffer.forget(aOldBuffer);
} }
protected: protected:
@ -113,4 +141,4 @@ protected:
} }
} }
#endif #endif

View File

@ -339,9 +339,8 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData)
// canvas resizes // canvas resizes
if (IsSurfaceDescriptorValid(mBackBuffer)) { if (IsSurfaceDescriptorValid(mBackBuffer)) {
nsRefPtr<gfxASurface> backSurface = AutoOpenSurface backSurface(OPEN_READ_ONLY, mBackBuffer);
BasicManager()->OpenDescriptor(mBackBuffer); if (gfxIntSize(mBounds.width, mBounds.height) != backSurface.Size()) {
if (gfxIntSize(mBounds.width, mBounds.height) != backSurface->GetSize()) {
DestroyBackBuffer(); DestroyBackBuffer();
} }
} }
@ -368,15 +367,13 @@ BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
NS_RUNTIMEABORT("creating CanvasLayer back buffer failed!"); NS_RUNTIMEABORT("creating CanvasLayer back buffer failed!");
} }
nsRefPtr<gfxASurface> backSurface = AutoOpenSurface autoBackSurface(OPEN_READ_WRITE, mBackBuffer);
BasicManager()->OpenDescriptor(mBackBuffer);
if (aMaskLayer) { if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData()) static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nsnull); ->Paint(aContext, nsnull);
} }
UpdateSurface(backSurface, nsnull); UpdateSurface(autoBackSurface.Get(), nsnull);
FireDidTransactionCallback(); FireDidTransactionCallback();
BasicManager()->PaintedCanvas(BasicManager()->Hold(this), BasicManager()->PaintedCanvas(BasicManager()->Hold(this),
@ -437,15 +434,14 @@ void
BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip, BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
CanvasSurface* aNewBack) CanvasSurface* aNewBack)
{ {
nsRefPtr<gfxASurface> surface = AutoOpenSurface autoSurface(OPEN_READ_ONLY, aNewFront);
BasicManager()->OpenDescriptor(aNewFront);
// Destroy mFrontBuffer if size different // Destroy mFrontBuffer if size different
gfxIntSize sz = surface->GetSize(); gfxIntSize sz = autoSurface.Size();
bool surfaceConfigChanged = sz != gfxIntSize(mBounds.width, mBounds.height); bool surfaceConfigChanged = sz != gfxIntSize(mBounds.width, mBounds.height);
if (IsSurfaceDescriptorValid(mFrontSurface)) { if (IsSurfaceDescriptorValid(mFrontSurface)) {
nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontSurface); AutoOpenSurface autoFront(OPEN_READ_ONLY, mFrontSurface);
surfaceConfigChanged = surfaceConfigChanged || surfaceConfigChanged = surfaceConfigChanged ||
surface->GetContentType() != front->GetContentType(); autoSurface.ContentType() != autoFront.ContentType();
} }
if (surfaceConfigChanged) { if (surfaceConfigChanged) {
DestroyFrontBuffer(); DestroyFrontBuffer();
@ -459,7 +455,7 @@ BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
} else { } else {
*aNewBack = null_t(); *aNewBack = null_t();
} }
mFrontSurface = aNewFront.get_SurfaceDescriptor(); mFrontSurface = aNewFront;
} }
void void
@ -472,9 +468,8 @@ BasicShadowCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
return; return;
} }
nsRefPtr<gfxASurface> surface = AutoOpenSurface autoSurface(OPEN_READ_ONLY, mFrontSurface);
BasicManager()->OpenDescriptor(mFrontSurface); nsRefPtr<gfxPattern> pat = new gfxPattern(autoSurface.Get());
nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
pat->SetFilter(mFilter); pat->SetFilter(mFilter);
pat->SetExtend(gfxPattern::EXTEND_PAD); pat->SetExtend(gfxPattern::EXTEND_PAD);

View File

@ -9,8 +9,8 @@
using namespace mozilla::gfx; using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
class BasicColorLayer : public ColorLayer, public BasicImplData { class BasicColorLayer : public ColorLayer, public BasicImplData {
public: public:
BasicColorLayer(BasicLayerManager* aLayerManager) : BasicColorLayer(BasicLayerManager* aLayerManager) :

View File

@ -9,8 +9,8 @@
using namespace mozilla::gfx; using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
BasicContainerLayer::~BasicContainerLayer() BasicContainerLayer::~BasicContainerLayer()

View File

@ -11,7 +11,7 @@
using namespace mozilla::gfx; using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
class BasicImageLayer : public ImageLayer, public BasicImplData { class BasicImageLayer : public ImageLayer, public BasicImplData {
public: public:
@ -41,7 +41,8 @@ public:
gfxContext* aContext, gfxContext* aContext,
Layer* aMaskLayer); Layer* aMaskLayer);
virtual already_AddRefed<gfxASurface> GetAsSurface(); virtual bool GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor);
protected: protected:
BasicLayerManager* BasicManager() BasicLayerManager* BasicManager()
@ -86,9 +87,6 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
return nsnull; return nsnull;
} }
NS_ASSERTION(surface->GetContentType() != gfxASurface::CONTENT_ALPHA,
"Image layer has alpha image");
nsRefPtr<gfxPattern> pat = new gfxPattern(surface); nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
if (!pat) { if (!pat) {
return nsnull; return nsnull;
@ -154,15 +152,18 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern,
aPattern->SetExtend(extend); aPattern->SetExtend(extend);
} }
already_AddRefed<gfxASurface> bool
BasicImageLayer::GetAsSurface() BasicImageLayer::GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor)
{ {
if (!mContainer) { if (!mContainer) {
return nsnull; return false;
} }
gfxIntSize dontCare; gfxIntSize dontCare;
return mContainer->GetCurrentAsSurface(&dontCare); nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&dontCare);
*aSurface = surface.forget().get();
return true;
} }
class BasicShadowableImageLayer : public BasicImageLayer, class BasicShadowableImageLayer : public BasicImageLayer,
@ -196,9 +197,9 @@ public:
mBackBuffer = aBuffer; mBackBuffer = aBuffer;
} }
virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer, virtual void SetBackBufferYUVImage(const SurfaceDescriptor& aYBuffer,
gfxSharedImageSurface* aUBuffer, const SurfaceDescriptor& aUBuffer,
gfxSharedImageSurface* aVBuffer) const SurfaceDescriptor& aVBuffer)
{ {
mBackBufferY = aYBuffer; mBackBufferY = aYBuffer;
mBackBufferU = aUBuffer; mBackBufferU = aUBuffer;
@ -207,7 +208,9 @@ public:
virtual void Disconnect() virtual void Disconnect()
{ {
mBackBufferY = mBackBufferU = mBackBufferV = nsnull; mBackBufferY = SurfaceDescriptor();
mBackBufferU = SurfaceDescriptor();
mBackBufferV = SurfaceDescriptor();
mBackBuffer = SurfaceDescriptor(); mBackBuffer = SurfaceDescriptor();
BasicShadowableLayer::Disconnect(); BasicShadowableLayer::Disconnect();
} }
@ -217,11 +220,11 @@ public:
if (IsSurfaceDescriptorValid(mBackBuffer)) { if (IsSurfaceDescriptorValid(mBackBuffer)) {
BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer); BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
} }
if (mBackBufferY) { if (IsSurfaceDescriptorValid(mBackBufferY)) {
BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferY); BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBufferY);
BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferU); BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBufferU);
BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferV); BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBufferV);
} }
} }
private: private:
@ -234,9 +237,9 @@ private:
// for RGB images only mBackSurface is used. // for RGB images only mBackSurface is used.
SurfaceDescriptor mBackBuffer; SurfaceDescriptor mBackBuffer;
bool mBufferIsOpaque; bool mBufferIsOpaque;
nsRefPtr<gfxSharedImageSurface> mBackBufferY; SurfaceDescriptor mBackBufferY;
nsRefPtr<gfxSharedImageSurface> mBackBufferU; SurfaceDescriptor mBackBufferU;
nsRefPtr<gfxSharedImageSurface> mBackBufferV; SurfaceDescriptor mBackBufferV;
gfxIntSize mCbCrSize; gfxIntSize mCbCrSize;
}; };
@ -271,38 +274,52 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
const PlanarYCbCrImage::Data *data = YCbCrImage->GetData(); const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
NS_ASSERTION(data, "Must be able to retrieve yuv data from image!"); NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize || !mBackBufferY) { if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize || !IsSurfaceDescriptorValid(mBackBufferY)) {
DestroyBackBuffer(); DestroyBackBuffer();
mSize = data->mYSize; mSize = data->mYSize;
mCbCrSize = data->mCbCrSize; mCbCrSize = data->mCbCrSize;
if (!BasicManager()->AllocBuffer(mSize, gfxASurface::CONTENT_ALPHA, // We either allocate all three planes or none.
getter_AddRefs(mBackBufferY)) || if (!BasicManager()->AllocBufferWithCaps(mSize,
!BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA, gfxASurface::CONTENT_ALPHA,
getter_AddRefs(mBackBufferU)) || MAP_AS_IMAGE_SURFACE,
!BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA, &mBackBufferY) ||
getter_AddRefs(mBackBufferV))) { !BasicManager()->AllocBufferWithCaps(mCbCrSize,
gfxASurface::CONTENT_ALPHA,
MAP_AS_IMAGE_SURFACE,
&mBackBufferU) ||
!BasicManager()->AllocBufferWithCaps(mCbCrSize,
gfxASurface::CONTENT_ALPHA,
MAP_AS_IMAGE_SURFACE,
&mBackBufferV)) {
NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!"); NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
} }
} }
AutoOpenSurface dyas(OPEN_READ_WRITE, mBackBufferY);
gfxImageSurface* dy = dyas.GetAsImage();
for (int i = 0; i < data->mYSize.height; i++) { for (int i = 0; i < data->mYSize.height; i++) {
memcpy(mBackBufferY->Data() + i * mBackBufferY->Stride(), memcpy(dy->Data() + i * dy->Stride(),
data->mYChannel + i * data->mYStride, data->mYChannel + i * data->mYStride,
data->mYSize.width); data->mYSize.width);
} }
AutoOpenSurface duas(OPEN_READ_WRITE, mBackBufferU);
gfxImageSurface* du = duas.GetAsImage();
AutoOpenSurface dvas(OPEN_READ_WRITE, mBackBufferV);
gfxImageSurface* dv = dvas.GetAsImage();
for (int i = 0; i < data->mCbCrSize.height; i++) { for (int i = 0; i < data->mCbCrSize.height; i++) {
memcpy(mBackBufferU->Data() + i * mBackBufferU->Stride(), memcpy(du->Data() + i * du->Stride(),
data->mCbChannel + i * data->mCbCrStride, data->mCbChannel + i * data->mCbCrStride,
data->mCbCrSize.width); data->mCbCrSize.width);
memcpy(mBackBufferV->Data() + i * mBackBufferV->Stride(), memcpy(dv->Data() + i * dv->Stride(),
data->mCrChannel + i * data->mCbCrStride, data->mCrChannel + i * data->mCbCrStride,
data->mCbCrSize.width); data->mCbCrSize.width);
} }
YUVImage yuv(mBackBufferY->GetShmem(), YUVImage yuv(mBackBufferY, mBackBufferU, mBackBufferV,
mBackBufferU->GetShmem(),
mBackBufferV->GetShmem(),
data->GetPictureRect()); data->GetPictureRect());
BasicManager()->PaintedImage(BasicManager()->Hold(this), BasicManager()->PaintedImage(BasicManager()->Hold(this),
@ -336,9 +353,8 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!"); NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
} }
nsRefPtr<gfxASurface> backSurface = AutoOpenSurface backSurface(OPEN_READ_WRITE, mBackBuffer);
BasicManager()->OpenDescriptor(mBackBuffer); nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface.Get());
nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface);
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
PaintContext(pat, PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)), nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
@ -377,7 +393,8 @@ public:
} }
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer); virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
already_AddRefed<gfxASurface> GetAsSurface(); virtual bool GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor);
protected: protected:
BasicShadowLayerManager* BasicManager() BasicShadowLayerManager* BasicManager()
@ -393,18 +410,17 @@ void
BasicShadowImageLayer::Swap(const SharedImage& aNewFront, BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
SharedImage* aNewBack) SharedImage* aNewBack)
{ {
nsRefPtr<gfxASurface> surface = AutoOpenSurface autoSurface(OPEN_READ_ONLY, aNewFront);
BasicManager()->OpenDescriptor(aNewFront);
// Destroy mFrontBuffer if size different or image type is different // Destroy mFrontBuffer if size different or image type is different
bool surfaceConfigChanged = surface->GetSize() != mSize; bool surfaceConfigChanged = autoSurface.Size() != mSize;
if (IsSurfaceDescriptorValid(mFrontBuffer)) { if (IsSurfaceDescriptorValid(mFrontBuffer)) {
nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontBuffer); AutoOpenSurface autoFront(OPEN_READ_ONLY, mFrontBuffer);
surfaceConfigChanged = surfaceConfigChanged || surfaceConfigChanged = surfaceConfigChanged ||
surface->GetContentType() != front->GetContentType(); autoSurface.ContentType() != autoFront.ContentType();
} }
if (surfaceConfigChanged) { if (surfaceConfigChanged) {
DestroyFrontBuffer(); DestroyFrontBuffer();
mSize = surface->GetSize(); mSize = autoSurface.Size();
} }
// If mFrontBuffer // If mFrontBuffer
@ -413,7 +429,7 @@ BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
} else { } else {
*aNewBack = null_t(); *aNewBack = null_t();
} }
mFrontBuffer = aNewFront.get_SurfaceDescriptor(); mFrontBuffer = aNewFront;
} }
void void
@ -423,9 +439,8 @@ BasicShadowImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
return; return;
} }
nsRefPtr<gfxASurface> surface = AutoOpenSurface autoSurface(OPEN_READ_ONLY, mFrontBuffer);
BasicManager()->OpenDescriptor(mFrontBuffer); nsRefPtr<gfxPattern> pat = new gfxPattern(autoSurface.Get());
nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
pat->SetFilter(mFilter); pat->SetFilter(mFilter);
// The visible region can extend outside the image, so just draw // The visible region can extend outside the image, so just draw
@ -437,14 +452,16 @@ BasicShadowImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
aMaskLayer); aMaskLayer);
} }
already_AddRefed<gfxASurface> bool
BasicShadowImageLayer::GetAsSurface() BasicShadowImageLayer::GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor)
{ {
if (!IsSurfaceDescriptorValid(mFrontBuffer)) { if (!IsSurfaceDescriptorValid(mFrontBuffer)) {
return nsnull; return false;
} }
return BasicManager()->OpenDescriptor(mFrontBuffer); *aDescriptor = mFrontBuffer;
return true;
} }
already_AddRefed<ImageLayer> already_AddRefed<ImageLayer>

View File

@ -101,11 +101,14 @@ public:
/** /**
* Return a surface for this layer. Will use an existing surface, if * Return a surface for this layer. Will use an existing surface, if
* possible, or may create a temporary surface. * possible, or may create a temporary surface. Implement this
* Implement this method for any layers that might be used as a mask. * method for any layers that might be used as a mask. Should only
* Should only return null if a surface cannor be created. * return false if a surface cannot be created. If true is
* returned, only one of |aSurface| or |aDescriptor| is valid.
*/ */
virtual already_AddRefed<gfxASurface> GetAsSurface() { return nsnull; } virtual bool GetAsSurface(gfxASurface** aSurface,
SurfaceDescriptor* aDescriptor)
{ return false; }
bool GetClipToVisibleRegion() { return mClipToVisibleRegion; } bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; } void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }

View File

@ -10,6 +10,7 @@
#include "gfxSharedImageSurface.h" #include "gfxSharedImageSurface.h"
#include "gfxImageSurface.h" #include "gfxImageSurface.h"
#include "gfxUtils.h" #include "gfxUtils.h"
#include "nsXULAppAPI.h"
#include "RenderTrace.h" #include "RenderTrace.h"
#include "sampler.h" #include "sampler.h"
@ -24,7 +25,7 @@
using namespace mozilla::gfx; using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
/** /**
* Clips to the smallest device-pixel-aligned rectangle containing aRect * Clips to the smallest device-pixel-aligned rectangle containing aRect
@ -839,7 +840,6 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion()); gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
} }
AutoSetOperator setOperator(aTarget, container->GetOperator()); AutoSetOperator setOperator(aTarget, container->GetOperator());
gfxMatrix temp = aTarget->CurrentMatrix();
PaintWithMask(aTarget, aLayer->GetEffectiveOpacity(), PaintWithMask(aTarget, aLayer->GetEffectiveOpacity(),
HasShadowManager() ? nsnull : aLayer->GetMaskLayer()); HasShadowManager() ? nsnull : aLayer->GetMaskLayer());
} }
@ -951,7 +951,8 @@ BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
// If we have a non-default target, we need to let our shadow manager draw // If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction. // to it. This will happen at the end of the transaction.
if (aTarget && (aTarget != mDefaultTarget)) { if (aTarget && (aTarget != mDefaultTarget) &&
XRE_GetProcessType() == GeckoProcessType_Default) {
mShadowTarget = aTarget; mShadowTarget = aTarget;
// Create a temporary target for ourselves, so that mShadowTarget is only // Create a temporary target for ourselves, so that mShadowTarget is only
@ -1048,13 +1049,12 @@ BasicShadowLayerManager::ForwardTransaction()
layer->SetBackBuffer(newBack.get_SurfaceDescriptor()); layer->SetBackBuffer(newBack.get_SurfaceDescriptor());
} else if (newBack.type() == SharedImage::TYUVImage) { } else if (newBack.type() == SharedImage::TYUVImage) {
const YUVImage& yuv = newBack.get_YUVImage(); const YUVImage& yuv = newBack.get_YUVImage();
nsRefPtr<gfxSharedImageSurface> YSurf = gfxSharedImageSurface::Open(yuv.Ydata()); layer->SetBackBufferYUVImage(yuv.Ydata(), yuv.Udata(), yuv.Vdata());
nsRefPtr<gfxSharedImageSurface> USurf = gfxSharedImageSurface::Open(yuv.Udata());
nsRefPtr<gfxSharedImageSurface> VSurf = gfxSharedImageSurface::Open(yuv.Vdata());
layer->SetBackBufferYUVImage(YSurf, USurf, VSurf);
} else { } else {
layer->SetBackBuffer(SurfaceDescriptor()); layer->SetBackBuffer(SurfaceDescriptor());
layer->SetBackBufferYUVImage(nsnull, nsnull, nsnull); layer->SetBackBufferYUVImage(SurfaceDescriptor(),
SurfaceDescriptor(),
SurfaceDescriptor());
} }
break; break;
@ -1127,7 +1127,7 @@ BasicShadowLayerManager::CreateThebesLayer()
} }
} }
BasicShadowableLayer::~BasicShadowableLayer() BasicShadowableLayer::~BasicShadowableLayer()
{ {
if (HasShadow()) { if (HasShadow()) {

View File

@ -279,11 +279,11 @@ public:
NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks"); NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
} }
virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer, virtual void SetBackBufferYUVImage(const SurfaceDescriptor& aYBuffer,
gfxSharedImageSurface* aUBuffer, const SurfaceDescriptor& aUBuffer,
gfxSharedImageSurface* aVBuffer) const SurfaceDescriptor& aVBuffer)
{ {
NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks"); NS_RUNTIMEABORT("if this default impl is called, the buffers leak");
} }
virtual void Disconnect() virtual void Disconnect()

View File

@ -4,65 +4,114 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BasicLayersImpl.h" #include "BasicLayersImpl.h"
#include "mozilla/layers/PLayers.h"
using namespace mozilla::gfx; using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
already_AddRefed<gfxASurface> void
GetMaskSurfaceAndTransform(Layer* aMaskLayer, gfxMatrix* aMaskTransform) AutoMaskData::Construct(const gfxMatrix& aTransform,
gfxASurface* aSurface)
{ {
if (aMaskLayer) { MOZ_ASSERT(!IsConstructed());
nsRefPtr<gfxASurface> maskSurface = mTransform = aTransform;
static_cast<BasicImplData*>(aMaskLayer->ImplData())->GetAsSurface(); mSurface = aSurface;
if (maskSurface) {
bool maskIs2D =
aMaskLayer->GetEffectiveTransform().CanDraw2D(aMaskTransform);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
return maskSurface.forget();
}
}
return nsnull;
} }
void
AutoMaskData::Construct(const gfxMatrix& aTransform,
const SurfaceDescriptor& aSurface)
{
MOZ_ASSERT(!IsConstructed());
mTransform = aTransform;
mSurfaceOpener.construct(OPEN_READ_ONLY, aSurface);
}
gfxASurface*
AutoMaskData::GetSurface()
{
MOZ_ASSERT(IsConstructed());
if (mSurface) {
return mSurface.get();
}
return mSurfaceOpener.ref().Get();
}
const gfxMatrix&
AutoMaskData::GetTransform()
{
MOZ_ASSERT(IsConstructed());
return mTransform;
}
bool
AutoMaskData::IsConstructed()
{
return !!mSurface || !mSurfaceOpener.empty();
}
bool
GetMaskData(Layer* aMaskLayer, AutoMaskData* aMaskData)
{
if (aMaskLayer) {
nsRefPtr<gfxASurface> surface;
SurfaceDescriptor descriptor;
if (static_cast<BasicImplData*>(aMaskLayer->ImplData())
->GetAsSurface(getter_AddRefs(surface), &descriptor) &&
(surface || IsSurfaceDescriptorValid(descriptor))) {
gfxMatrix transform;
DebugOnly<bool> maskIs2D =
aMaskLayer->GetEffectiveTransform().CanDraw2D(&transform);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
if (surface) {
aMaskData->Construct(transform, surface);
} else {
aMaskData->Construct(transform, descriptor);
}
return true;
}
}
return false;
}
void void
PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer) PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{ {
gfxMatrix maskTransform; AutoMaskData mask;
if (nsRefPtr<gfxASurface> maskSurface = if (GetMaskData(aMaskLayer, &mask)) {
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
if (aOpacity < 1.0) { if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->Paint(aOpacity); aContext->Paint(aOpacity);
aContext->PopGroupToSource(); aContext->PopGroupToSource();
} }
aContext->SetMatrix(maskTransform); aContext->SetMatrix(mask.GetTransform());
aContext->Mask(maskSurface); aContext->Mask(mask.GetSurface());
return; return;
} }
// if there is no mask, just paint normally // if there is no mask, just paint normally
aContext->Paint(aOpacity); aContext->Paint(aOpacity);
} }
void void
FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer) FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{ {
gfxMatrix maskTransform; AutoMaskData mask;
if (nsRefPtr<gfxASurface> maskSurface = if (GetMaskData(aMaskLayer, &mask)) {
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
if (aOpacity < 1.0) { if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->FillWithOpacity(aOpacity); aContext->FillWithOpacity(aOpacity);
aContext->PopGroupToSource(); aContext->PopGroupToSource();
aContext->SetMatrix(maskTransform); aContext->SetMatrix(mask.GetTransform());
aContext->Mask(maskSurface); aContext->Mask(mask.GetSurface());
} else { } else {
aContext->Save(); aContext->Save();
aContext->Clip(); aContext->Clip();
aContext->SetMatrix(maskTransform); aContext->SetMatrix(mask.GetTransform());
aContext->Mask(maskSurface); aContext->Mask(mask.GetSurface());
aContext->NewPath(); aContext->NewPath();
aContext->Restore(); aContext->Restore();
} }
@ -71,8 +120,8 @@ FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
// if there is no mask, just fill normally // if there is no mask, just fill normally
aContext->FillWithOpacity(aOpacity); aContext->FillWithOpacity(aOpacity);
} }
BasicImplData* BasicImplData*
ToData(Layer* aLayer) ToData(Layer* aLayer)
{ {
@ -96,6 +145,6 @@ ShouldShadow(Layer* aLayer)
return true; return true;
} }
} }
} }

View File

@ -6,6 +6,7 @@
#ifndef GFX_BASICLAYERSIMPL_H #ifndef GFX_BASICLAYERSIMPL_H
#define GFX_BASICLAYERSIMPL_H #define GFX_BASICLAYERSIMPL_H
#include "ipc/AutoOpenSurface.h"
#include "ipc/ShadowLayerChild.h" #include "ipc/ShadowLayerChild.h"
#include "BasicLayers.h" #include "BasicLayers.h"
#include "BasicImplData.h" #include "BasicImplData.h"
@ -62,14 +63,58 @@ protected:
} }
}; };
/**
* Drawing with a mask requires a mask surface and a transform.
* Sometimes the mask surface is a direct gfxASurface, but other times
* it's a SurfaceDescriptor. For SurfaceDescriptor, we need to use a
* scoped AutoOpenSurface to get a gfxASurface for the
* SurfaceDescriptor.
*
* This helper class manages the gfxASurface-or-SurfaceDescriptor
* logic.
*/
class NS_STACK_CLASS AutoMaskData {
public:
AutoMaskData() { }
~AutoMaskData() { }
/**
* Construct this out of either a gfxASurface or a
* SurfaceDescriptor. Construct() must only be called once.
* GetSurface() and GetTransform() must not be called until this has
* been constructed.
*/
void Construct(const gfxMatrix& aTransform,
gfxASurface* aSurface);
void Construct(const gfxMatrix& aTransform,
const SurfaceDescriptor& aSurface);
/** The returned surface can't escape the scope of |this|. */
gfxASurface* GetSurface();
const gfxMatrix& GetTransform();
private:
bool IsConstructed();
gfxMatrix mTransform;
nsRefPtr<gfxASurface> mSurface;
Maybe<AutoOpenSurface> mSurfaceOpener;
AutoMaskData(const AutoMaskData&) MOZ_DELETE;
AutoMaskData& operator=(const AutoMaskData&) MOZ_DELETE;
};
/* /*
* Extract a mask surface for a mask layer * Extract a mask surface for a mask layer
* Returns a surface for the mask layer if a mask layer is present and has a * Returns true and through outparams a surface for the mask layer if
* valid surface and transform; nsnull otherwise. * a mask layer is present and has a valid surface and transform;
* The transform for the layer will be put in aMaskTransform * false otherwise.
* The transform for the layer will be put in aMaskData
*/ */
already_AddRefed<gfxASurface> bool
GetMaskSurfaceAndTransform(Layer* aMaskLayer, gfxMatrix* aMaskTransform); GetMaskData(Layer* aMaskLayer, AutoMaskData* aMaskData);
// Paint the current source to a context using a mask, if present // Paint the current source to a context using a mask, if present
void void
@ -117,7 +162,7 @@ MaybeCreateShadowFor(BasicShadowableLayer* aLayer,
aLayer->SetShadow(shadow); aLayer->SetShadow(shadow);
(aMgr->*aMethod)(aLayer); (aMgr->*aMethod)(aLayer);
aMgr->Hold(aLayer->AsLayer()); aMgr->Hold(aLayer->AsLayer());
} }
#define MAYBE_CREATE_SHADOW(_type) \ #define MAYBE_CREATE_SHADOW(_type) \
MaybeCreateShadowFor(layer, this, \ MaybeCreateShadowFor(layer, this, \

View File

@ -228,6 +228,58 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
} }
} }
/**
* AutoOpenBuffer is a helper that builds on top of AutoOpenSurface,
* which we need to get a gfxASurface from a SurfaceDescriptor. For
* other layer types, simple lexical scoping of AutoOpenSurface is
* easy. For ThebesLayers, the lifetime of buffer mappings doesn't
* exactly match simple lexical scopes, so naively putting
* AutoOpenSurfaces on the stack doesn't always work. We use this
* helper to track openings instead.
*
* Any surface that's opened while painting this ThebesLayer will
* notify this helper and register itself for unmapping.
*
* We ignore buffer destruction here because the shadow layers
* protocol already ensures that destroyed buffers stay alive until
* end-of-transaction.
*/
struct NS_STACK_CLASS AutoBufferTracker {
AutoBufferTracker(BasicShadowableThebesLayer* aLayer)
: mLayer(aLayer)
{
MOZ_ASSERT(!mLayer->mBufferTracker);
mLayer->mBufferTracker = this;
if (IsSurfaceDescriptorValid(mLayer->mBackBuffer)) {
mInitialBuffer.construct(OPEN_READ_WRITE, mLayer->mBackBuffer);
mLayer->mBuffer.MapBuffer(mInitialBuffer.ref().Get());
}
}
~AutoBufferTracker() {
mLayer->mBufferTracker = nsnull;
mLayer->mBuffer.UnmapBuffer();
// mInitialBuffer and mNewBuffer will clean up after themselves if
// they were constructed.
}
gfxASurface*
CreatedBuffer(const SurfaceDescriptor& aDescriptor) {
Maybe<AutoOpenSurface>* surface = mNewBuffers.AppendElement();
surface->construct(OPEN_READ_WRITE, aDescriptor);
return surface->ref().Get();
}
Maybe<AutoOpenSurface> mInitialBuffer;
nsAutoTArray<Maybe<AutoOpenSurface>, 2> mNewBuffers;
BasicShadowableThebesLayer* mLayer;
private:
AutoBufferTracker(const AutoBufferTracker&) MOZ_DELETE;
AutoBufferTracker& operator=(const AutoBufferTracker&) MOZ_DELETE;
};
void void
BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext, BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer, Layer* aMaskLayer,
@ -240,6 +292,8 @@ BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
return; return;
} }
AutoBufferTracker tracker(this);
BasicThebesLayer::PaintThebes(aContext, nsnull, aCallback, aCallbackData, aReadback); BasicThebesLayer::PaintThebes(aContext, nsnull, aCallback, aCallbackData, aReadback);
if (aMaskLayer) { if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData()) static_cast<BasicImplData*>(aMaskLayer->ImplData())
@ -280,18 +334,22 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
return; return;
} }
nsRefPtr<gfxASurface> backBuffer; gfxASurface* backBuffer = mBuffer.GetBuffer();
if (!IsSurfaceDescriptorValid(mBackBuffer)) { if (!IsSurfaceDescriptorValid(mBackBuffer)) {
NS_ABORT_IF_FALSE(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer, MOZ_ASSERT(!backBuffer);
"should have a front RO buffer by now"); MOZ_ASSERT(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer);
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer(); const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer()); AutoOpenSurface roFrontBuffer(OPEN_READ_ONLY, roFront.buffer());
backBuffer = CreateBuffer(roFrontBuffer->GetContentType(), roFrontBuffer->GetSize()); AllocBackBuffer(roFrontBuffer.ContentType(), roFrontBuffer.Size());
} else {
backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
} }
mFrontAndBackBufferDiffer = false; mFrontAndBackBufferDiffer = false;
Maybe<AutoOpenSurface> autoBackBuffer;
if (!backBuffer) {
autoBackBuffer.construct(OPEN_READ_WRITE, mBackBuffer);
backBuffer = autoBackBuffer.ref().Get();
}
if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) { if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
// We didn't get back a read-only ref to our old back buffer (the // We didn't get back a read-only ref to our old back buffer (the
// parent's new front buffer). If the parent is pushing updates // parent's new front buffer). If the parent is pushing updates
@ -310,10 +368,10 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
mFrontUpdatedRegion.GetBounds().height)); mFrontUpdatedRegion.GetBounds().height));
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer(); const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer()); AutoOpenSurface autoROFront(OPEN_READ_ONLY, roFront.buffer());
mBuffer.SetBackingBufferAndUpdateFrom( mBuffer.SetBackingBufferAndUpdateFrom(
backBuffer, backBuffer,
roFrontBuffer, roFront.rect(), roFront.rotation(), autoROFront.Get(), roFront.rect(), roFront.rotation(),
mFrontUpdatedRegion); mFrontUpdatedRegion);
mIsNewBuffer = false; mIsNewBuffer = false;
// Now the new back buffer has the same (interesting) pixels as the // Now the new back buffer has the same (interesting) pixels as the
@ -364,6 +422,23 @@ BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
mBackBuffer); mBackBuffer);
} }
void
BasicShadowableThebesLayer::AllocBackBuffer(Buffer::ContentType aType,
const nsIntSize& aSize)
{
// This function may *not* open the buffer it allocates.
if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
aType,
&mBackBuffer)) {
enum { buflen = 256 };
char buf[buflen];
PR_snprintf(buf, buflen,
"creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
aSize.width, aSize.height, int(aType));
NS_RUNTIMEABORT(buf);
}
}
already_AddRefed<gfxASurface> already_AddRefed<gfxASurface>
BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType, BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
const nsIntSize& aSize) const nsIntSize& aSize)
@ -382,24 +457,15 @@ BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
mBackBuffer = SurfaceDescriptor(); mBackBuffer = SurfaceDescriptor();
} }
// XXX error handling AllocBackBuffer(aType, aSize);
if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
aType,
&mBackBuffer)) {
enum { buflen = 256 };
char buf[buflen];
PR_snprintf(buf, buflen,
"creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
aSize.width, aSize.height, int(aType));
NS_RUNTIMEABORT(buf);
}
NS_ABORT_IF_FALSE(!mIsNewBuffer, NS_ABORT_IF_FALSE(!mIsNewBuffer,
"Bad! Did we create a buffer twice without painting?"); "Bad! Did we create a buffer twice without painting?");
mIsNewBuffer = true; mIsNewBuffer = true;
return BasicManager()->OpenDescriptor(mBackBuffer); nsRefPtr<gfxASurface> buffer = mBufferTracker->CreatedBuffer(mBackBuffer);
return buffer.forget();
} }
void void
@ -483,12 +549,10 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
OptionalThebesBuffer* aReadOnlyFront, OptionalThebesBuffer* aReadOnlyFront,
nsIntRegion* aFrontUpdatedRegion) nsIntRegion* aFrontUpdatedRegion)
{ {
nsRefPtr<gfxASurface> newFrontBuffer =
BasicManager()->OpenDescriptor(aNewFront.buffer());
if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) { if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
nsRefPtr<gfxASurface> currentFront = BasicManager()->OpenDescriptor(mFrontBufferDescriptor); AutoOpenSurface autoNewFrontBuffer(OPEN_READ_ONLY, aNewFront.buffer());
if (currentFront->GetSize() != newFrontBuffer->GetSize()) { AutoOpenSurface autoCurrentFront(OPEN_READ_ONLY, mFrontBufferDescriptor);
if (autoCurrentFront.Size() != autoNewFrontBuffer.Size()) {
// Current front buffer is obsolete // Current front buffer is obsolete
DestroyFrontBuffer(); DestroyFrontBuffer();
} }
@ -504,12 +568,11 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
// They might overlap with our old pixels. // They might overlap with our old pixels.
aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion); aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
nsRefPtr<gfxASurface> unused;
nsIntRect backRect; nsIntRect backRect;
nsIntPoint backRotation; nsIntPoint backRotation;
mFrontBuffer.Swap( mFrontBuffer.Swap(
newFrontBuffer, aNewFront.rect(), aNewFront.rotation(), aNewFront.rect(), aNewFront.rotation(),
getter_AddRefs(unused), &backRect, &backRotation); &backRect, &backRotation);
if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) { if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) {
aNewBack->get_ThebesBuffer().rect() = backRect; aNewBack->get_ThebesBuffer().rect() = backRect;
@ -534,11 +597,16 @@ BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
NS_ASSERTION(BasicManager()->IsRetained(), NS_ASSERTION(BasicManager()->IsRetained(),
"ShadowThebesLayer makes no sense without retained mode"); "ShadowThebesLayer makes no sense without retained mode");
if (!mFrontBuffer.GetBuffer()) { if (!IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
return; return;
} }
AutoOpenSurface autoFrontBuffer(OPEN_READ_ONLY, mFrontBufferDescriptor);
mFrontBuffer.MapBuffer(autoFrontBuffer.Get());
mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer); mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer);
mFrontBuffer.UnmapBuffer();
} }
already_AddRefed<ThebesLayer> already_AddRefed<ThebesLayer>

View File

@ -103,14 +103,19 @@ protected:
Buffer mBuffer; Buffer mBuffer;
}; };
struct AutoBufferTracker;
class BasicShadowableThebesLayer : public BasicThebesLayer, class BasicShadowableThebesLayer : public BasicThebesLayer,
public BasicShadowableLayer public BasicShadowableLayer
{ {
friend struct AutoBufferTracker;
typedef BasicThebesLayer Base; typedef BasicThebesLayer Base;
public: public:
BasicShadowableThebesLayer(BasicShadowLayerManager* aManager) BasicShadowableThebesLayer(BasicShadowLayerManager* aManager)
: BasicThebesLayer(aManager) : BasicThebesLayer(aManager)
, mBufferTracker(nsnull)
, mIsNewBuffer(false) , mIsNewBuffer(false)
, mFrontAndBackBufferDiffer(false) , mFrontAndBackBufferDiffer(false)
{ {
@ -163,6 +168,10 @@ private:
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData) MOZ_OVERRIDE; void* aCallbackData) MOZ_OVERRIDE;
// This function may *not* open the buffer it allocates.
void
AllocBackBuffer(Buffer::ContentType aType, const nsIntSize& aSize);
virtual already_AddRefed<gfxASurface> virtual already_AddRefed<gfxASurface>
CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE; CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
@ -180,6 +189,12 @@ private:
nsIntRect mBackBufferRect; nsIntRect mBackBufferRect;
nsIntPoint mBackBufferRectRotation; nsIntPoint mBackBufferRectRotation;
// This helper object lives on the stack during its lifetime and
// keeps track of buffers we might have mapped and/or allocated.
// When it goes out of scope on the stack, it unmaps whichever
// buffers have been mapped (if any).
AutoBufferTracker* mBufferTracker;
bool mIsNewBuffer; bool mIsNewBuffer;
OptionalThebesBuffer mROFrontBuffer; OptionalThebesBuffer mROFrontBuffer;
nsIntRegion mFrontUpdatedRegion; nsIntRegion mFrontUpdatedRegion;

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