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
// nsIAccessibleTable
NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::)
// Accessible
virtual TableAccessible* AsTable() { return this; }

View File

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

View File

@ -65,65 +65,4 @@ protected:
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_

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@ ContentPermissionPrompt.prototype = {
return;
let browser = Services.wm.getMostRecentWindow("navigator:browser");
let content = browser.content;
let content = browser.getContentWindow();
if (!content)
return;
@ -42,8 +42,8 @@ ContentPermissionPrompt.prototype = {
content.addEventListener("mozContentEvent", function contentEvent(evt) {
if (evt.detail.id != requestId)
return;
evt.target.removeEventListener(evt.type, contentEvent);
content.removeEventListener(evt.type, contentEvent);
if (evt.detail.type == "permission-allow") {
request.allow();
return;
@ -52,10 +52,15 @@ ContentPermissionPrompt.prototype = {
request.cancel();
});
browser.shell.sendEvent(browser.content, "mozChromeEvent", {
"type": "permission-prompt", "permission": request.type,
"id": requestId, "url": request.uri.spec
});
let details = {
"type": "permission-prompt",
"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}"),

View File

@ -140,6 +140,12 @@ var gPluginHandler = {
self.pluginUnavailable(plugin, event.type);
break;
case "PluginVulnerableUpdatable":
let updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
self.addLinkClickCallback(updateLink, "openPluginUpdatePage");
/* FALLTHRU */
case "PluginVulnerableNoUpdate":
case "PluginClickToPlay":
self._handleClickToPlayEvent(plugin);
break;
@ -151,9 +157,10 @@ var gPluginHandler = {
}
// 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");
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";
}
},
@ -225,6 +232,12 @@ var gPluginHandler = {
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
// Callback for user clicking "submit a report" link
submitReport : function(pluginDumpID, browserDumpID) {
@ -258,15 +271,18 @@ var gPluginHandler = {
objLoadingContent.playPlugin();
return;
} else if (pluginsPermission == Ci.nsIPermissionManager.DENY_ACTION) {
if (overlay)
overlay.style.visibility = "hidden";
return;
}
let overlay = doc.getAnonymousElementByAttribute(aPlugin, "class", "mainBox");
// The overlay is null if the XBL binding is not attached (element is display:none).
if (overlay) {
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);
}, true);
}

View File

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

View File

@ -517,5 +517,103 @@ function test17() {
var missingNotification = PopupNotifications.getNotification("missing-plugins", gTestBrowser);
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();
}

View File

@ -57,6 +57,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_pause-exceptions.js \
browser_dbg_multiple-windows.js \
browser_dbg_menustatus.js \
browser_dbg_bfcache.js \
head.js \
$(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

@ -510,6 +510,27 @@ class DeviceManager:
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:
def __init__(self):
pass

View File

@ -95,24 +95,13 @@ class DeviceManagerADB(DeviceManager):
# success: <return code>
# failure: 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,
# 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
if cwd:

View File

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

View File

@ -191,7 +191,7 @@ endif
profiledbuild::
$(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)
$(MAKE) -f $(TOPSRCDIR)/client.mk maybe_clobber_profiledbuild
$(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
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
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_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 {
public:
nsObjectLoadingContent *mContent;
@ -181,6 +167,12 @@ nsPluginErrorEvent::Run()
case ePluginClickToPlay:
type = NS_LITERAL_STRING("PluginClickToPlay");
break;
case ePluginVulnerableUpdatable:
type = NS_LITERAL_STRING("PluginVulnerableUpdatable");
break;
case ePluginVulnerableNoUpdate:
type = NS_LITERAL_STRING("PluginVulnerableNoUpdate");
break;
case ePluginUnsupported:
type = NS_LITERAL_STRING("PluginNotFound");
break;
@ -484,7 +476,11 @@ nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMETy
return rv;
}
if (!mShouldPlay) {
if (!pluginHost->IsPluginClickToPlayForType(aMIMEType.get())) {
mCTPPlayable = true;
}
if (!mCTPPlayable) {
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
MOZ_ASSERT(thisContent);
nsIDocument* ownerDoc = thisContent->OwnerDoc();
@ -505,12 +501,17 @@ nsresult nsObjectLoadingContent::IsPluginEnabledForType(const nsCString& aMIMETy
nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 permission;
rv = permissionManager->TestPermission(topUri,
"plugins",
&permission);
rv = permissionManager->TestPermission(topUri, "plugins", &permission);
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 {
return NS_ERROR_PLUGIN_CLICKTOPLAY;
}
@ -542,12 +543,9 @@ GetExtensionFromURI(nsIURI* uri, nsCString& ext)
*/
bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
{
if (!mShouldPlay) {
return false;
}
nsCAutoString ext;
GetExtensionFromURI(uri, ext);
bool enabled = false;
if (ext.IsEmpty()) {
return false;
@ -562,9 +560,18 @@ bool nsObjectLoadingContent::IsPluginEnabledByExtension(nsIURI* uri, nsCString&
const char* typeFromExt;
if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
mimeType = typeFromExt;
return true;
enabled = true;
if (!pluginHost->IsPluginClickToPlayForType(mimeType.get())) {
mCTPPlayable = true;
}
}
if (!mCTPPlayable) {
return false;
} else {
return enabled;
}
}
nsresult
@ -598,13 +605,8 @@ nsObjectLoadingContent::nsObjectLoadingContent()
, mIsStopping(false)
, mSrcStreamLoading(false)
, mFallbackReason(ePluginOtherState)
{
InitPrefCache();
// 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;
}
, mCTPPlayable(false)
, mActivated(false) {}
nsObjectLoadingContent::~nsObjectLoadingContent()
{
@ -617,10 +619,6 @@ nsObjectLoadingContent::~nsObjectLoadingContent()
nsresult
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.
if (mInstanceOwner) {
return NS_OK;
@ -665,6 +663,14 @@ nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI*
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
// appShell->SuspendNative() with additional call(s) to
// appShell->ReturnNative().
@ -1191,6 +1197,10 @@ nsObjectLoadingContent::ObjectState() const
switch (mFallbackReason) {
case ePluginClickToPlay:
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:
state |= NS_EVENT_STATE_HANDLER_DISABLED;
break;
@ -1933,8 +1943,10 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
}
PluginSupportState pluginDisabledState = GetPluginDisabledState(aContentType);
if (pluginDisabledState == ePluginClickToPlay) {
return ePluginClickToPlay;
if (pluginDisabledState == ePluginClickToPlay ||
pluginDisabledState == ePluginVulnerableUpdatable ||
pluginDisabledState == ePluginVulnerableNoUpdate) {
return pluginDisabledState;
} else if (hasAlternateContent) {
return ePluginOtherState;
} else {
@ -1946,12 +1958,28 @@ PluginSupportState
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
{
nsresult rv = IsPluginEnabledForType(aContentType);
if (rv == NS_ERROR_PLUGIN_DISABLED)
if (rv == NS_ERROR_PLUGIN_DISABLED) {
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;
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
}
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED) {
return ePluginBlocklisted;
}
return ePluginUnsupported;
}
@ -2213,7 +2241,7 @@ nsObjectLoadingContent::PlayPlugin()
if (!nsContentUtils::IsCallerChrome())
return NS_OK;
mShouldPlay = true;
mCTPPlayable = true;
return LoadObject(mURI, true, mContentType, true);
}

View File

@ -38,7 +38,9 @@ enum PluginSupportState {
ePluginOutdated, // The plugin is considered outdated, but not disabled
ePluginOtherState, // Something else (e.g. uninitialized or not a plugin)
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.
bool mNetworkCreated : 1;
// Used to keep track of whether or not a plugin should be played.
// This is used for click-to-play plugins.
bool mShouldPlay : 1;
// Used to keep track of if a plugin is blocked by click-to-play.
// True indicates the plugin is not click-to-play or it has been clicked by
// 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.
// 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)
// Content is in the sub-suboptimal region.
#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!

View File

@ -282,7 +282,9 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener,
aTypeAtom == nsGkAtoms::ontouchcancel)) {
mMayHaveTouchEventListener = true;
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();
} else if (aTypeAtom == nsGkAtoms::onmouseenter ||
aTypeAtom == nsGkAtoms::onmouseleave) {

View File

@ -1848,12 +1848,6 @@ nsXBLPrototypeBinding::ReadContentNode(nsIObjectInputStream* aStream,
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;
if (attrCount > 0) {
attrs = new nsXULPrototypeAttribute[attrCount];
@ -1892,6 +1886,12 @@ nsXBLPrototypeBinding::ReadContentNode(nsIObjectInputStream* aStream,
rv = prototype->SetAttrAt(i, val, documentURI);
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 {
#endif

View File

@ -107,6 +107,28 @@ ConsoleAPI.prototype = {
timeEnd: function CA_timeEnd() {
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__: {
log: "r",
info: "r",
@ -119,7 +141,9 @@ ConsoleAPI.prototype = {
groupCollapsed: "r",
groupEnd: "r",
time: "r",
timeEnd: "r"
timeEnd: "r",
profile: "r",
profileEnd: "r"
}
};
@ -143,6 +167,8 @@ ConsoleAPI.prototype = {
groupEnd: genPropDesc('groupEnd'),
time: genPropDesc('time'),
timeEnd: genPropDesc('timeEnd'),
profile: genPropDesc('profile'),
profileEnd: genPropDesc('profileEnd'),
__noSuchMethod__: { enumerable: true, configurable: true, writable: true,
value: function() {} },
__mozillaConsole__: { value: true }

View File

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

View File

@ -10,9 +10,8 @@
function testSteps()
{
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.onsuccess = grabEventAndContinueHandler;
let event = yield;

View File

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

View File

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

View File

@ -13,7 +13,6 @@
function testSteps()
{
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
@ -35,7 +34,7 @@
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,8 +15,8 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const databaseInfo = [
{ name: window.location.pathname + "1", description: "Test Database 1" },
{ name: window.location.pathname + "2", description: "Test Database 2" }
{ name: window.location.pathname + "1" },
{ name: window.location.pathname + "2" }
];
const objectStoreName = "Blobs";
@ -25,7 +25,7 @@
let databases = [];
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
@ -24,7 +23,7 @@
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
@ -67,7 +66,7 @@
ok(hasFileInfo(name, 3), "Correct ref count");
{
let request = indexedDB.open(name, 1, description);
let request = indexedDB.open(name, 1);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
@ -25,7 +24,7 @@
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
@ -25,7 +24,7 @@
const objectData1 = { key: 1, object: { foo: blob, bar: blob } };
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
const blobData = { key: 1, blob: getRandomBlob(10000) };
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

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

View File

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

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
@ -72,7 +71,7 @@
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.onsuccess = grabEventAndContinueHandler;
let event = yield;

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,7 +15,6 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreInfo = [
{ name: "Blobs", options: { } },
@ -24,7 +23,7 @@
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,14 +15,13 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const name = window.location.pathname;
const description = "My Test Database";
const objectStoreName = "Blobs";
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -16,9 +16,8 @@
const DEFAULT_QUOTA_MB = 50;
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -15,8 +15,8 @@
const READ_WRITE = IDBTransaction.READ_WRITE;
const databaseInfo = [
{ name: window.location.pathname + "1", description: "Test Database 1" },
{ name: window.location.pathname + "2", description: "Test Database 2" }
{ name: window.location.pathname + "1" },
{ name: window.location.pathname + "2" }
];
const objectStoreName = "Blobs";
@ -25,7 +25,7 @@
let databases = [];
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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

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

View File

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

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps()
{
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.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;

View File

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

View File

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

View File

@ -8,13 +8,12 @@ var testGenerator = testSteps();
function testSteps()
{
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 sortedKeys = [-1, 0, 1, 10, 2000, "a", "b", "q", "two", "z"];
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.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;

View File

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

View File

@ -8,11 +8,10 @@ var testGenerator = testSteps();
function testSteps()
{
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 ];
let request = indexedDB.open(name, 1, description);
let request = indexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;

View File

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

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps()
{
const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People";
const objectStoreData = [
@ -52,7 +51,7 @@ function testSteps()
{ 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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps()
{
const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People";
const objectStoreData = [
@ -52,7 +51,7 @@ function testSteps()
{ 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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps()
{
const name = this.window ? this.window ? window.location.pathname : "Splendid Test" : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People";
@ -53,7 +52,7 @@ function testSteps()
{ 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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,7 +8,6 @@ var testGenerator = testSteps();
function testSteps()
{
const name = this.window ? window.location.pathname : "Splendid Test";
const description = "My Test Database";
const objectStoreName = "People";
@ -39,7 +38,7 @@ function testSteps()
{ 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.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps()
{
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.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;

View File

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

View File

@ -9,9 +9,8 @@ function testSteps()
{
const IDBObjectStore = Components.interfaces.nsIIDBObjectStore;
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.onupgradeneeded = grabEventAndContinueHandler;
var event = yield;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps()
{
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");
request.onerror = errorHandler;

View File

@ -8,9 +8,8 @@ var testGenerator = testSteps();
function testSteps()
{
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.onsuccess = grabEventAndContinueHandler;
let event = yield;
@ -30,7 +29,7 @@ function testSteps()
for (let i = 0; i < versions.length; i++) {
let version = versions[i];
let request = indexedDB.open(name, version, description);
let request = indexedDB.open(name, version);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield;

View File

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

View File

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

View File

@ -49,6 +49,10 @@ public:
bool
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
the protocol.
*/
@ -135,7 +139,7 @@ CrashReporterParent::GenerateCrashReport(Toplevel* t,
const AnnotationTable* processNotes)
{
nsCOMPtr<nsIFile> crashDump;
if (t->TakeMinidump(getter_AddRefs(crashDump)) &&
if (t->TakeMinidump(getter_AddRefs(crashDump), NULL) &&
CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) {
return GenerateChildData(processNotes);
}

View File

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

View File

@ -342,8 +342,10 @@ nsPluginHost::nsPluginHost()
Preferences::GetBool("plugin.override_internal_types", false);
mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
mPluginsClickToPlay = Preferences::GetBool("plugins.click_to_play", false);
Preferences::AddStrongObserver(this, "plugin.disable");
Preferences::AddStrongObserver(this, "plugins.click_to_play");
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
@ -1295,6 +1297,36 @@ nsPluginHost::IsPluginEnabledForType(const char* aMimeType)
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
static int CompareExtensions(const char *aExtensionList, const char *aExtension)
{
@ -2074,19 +2106,32 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
EmptyString(), &state);
if (NS_SUCCEEDED(rv)) {
// If the blocklist says so then block the plugin. If the blocklist says
// it is risky and we have never seen this plugin before then disable it
if (state == nsIBlocklistService::STATE_BLOCKED)
// If the blocklist says so, block the plugin.
// If the blocklist says it is risky and we have never seen this
// plugin before, then disable it.
// If the blocklist says this is an outdated plugin, warn about
// outdated plugins.
// If the blocklist says the plugin is one of the click-to-play
// states, set the click-to-play flag.
if (state == nsIBlocklistService::STATE_BLOCKED) {
pluginTag->Mark(NS_PLUGIN_FLAG_BLOCKLISTED);
else if (state == nsIBlocklistService::STATE_SOFTBLOCKED && !seenBefore)
}
if (state == nsIBlocklistService::STATE_SOFTBLOCKED && !seenBefore) {
enabled = false;
else if (state == nsIBlocklistService::STATE_OUTDATED && !seenBefore)
}
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);
}
// 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.
@ -3302,6 +3347,7 @@ NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
}
if (!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
mPluginsClickToPlay = Preferences::GetBool("plugins.click_to_play", false);
// Unload or load plugins as needed
if (mPluginsDisabled) {
UnloadPlugins();

View File

@ -85,6 +85,8 @@ public:
nsIPluginInstanceOwner *aOwner);
nsresult IsPluginEnabledForType(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 GetPlugins(PRUint32 aPluginCount, nsIDOMPlugin** aPluginArray);
@ -281,6 +283,8 @@ private:
// set by pref plugin.disable
bool mPluginsDisabled;
// set by pref plugins.click_to_play
bool mPluginsClickToPlay;
// 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.

View File

@ -320,6 +320,30 @@ nsPluginTag::SetBlocklisted(bool aBlocklisted)
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)
{
bool wasEnabled = IsEnabled();

View File

@ -27,6 +27,7 @@ struct nsPluginInfo;
#define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache
// 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_CLICKTOPLAY 0x0020 // this is a click-to-play plugin
// A linked-list of plugin information that is used for instantiating plugins
// and reflecting plugin information into JavaScript.

View File

@ -27,9 +27,6 @@
#include "nsAutoPtr.h"
#include "nsCRT.h"
#ifdef MOZ_CRASHREPORTER
#include "mozilla/dom/CrashReporterParent.h"
#endif
#include "nsNPAPIPlugin.h"
#include "nsIFile.h"
@ -49,6 +46,12 @@ using namespace mozilla;
using namespace mozilla::plugins;
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 kParentTimeoutPref[] = "dom.ipc.plugins.parentTimeoutSecs";
static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
@ -133,9 +136,9 @@ PluginModuleParent::~PluginModuleParent()
#ifdef MOZ_CRASHREPORTER_INJECTOR
if (mFlashProcess1)
CrashReporter::UnregisterInjectorCallback(mFlashProcess1);
UnregisterInjectorCallback(mFlashProcess1);
if (mFlashProcess2)
CrashReporter::UnregisterInjectorCallback(mFlashProcess2);
UnregisterInjectorCallback(mFlashProcess2);
#endif
Preferences::UnregisterCallback(TimeoutChanged, kChildTimeoutPref, this);
@ -144,7 +147,7 @@ PluginModuleParent::~PluginModuleParent()
#ifdef MOZ_CRASHREPORTER
void
PluginModuleParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes)
PluginModuleParent::WriteExtraDataForMinidump(AnnotationTable& notes)
{
typedef nsDependentCString CS;
@ -200,7 +203,6 @@ bool
PluginModuleParent::ShouldContinueFromReplyTimeout()
{
#ifdef MOZ_CRASHREPORTER
if (mPluginDumpID.IsEmpty()) {
CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter->GeneratePairedMinidump(this)) {
mBrowserDumpID = crashReporter->ParentDumpID();
@ -213,7 +215,6 @@ PluginModuleParent::ShouldContinueFromReplyTimeout()
} else {
NS_WARNING("failed to capture paired minidumps from hang");
}
}
#endif
// this must run before the error notification from the channel,
@ -237,33 +238,99 @@ PluginModuleParent::CrashReporter()
}
#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
PluginModuleParent::ActorDestroy(ActorDestroyReason why)
{
switch (why) {
case AbnormalShutdown: {
#ifdef MOZ_CRASHREPORTER
CrashReporterParent* crashReporter = CrashReporter();
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!");
}
ProcessFirstMinidump();
#endif
mShutdown = true;
@ -1248,33 +1315,8 @@ PluginModuleParent::InitializeInjector()
}
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();
KillProcess(OtherProcess(), 1, false);
}

View File

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

View File

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

View File

@ -236,9 +236,14 @@ var WifiManager = (function() {
function scanCommand(forceActive, callback) {
if (forceActive && !scanModeActive) {
doSetScanModeCommand(true, function(ok) {
ok && doBooleanCommand("SCAN", "OK", function(ok) {
ok && doSetScanModeCommand(false, callback);
// Note: we ignore errors from doSetScanMode.
doSetScanModeCommand(true, function(ignore) {
doBooleanCommand("SCAN", "OK", function(ok) {
doSetScanModeCommand(false, function(ignore) {
// The result of scanCommand is the result of the actual SCAN
// request.
callback(ok);
});
});
});
return;
@ -603,7 +608,7 @@ var WifiManager = (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
// 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)
{
nsRangeStore &item = mArray[i];
nsRangeStore* item = mArray[i];
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"selection state mArray[i].startNode");
cb.NoteXPCOMChild(item.startNode);
cb.NoteXPCOMChild(item->startNode);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"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++)
{
mArray.AppendElement();
mArray[i] = new nsRangeStore();
}
}
@ -71,7 +72,7 @@ nsSelectionState::SaveSelection(nsISelection *aSel)
{
nsCOMPtr<nsIDOMRange> range;
res = aSel->GetRangeAt(i, getter_AddRefs(range));
mArray[i].StoreRange(range);
mArray[i]->StoreRange(range);
}
return res;
@ -91,7 +92,7 @@ nsSelectionState::RestoreSelection(nsISelection *aSel)
for (i=0; i<arrayCount; i++)
{
nsRefPtr<nsRange> range;
mArray[i].GetRange(getter_AddRefs(range));
mArray[i]->GetRange(getter_AddRefs(range));
NS_ENSURE_TRUE(range, NS_ERROR_UNEXPECTED);
res = aSel->AddRange(range);
@ -106,7 +107,7 @@ nsSelectionState::IsCollapsed()
{
if (1 != mArray.Length()) return false;
nsRefPtr<nsRange> range;
mArray[0].GetRange(getter_AddRefs(range));
mArray[0]->GetRange(getter_AddRefs(range));
NS_ENSURE_TRUE(range, false);
bool bIsCollapsed = false;
range->GetCollapsed(&bIsCollapsed);
@ -124,8 +125,8 @@ nsSelectionState::IsEqual(nsSelectionState *aSelState)
for (i=0; i<myCount; i++)
{
nsRefPtr<nsRange> myRange, itsRange;
mArray[i].GetRange(getter_AddRefs(myRange));
aSelState->mArray[i].GetRange(getter_AddRefs(itsRange));
mArray[i]->GetRange(getter_AddRefs(myRange));
aSelState->mArray[i]->GetRange(getter_AddRefs(itsRange));
NS_ENSURE_TRUE(myRange && itsRange, false);
PRInt16 compResult;
@ -190,7 +191,7 @@ nsRangeUpdater::RegisterSelectionState(nsSelectionState &aSelState)
for (i=0; i<theCount; i++)
{
RegisterRangeItem(&aSelState.mArray[i]);
RegisterRangeItem(aSelState.mArray[i]);
}
return NS_OK;
@ -204,7 +205,7 @@ nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState)
for (i=0; i<theCount; i++)
{
DropRangeItem(&aSelState.mArray[i]);
DropRangeItem(aSelState.mArray[i]);
}
return NS_OK;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -140,6 +140,14 @@ EXPORTS_mozilla/layers += ShadowLayerUtilsD3D10.h
DEFINES += -DMOZ_ENABLE_D3D10_LAYER
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)/ipc/chromium/chromium-config.mk

View File

@ -171,6 +171,16 @@ protected:
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|,
* which must be contained within a single quadrant.

View File

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

View File

@ -58,6 +58,27 @@ public:
gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
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:
BasicThebesLayerBuffer(gfxASurface* aBuffer,
const nsIntRect& aRect, const nsIntPoint& aRotation)
@ -87,18 +108,25 @@ public:
MOZ_COUNT_DTOR(ShadowThebesLayerBuffer);
}
void Swap(gfxASurface* aNewBuffer,
const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
gfxASurface** aOldBuffer,
/**
* Swap in the old "virtual buffer" (see above) attributes in aNew*
* 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)
{
*aOldRect = BufferRect();
*aOldRotation = BufferRotation();
nsRefPtr<gfxASurface> oldBuffer;
oldBuffer = SetBuffer(aNewBuffer,
aNewRect, aNewRotation);
oldBuffer.forget(aOldBuffer);
oldBuffer = SetBuffer(nsnull, aNewRect, aNewRotation);
MOZ_ASSERT(!oldBuffer);
}
protected:

View File

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

View File

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

View File

@ -101,11 +101,14 @@ public:
/**
* Return a surface for this layer. Will use an existing surface, if
* possible, or may create a temporary surface.
* Implement this method for any layers that might be used as a mask.
* Should only return null if a surface cannor be created.
* possible, or may create a temporary surface. Implement this
* method for any layers that might be used as a mask. Should only
* 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; }
void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }

View File

@ -10,6 +10,7 @@
#include "gfxSharedImageSurface.h"
#include "gfxImageSurface.h"
#include "gfxUtils.h"
#include "nsXULAppAPI.h"
#include "RenderTrace.h"
#include "sampler.h"
@ -839,7 +840,6 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
}
AutoSetOperator setOperator(aTarget, container->GetOperator());
gfxMatrix temp = aTarget->CurrentMatrix();
PaintWithMask(aTarget, aLayer->GetEffectiveOpacity(),
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
// 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;
// Create a temporary target for ourselves, so that mShadowTarget is only
@ -1048,13 +1049,12 @@ BasicShadowLayerManager::ForwardTransaction()
layer->SetBackBuffer(newBack.get_SurfaceDescriptor());
} else if (newBack.type() == SharedImage::TYUVImage) {
const YUVImage& yuv = newBack.get_YUVImage();
nsRefPtr<gfxSharedImageSurface> YSurf = gfxSharedImageSurface::Open(yuv.Ydata());
nsRefPtr<gfxSharedImageSurface> USurf = gfxSharedImageSurface::Open(yuv.Udata());
nsRefPtr<gfxSharedImageSurface> VSurf = gfxSharedImageSurface::Open(yuv.Vdata());
layer->SetBackBufferYUVImage(YSurf, USurf, VSurf);
layer->SetBackBufferYUVImage(yuv.Ydata(), yuv.Udata(), yuv.Vdata());
} else {
layer->SetBackBuffer(SurfaceDescriptor());
layer->SetBackBufferYUVImage(nsnull, nsnull, nsnull);
layer->SetBackBufferYUVImage(SurfaceDescriptor(),
SurfaceDescriptor(),
SurfaceDescriptor());
}
break;

View File

@ -279,11 +279,11 @@ public:
NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
}
virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer,
gfxSharedImageSurface* aUBuffer,
gfxSharedImageSurface* aVBuffer)
virtual void SetBackBufferYUVImage(const SurfaceDescriptor& aYBuffer,
const SurfaceDescriptor& aUBuffer,
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()

View File

@ -4,41 +4,91 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BasicLayersImpl.h"
#include "mozilla/layers/PLayers.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
already_AddRefed<gfxASurface>
GetMaskSurfaceAndTransform(Layer* aMaskLayer, gfxMatrix* aMaskTransform)
void
AutoMaskData::Construct(const gfxMatrix& aTransform,
gfxASurface* aSurface)
{
MOZ_ASSERT(!IsConstructed());
mTransform = aTransform;
mSurface = aSurface;
}
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> maskSurface =
static_cast<BasicImplData*>(aMaskLayer->ImplData())->GetAsSurface();
if (maskSurface) {
bool maskIs2D =
aMaskLayer->GetEffectiveTransform().CanDraw2D(aMaskTransform);
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?!");
return maskSurface.forget();
if (surface) {
aMaskData->Construct(transform, surface);
} else {
aMaskData->Construct(transform, descriptor);
}
return true;
}
}
return nsnull;
return false;
}
void
PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
AutoMaskData mask;
if (GetMaskData(aMaskLayer, &mask)) {
if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->Paint(aOpacity);
aContext->PopGroupToSource();
}
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
aContext->SetMatrix(mask.GetTransform());
aContext->Mask(mask.GetSurface());
return;
}
@ -49,20 +99,19 @@ PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
void
FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
AutoMaskData mask;
if (GetMaskData(aMaskLayer, &mask)) {
if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->FillWithOpacity(aOpacity);
aContext->PopGroupToSource();
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
aContext->SetMatrix(mask.GetTransform());
aContext->Mask(mask.GetSurface());
} else {
aContext->Save();
aContext->Clip();
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
aContext->SetMatrix(mask.GetTransform());
aContext->Mask(mask.GetSurface());
aContext->NewPath();
aContext->Restore();
}

View File

@ -6,6 +6,7 @@
#ifndef GFX_BASICLAYERSIMPL_H
#define GFX_BASICLAYERSIMPL_H
#include "ipc/AutoOpenSurface.h"
#include "ipc/ShadowLayerChild.h"
#include "BasicLayers.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
* Returns a surface for the mask layer if a mask layer is present and has a
* valid surface and transform; nsnull otherwise.
* The transform for the layer will be put in aMaskTransform
* Returns true and through outparams a surface for the mask layer if
* a mask layer is present and has a valid surface and transform;
* false otherwise.
* The transform for the layer will be put in aMaskData
*/
already_AddRefed<gfxASurface>
GetMaskSurfaceAndTransform(Layer* aMaskLayer, gfxMatrix* aMaskTransform);
bool
GetMaskData(Layer* aMaskLayer, AutoMaskData* aMaskData);
// Paint the current source to a context using a mask, if present
void

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
BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
@ -240,6 +292,8 @@ BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
return;
}
AutoBufferTracker tracker(this);
BasicThebesLayer::PaintThebes(aContext, nsnull, aCallback, aCallbackData, aReadback);
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
@ -280,18 +334,22 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
return;
}
nsRefPtr<gfxASurface> backBuffer;
gfxASurface* backBuffer = mBuffer.GetBuffer();
if (!IsSurfaceDescriptorValid(mBackBuffer)) {
NS_ABORT_IF_FALSE(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer,
"should have a front RO buffer by now");
MOZ_ASSERT(!backBuffer);
MOZ_ASSERT(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer);
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
backBuffer = CreateBuffer(roFrontBuffer->GetContentType(), roFrontBuffer->GetSize());
} else {
backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
AutoOpenSurface roFrontBuffer(OPEN_READ_ONLY, roFront.buffer());
AllocBackBuffer(roFrontBuffer.ContentType(), roFrontBuffer.Size());
}
mFrontAndBackBufferDiffer = false;
Maybe<AutoOpenSurface> autoBackBuffer;
if (!backBuffer) {
autoBackBuffer.construct(OPEN_READ_WRITE, mBackBuffer);
backBuffer = autoBackBuffer.ref().Get();
}
if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
// 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
@ -310,10 +368,10 @@ BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
mFrontUpdatedRegion.GetBounds().height));
const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
AutoOpenSurface autoROFront(OPEN_READ_ONLY, roFront.buffer());
mBuffer.SetBackingBufferAndUpdateFrom(
backBuffer,
roFrontBuffer, roFront.rect(), roFront.rotation(),
autoROFront.Get(), roFront.rect(), roFront.rotation(),
mFrontUpdatedRegion);
mIsNewBuffer = false;
// Now the new back buffer has the same (interesting) pixels as the
@ -364,6 +422,23 @@ BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
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>
BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
const nsIntSize& aSize)
@ -382,24 +457,15 @@ BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
mBackBuffer = SurfaceDescriptor();
}
// XXX error handling
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);
}
AllocBackBuffer(aType, aSize);
NS_ABORT_IF_FALSE(!mIsNewBuffer,
"Bad! Did we create a buffer twice without painting?");
mIsNewBuffer = true;
return BasicManager()->OpenDescriptor(mBackBuffer);
nsRefPtr<gfxASurface> buffer = mBufferTracker->CreatedBuffer(mBackBuffer);
return buffer.forget();
}
void
@ -483,12 +549,10 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
OptionalThebesBuffer* aReadOnlyFront,
nsIntRegion* aFrontUpdatedRegion)
{
nsRefPtr<gfxASurface> newFrontBuffer =
BasicManager()->OpenDescriptor(aNewFront.buffer());
if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
nsRefPtr<gfxASurface> currentFront = BasicManager()->OpenDescriptor(mFrontBufferDescriptor);
if (currentFront->GetSize() != newFrontBuffer->GetSize()) {
AutoOpenSurface autoNewFrontBuffer(OPEN_READ_ONLY, aNewFront.buffer());
AutoOpenSurface autoCurrentFront(OPEN_READ_ONLY, mFrontBufferDescriptor);
if (autoCurrentFront.Size() != autoNewFrontBuffer.Size()) {
// Current front buffer is obsolete
DestroyFrontBuffer();
}
@ -504,12 +568,11 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
// They might overlap with our old pixels.
aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
nsRefPtr<gfxASurface> unused;
nsIntRect backRect;
nsIntPoint backRotation;
mFrontBuffer.Swap(
newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
getter_AddRefs(unused), &backRect, &backRotation);
aNewFront.rect(), aNewFront.rotation(),
&backRect, &backRotation);
if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) {
aNewBack->get_ThebesBuffer().rect() = backRect;
@ -534,11 +597,16 @@ BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
NS_ASSERTION(BasicManager()->IsRetained(),
"ShadowThebesLayer makes no sense without retained mode");
if (!mFrontBuffer.GetBuffer()) {
if (!IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
return;
}
AutoOpenSurface autoFrontBuffer(OPEN_READ_ONLY, mFrontBufferDescriptor);
mFrontBuffer.MapBuffer(autoFrontBuffer.Get());
mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer);
mFrontBuffer.UnmapBuffer();
}
already_AddRefed<ThebesLayer>

View File

@ -103,14 +103,19 @@ protected:
Buffer mBuffer;
};
struct AutoBufferTracker;
class BasicShadowableThebesLayer : public BasicThebesLayer,
public BasicShadowableLayer
{
friend struct AutoBufferTracker;
typedef BasicThebesLayer Base;
public:
BasicShadowableThebesLayer(BasicShadowLayerManager* aManager)
: BasicThebesLayer(aManager)
, mBufferTracker(nsnull)
, mIsNewBuffer(false)
, mFrontAndBackBufferDiffer(false)
{
@ -163,6 +168,10 @@ private:
LayerManager::DrawThebesLayerCallback aCallback,
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>
CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
@ -180,6 +189,12 @@ private:
nsIntRect mBackBufferRect;
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;
OptionalThebesBuffer mROFrontBuffer;
nsIntRegion mFrontUpdatedRegion;

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ipc/AutoOpenSurface.h"
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
#include "ShadowBufferD3D9.h"
@ -311,12 +312,11 @@ ShadowCanvasLayerD3D9::Swap(const CanvasSurface& aNewFront,
NS_ASSERTION(aNewFront.type() == CanvasSurface::TSurfaceDescriptor,
"ShadowCanvasLayerD3D9::Swap expected CanvasSurface surface");
nsRefPtr<gfxASurface> surf =
ShadowLayerForwarder::OpenDescriptor(aNewFront);
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront);
if (!mBuffer) {
Init(needYFlip);
}
mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
mBuffer->Upload(surf.Get(), GetVisibleRegion().GetBounds());
*aNewBack = aNewFront;
}

View File

@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ipc/AutoOpenSurface.h"
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
#include "ShadowBufferD3D9.h"
@ -551,19 +552,17 @@ ShadowImageLayerD3D9::Swap(const SharedImage& aNewFront,
if (!mBuffer) {
mBuffer = new ShadowBufferD3D9(this);
}
nsRefPtr<gfxASurface> surf =
ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront.get_SurfaceDescriptor());
mBuffer->Upload(surf.Get(), GetVisibleRegion().GetBounds());
} else {
const YUVImage& yuv = aNewFront.get_YUVImage();
nsRefPtr<gfxSharedImageSurface> surfY =
gfxSharedImageSurface::Open(yuv.Ydata());
nsRefPtr<gfxSharedImageSurface> surfU =
gfxSharedImageSurface::Open(yuv.Udata());
nsRefPtr<gfxSharedImageSurface> surfV =
gfxSharedImageSurface::Open(yuv.Vdata());
AutoOpenSurface asurfY(OPEN_READ_ONLY, yuv.Ydata());
AutoOpenSurface asurfU(OPEN_READ_ONLY, yuv.Udata());
AutoOpenSurface asurfV(OPEN_READ_ONLY, yuv.Vdata());
gfxImageSurface* surfY = asurfY.GetAsImage();
gfxImageSurface* surfU = asurfU.GetAsImage();
gfxImageSurface* surfV = asurfV.GetAsImage();
PlanarYCbCrImage::Data data;
data.mYChannel = surfY->Data();

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