Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2013-06-11 21:03:14 -04:00
commit 8ac6e127df
213 changed files with 3976 additions and 2291 deletions

View File

@ -133,7 +133,7 @@ GARBAGE += $(addprefix $(FINAL_TARGET)/defaults/pref/, firefox.js)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
ifdef MOZ_WIDGET_GTK
libs::
$(INSTALL) $(IFLAGS1) $(DIST)/branding/mozicon128.png $(FINAL_TARGET)/icons
$(INSTALL) $(IFLAGS1) $(DIST)/branding/default16.png $(FINAL_TARGET)/chrome/icons/default

View File

@ -26,11 +26,11 @@ DEFINES += \
-DPRE_RELEASE_SUFFIX="$(PRE_RELEASE_SUFFIX)" \
$(NULL)
ifneq (,$(filter windows gtk2 cocoa, $(MOZ_WIDGET_TOOLKIT)))
ifneq (,$(filter windows gtk2 gtk3 cocoa, $(MOZ_WIDGET_TOOLKIT)))
DEFINES += -DHAVE_SHELL_SERVICE=1
endif
ifneq (,$(filter windows cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
ifneq (,$(filter windows cocoa gtk2 gtk3, $(MOZ_WIDGET_TOOLKIT)))
DEFINES += -DCONTEXT_COPY_IMAGE_CONTENTS=1
endif
@ -38,6 +38,6 @@ ifneq (,$(filter windows cocoa, $(MOZ_WIDGET_TOOLKIT)))
DEFINES += -DCAN_DRAW_IN_TITLEBAR=1
endif
ifneq (,$(filter windows gtk2, $(MOZ_WIDGET_TOOLKIT)))
ifneq (,$(filter windows gtk2 gtk3, $(MOZ_WIDGET_TOOLKIT)))
DEFINES += -DMENUBAR_CAN_AUTOHIDE=1
endif

View File

@ -337,8 +337,8 @@
<key keycode="&findAgainCmd.commandkey2;" command="cmd_findPrevious" modifiers="shift"/>
<key id="addBookmarkAsKb" key="&bookmarkThisPageCmd.commandkey;" command="Browser:AddBookmarkAs" modifiers="accel"/>
# Accel+Shift+A-F are reserved on GTK2
#ifndef MOZ_WIDGET_GTK2
# Accel+Shift+A-F are reserved on GTK
#ifndef MOZ_WIDGET_GTK
<key id="bookmarkAllTabsKb" key="&bookmarkThisPageCmd.commandkey;" oncommand="PlacesCommandHook.bookmarkCurrentPages();" modifiers="accel,shift"/>
<key id="manBookmarkKb" key="&bookmarksCmd.commandkey;" command="Browser:ShowAllBookmarks" modifiers="accel,shift"/>
#else

View File

@ -37,6 +37,7 @@
<stringbundleset id="pageinfobundleset">
<stringbundle id="pageinfobundle" src="chrome://browser/locale/pageInfo.properties"/>
<stringbundle id="pkiBundle" src="chrome://pippki/locale/pippki.properties"/>
<stringbundle id="browserBundle" src="chrome://browser/locale/browser.properties"/>
</stringbundleset>
<commandset id="pageInfoCommandSet">
@ -396,6 +397,7 @@
<label class="permPluginTemplateLabel"/>
<spacer flex="1"/>
<radiogroup class="permPluginTemplateRadioGroup" orient="horizontal" command="cmd_pluginsToggle">
<radio class="permPluginTemplateRadioDefault" label="&permUseDefault;"/>
<radio class="permPluginTemplateRadioAsk" label="&permAskAlways;"/>
<radio class="permPluginTemplateRadioAllow" label="&permAllow;"/>
<radio class="permPluginTemplateRadioBlock" label="&permBlock;"/>

View File

@ -188,14 +188,15 @@ function onRadioClick(aPartId)
var radioGroup = document.getElementById(aPartId + "RadioGroup");
var id = radioGroup.selectedItem.id;
var permission = id.split('#')[1];
permissionManager.add(gPermURI, aPartId, permission);
if (permission == UNKNOWN) {
permissionManager.remove(gPermURI, aPartId);
} else {
permissionManager.add(gPermURI, aPartId, permission);
}
if (aPartId == "indexedDB" &&
(permission == ALLOW || permission == BLOCK)) {
permissionManager.remove(gPermURI.host, "indexedDB-unlimited");
}
if (aPartId == "fullscreen" && permission == UNKNOWN) {
permissionManager.remove(gPermURI.host, "fullscreen");
}
}
function setRadioState(aPartId, aValue)
@ -268,21 +269,22 @@ function makeNicePluginName(aName) {
}
function fillInPluginPermissionTemplate(aPluginName, aPermissionString) {
let permPluginTemplate = document.getElementById("permPluginTemplate");
let permPluginTemplate = document.getElementById("permPluginTemplate").cloneNode(true);
permPluginTemplate.setAttribute("permString", aPermissionString);
let attrs = [
[ ".permPluginTemplateLabel", "value", aPluginName ],
[ ".permPluginTemplateRadioGroup", "id", aPermissionString + "RadioGroup" ],
[ ".permPluginTemplateRadioAsk", "id", aPermissionString + "#0" ],
[ ".permPluginTemplateRadioDefault", "id", aPermissionString + "#0" ],
[ ".permPluginTemplateRadioAsk", "id", aPermissionString + "#3" ],
[ ".permPluginTemplateRadioAllow", "id", aPermissionString + "#1" ],
[ ".permPluginTemplateRadioBlock", "id", aPermissionString + "#2" ]
];
for (let attr of attrs) {
document.querySelector(attr[0]).setAttribute(attr[1], attr[2]);
permPluginTemplate.querySelector(attr[0]).setAttribute(attr[1], attr[2]);
}
return permPluginTemplate.cloneNode(true);
return permPluginTemplate;
}
function clearPluginPermissionTemplate() {
@ -297,30 +299,36 @@ function clearPluginPermissionTemplate() {
}
function initPluginsRow() {
var vulnerableLabel = document.getElementById("browserBundle").getString("vulnerableNoUpdatePluginWarning");
let pluginHost = Components.classes["@mozilla.org/plugin/host;1"].getService(Components.interfaces.nsIPluginHost);
let tags = pluginHost.getPluginTags().filter(function(aTag) {
let mimeTypes = aTag.getMimeTypes();
if (mimeTypes.length < 1)
return false;
let mimeType = mimeTypes[0];
return (!aTag.disabled && pluginHost.isPluginClickToPlayForType(mimeType));
});
tags.sort(function(tagA, tagB) {
let nameA = makeNicePluginName(tagA.name);
let nameB = makeNicePluginName(tagB.name);
return nameA < nameB ? -1 : (nameA == nameB ? 0 : 1);
});
let permissionMap = Map();
let permissionEntries = [];
for (let plugin of tags) {
let mimeType = plugin.getMimeTypes()[0];
let permString = pluginHost.getPermissionStringForType(mimeType);
let pluginName = makeNicePluginName(plugin.name)
let permEntry = fillInPluginPermissionTemplate(pluginName, permString);
permissionEntries.push(permEntry);
for (let plugin of pluginHost.getPluginTags()) {
if (plugin.disabled) {
continue;
}
for (let mimeType of plugin.getMimeTypes()) {
let permString = pluginHost.getPermissionStringForType(mimeType);
if (!permissionMap.has(permString)) {
var name = makeNicePluginName(plugin.name);
if (permString.startsWith("plugin-vulnerable:")) {
name += " \u2014 " + vulnerableLabel;
}
permissionMap.set(permString, name);
}
}
}
let entries = [{name: item[1], permission: item[0]} for (item of permissionMap)];
entries.sort(function(a, b) {
return a.name < b.name ? -1 : (a.name == b.name ? 0 : 1);
});
let permissionEntries = [
fillInPluginPermissionTemplate(p.name, p.permission) for (p of entries)
];
let permPluginsRow = document.getElementById("permPluginsRow");
clearPluginPermissionTemplate();
if (permissionEntries.length < 1) {

View File

@ -39,7 +39,7 @@ MOCHITEST_FILES = \
$(NULL)
# test_contextmenu.html is disabled on Linux due to bug 513558
ifneq (gtk2,$(MOZ_WIDGET_TOOLKIT))
ifdef MOZ_WIDGET_GTK
MOCHITEST_FILES += \
audio.ogg \
test_contextmenu.html \
@ -318,6 +318,7 @@ _BROWSER_FILES = \
blockPluginVulnerableUpdatable.xml \
blockPluginVulnerableNoUpdate.xml \
blockNoPlugins.xml \
blockPluginHard.xml \
browser_utilityOverlay.js \
browser_bug676619.js \
download_page.html \

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000">
<emItems>
</emItems>
<pluginItems>
<pluginItem blockID="p9999">
<match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" />
<versionRange severity="2"></versionRange>
</pluginItem>
</pluginItems>
</blocklist>

View File

@ -1,5 +1,5 @@
const gHttpTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
const EXPECTED_PLUGINSCRIPTED_EVENT_COUNT = 7;
const EXPECTED_PLUGINSCRIPTED_EVENT_COUNT = 6;
var gTestBrowser = null;
var gNextTestList = [];
@ -107,16 +107,12 @@ function testDenyPermissionPart1() {
}
function testDenyPermissionPart2() {
var condition = function() gPluginScriptedFired;
var condition = function() XPCNativeWrapper.unwrap(gTestBrowser.contentWindow).gScriptingFinished;
waitForCondition(condition, testDenyPermissionPart3, "test deny permission: waited too long for PluginScripted event");
}
function testDenyPermissionPart3() {
var condition = function() gTestBrowser._pluginScriptedState == gPluginHandler.PLUGIN_SCRIPTED_STATE_DONE;
waitForCondition(condition, testDenyPermissionPart4, "test deny permission: waited too long for PluginScripted event handling");
}
function testDenyPermissionPart4() {
ok(!gPluginScriptedFired, "Should not fire plugin-scripted event for disabled plugins");
var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(!notification, "test deny permission: should not have a click-to-play notification");

View File

@ -51,52 +51,57 @@ function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref("plugins.click_to_play", true);
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_ENABLED;
gBrowser.selectedTab = gBrowser.addTab();
gTestBrowser = gBrowser.selectedBrowser;
gPermissionManager.remove("127.0.0.1:8888", gTestPermissionString);
gPermissionManager.remove("127.0.0.1:8888", gSecondTestPermissionString);
doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart1a);
}
// By default, everything should be click-to-play. So: no plugins should be
// activated, and the radio buttons in Page Info should be "Always Ask"
// The first test plugin is CtP and the second test plugin is enabled.
function testPart1a() {
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(notification, "part 1a: should have a click-to-play notification");
let test = gTestBrowser.contentDocument.getElementById("test");
let objLoadingContent = test.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "part 1a: Test plugin should not be activated");
let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA");
let objLoadingContent = secondtest.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "part 1a: Second Test plugin should not be activated");
ok(objLoadingContent.activated, "part 1a: Second Test plugin should be activated");
doOnOpenPageInfo(testPart1b);
}
function testPart1b() {
let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
let testRadioAsk = gPageInfo.document.getElementById(gTestPermissionString + "#0");
is(testRadioGroup.selectedItem, testRadioAsk, "part 1b: Test radio group should be set to 'Always Ask'");
let testRadioDefault = gPageInfo.document.getElementById(gTestPermissionString + "#0");
var qString = "#" + gTestPermissionString.replace(':', '\\:') + "\\#0";
is(testRadioGroup.selectedItem, testRadioDefault, "part 1b: Test radio group should be set to 'Default'");
let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1");
testRadioGroup.selectedItem = testRadioAllow;
testRadioAllow.doCommand();
let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0");
is(secondtestRadioGroup.selectedItem, secondtestRadioAsk, "part 1b: Second Test radio group should be set to 'Always Ask'");
let secondtestRadioDefault = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0");
is(secondtestRadioGroup.selectedItem, secondtestRadioDefault, "part 1b: Second Test radio group should be set to 'Default'");
let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#3");
secondtestRadioGroup.selectedItem = secondtestRadioAsk;
secondtestRadioAsk.doCommand();
doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart2);
}
// Now, the Test plugin should be allowed.
// Now, the Test plugin should be allowed, and the Test2 plugin should be CtP
function testPart2() {
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(notification, "part 2: should have a click-to-play notification");
let test = gTestBrowser.contentDocument.getElementById("test");
let objLoadingContent = test.QueryInterface(Ci.nsIObjectLoadingContent);
ok(objLoadingContent.activated, "part 2: Test plugin should be activated");
let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA");
let objLoadingContent = secondtest.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "part 2: Second Test plugin should not be activated");
let test = gTestBrowser.contentDocument.getElementById("test").
QueryInterface(Ci.nsIObjectLoadingContent);
ok(test.activated, "part 2: Test plugin should be activated");
let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA").
QueryInterface(Ci.nsIObjectLoadingContent);
ok(!secondtest.activated, "part 2: Second Test plugin should not be activated");
is(secondtest.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
"part 2: Second test plugin should be click-to-play.");
let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
let testRadioAllow = gPageInfo.document.getElementById(gTestPermissionString + "#1");
@ -106,7 +111,7 @@ function testPart2() {
testRadioBlock.doCommand();
let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0");
let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#3");
is(secondtestRadioGroup.selectedItem, secondtestRadioAsk, "part 2: Second Test radio group should be set to 'Always Ask'");
let secondtestRadioBlock = gPageInfo.document.getElementById(gSecondTestPermissionString + "#2");
secondtestRadioGroup.selectedItem = secondtestRadioBlock;
@ -117,19 +122,18 @@ function testPart2() {
// Now, all the things should be blocked
function testPart3() {
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(!notification, "part 3: should not have a click-to-play notification");
let test = gTestBrowser.contentDocument.getElementById("test").
QueryInterface(Ci.nsIObjectLoadingContent);
ok(!test.activated, "part 3: Test plugin should not be activated");
is(test.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED,
"part 3: Test plugin should be marked as PLUGIN_DISABLED");
let test = gTestBrowser.contentDocument.getElementById("test");
let objLoadingContent = test.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "part 3: Test plugin should not be activated");
let overlay = gTestBrowser.contentDocument.getAnonymousElementByAttribute(test, "class", "mainBox");
ok(overlay.style.visibility == "hidden", "part 3: Test plugin should not have visible overlay");
let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA");
let objLoadingContent = secondtest.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "part 3: Second Test plugin should not be activated");
let overlay = gTestBrowser.contentDocument.getAnonymousElementByAttribute(secondtest, "class", "mainBox");
ok(overlay.style.visibility == "hidden", "part 3: Second Test plugin should not have visible overlay");
let secondtest = gTestBrowser.contentDocument.getElementById("secondtestA").
QueryInterface(Ci.nsIObjectLoadingContent);
ok(!secondtest.activated, "part 3: Second Test plugin should not be activated");
is(secondtest.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED,
"part 3: Second test plugin should be marked as PLUGIN_DISABLED");
// reset permissions
gPermissionManager.remove("127.0.0.1:8888", gTestPermissionString);
@ -137,21 +141,21 @@ function testPart3() {
// check that changing the permissions affects the radio state in the
// open Page Info window
let testRadioGroup = gPageInfo.document.getElementById(gTestPermissionString + "RadioGroup");
let testRadioAsk = gPageInfo.document.getElementById(gTestPermissionString + "#0");
is(testRadioGroup.selectedItem, testRadioAsk, "part 3: Test radio group should be set to 'Ask'");
let testRadioDefault = gPageInfo.document.getElementById(gTestPermissionString + "#0");
is(testRadioGroup.selectedItem, testRadioDefault, "part 3: Test radio group should be set to 'Default'");
let secondtestRadioGroup = gPageInfo.document.getElementById(gSecondTestPermissionString + "RadioGroup");
let secondtestRadioAsk = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0");
is(secondtestRadioGroup.selectedItem, secondtestRadioAsk, "part 3: Second Test radio group should be set to 'Always Ask'");
let secondtestRadioDefault = gPageInfo.document.getElementById(gSecondTestPermissionString + "#0");
is(secondtestRadioGroup.selectedItem, secondtestRadioDefault, "part 3: Second Test radio group should be set to 'Default'");
doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart4a);
}
// Now test that the popup notification influences Page Info
// Now test that setting permission directly (as from the popup notification)
// immediately influences Page Info.
function testPart4a() {
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(notification, "part 4a: should have a notification");
// simulate "always allow"
notification.secondaryActions[0].callback();
// simulate "allow" from the doorhanger
gPermissionManager.add(gTestBrowser.currentURI, gTestPermissionString, Ci.nsIPermissionManager.ALLOW_ACTION);
gPermissionManager.add(gTestBrowser.currentURI, gSecondTestPermissionString, Ci.nsIPermissionManager.ALLOW_ACTION);
// check (again) that changing the permissions affects the radio state in the
// open Page Info window
@ -179,43 +183,5 @@ function testPart4b() {
Services.prefs.setBoolPref("plugins.click_to_play", false);
gPageInfo.close();
doOnPageLoad(gHttpTestRoot + "plugin_two_types.html", testPart5a);
}
// check that if there are no click-to-play plugins, the plugin row is hidden
function testPart5a() {
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(!notification, "part 5a: should not have a click-to-play notification");
doOnOpenPageInfo(testPart5b);
}
function testPart5b() {
ok(gPageInfo.document.getElementById("permPluginsRow").hidden, "part 5b: plugin permission row should be hidden");
gPageInfo.close();
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginVulnerableUpdatable.xml",
function() {
doOnPageLoad(gHttpTestRoot + "plugin_test.html", testPart6a);
});
}
// check that if plugins.click_to_play is false, but there is a
// click-to-play blocklisted plugin, we show the plugin row
function testPart6a() {
let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
ok(notification, "part 6a: should have a click-to-play notification");
doOnOpenPageInfo(testPart6b);
}
function testPart6b() {
ok(!gPageInfo.document.getElementById("permPluginsRow").hidden, "part 6b: plugin permission row should not be hidden");
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml",
function() {
resetBlocklist();
gPageInfo.close();
finishTest();
});
finishTest();
}

View File

@ -58,12 +58,16 @@ TabOpenListener.prototype = {
function test() {
waitForExplicitFinish();
requestLongerTimeout(2);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
Services.prefs.clearUserPref("plugins.click_to_play");
getTestPlugin().enabledState = Ci.nsIPluginTag.STATE_ENABLED;
getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_ENABLED;
});
Services.prefs.setBoolPref("plugins.click_to_play", false);
Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
var plugin = getTestPlugin();
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
@ -117,7 +121,6 @@ function test1() {
var plugin = getTestPlugin();
ok(plugin, "Should have a test plugin");
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = false;
prepareTest(test2, gTestRoot + "plugin_test.html");
}
@ -159,14 +162,19 @@ function test4(tab, win) {
}
function prepareTest5() {
info("prepareTest5");
var plugin = getTestPlugin();
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = true;
prepareTest(test5, gTestRoot + "plugin_test.html");
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml",
function() {
info("prepareTest5 callback");
prepareTest(test5, gTestRoot + "plugin_test.html");
});
}
// Tests a page with a blocked plugin in it.
function test5() {
info("test5");
var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 5, Should not have displayed the missing plugin notification");
ok(notificationBox.getNotificationWithValue("blocked-plugins"), "Test 5, Should have displayed the blocked plugin notification");
@ -204,11 +212,12 @@ function test7() {
Services.prefs.setBoolPref("plugins.click_to_play", true);
var plugin = getTestPlugin();
plugin.blocklisted = false;
plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
prepareTest(test8, gTestRoot + "plugin_test.html");
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
prepareTest(test8, gTestRoot + "plugin_test.html");
});
}
// Tests a page with a working plugin that is click-to-play
@ -466,8 +475,10 @@ function test13c() {
var plugin = gTestBrowser.contentDocument.getElementById("test");
var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "Test 13c, Plugin should not be activated");
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, "Test 13c, Plugin should be disabled");
var overlay = gTestBrowser.contentDocument.getAnonymousElementByAttribute(plugin, "class", "mainBox");
ok(overlay.style.visibility == "hidden", "Test 13c, Plugin should not have visible overlay");
ok(overlay.style.visibility != "visible", "Test 13c, Plugin should have visible overlay");
prepareTest(test13d, gHttpTestRoot + "plugin_two_types.html");
}
@ -482,14 +493,16 @@ function test13d() {
var test = gTestBrowser.contentDocument.getElementById("test");
var objLoadingContent = test.QueryInterface(Ci.nsIObjectLoadingContent);
var overlay = gTestBrowser.contentDocument.getAnonymousElementByAttribute(test, "class", "mainBox");
ok(overlay.style.visibility == "hidden", "Test 13d, Test plugin should not have visible overlay");
ok(overlay.style.visibility != "hidden", "Test 13d, Test plugin should have visible overlay");
ok(!objLoadingContent.activated, "Test 13d, Test plugin should not be activated");
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, "Test 13d, Test plugin should be disabled");
var secondtestA = gTestBrowser.contentDocument.getElementById("secondtestA");
var objLoadingContent = secondtestA.QueryInterface(Ci.nsIObjectLoadingContent);
var overlay = gTestBrowser.contentDocument.getAnonymousElementByAttribute(secondtestA, "class", "mainBox");
ok(overlay.style.visibility != "hidden", "Test 13d, Test plugin should have visible overlay");
ok(!objLoadingContent.activated, "Test 13d, Second Test plugin (A) should not be activated");
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY, "Test 13d, Test plugin should be disabled");
var secondtestB = gTestBrowser.contentDocument.getElementById("secondtestB");
var objLoadingContent = secondtestB.QueryInterface(Ci.nsIObjectLoadingContent);
@ -533,7 +546,6 @@ function test14() {
Services.prefs.setBoolPref("plugins.click_to_play", true);
var plugin = getTestPlugin();
plugin.blocklisted = false;
plugin.enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
getTestPlugin("Second Test Plug-in").enabledState = Ci.nsIPluginTag.STATE_CLICKTOPLAY;
prepareTest(test15, gTestRoot + "plugin_alternate_content.html");
@ -1156,8 +1168,9 @@ function test25c() {
ok(secondtest, "Test 25c, Found second test plugin in page");
var objLoadingContent = secondtest.QueryInterface(Ci.nsIObjectLoadingContent);
ok(!objLoadingContent.activated, "Test 25c, second test plugin should not be activated");
is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, "Test 25c, second test plugin should be disabled");
var overlay = gTestBrowser.contentDocument.getAnonymousElementByAttribute(secondtest, "class", "mainBox");
ok(overlay.style.visibility == "hidden", "Test 25c, second test plugin should not have visible overlay");
ok(overlay.style.visibility != "hidden", "Test 25c, second test plugin should have visible overlay");
Services.perms.remove("127.0.0.1:8888", gPluginHost.getPermissionStringForType("application/x-test"));
Services.perms.remove("127.0.0.1:8888", gPluginHost.getPermissionStringForType("application/x-second-test"));

View File

@ -163,6 +163,8 @@ function test3() {
registerPlayPreview('application/x-test', 'about:');
Services.prefs.setBoolPref("plugins.click_to_play", false);
var plugin = getTestPlugin();
plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
prepareTest(test4, gTestRoot + "plugin_test.html");
}

View File

@ -4,11 +4,14 @@
<body onload="scriptPlugin()">
<embed id="test" type="application/x-test"/>
<script>
var gScriptingFinished = false;
function scriptPlugin() {
try {
document.getElementById("test").getObjectValue();
}
catch (e) {}
catch (e) {
setTimeout(function() { gScriptingFinished = true; }, 0);
}
}
</script>
</body>

View File

@ -44,7 +44,7 @@ BRANDING_FILES := \
$(NULL)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
ifdef MOZ_WIDGET_GTK
BRANDING_FILES := \
default16.png \
default32.png \

View File

@ -44,7 +44,7 @@ BRANDING_FILES := \
$(NULL)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
ifdef MOZ_WIDGET_GTK
BRANDING_FILES := \
default16.png \
default32.png \

View File

@ -38,7 +38,7 @@ SHARED_LIBRARY_LIBS = \
../dirprovider/$(LIB_PREFIX)browserdir_s.$(LIB_SUFFIX) \
$(NULL)
ifneq (,$(filter windows cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
ifneq (,$(filter windows cocoa gtk2 gtk3, $(MOZ_WIDGET_TOOLKIT)))
SHARED_LIBRARY_LIBS += ../shell/src/$(LIB_PREFIX)shellservice_s.$(LIB_SUFFIX)
endif
@ -57,7 +57,7 @@ SHARED_LIBRARY_LIBS += ../migration/src/$(LIB_PREFIX)migration_s.$(LIB_SUFFIX)
# Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
# GTK2: Need to link with glib for GNOME shell service
ifneq (,$(filter cocoa gtk2,$(MOZ_WIDGET_TOOLKIT)))
ifneq (,$(filter cocoa gtk2 gtk3,$(MOZ_WIDGET_TOOLKIT)))
EXTRA_DSO_LDOPTS += \
$(TK_LIBS) \
$(NULL)

View File

@ -12,7 +12,7 @@
#include "nsWindowsShellService.h"
#elif defined(XP_MACOSX)
#include "nsMacShellService.h"
#elif defined(MOZ_WIDGET_GTK2)
#elif defined(MOZ_WIDGET_GTK)
#include "nsGNOMEShellService.h"
#endif
@ -36,7 +36,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(DirectoryProvider)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService)
#elif defined(XP_MACOSX)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
#elif defined(MOZ_WIDGET_GTK2)
#elif defined(MOZ_WIDGET_GTK)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
#endif
@ -49,7 +49,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer)
NS_DEFINE_NAMED_CID(NS_BROWSERDIRECTORYPROVIDER_CID);
#if defined(XP_WIN)
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
#elif defined(MOZ_WIDGET_GTK2)
#elif defined(MOZ_WIDGET_GTK)
NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID);
#endif
NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID);
@ -64,7 +64,7 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = {
{ &kNS_BROWSERDIRECTORYPROVIDER_CID, false, NULL, DirectoryProviderConstructor },
#if defined(XP_WIN)
{ &kNS_SHELLSERVICE_CID, false, NULL, nsWindowsShellServiceConstructor },
#elif defined(MOZ_WIDGET_GTK2)
#elif defined(MOZ_WIDGET_GTK)
{ &kNS_SHELLSERVICE_CID, false, NULL, nsGNOMEShellServiceConstructor },
#endif
{ &kNS_FEEDSNIFFER_CID, false, NULL, nsFeedSnifferConstructor },
@ -81,7 +81,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
{ NS_BROWSERDIRECTORYPROVIDER_CONTRACTID, &kNS_BROWSERDIRECTORYPROVIDER_CID },
#if defined(XP_WIN)
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
#elif defined(MOZ_WIDGET_GTK2)
#elif defined(MOZ_WIDGET_GTK)
{ NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
#endif
{ NS_FEEDSNIFFER_CONTRACTID, &kNS_FEEDSNIFFER_CID },
@ -129,4 +129,3 @@ static const mozilla::Module kBrowserModule = {
};
NSMODULE_DEFN(nsBrowserCompsModule) = &kBrowserModule;

View File

@ -17,6 +17,6 @@ DEFINES += \
-DMOZ_MACBUNDLE_NAME=$(MOZ_MACBUNDLE_NAME) \
$(NULL)
ifneq (,$(filter windows gtk2 cocoa, $(MOZ_WIDGET_TOOLKIT)))
ifneq (,$(filter windows gtk2 gtk3 cocoa, $(MOZ_WIDGET_TOOLKIT)))
DEFINES += -DHAVE_SHELL_SERVICE=1
endif

View File

@ -79,7 +79,7 @@ const PREF_AUDIO_FEED_SELECTED_READER = "browser.audioFeeds.handler.default";
const kActionUsePlugin = 5;
/*
#ifdef MOZ_WIDGET_GTK2
#ifdef MOZ_WIDGET_GTK
*/
const ICON_URL_APP = "moz-icon://dummy.exe?size=16";
/*

View File

@ -26,7 +26,7 @@ else
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
LIBRARY_NAME = shellservice_s
else
ifeq ($(MOZ_WIDGET_TOOLKIT), gtk2)
ifdef MOZ_WIDGET_GTK
LIBRARY_NAME = shellservice_s
endif
endif

View File

@ -14,7 +14,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
CPP_SOURCES += [
'nsMacShellService.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
elif CONFIG['MOZ_WIDGET_GTK']:
CPP_SOURCES += [
'nsGNOMEShellService.cpp',
]

View File

@ -27,7 +27,7 @@
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "prprf.h"
#ifdef MOZ_WIDGET_GTK2
#if defined(MOZ_WIDGET_GTK)
#include "nsIImageToPixbuf.h"
#endif
#include "nsXULAppAPI.h"
@ -368,7 +368,7 @@ nsGNOMEShellService::GetCanSetDesktopBackground(bool* aResult)
static nsresult
WriteImage(const nsCString& aPath, imgIContainer* aImage)
{
#ifndef MOZ_WIDGET_GTK2
#if !defined(MOZ_WIDGET_GTK)
return NS_ERROR_NOT_AVAILABLE;
#else
nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =

View File

@ -42,8 +42,8 @@ ifdef MOZ_ENABLE_GNOME_COMPONENT
DEFINES += -DMOZ_ENABLE_GNOME_COMPONENT=1
endif
ifeq (gtk2, $(MOZ_WIDGET_TOOLKIT))
DEFINES += -DMOZ_GTK2=1
ifdef MOZ_WIDGET_GTK
DEFINES += -DMOZ_GTK=1
endif
ifdef MOZ_NATIVE_NSPR

View File

@ -226,7 +226,7 @@
@BINPATH@/components/exthelper.xpt
@BINPATH@/components/fastfind.xpt
@BINPATH@/components/feeds.xpt
#ifdef MOZ_GTK2
#ifdef MOZ_GTK
@BINPATH@/components/filepicker.xpt
#endif
@BINPATH@/components/find.xpt
@ -370,7 +370,7 @@
@BINPATH@/components/crypto-SDR.js
@BINPATH@/components/jsconsole-clhandler.manifest
@BINPATH@/components/jsconsole-clhandler.js
#ifdef MOZ_GTK2
#ifdef MOZ_GTK
@BINPATH@/components/nsFilePicker.manifest
@BINPATH@/components/nsFilePicker.js
#endif
@ -570,7 +570,7 @@
@BINPATH@/chrome/toolkit.manifest
@BINPATH@/chrome/recording.manifest
@BINPATH@/chrome/recording/*
#ifdef MOZ_GTK2
#ifdef MOZ_GTK
@BINPATH@/browser/chrome/icons/default/default16.png
@BINPATH@/browser/chrome/icons/default/default32.png
@BINPATH@/browser/chrome/icons/default/default48.png

View File

@ -21,7 +21,7 @@ STDCXX_COMPAT =
ifneq (WINNT,$(HOST_OS_ARCH))
HOST_PROGRAM = nsinstall_real$(HOST_BIN_SUFFIX)
HOST_CSRCS = nsinstall.c pathsub.c
DISABLED_HOST_CSRCS = nsinstall.c pathsub.c
endif
ifndef CROSS_COMPILE

View File

@ -13,3 +13,8 @@ CONFIGURE_SUBST_FILES += [
'tests/src-simple/Makefile',
]
if CONFIG['HOST_OS_ARCH'] != 'WINNT':
HOST_CSRCS += [
'nsinstall.c',
'pathsub.c',
]

View File

@ -529,26 +529,17 @@ IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
return false;
}
nsresult
IsPluginEnabledForType(const nsCString& aMIMEType)
bool
PluginExistsForType(const char* aMIMEType)
{
nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
if (!pluginHost) {
NS_NOTREACHED("No pluginhost");
return NS_ERROR_FAILURE;
return false;
}
nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get());
// Check to see if the plugin is disabled before deciding if it
// should be in the "click to play" state, since we only want to
// display "click to play" UI for enabled plugins.
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
return pluginHost->PluginExistsForType(aMIMEType);
}
///
@ -1297,9 +1288,8 @@ nsObjectLoadingContent::UpdateObjectParameters()
thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::classid, classIDAttr);
if (!classIDAttr.IsEmpty()) {
// Our classid support is limited to 'java:' ids
rv = IsPluginEnabledForType(NS_LITERAL_CSTRING("application/x-java-vm"));
if (NS_SUCCEEDED(rv) &&
StringBeginsWith(classIDAttr, NS_LITERAL_STRING("java:"))) {
if (StringBeginsWith(classIDAttr, NS_LITERAL_STRING("java:")) &&
PluginExistsForType("application/x-java-vm")) {
newMime.Assign("application/x-java-vm");
isJava = true;
} else {
@ -1709,16 +1699,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
// type, but the parameters are invalid e.g. a embed tag with type "image/png"
// but no URI -- don't show a plugin error or unknown type error in that case.
if (mType == eType_Null && GetTypeOfContent(mContentType) == eType_Null) {
// See if a disabled or blocked plugin could've handled this
nsresult pluginsupport = IsPluginEnabledForType(mContentType);
if (pluginsupport == NS_ERROR_PLUGIN_DISABLED) {
fallbackType = eFallbackDisabled;
} else if (pluginsupport == NS_ERROR_PLUGIN_BLOCKLISTED) {
fallbackType = eFallbackBlocklisted;
} else {
// Completely unknown type
fallbackType = eFallbackUnsupported;
}
fallbackType = eFallbackUnsupported;
}
// Explicit user activation should reset if the object changes content types
@ -2269,7 +2250,8 @@ nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType)
return eType_Document;
}
if ((caps & eSupportPlugins) && NS_SUCCEEDED(IsPluginEnabledForType(aMIMEType))) {
if (caps & eSupportPlugins && PluginExistsForType(aMIMEType.get())) {
// ShouldPlay will handle checking for disabled plugins
return eType_Plugin;
}
@ -2729,9 +2711,7 @@ nsObjectLoadingContent::CancelPlayPreview()
bool
nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
{
// mActivated is true if we've been activated via PlayPlugin() (e.g. user has
// clicked through). Otherwise, only play if click-to-play is off or if page
// is whitelisted
nsresult rv;
nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
@ -2754,32 +2734,46 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
return true;
}
bool isCTP;
nsresult rv = pluginHost->IsPluginClickToPlayForType(mContentType, &isCTP);
if (NS_FAILED(rv)) {
return false;
}
// Order of checks:
// * Already activated? Then ok
// * Assume a default of click-to-play
// * If blocklisted, override the reason with the blocklist reason
// * If not blocklisted but playPreview, override the reason with the
// playPreview reason.
// * Check per-site permissions and follow those if specified.
// * Honor per-plugin disabled permission
// * Blocklisted plugins are forced to CtP
// * Check per-plugin permission and follow that.
if (!isCTP || mActivated) {
if (mActivated) {
return true;
}
// set the fallback reason
// Before we check permissions, get the blocklist state of this plugin to set
// the fallback reason correctly.
aReason = eFallbackClickToPlay;
// (if it's click-to-play, it might be because of the blocklist)
uint32_t state;
rv = pluginHost->GetBlocklistStateForType(mContentType.get(), &state);
NS_ENSURE_SUCCESS(rv, false);
if (state == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
uint32_t blocklistState = nsIBlocklistService::STATE_NOT_BLOCKED;
pluginHost->GetBlocklistStateForType(mContentType.get(), &blocklistState);
if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
aReason = eFallbackVulnerableUpdatable;
}
else if (state == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
else if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
aReason = eFallbackVulnerableNoUpdate;
}
else if (blocklistState == nsIBlocklistService::STATE_BLOCKED) {
// no override possible
aReason = eFallbackBlocklisted;
return false;
}
// If plugin type is click-to-play and we have not been explicitly clicked.
// check if permissions lets this page bypass - (e.g. user selected 'Always
// play plugins on this page')
if (aReason == eFallbackClickToPlay && isPlayPreviewSpecified &&
!mPlayPreviewCanceled && !ignoreCTP) {
// play preview in click-to-play mode is shown instead of standard CTP UI
aReason = eFallbackPlayPreview;
}
// Check the permission manager for permission based on the principal of
// the toplevel content.
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
MOZ_ASSERT(thisContent);
@ -2800,7 +2794,6 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, false);
bool allowPerm = false;
// For now we always say that the system principal uses click-to-play since
// that maintains current behavior and we have tests that expect this.
// What we really should do is disable plugins entirely in pages that use
@ -2815,16 +2808,43 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
permissionString.Data(),
&permission);
NS_ENSURE_SUCCESS(rv, false);
allowPerm = permission == nsIPermissionManager::ALLOW_ACTION;
switch (permission) {
case nsIPermissionManager::ALLOW_ACTION:
return true;
case nsIPermissionManager::DENY_ACTION:
aReason = eFallbackDisabled;
return false;
case nsIPermissionManager::PROMPT_ACTION:
return false;
case nsIPermissionManager::UNKNOWN_ACTION:
break;
default:
MOZ_ASSERT(false);
return false;
}
}
if (aReason == eFallbackClickToPlay && isPlayPreviewSpecified &&
!mPlayPreviewCanceled && !ignoreCTP) {
// play preview in click-to-play mode is shown instead of standard CTP UI
aReason = eFallbackPlayPreview;
uint32_t enabledState = nsIPluginTag::STATE_DISABLED;
pluginHost->GetStateForType(mContentType, &enabledState);
if (nsIPluginTag::STATE_DISABLED == enabledState) {
aReason = eFallbackDisabled;
return false;
}
return allowPerm;
// No site-specific permissions. Vulnerable plugins are automatically CtP
if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE ||
blocklistState == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
return false;
}
switch (enabledState) {
case nsIPluginTag::STATE_ENABLED:
return true;
case nsIPluginTag::STATE_CLICKTOPLAY:
return false;
}
MOZ_NOT_REACHED("Unexpected enabledState");
return false;
}
nsIDocument*

View File

@ -17,6 +17,8 @@ MOCHITEST_FILES = \
MOCHITEST_CHROME_FILES = \
test_bug206691.xul \
test_bug391728.html \
blockPluginHard.xml \
blockNoPlugins.xml \
file_bug391728.html \
file_bug391728_2.html \
test_bug421622.xul \

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310001">
<emItems>
</emItems>
<pluginItems>
</pluginItems>
</blocklist>

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000">
<emItems>
</emItems>
<pluginItems>
<pluginItem blockID="p9999">
<match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" />
<versionRange severity="2"></versionRange>
</pluginItem>
</pluginItems>
</blocklist>

View File

@ -36,24 +36,20 @@ document.addEventListener("PluginBindingAttached", plugin_binding_attached, true
<div><object id="plugin3" style="width: 100px; height: 100px" type="application/x-test"></object></div>
<div><object id="plugin4" style="width: 100px; height: 100px" data="data:application/x-test,test"></object></div>
<!-- The mimetype of the actual data is supposed to be used in preference -->
<div><embed id="plugin5" style="width: 100px; height: 100px" type="application/x-unknown" src="data:application/x-test,test"></div>
<div><object id="plugin6" style="width: 100px; height: 100px" type="application/x-unknown" data="data:application/x-test,test"></object></div>
<!-- Params are not considered content -->
<div><object id="plugin7" style="width: 100px; height: 100px" type="application/x-test">
<div><object id="plugin5" style="width: 100px; height: 100px" type="application/x-test">
<param name="foo" value="bar">
</object></div>
<div><object id="plugin8" style="width: 100px; height: 100px" data="data:application/x-test,test">
<div><object id="plugin6" style="width: 100px; height: 100px" data="data:application/x-test,test">
<param name="foo" value="bar">
</object></div>
<!-- Nor is whitespace -->
<div><object id="plugin9" style="width: 100px; height: 100px" type="application/x-test">
<div><object id="plugin7" style="width: 100px; height: 100px" type="application/x-test">
</object></div>
<div><object id="plugin10" style="width: 100px; height: 100px" data="data:application/x-test,test">
<div><object id="plugin8" style="width: 100px; height: 100px" data="data:application/x-test,test">
</object></div>
@ -69,14 +65,14 @@ document.addEventListener("PluginBindingAttached", plugin_binding_attached, true
<!-- Even other plugins are considered content so no errors dispatched from these
objects, but the inner embeds do get processed -->
<div><object id="fallback3" style="width: 100px; height: 100px" type="application/x-test">
<embed id="plugin11" style="width: 100px; height: 100px" type="application/x-test">
<embed id="plugin9" style="width: 100px; height: 100px" type="application/x-test">
</object></div>
<div><object id="fallback4" style="width: 100px; height: 100px" data="data:application/x-test,test">
<embed id="plugin12" style="width: 100px; height: 100px" type="application/x-test">
<embed id="plugin10" style="width: 100px; height: 100px" type="application/x-test">
</object></div>
<!-- pluginurl was removed in bug 548133, and should not affect fallback -->
<div><object id="plugin13" style="width: 100px; height: 100px" data="data:application/x-test,test">
<div><object id="plugin11" style="width: 100px; height: 100px" data="data:application/x-test,test">
<param name="pluginurl">
</object></div>

View File

@ -36,24 +36,20 @@ document.addEventListener("PluginBindingAttached", plugin_binding_attached, true
<div><object id="plugin3" style="width: 100px; height: 100px" type="application/x-unknown"></object></div>
<div><object id="plugin4" style="width: 100px; height: 100px" data="data:application/x-unknown,test"></object></div>
<!-- The mimetype of the actual data is supposed to be used in preference -->
<div><embed id="plugin5" style="width: 100px; height: 100px" type="application/x-test" src="data:application/x-unknown,test"></div>
<div><object id="plugin6" style="width: 100px; height: 100px" type="application/x-test" data="data:application/x-unknown,test"></object></div>
<!-- Params are not considered content -->
<div><object id="plugin7" style="width: 100px; height: 100px" type="application/x-unknown">
<div><object id="plugin5" style="width: 100px; height: 100px" type="application/x-unknown">
<param name="foo" value="bar">
</object></div>
<div><object id="plugin8" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
<div><object id="plugin6" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
<param name="foo" value="bar">
</object></div>
<!-- Nor is whitespace -->
<div><object id="plugin9" style="width: 100px; height: 100px" type="application/x-unknown">
<div><object id="plugin7" style="width: 100px; height: 100px" type="application/x-unknown">
</object></div>
<div><object id="plugin10" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
<div><object id="plugin8" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
</object></div>
@ -69,14 +65,14 @@ document.addEventListener("PluginBindingAttached", plugin_binding_attached, true
<!-- Even other plugins are considered content so no errors dispatched from these
objects, but the inner embeds do get processed -->
<div><object id="fallback3" style="width: 100px; height: 100px" type="application/x-unknown">
<embed id="plugin11" style="width: 100px; height: 100px" type="application/x-unknown">
<embed id="plugin9" style="width: 100px; height: 100px" type="application/x-unknown">
</object></div>
<div><object id="fallback4" style="width: 100px; height: 100px" data="data:application/x-unknown,test">
<embed id="plugin12" style="width: 100px; height: 100px" type="application/x-unknown">
<embed id="plugin10" style="width: 100px; height: 100px" type="application/x-unknown">
</object></div>
<!-- pluginurl was removed in bug 548133, and should not affect fallback -->
<div><object id="plugin13" style="width: 100px; height: 100px" type="application/x-unknown">
<div><object id="plugin11" style="width: 100px; height: 100px" type="application/x-unknown">
<param name="pluginurl">
</object></div>

View File

@ -17,9 +17,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391728
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
const gHttpTestRoot = location.toString().replace("chrome://mochitests/content/", "http://127.0.0.1:8888/").split(/\//).slice(0, -1).join('/') + '/';
Components.utils.import("resource://gre/modules/Services.jsm");
/** Test for Bug 391728 **/
// Plugins that should dispatch error events and have the pseudo classes set
const PLUGIN_COUNT = 13;
const PLUGIN_COUNT = 11;
// Plugins that should neither dispatch error events or have the pseudo classes set
const FALLBACK_COUNT = 5;
const OBJLC = Components.interfaces.nsIObjectLoadingContent;
@ -46,16 +50,39 @@ function plugin_binding_attached(event) {
}
function init_test() {
// Make sure the blocklist is off for the duration of this test
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.setBoolPref("extensions.blocklist.enabled", false);
if (!PluginUtils.withTestPlugin(start_test))
SimpleTest.finish();
}
function updateBlocklist(aCallback) {
var blocklistNotifier = Components.classes["@mozilla.org/extensions/blocklist;1"]
.getService(Components.interfaces.nsITimerCallback);
var observer = function() {
aCallback();
Services.obs.removeObserver(observer, "blocklist-updated");
};
Services.obs.addObserver(observer, "blocklist-updated", false);
blocklistNotifier.notify(null);
}
var _originalBlocklistURL = null;
function setAndUpdateBlocklist(aURL, aCallback) {
info("Setting blocklist to " + aURL);
if (!_originalBlocklistURL) {
_originalBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url");
}
Services.prefs.setCharPref("extensions.blocklist.url", aURL);
updateBlocklist(aCallback);
}
function resetBlocklist() {
info("resetting blocklist URL to " + _originalBlocklistURL);
Services.prefs.setCharPref("extensions.blocklist.url", _originalBlocklistURL);
}
function start_test(plugin) {
Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
is(plugin.description, "Plug-in for testing purposes.\u2122 " +
"(\u0939\u093f\u0928\u094d\u0926\u0940 " +
"\u4e2d\u6587 " +
@ -71,11 +98,9 @@ function start_test(plugin) {
}
function finish_test(plugin) {
Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
resetBlocklist();
plugin.enabledState = Components.interfaces.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = false;
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.clearUserPref("extensions.blocklist.enabled");
SimpleTest.finish();
}
@ -139,8 +164,11 @@ function test_disabled(plugin) {
test_style("dotted");
ok(plugin.disabled, "Plugin lost its disabled status");
plugin.enabledState = Components.interfaces.nsIPluginTag.STATE_ENABLED;
plugin.blocklisted = true;
load_frame(test_blocked, "file_bug391728");
setAndUpdateBlocklist(gHttpTestRoot + "blockPluginHard.xml",
function() {
load_frame(test_blocked, "file_bug391728");
});
}
function test_blocked(plugin) {
@ -159,7 +187,10 @@ function test_unknown(plugin) {
is(gDisabled.length, 0, "Should not have been any disabled plugins");
is(gBlocked.length, 0, "Should not have been any blocked plugins");
test_style("none");
finish_test(plugin);
setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", function() {
ok(!plugin.blocklisted, "Plugin shouldn't remain blocklisted");
finish_test(plugin);
});
}
SimpleTest.waitForExplicitFinish();

View File

@ -324,6 +324,10 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
NS_ENSURE_SUCCESS(rv, rv);
if (!iter) {
return NS_OK;
}
nsCOMPtr<nsISupports> tmp;
bool prefSaved = false;
bool loop = true;

View File

@ -132,7 +132,7 @@ HTMLTrackElement::Track()
void
HTMLTrackElement::CreateTextTrack()
{
DOMString label, srcLang;
nsString label, srcLang;
GetSrclang(srcLang);
GetLabel(label);
mTrack = new TextTrack(OwnerDoc()->GetParentObject(), Kind(), label, srcLang);

View File

@ -64,6 +64,10 @@ public:
{
GetHTMLAttr(nsGkAtoms::srclang, aSrclang);
}
void GetSrclang(nsString& aSrclang) const
{
GetHTMLAttr(nsGkAtoms::srclang, aSrclang);
}
void SetSrclang(const nsAString& aSrclang, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::srclang, aSrclang, aError);
@ -73,6 +77,10 @@ public:
{
GetHTMLAttr(nsGkAtoms::label, aLabel);
}
void GetLabel(nsString& aLabel) const
{
GetHTMLAttr(nsGkAtoms::label, aLabel);
}
void SetLabel(const nsAString& aLabel, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::label, aLabel, aError);

View File

@ -1494,6 +1494,13 @@ MediaStream::SetGraphImpl(MediaStreamGraphImpl* aGraph)
mGraph = aGraph;
}
void
MediaStream::SetGraphImpl(MediaStreamGraph* aGraph)
{
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(aGraph);
SetGraphImpl(graph);
}
StreamTime
MediaStream::GraphTimeToStreamTime(GraphTime aTime)
{

View File

@ -294,6 +294,7 @@ public:
* Sets the graph that owns this stream. Should only be called once.
*/
void SetGraphImpl(MediaStreamGraphImpl* aGraph);
void SetGraphImpl(MediaStreamGraph* aGraph);
// Control API.
// Since a stream can be played multiple ways, we need to combine independent
@ -302,20 +303,20 @@ public:
// a single audio output stream is used; the volumes are combined.
// Currently only the first enabled audio track is played.
// XXX change this so all enabled audio tracks are mixed and played.
void AddAudioOutput(void* aKey);
void SetAudioOutputVolume(void* aKey, float aVolume);
void RemoveAudioOutput(void* aKey);
virtual void AddAudioOutput(void* aKey);
virtual void SetAudioOutputVolume(void* aKey, float aVolume);
virtual void RemoveAudioOutput(void* aKey);
// Since a stream can be played multiple ways, we need to be able to
// play to multiple VideoFrameContainers.
// Only the first enabled video track is played.
void AddVideoOutput(VideoFrameContainer* aContainer);
void RemoveVideoOutput(VideoFrameContainer* aContainer);
virtual void AddVideoOutput(VideoFrameContainer* aContainer);
virtual void RemoveVideoOutput(VideoFrameContainer* aContainer);
// Explicitly block. Useful for example if a media element is pausing
// and we need to stop its stream emitting its buffered data.
void ChangeExplicitBlockerCount(int32_t aDelta);
virtual void ChangeExplicitBlockerCount(int32_t aDelta);
// Events will be dispatched by calling methods of aListener.
void AddListener(MediaStreamListener* aListener);
void RemoveListener(MediaStreamListener* aListener);
virtual void AddListener(MediaStreamListener* aListener);
virtual void RemoveListener(MediaStreamListener* aListener);
// A disabled track has video replaced by black, and audio replaced by
// silence.
void SetTrackEnabled(TrackID aTrackID, bool aEnabled);

View File

@ -10,6 +10,15 @@ using namespace mozilla::dom;
namespace mozilla {
CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
: MediaStream(aWrapper)
, mMutex("mozilla::camera::CameraPreviewMediaStream")
, mFrameCallback(nullptr)
{
SetGraphImpl(MediaStreamGraph::GetInstance());
mIsConsumed = false;
}
void
CameraPreviewMediaStream::AddAudioOutput(void* aKey)
{

View File

@ -23,26 +23,21 @@ public:
* A camera preview requests no delay and no buffering stream.
* But the SourceMediaStream do not support it.
*/
class CameraPreviewMediaStream : public MediaStream {
class CameraPreviewMediaStream : public MediaStream
{
typedef mozilla::layers::Image Image;
public:
CameraPreviewMediaStream(DOMMediaStream* aWrapper) :
MediaStream(aWrapper),
mMutex("mozilla::camera::CameraPreviewMediaStream"),
mFrameCallback(nullptr)
{
mIsConsumed = false;
}
CameraPreviewMediaStream(DOMMediaStream* aWrapper);
virtual void AddAudioOutput(void* aKey);
virtual void SetAudioOutputVolume(void* aKey, float aVolume);
virtual void RemoveAudioOutput(void* aKey);
virtual void AddVideoOutput(VideoFrameContainer* aContainer);
virtual void RemoveVideoOutput(VideoFrameContainer* aContainer);
virtual void ChangeExplicitBlockerCount(int32_t aDelta);
virtual void AddListener(MediaStreamListener* aListener);
virtual void RemoveListener(MediaStreamListener* aListener);
virtual void AddAudioOutput(void* aKey) MOZ_OVERRIDE;
virtual void SetAudioOutputVolume(void* aKey, float aVolume) MOZ_OVERRIDE;
virtual void RemoveAudioOutput(void* aKey) MOZ_OVERRIDE;
virtual void AddVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
virtual void RemoveVideoOutput(VideoFrameContainer* aContainer) MOZ_OVERRIDE;
virtual void ChangeExplicitBlockerCount(int32_t aDelta) MOZ_OVERRIDE;
virtual void AddListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
virtual void RemoveListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
virtual void Destroy();
// Call these on any thread.
@ -60,7 +55,6 @@ protected:
CameraPreviewFrameCallback* mFrameCallback;
};
}
#endif // DOM_CAMERA_CAMERAPREVIEWMEDIASTREAM_H

View File

@ -97,6 +97,9 @@ interface nsIPluginHost : nsISupports
ACString getPermissionStringForType(in AUTF8String mimeType);
bool isPluginClickToPlayForType(in AUTF8String mimeType);
/**
* Get the nsIPluginTag state for this MIME type.
*/
unsigned long getStateForType(in AUTF8String mimeType);
};

View File

@ -5,7 +5,7 @@
#include "nsISupports.idl"
[scriptable, uuid(00ea1f72-a57a-49bb-ac57-478902d9228b)]
[scriptable, uuid(0354d96d-3fd3-4365-a0a2-6c807ec1ce95)]
interface nsIPluginTag : nsISupports
{
// enabledState is stored as one of the following as an integer in prefs,
@ -19,7 +19,12 @@ interface nsIPluginTag : nsISupports
readonly attribute AUTF8String fullpath;
readonly attribute AUTF8String version;
readonly attribute AUTF8String name;
attribute boolean blocklisted;
/**
* true only if this plugin is "hardblocked" and cannot be enabled.
*/
readonly attribute boolean blocklisted;
readonly attribute boolean disabled;
readonly attribute boolean clicktoplay;
attribute unsigned long enabledState;

View File

@ -1790,13 +1790,6 @@ nsNPAPIPluginInstance::CheckJavaC2PJSObjectQuirk(uint16_t paramCount,
return;
}
bool isClickToPlay;
nsAutoCString mimeType(mMIMEType);
rv = pluginHost->IsPluginClickToPlayForType(mimeType, &isClickToPlay);
if (NS_FAILED(rv) || !isClickToPlay) {
return;
}
nsPluginTag* pluginTag = pluginHost->TagForPlugin(mPlugin);
if (!pluginTag ||
!pluginTag->mIsJavaPlugin) {
@ -1807,10 +1800,10 @@ nsNPAPIPluginInstance::CheckJavaC2PJSObjectQuirk(uint16_t paramCount,
bool haveCodeParam = false;
bool isCodeParamEmpty = true;
for (uint16_t i = 0; i < paramCount; ++i) {
if (PL_strcasecmp(paramNames[i], "code") == 0) {
for (uint16_t i = paramCount; i > 0; --i) {
if (PL_strcasecmp(paramNames[i - 1], "code") == 0) {
haveCodeParam = true;
if (strlen(paramValues[i]) > 0) {
if (strlen(paramValues[i - 1]) > 0) {
isCodeParamEmpty = false;
}
break;

View File

@ -1043,57 +1043,31 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType,
return rv;
}
nsresult
nsPluginHost::IsPluginEnabledForType(const char* aMimeType)
bool
nsPluginHost::PluginExistsForType(const char* aMimeType)
{
nsPluginTag *plugin = FindPluginForType(aMimeType, true);
if (plugin)
return NS_OK;
// Pass false as the second arg so we can return NS_ERROR_PLUGIN_DISABLED
// for disabled plug-ins.
plugin = FindPluginForType(aMimeType, false);
if (!plugin)
return NS_ERROR_FAILURE;
if (!plugin->IsActive()) {
if (plugin->IsBlocklisted())
return NS_ERROR_PLUGIN_BLOCKLISTED;
else
return NS_ERROR_PLUGIN_DISABLED;
}
return NS_OK;
nsPluginTag *plugin = FindPluginForType(aMimeType, false);
return nullptr != plugin;
}
NS_IMETHODIMP
nsPluginHost::IsPluginClickToPlayForType(const nsACString &aMimeType, bool *aResult)
nsPluginHost::GetStateForType(const nsACString &aMimeType, uint32_t* aResult)
{
nsPluginTag *plugin = FindPluginForType(aMimeType.Data(), true);
if (!plugin) {
return NS_ERROR_UNEXPECTED;
}
uint32_t blocklistState = nsIBlocklistService::STATE_NOT_BLOCKED;
nsresult rv = GetBlocklistStateForType(aMimeType.Data(), &blocklistState);
NS_ENSURE_SUCCESS(rv, rv);
if ((mPluginsClickToPlay && plugin->IsClicktoplay()) ||
blocklistState == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE ||
blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
*aResult = true;
}
else {
*aResult = false;
}
return NS_OK;
return plugin->GetEnabledState(aResult);
}
nsresult
nsPluginHost::GetBlocklistStateForType(const char *aMimeType, uint32_t *aState)
{
nsPluginTag *plugin = FindPluginForType(aMimeType, true);
if (!plugin) {
plugin = FindPluginForType(aMimeType, false);
}
if (plugin) {
nsCOMPtr<nsIBlocklistService> blocklist = do_GetService("@mozilla.org/extensions/blocklist;1");
if (blocklist) {
@ -1115,6 +1089,9 @@ nsPluginHost::GetPermissionStringForType(const nsACString &aMimeType, nsACString
nsresult rv = GetBlocklistStateForType(aMimeType.Data(), &blocklistState);
NS_ENSURE_SUCCESS(rv, rv);
nsPluginTag *tag = FindPluginForType(aMimeType.Data(), true);
if (!tag) {
tag = FindPluginForType(aMimeType.Data(), false);
}
if (!tag) {
return NS_ERROR_FAILURE;
}
@ -1967,16 +1944,10 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
EmptyString(), &state);
if (NS_SUCCEEDED(rv)) {
// 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->SetBlocklisted(true);
}
if (state == nsIBlocklistService::STATE_SOFTBLOCKED && !seenBefore) {
pluginTag->SetEnabledState(nsIPluginTag::STATE_DISABLED);
}

View File

@ -79,7 +79,8 @@ public:
nsresult SetUpPluginInstance(const char *aMimeType,
nsIURI *aURL,
nsPluginInstanceOwner *aOwner);
nsresult IsPluginEnabledForType(const char* aMimeType);
bool PluginExistsForType(const char* aMimeType);
nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
nsresult GetBlocklistStateForType(const char *aMimeType, uint32_t *state);

View File

@ -11,6 +11,7 @@
#include "nsServiceManagerUtils.h"
#include "nsPluginsDir.h"
#include "nsPluginHost.h"
#include "nsIBlocklistService.h"
#include "nsIUnicodeDecoder.h"
#include "nsIPlatformCharset.h"
#include "nsICharsetConverterManager.h"
@ -30,7 +31,6 @@ using mozilla::TimeStamp;
// no longer used 0x0002 // reuse only if regenerating pluginreg.dat
#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
inline char* new_str(const char* str)
@ -63,12 +63,6 @@ GetStatePrefNameForPlugin(nsPluginTag* aTag)
return MakePrefNameForPlugin("state", aTag);
}
static nsCString
GetBlocklistedPrefNameForPlugin(nsPluginTag* aTag)
{
return MakePrefNameForPlugin("blocklisted", aTag);
}
NS_IMPL_ISUPPORTS1(DOMMimeTypeImpl, nsIDOMMimeType)
/* nsPluginTag */
@ -332,7 +326,14 @@ nsPluginTag::GetDisabled(bool* aDisabled)
bool
nsPluginTag::IsBlocklisted()
{
return Preferences::GetBool(GetBlocklistedPrefNameForPlugin(this).get(), false);
nsCOMPtr<nsIBlocklistService> bls = do_GetService("@mozilla.org/extensions/blocklist;1");
if (!bls) {
return false;
}
uint32_t state = nsIBlocklistService::STATE_NOT_BLOCKED;
bls->GetPluginBlocklistState(this, EmptyString(), EmptyString(), &state);
return state == nsIBlocklistService::STATE_BLOCKED;
}
NS_IMETHODIMP
@ -342,26 +343,6 @@ nsPluginTag::GetBlocklisted(bool* aBlocklisted)
return NS_OK;
}
NS_IMETHODIMP
nsPluginTag::SetBlocklisted(bool blocklisted)
{
if (blocklisted == IsBlocklisted()) {
return NS_OK;
}
const nsCString pref = GetBlocklistedPrefNameForPlugin(this);
if (blocklisted) {
Preferences::SetBool(pref.get(), true);
} else {
Preferences::ClearUser(pref.get());
}
if (nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst()) {
host->UpdatePluginInfo(this);
}
return NS_OK;
}
bool
nsPluginTag::IsClicktoplay()
{
@ -556,8 +537,4 @@ void nsPluginTag::ImportFlagsToPrefs(uint32_t flags)
if (!(flags & NS_PLUGIN_FLAG_ENABLED)) {
SetPluginState(ePluginState_Disabled);
}
if (flags & NS_PLUGIN_FLAG_BLOCKLISTED) {
Preferences::SetBool(GetBlocklistedPrefNameForPlugin(this).get(), true);
}
}

View File

@ -11,7 +11,7 @@
Components.utils.import("resource://gre/modules/Services.jsm");
var pluginHost = Components.classes["@mozilla.org/plugin/host;1"]
.getService(Components.interfaces.nsIPluginHost);
ok(!pluginHost.isPluginClickToPlayForType("application/x-test"), "click-to-play should be off to begin with");
is(pluginHost.getStateForType("application/x-test"), Components.interfaces.nsIPluginTag.STATE_ENABLED, "click-to-play should be off to begin with");
Services.prefs.setBoolPref("plugins.click_to_play", true);
var pluginTags = pluginHost.getPluginTags();
@ -24,11 +24,11 @@
}
ok(testPlugin, "Should have Test Plug-in");
testPlugin.enabledState = Components.interfaces.nsIPluginTag.STATE_CLICKTOPLAY;
ok(pluginHost.isPluginClickToPlayForType("application/x-test"), "click-to-play should be on for Test Plug-in now");
ok(!pluginHost.isPluginClickToPlayForType("application/x-second-test"), "click-to-play should still be off for the Second Test Plug-in");
is(pluginHost.getStateForType("application/x-test"), Components.interfaces.nsIPluginTag.STATE_CLICKTOPLAY, "click-to-play should be on for Test Plug-in now");
is(pluginHost.getStateForType("application/x-second-test"), Components.interfaces.nsIPluginTag.STATE_ENABLED, "click-to-play should still be off for the Second Test Plug-in");
testPlugin.enabledState = Components.interfaces.nsIPluginTag.STATE_ENABLED;
ok(!pluginHost.isPluginClickToPlayForType("application/x-test"), "click-to-play should be off for Test Plug-in now");
is(pluginHost.getStateForType("application/x-test"), Components.interfaces.nsIPluginTag.STATE_ENABLED, "click-to-play should be off for Test Plug-in now");
Services.prefs.clearUserPref("plugins.click_to_play");
</script>

View File

@ -55,7 +55,6 @@ function run_test() {
const pluginName = file.leafName.substring(0, file.leafName.length - suffix.length).toLowerCase();
const pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
const statePref = "plugin.state." + pluginName;
const blocklistedPref = "plugin.blocklisted." + pluginName;
// write plugin registry data
let registry = "";
@ -83,7 +82,6 @@ function run_test() {
// check that the expected plugin state was loaded correctly from the registry
do_check_true(plugin.disabled);
do_check_false(plugin.blocklisted);
do_check_false(plugin.clicktoplay);
// ... and imported into prefs, with 0 being the disabled state
do_check_eq(0, Services.prefs.getIntPref(statePref));

View File

@ -31,7 +31,7 @@ endif
DEFINES += -DMOZ_GFX -DUSE_CAIRO -DGFX2D_INTERNAL
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gtk2 gonk qt))
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gtk2 gtk3 gonk qt))
DEFINES += -DMOZ_ENABLE_FREETYPE
endif

View File

@ -58,7 +58,7 @@ if CONFIG['MOZ_ENABLE_SKIA']:
'image_operations.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gonk', 'qt'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
CPP_SOURCES += [
'ScaledFontFreetype.cpp',
]

View File

@ -142,7 +142,7 @@ ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
CSRCS += cairo-quartz-surface.c cairo-quartz-image-surface.c cairo-quartz-font.c
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
ifdef MOZ_WIDGET_GTK
CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) $(PS_CSRCS)
endif

View File

@ -49,7 +49,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'beos':
CPP_SOURCES += [
'cairo-beos-surface.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
elif CONFIG['MOZ_WIDGET_GTK']:
EXPORTS.cairo += [
'cairo-pdf.h',
'cairo-ps.h',

View File

@ -35,7 +35,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
GL_PROVIDER = CGL
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
ifdef MOZ_WIDGET_GTK
ifdef MOZ_PLATFORM_MAEMO
GL_PROVIDER = EGL
else

View File

@ -14,7 +14,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
gl_provider = 'WGL'
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
gl_provider = 'CGL'
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
elif CONFIG['MOZ_WIDGET_GTK']:
if CONFIG['fdef MOZ_PLATFORM_MAEMO']:
gl_provider = 'EGL'
else:

View File

@ -22,8 +22,8 @@ include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_PANGO_CFLAGS)
ifdef MOZ_WIDGET_GTK
CXXFLAGS += $(MOZ_PANGO_CFLAGS)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)

View File

@ -68,7 +68,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
OS_LIBS += -framework Cocoa
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
ifdef MOZ_WIDGET_GTK
OS_LIBS += $(MOZ_PANGO_LIBS) $(XLIBS)
CXXFLAGS += $(MOZ_PANGO_CFLAGS)
endif

View File

@ -24,7 +24,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/content/xml/document/src \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gtk2 gonk qt))
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gtk2 gtk3 gonk qt))
DEFINES += -DMOZ_ENABLE_FREETYPE
endif
@ -88,7 +88,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
CXXFLAGS += $(CAIRO_FT_CFLAGS)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
ifdef MOZ_WIDGET_GTK
CXXFLAGS += $(MOZ_PANGO_CFLAGS)
endif

View File

@ -96,7 +96,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
'nsUnicodeRange.cpp',
'gfxQuartzNativeDrawing.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
elif CONFIG['MOZ_WIDGET_GTK']:
EXPORTS += [
'gfxFT2FontBase.h',
'gfxGdkNativeRenderer.h',

View File

@ -260,7 +260,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
unsigned staticLevel;
RootedValue thisv(cx);
if (evalType == DIRECT_EVAL) {
JS_ASSERT_IF(caller.isStackFrame(), !caller.asStackFrame()->runningInIon());
JS_ASSERT_IF(caller.isStackFrame(), !caller.asStackFrame()->runningInJit());
staticLevel = caller.script()->staticLevel + 1;
// Direct calls to eval are supposed to see the caller's |this|. If we

View File

@ -16,7 +16,7 @@ VISIBILITY_FLAGS =
ifneq (WINNT,$(HOST_OS_ARCH))
HOST_PROGRAM = nsinstall_real$(HOST_BIN_SUFFIX)
HOST_CSRCS = nsinstall.c pathsub.c
DISABLED_HOST_CSRCS = nsinstall.c pathsub.c
endif
# IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have

View File

@ -4,3 +4,9 @@
# 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/.
if CONFIG['HOST_OS_ARCH'] != 'WINNT':
HOST_CSRCS += [
'nsinstall.c',
'pathsub.c',
]

View File

@ -275,15 +275,15 @@ MarkRangeConservativelyAndSkipIon(JSTracer *trc, JSRuntime *rt, const uintptr_t
const uintptr_t *i = begin;
#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION)
// Walk only regions in between Ion activations. Note that non-volatile
// registers are spilled to the stack before the entry Ion frame, ensuring
// Walk only regions in between JIT activations. Note that non-volatile
// registers are spilled to the stack before the entry frame, ensuring
// that the conservative scanner will still see them.
for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
uintptr_t *ionMin, *ionEnd;
ion.ionStackRange(ionMin, ionEnd);
for (ion::JitActivationIterator iter(rt); !iter.done(); ++iter) {
uintptr_t *jitMin, *jitEnd;
iter.jitStackRange(jitMin, jitEnd);
MarkRangeConservatively(trc, i, ionMin);
i = ionEnd;
MarkRangeConservatively(trc, i, jitMin);
i = jitEnd;
}
#endif
@ -742,7 +742,7 @@ js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
rt->stackSpace.mark(trc);
#ifdef JS_ION
ion::MarkIonActivations(rt, trc);
ion::MarkJitActivations(rt, trc);
#endif
for (CompartmentsIter c(rt); !c.done(); c.next())

View File

@ -119,7 +119,7 @@ CheckStackRootsRange(JSRuntime *rt, uintptr_t *begin, uintptr_t *end, Rooter *rb
}
static void
CheckStackRootsRangeAndSkipIon(JSRuntime *rt, uintptr_t *begin, uintptr_t *end, Rooter *rbegin, Rooter *rend)
CheckStackRootsRangeAndSkipJit(JSRuntime *rt, uintptr_t *begin, uintptr_t *end, Rooter *rbegin, Rooter *rend)
{
/*
* Regions of the stack between Ion activiations are marked exactly through
@ -129,16 +129,16 @@ CheckStackRootsRangeAndSkipIon(JSRuntime *rt, uintptr_t *begin, uintptr_t *end,
uintptr_t *i = begin;
#if defined(JS_ION)
for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
uintptr_t *ionMin, *ionEnd;
ion.ionStackRange(ionMin, ionEnd);
for (ion::JitActivationIterator iter(rt); !iter.done(); ++iter) {
uintptr_t *jitMin, *jitEnd;
iter.jitStackRange(jitMin, jitEnd);
uintptr_t *upto = Min(ionMin, end);
uintptr_t *upto = Min(jitMin, end);
if (upto > i)
CheckStackRootsRange(rt, i, upto, rbegin, rend);
else
break;
i = ionEnd;
i = jitEnd;
}
#endif
@ -296,7 +296,7 @@ JS::CheckStackRoots(JSContext *cx)
}
}
CheckStackRootsRangeAndSkipIon(rt, stackMin, stackEnd, firstToScan, rooters.end());
CheckStackRootsRangeAndSkipJit(rt, stackMin, stackEnd, firstToScan, rooters.end());
CheckStackRootsRange(rt, cgcd->registerSnapshot.words,
ArrayEnd(cgcd->registerSnapshot.words),
firstToScan, rooters.end());

View File

@ -3402,8 +3402,8 @@ CheckCallArgs(FunctionCompiler &f, ParseNode *callNode, Use use, FunctionCompile
if (!CheckExpr(f, argNode, use, &argDef, &argType))
return false;
if (argType.isVoid())
return f.fail(argNode, "void is not a valid argument type");
if (argType.toMIRType() == MIRType_None)
return f.failf(argNode, "%s is not a valid argument type", argType.toChars());
if (!f.passArg(argDef, argType, args))
return false;

View File

@ -69,9 +69,9 @@ ion::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
JSContext *cx = GetIonContext()->cx;
// We don't have an exit frame.
cx->mainThread().ionTop = NULL;
IonActivationIterator ionActivations(cx);
IonBailoutIterator iter(ionActivations, sp);
IonActivation *activation = ionActivations.activation();
JitActivationIterator jitActivations(cx->runtime());
IonBailoutIterator iter(jitActivations, sp);
JitActivation *activation = jitActivations.activation()->asJit();
IonSpew(IonSpew_Bailouts, "Took bailout! Snapshot offset: %d", iter.snapshotOffset());
@ -100,9 +100,9 @@ ion::InvalidationBailout(InvalidationBailoutStack *sp, size_t *frameSizeOut,
// We don't have an exit frame.
cx->mainThread().ionTop = NULL;
IonActivationIterator ionActivations(cx);
IonBailoutIterator iter(ionActivations, sp);
IonActivation *activation = ionActivations.activation();
JitActivationIterator jitActivations(cx->runtime());
IonBailoutIterator iter(jitActivations, sp);
JitActivation *activation = jitActivations.activation()->asJit();
IonSpew(IonSpew_Bailouts, "Took invalidation bailout! Snapshot offset: %d", iter.snapshotOffset());

View File

@ -122,8 +122,8 @@ class IonBailoutIterator : public IonFrameIterator
IonScript *topIonScript_;
public:
IonBailoutIterator(const IonActivationIterator &activations, BailoutStack *sp);
IonBailoutIterator(const IonActivationIterator &activations, InvalidationBailoutStack *sp);
IonBailoutIterator(const JitActivationIterator &activations, BailoutStack *sp);
IonBailoutIterator(const JitActivationIterator &activations, InvalidationBailoutStack *sp);
SnapshotOffset snapshotOffset() const {
JS_ASSERT(topIonScript_);

View File

@ -999,7 +999,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
}
uint32_t
ion::BailoutIonToBaseline(JSContext *cx, IonActivation *activation, IonBailoutIterator &iter,
ion::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIterator &iter,
bool invalidate, BaselineBailoutInfo **bailoutInfo)
{
JS_ASSERT(bailoutInfo != NULL);
@ -1214,7 +1214,10 @@ ion::FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo)
// that script->needsArgsObj() implies frame->hasArgsObj().
RootedScript innerScript(cx, NULL);
RootedScript outerScript(cx, NULL);
IonFrameIterator iter(cx);
JS_ASSERT(cx->mainThread().currentlyRunningInJit());
IonFrameIterator iter(cx->mainThread().ionTop);
uint32_t frameno = 0;
while (frameno < numFrames) {
JS_ASSERT(!iter.isOptimizedJS());

View File

@ -676,7 +676,9 @@ ICStubCompiler::emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, Reg
static bool
IsTopFrameConstructing(JSContext *cx)
{
IonFrameIterator iter(cx);
JS_ASSERT(cx->mainThread().currentlyRunningInJit());
JitActivationIterator activations(cx->runtime());
IonFrameIterator iter(activations);
JS_ASSERT(iter.type() == IonFrame_Exit);
++iter;

View File

@ -116,9 +116,11 @@ EnterBaseline(JSContext *cx, StackFrame *fp, void *jitcode, bool osr)
{
AssertCompartmentUnchanged pcc(cx);
IonContext ictx(cx, NULL);
IonActivation activation(cx, fp);
JitActivation activation(cx, fp->isConstructing());
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
fp->setRunningInJit();
// Pass the scope chain for global and eval frames.
JSObject *scopeChain = NULL;
if (!fp->isNonEvalFunctionFrame())
@ -132,6 +134,8 @@ EnterBaseline(JSContext *cx, StackFrame *fp, void *jitcode, bool osr)
// Single transition point from Interpreter to Baseline.
enter(jitcode, maxArgc, maxArgv, osr ? fp : NULL, calleeToken, scopeChain, numStackValues,
result.address());
fp->clearRunningInJit();
}
JS_ASSERT(fp == cx->fp());
@ -813,7 +817,7 @@ ion::ToggleBaselineSPS(JSRuntime *runtime, bool enable)
}
static void
MarkActiveBaselineScripts(JSContext *cx, const IonActivationIterator &activation)
MarkActiveBaselineScripts(JSContext *cx, const JitActivationIterator &activation)
{
for (ion::IonFrameIterator iter(activation); !iter.done(); ++iter) {
switch (iter.type()) {
@ -836,10 +840,10 @@ MarkActiveBaselineScripts(JSContext *cx, const IonActivationIterator &activation
void
ion::MarkActiveBaselineScripts(Zone *zone)
{
// First check if there is an IonActivation on the stack, so that there
// First check if there is a JitActivation on the stack, so that there
// must be a valid IonContext.
IonActivationIterator iter(zone->rt);
if (!iter.more())
JitActivationIterator iter(zone->rt);
if (iter.done())
return;
// If baseline is disabled, there are no baseline scripts on the stack.
@ -847,7 +851,7 @@ ion::MarkActiveBaselineScripts(Zone *zone)
if (!ion::IsBaselineEnabled(cx))
return;
for (; iter.more(); ++iter) {
for (; !iter.done(); ++iter) {
if (iter.activation()->compartment()->zone() == zone)
MarkActiveBaselineScripts(cx, iter);
}

View File

@ -319,7 +319,7 @@ struct BaselineBailoutInfo
};
uint32_t
BailoutIonToBaseline(JSContext *cx, IonActivation *activation, IonBailoutIterator &iter,
BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIterator &iter,
bool invalidate, BaselineBailoutInfo **bailoutInfo);
// Mark baseline scripts on the stack as active, so that they are not discarded

View File

@ -408,32 +408,6 @@ IonCompartment::getVMWrapper(const VMFunction &f)
return p->value;
}
IonActivation::IonActivation(JSContext *cx, StackFrame *fp)
: cx_(cx),
compartment_(cx->compartment()),
prev_(cx->mainThread().ionActivation),
entryfp_(fp),
prevIonTop_(cx->mainThread().ionTop),
prevIonJSContext_(cx->mainThread().ionJSContext),
prevpc_(NULL)
{
if (fp)
fp->setRunningInIon();
cx->mainThread().ionJSContext = cx;
cx->mainThread().ionActivation = this;
}
IonActivation::~IonActivation()
{
JS_ASSERT(cx_->mainThread().ionActivation == this);
if (entryfp_)
entryfp_->clearRunningInIon();
cx_->mainThread().ionActivation = prev();
cx_->mainThread().ionTop = prevIonTop_;
cx_->mainThread().ionJSContext = prevIonJSContext_;
}
IonCode *
IonCode::New(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutablePool *pool)
{
@ -935,12 +909,11 @@ namespace ion {
bool
OptimizeMIR(MIRGenerator *mir)
{
IonSpewPass("BuildSSA");
// Note: don't call AssertGraphCoherency before SplitCriticalEdges,
// the graph is not in RPO at this point.
MIRGraph &graph = mir->graph();
IonSpewPass("BuildSSA");
AssertBasicGraphCoherency(graph);
if (mir->shouldCancel("Start"))
return false;
@ -1836,12 +1809,17 @@ EnterIon(JSContext *cx, StackFrame *fp, void *jitcode)
{
AssertCompartmentUnchanged pcc(cx);
IonContext ictx(cx, NULL);
IonActivation activation(cx, fp);
JitActivation activation(cx, fp->isConstructing());
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
AutoFlushInhibitor afi(cx->compartment()->ionCompartment());
fp->setRunningInJit();
// Single transition point from Interpreter to Ion.
enter(jitcode, maxArgc, maxArgv, fp, calleeToken, /* scopeChain = */ NULL, 0,
result.address());
fp->clearRunningInJit();
}
JS_ASSERT(fp == cx->fp());
@ -1901,29 +1879,7 @@ ion::FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args)
JS_ASSERT(ion::IsEnabled(cx));
JS_ASSERT(!ion->bailoutExpected());
bool clearCallingIntoIon = false;
StackFrame *fp = cx->fp();
// Two cases we have to handle:
//
// (1) fp does not begin an Ion activation. This works exactly
// like invoking Ion from JM: entryfp is set to fp and fp
// has the callingIntoIon flag set.
//
// (2) fp already begins another IonActivation, for instance:
// JM -> Ion -> array_sort -> Ion
// In this cas we use an IonActivation with entryfp == NULL
// and prevpc != NULL.
IonActivation activation(cx, NULL);
if (!fp->beginsIonActivation()) {
fp->setCallingIntoIon();
clearCallingIntoIon = true;
activation.setEntryFp(fp);
} else {
JS_ASSERT(!activation.entryfp());
}
activation.setPrevPc(cx->regs().pc);
JitActivation activation(cx, /* firstFrameIsConstructing = */false);
EnterIonCode enter = cx->compartment()->ionCompartment()->enterJIT();
void *calleeToken = CalleeToToken(fun);
@ -1932,13 +1888,9 @@ ion::FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args)
JS_ASSERT(args.length() >= fun->nargs);
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
enter(jitcode, args.length() + 1, args.array() - 1, fp, calleeToken,
enter(jitcode, args.length() + 1, args.array() - 1, NULL, calleeToken,
/* scopeChain = */ NULL, 0, result.address());
if (clearCallingIntoIon)
fp->clearCallingIntoIon();
JS_ASSERT(fp == cx->fp());
JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
args.rval().set(result);
@ -2083,12 +2035,12 @@ ion::InvalidateAll(FreeOp *fop, Zone *zone)
FinishAllOffThreadCompilations(comp->ionCompartment());
}
for (IonActivationIterator iter(fop->runtime()); iter.more(); ++iter) {
for (JitActivationIterator iter(fop->runtime()); !iter.done(); ++iter) {
if (iter.activation()->compartment()->zone() == zone) {
IonContext ictx(zone->rt);
AutoFlushCache afc("InvalidateAll", zone->rt->ionRuntime());
IonSpew(IonSpew_Invalidate, "Invalidating all frames for GC");
InvalidateActivation(fop, iter.top(), true);
InvalidateActivation(fop, iter.jitTop(), true);
}
}
}
@ -2126,8 +2078,8 @@ ion::Invalidate(types::TypeCompartment &types, FreeOp *fop,
return;
}
for (IonActivationIterator iter(fop->runtime()); iter.more(); ++iter)
InvalidateActivation(fop, iter.top(), false);
for (JitActivationIterator iter(fop->runtime()); !iter.done(); ++iter)
InvalidateActivation(fop, iter.jitTop(), false);
// Drop the references added above. If a script was never active, its
// IonScript will be immediately destroyed. Otherwise, it will be held live

View File

@ -907,28 +907,8 @@ CheckUseImpliesOperand(MInstruction *ins, MUse *use)
}
#endif // DEBUG
#ifdef DEBUG
static void
AssertReversePostOrder(MIRGraph &graph)
{
// Check that every block is visited after all its predecessors (except backedges).
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
JS_ASSERT(!block->isMarked());
for (size_t i = 0; i < block->numPredecessors(); i++) {
MBasicBlock *pred = block->getPredecessor(i);
JS_ASSERT_IF(!pred->isLoopBackedge(), pred->isMarked());
}
block->mark();
}
graph.unmarkBlocks();
}
#endif
void
ion::AssertGraphCoherency(MIRGraph &graph)
ion::AssertBasicGraphCoherency(MIRGraph &graph)
{
#ifdef DEBUG
// Assert successor and predecessor list coherency.
@ -954,7 +934,34 @@ ion::AssertGraphCoherency(MIRGraph &graph)
}
JS_ASSERT(graph.numBlocks() == count);
#endif
}
#ifdef DEBUG
static void
AssertReversePostOrder(MIRGraph &graph)
{
// Check that every block is visited after all its predecessors (except backedges).
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
JS_ASSERT(!block->isMarked());
for (size_t i = 0; i < block->numPredecessors(); i++) {
MBasicBlock *pred = block->getPredecessor(i);
JS_ASSERT_IF(!pred->isLoopBackedge(), pred->isMarked());
}
block->mark();
}
graph.unmarkBlocks();
}
#endif
void
ion::AssertGraphCoherency(MIRGraph &graph)
{
#ifdef DEBUG
AssertBasicGraphCoherency(graph);
AssertReversePostOrder(graph);
#endif
}

View File

@ -47,6 +47,9 @@ BuildDominatorTree(MIRGraph &graph);
bool
BuildPhiReverseMapping(MIRGraph &graph);
void
AssertBasicGraphCoherency(MIRGraph &graph);
void
AssertGraphCoherency(MIRGraph &graph);

View File

@ -51,7 +51,8 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
failedBoundsCheck_(info->script()->failedBoundsCheck),
failedShapeGuard_(info->script()->failedShapeGuard),
nonStringIteration_(false),
lazyArguments_(NULL)
lazyArguments_(NULL),
inlineCallInfo_(NULL)
{
script_.init(info->script());
pc = info->startPC();
@ -160,9 +161,13 @@ IonBuilder::getSingleCallTarget(types::StackTypeSet *calleeTypes)
bool
IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
AutoObjectVector &targets, uint32_t maxTargets)
AutoObjectVector &targets,
uint32_t maxTargets,
bool *gotLambda)
{
JS_ASSERT(targets.length() == 0);
JS_ASSERT(gotLambda);
*gotLambda = false;
if (!calleeTypes)
return true;
@ -179,16 +184,33 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
return false;
for(unsigned i = 0; i < objCount; i++) {
JSObject *obj = calleeTypes->getSingleObject(i);
if (!obj || !obj->isFunction()) {
targets.clear();
return true;
if (obj) {
if (!obj->isFunction()) {
targets.clear();
return true;
}
if (obj->toFunction()->isInterpreted() && !obj->toFunction()->getOrCreateScript(cx))
return false;
DebugOnly<bool> appendOk = targets.append(obj);
JS_ASSERT(appendOk);
} else {
types::TypeObject *typeObj = calleeTypes->getTypeObject(i);
JS_ASSERT(typeObj);
if (!typeObj->isFunction() || !typeObj->interpretedFunction) {
targets.clear();
return true;
}
DebugOnly<bool> appendOk = targets.append(typeObj->interpretedFunction);
JS_ASSERT(appendOk);
*gotLambda = true;
}
if (obj->toFunction()->isInterpreted() && !obj->toFunction()->getOrCreateScript(cx))
return false;
if (!targets.append(obj))
return false;
}
// For now, only inline "singleton" lambda calls
if (*gotLambda && targets.length() > 1)
targets.clear();
return true;
}
@ -209,9 +231,6 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target)
if (!targetScript->compileAndGo)
return false;
if (targetScript->analysis()->usesScopeChain())
return false;
types::TypeObject *targetType = target->getType(cx);
if (!targetType || targetType->unknownProperties())
return false;
@ -220,7 +239,7 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target)
}
bool
IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
IonBuilder::canInlineTarget(JSFunction *target)
{
if (!target->isInterpreted()) {
IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted");
@ -572,6 +591,8 @@ bool
IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
CallInfo &callInfo)
{
inlineCallInfo_ = &callInfo;
if (!script()->ensureHasBytecodeTypeMap(cx))
return false;
@ -614,23 +635,21 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
if (!current->addPredecessorWithoutPhis(predecessor))
return false;
// Save the actual arguments the caller used to call this inlined call,
// to shortcut operations on "arguments" in the inlined call.
JS_ASSERT(inlinedArguments_.length() == 0);
if (!inlinedArguments_.append(callInfo.argv().begin(), callInfo.argv().end()))
return false;
// Initialize scope chain slot to Undefined. It's set later by |initScopeChain|.
{
MInstruction *scope = MConstant::New(UndefinedValue());
current->add(scope);
current->initSlot(info().scopeChainSlot(), scope);
}
// canEnterInlinedFunction vetoes scripts which use the scope chain or needs an
// arguments object.
JS_ASSERT(!script()->analysis()->usesScopeChain());
MInstruction *scope = MConstant::New(UndefinedValue());
current->add(scope);
current->initSlot(info().scopeChainSlot(), scope);
// Initialize |arguments| slot.
if (info().hasArguments()) {
MInstruction *argsObj = MConstant::New(UndefinedValue());
current->add(argsObj);
current->initSlot(info().argsObjSlot(), argsObj);
}
// Initialize |this| slot.
current->initSlot(info().thisSlot(), callInfo.thisArg());
IonSpew(IonSpew_Inlining, "Initializing %u arg slots", info().nargs());
@ -653,6 +672,10 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
current->initSlot(info().argSlot(i), arg);
}
// Initialize the scope chain now that args are initialized.
if (!initScopeChain(callInfo.fun()))
return false;
IonSpew(IonSpew_Inlining, "Initializing %u local slots", info().nlocals());
// Initialize local variables.
@ -765,7 +788,7 @@ IonBuilder::initParameters()
}
bool
IonBuilder::initScopeChain()
IonBuilder::initScopeChain(MDefinition *callee)
{
MInstruction *scope = NULL;
@ -784,9 +807,11 @@ IonBuilder::initScopeChain()
return abort("non-CNG global scripts are not supported");
if (JSFunction *fun = info().fun()) {
MCallee *callee = MCallee::New();
current->add(callee);
if (!callee) {
MCallee *calleeIns = MCallee::New();
current->add(calleeIns);
callee = calleeIns;
}
scope = MFunctionEnvironment::New(callee);
current->add(scope);
@ -1392,12 +1417,14 @@ IonBuilder::inspectOpcode(JSOp op)
case JSOP_CALLEE:
{
MInstruction *callee;
if (inliningDepth_ == 0)
callee = MCallee::New();
else
callee = MConstant::New(ObjectValue(*info().fun()));
current->add(callee);
MDefinition *callee;
if (inliningDepth_ == 0) {
MInstruction *calleeIns = MCallee::New();
current->add(calleeIns);
callee = calleeIns;
} else {
callee = inlineCallInfo_->fun();
}
current->push(callee);
return true;
}
@ -3556,7 +3583,7 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
return true;
// Determine whether inlining is possible at callee site
if (!canInlineTarget(target, callInfo))
if (!canInlineTarget(target))
return false;
// Heuristics!
@ -3834,9 +3861,6 @@ IonBuilder::makePolyInlineDispatch(JSContext *cx, CallInfo &callInfo,
IonBuilder::InliningStatus
IonBuilder::inlineSingleCall(CallInfo &callInfo, JSFunction *target)
{
// The inlined target must always be explicitly provided as a constant.
JS_ASSERT(callInfo.fun()->isConstant());
// Expects formals to be popped and wrapped.
if (target->isNative())
return inlineNativeCall(callInfo, target->native());
@ -3848,7 +3872,7 @@ IonBuilder::inlineSingleCall(CallInfo &callInfo, JSFunction *target)
IonBuilder::InliningStatus
IonBuilder::inlineCallsite(AutoObjectVector &targets, AutoObjectVector &originals,
CallInfo &callInfo)
bool lambda, CallInfo &callInfo)
{
if (!inliningEnabled())
return InliningStatus_NotInlined;
@ -3868,11 +3892,20 @@ IonBuilder::inlineCallsite(AutoObjectVector &targets, AutoObjectVector &original
if (!makeInliningDecision(target, callInfo))
return InliningStatus_NotInlined;
// Replace the function with an MConstant.
// Inlining will elminate uses of the original callee, but it needs to
// be preserved in phis if we bail out. Mark the old callee definition as
// folded to ensure this happens.
callInfo.fun()->setFoldedUnchecked();
MConstant *constFun = MConstant::New(ObjectValue(*target));
current->add(constFun);
callInfo.setFun(constFun);
// If the callee is not going to be a lambda (which may vary across
// different invocations), then the callee definition can be replaced by a
// constant.
if (!lambda) {
// Replace the function with an MConstant.
MConstant *constFun = MConstant::New(ObjectValue(*target));
current->add(constFun);
callInfo.setFun(constFun);
}
return inlineSingleCall(callInfo, target);
}
@ -4628,7 +4661,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
// Arguments
Vector<MDefinition *> args(cx);
if (!args.append(inlinedArguments_.begin(), inlinedArguments_.end()))
if (!args.append(inlineCallInfo_->argv().begin(), inlineCallInfo_->argv().end()))
return false;
callInfo.setArgs(&args);
@ -4679,11 +4712,13 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
// Acquire known call target if existent.
AutoObjectVector originals(cx);
bool gotLambda;
types::StackTypeSet *calleeTypes = current->peek(calleeDepth)->resultTypeSet();
if (calleeTypes) {
if (!getPolyCallTargets(calleeTypes, originals, 4))
if (!getPolyCallTargets(calleeTypes, originals, 4, &gotLambda))
return false;
}
JS_ASSERT_IF(gotLambda, originals.length() <= 1);
// If any call targets need to be cloned, clone them. Keep track of the
// originals as we need to case on them for poly inline.
@ -4707,8 +4742,11 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
if (!callInfo.init(current, argc))
return false;
if (gotLambda && targets.length() > 0)
callInfo.setLambda(true);
// Try inlining
InliningStatus status = inlineCallsite(targets, originals, callInfo);
InliningStatus status = inlineCallsite(targets, originals, gotLambda, callInfo);
if (status == InliningStatus_Inlined)
return true;
if (status == InliningStatus_Error)
@ -6947,7 +6985,7 @@ IonBuilder::jsop_arguments_length()
}
// We are inlining and know the number of arguments the callee pushed
return pushConstant(Int32Value(inlinedArguments_.length()));
return pushConstant(Int32Value(inlineCallInfo_->argv().length()));
}
bool
@ -7010,7 +7048,7 @@ IonBuilder::jsop_rest()
}
// We know the exact number of arguments the callee pushed.
unsigned numActuals = inlinedArguments_.length();
unsigned numActuals = inlineCallInfo_->argv().length();
unsigned numFormals = info().nargs() - 1;
unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
JSObject *templateObject = getNewArrayTemplateObject(numRest);
@ -7043,7 +7081,7 @@ IonBuilder::jsop_rest()
current->add(index);
MInstruction *store;
MDefinition *arg = inlinedArguments_[i];
MDefinition *arg = inlineCallInfo_->argv()[i];
if (elemTypes && !TypeSetIncludes(elemTypes, arg->type(), arg->resultTypeSet())) {
elemTypes->addFreeze(cx);
store = MCallSetElement::New(array, index, arg);

View File

@ -219,8 +219,10 @@ class IonBuilder : public MIRGenerator
JSFunction *getSingleCallTarget(types::StackTypeSet *calleeTypes);
bool getPolyCallTargets(types::StackTypeSet *calleeTypes,
AutoObjectVector &targets, uint32_t maxTargets);
bool canInlineTarget(JSFunction *target, CallInfo &callInfo);
AutoObjectVector &targets,
uint32_t maxTargets,
bool *gotLambda);
bool canInlineTarget(JSFunction *target);
void popCfgStack();
DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge);
@ -311,7 +313,7 @@ class IonBuilder : public MIRGenerator
bool initParameters();
void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex);
void rewriteParameters();
bool initScopeChain();
bool initScopeChain(MDefinition *callee = NULL);
bool initArgumentsObject();
bool pushConstant(const Value &v);
@ -508,7 +510,7 @@ class IonBuilder : public MIRGenerator
// Call functions
InliningStatus inlineCallsite(AutoObjectVector &targets, AutoObjectVector &originals,
CallInfo &callInfo);
bool lambda, CallInfo &callInfo);
bool inlineCalls(CallInfo &callInfo, AutoObjectVector &targets, AutoObjectVector &originals,
Vector<bool> &choiceSet, MGetPropertyCache *maybeCache);
@ -604,7 +606,6 @@ class IonBuilder : public MIRGenerator
BaselineInspector *inspector;
size_t inliningDepth_;
Vector<MDefinition *, 0, IonAllocPolicy> inlinedArguments_;
// Cutoff to disable compilation if excessive time is spent reanalyzing
// loop bodies to compute a fixpoint of the types for loop variables.
@ -625,6 +626,9 @@ class IonBuilder : public MIRGenerator
// If this script can use a lazy arguments object, it will be pre-created
// here.
MInstruction *lazyArguments_;
// If this is an inline builder, the call info for the builder.
const CallInfo *inlineCallInfo_;
};
class CallInfo
@ -634,6 +638,7 @@ class CallInfo
Vector<MDefinition *> args_;
bool constructing_;
bool lambda_;
public:
CallInfo(JSContext *cx, bool constructing)
@ -700,6 +705,10 @@ class CallInfo
return args_;
}
const Vector<MDefinition *> &argv() const {
return args_;
}
MDefinition *getArg(uint32_t i) {
JS_ASSERT(i < argc());
return args_[i];
@ -723,6 +732,13 @@ class CallInfo
return constructing_;
}
bool isLambda() const {
return lambda_;
}
void setLambda(bool lambda) {
lambda_ = lambda;
}
void wrapArgs(MBasicBlock *current) {
thisArg_ = wrap(current, thisArg_);
for (uint32_t i = 0; i < argc(); i++)

View File

@ -28,7 +28,6 @@ typedef void (*EnterIonCode)(void *code, int argc, Value *argv, StackFrame *fp,
CalleeToken calleeToken, JSObject *scopeChain,
size_t numStackValues, Value *vp);
class IonActivation;
class IonBuilder;
typedef Vector<IonBuilder*, 0, SystemAllocPolicy> OffThreadCompilationVector;
@ -175,7 +174,7 @@ class IonRuntime
class IonCompartment
{
friend class IonActivation;
friend class JitActivation;
// Ion state for the compartment's runtime.
IonRuntime *rt;
@ -310,63 +309,6 @@ class IonCompartment
}
};
class IonActivation
{
private:
JSContext *cx_;
JSCompartment *compartment_;
IonActivation *prev_;
StackFrame *entryfp_;
uint8_t *prevIonTop_;
JSContext *prevIonJSContext_;
// When creating an activation without a StackFrame, this field is used
// to communicate the calling pc for ScriptFrameIter.
jsbytecode *prevpc_;
public:
IonActivation(JSContext *cx, StackFrame *fp);
~IonActivation();
StackFrame *entryfp() const {
return entryfp_;
}
IonActivation *prev() const {
return prev_;
}
uint8_t *prevIonTop() const {
return prevIonTop_;
}
jsbytecode *prevpc() const {
JS_ASSERT_IF(entryfp_, entryfp_->callingIntoIon());
return prevpc_;
}
void setEntryFp(StackFrame *fp) {
JS_ASSERT_IF(fp, !entryfp_);
entryfp_ = fp;
}
void setPrevPc(jsbytecode *pc) {
JS_ASSERT_IF(pc, !prevpc_);
prevpc_ = pc;
}
JSCompartment *compartment() const {
return compartment_;
}
bool empty() const {
// If we have an entryfp, this activation is active. However, if
// FastInvoke is used, entryfp may be NULL and a non-NULL prevpc
// indicates this activation is not empty.
return !entryfp_ && !prevpc_;
}
static inline size_t offsetOfPrevPc() {
return offsetof(IonActivation, prevpc_);
}
static inline size_t offsetOfEntryFp() {
return offsetof(IonActivation, entryfp_);
}
};
// Called from JSCompartment::discardJitCode().
void InvalidateAll(FreeOp *fop, JS::Zone *zone);
void FinishInvalidation(FreeOp *fop, JSScript *script);

View File

@ -14,6 +14,10 @@
class JSFunction;
class JSScript;
namespace js {
class ActivationIterator;
};
namespace js {
namespace ion {
@ -52,7 +56,7 @@ enum FrameType
// An exit frame is necessary for transitioning from a JS frame into C++.
// From within C++, an exit frame is always the last frame in any
// IonActivation.
// JitActivation.
IonFrame_Exit,
// An OSR frame is added when performing OSR from within a bailout. It
@ -65,11 +69,10 @@ class IonCommonFrameLayout;
class IonJSFrameLayout;
class IonExitFrameLayout;
class IonActivation;
class IonActivationIterator;
class BaselineFrame;
class JitActivation;
class IonFrameIterator
{
protected:
@ -80,7 +83,7 @@ class IonFrameIterator
private:
mutable const SafepointIndex *cachedSafepointIndex_;
const IonActivation *activation_;
const JitActivation *activation_;
void dumpBaseline() const;
@ -94,7 +97,7 @@ class IonFrameIterator
activation_(NULL)
{ }
IonFrameIterator(const IonActivationIterator &activations);
IonFrameIterator(const ActivationIterator &activations);
IonFrameIterator(IonJSFrameLayout *fp);
// Current frame information.
@ -203,32 +206,6 @@ class IonFrameIterator
inline BaselineFrame *baselineFrame() const;
};
class IonActivationIterator
{
uint8_t *top_;
IonActivation *activation_;
private:
void settle();
public:
IonActivationIterator(JSContext *cx);
IonActivationIterator(JSRuntime *rt);
IonActivationIterator &operator++();
IonActivation *activation() const {
return activation_;
}
uint8_t *top() const {
return top_;
}
bool more() const;
// Returns the bottom and top addresses of the current activation.
void ionStackRange(uintptr_t *&min, uintptr_t *&end);
};
class IonJSFrameLayout;
class IonBailoutIterator;

View File

@ -30,13 +30,13 @@
namespace js {
namespace ion {
IonFrameIterator::IonFrameIterator(const IonActivationIterator &activations)
: current_(activations.top()),
IonFrameIterator::IonFrameIterator(const ActivationIterator &activations)
: current_(activations.jitTop()),
type_(IonFrame_Exit),
returnAddressToFp_(NULL),
frameSize_(0),
cachedSafepointIndex_(NULL),
activation_(activations.activation())
activation_(activations.activation()->asJit())
{
}
@ -597,45 +597,6 @@ EnsureExitFrame(IonCommonFrameLayout *frame)
frame->changePrevType(IonFrame_Unwound_OptimizedJS);
}
void
IonActivationIterator::settle()
{
while (activation_ && activation_->empty()) {
top_ = activation_->prevIonTop();
activation_ = activation_->prev();
}
}
IonActivationIterator::IonActivationIterator(JSContext *cx)
: top_(cx->mainThread().ionTop),
activation_(cx->mainThread().ionActivation)
{
settle();
}
IonActivationIterator::IonActivationIterator(JSRuntime *rt)
: top_(rt->mainThread.ionTop),
activation_(rt->mainThread.ionActivation)
{
settle();
}
IonActivationIterator &
IonActivationIterator::operator++()
{
JS_ASSERT(activation_);
top_ = activation_->prevIonTop();
activation_ = activation_->prev();
settle();
return *this;
}
bool
IonActivationIterator::more() const
{
return !!activation_;
}
CalleeToken
MarkCalleeToken(JSTracer *trc, CalleeToken token)
{
@ -790,9 +751,9 @@ MarkBaselineStubFrame(JSTracer *trc, const IonFrameIterator &frame)
}
void
IonActivationIterator::ionStackRange(uintptr_t *&min, uintptr_t *&end)
JitActivationIterator::jitStackRange(uintptr_t *&min, uintptr_t *&end)
{
IonFrameIterator frames(top());
IonFrameIterator frames(jitTop());
if (frames.isFakeExitFrame()) {
min = reinterpret_cast<uintptr_t *>(frames.fp());
@ -969,7 +930,7 @@ MarkIonExitFrame(JSTracer *trc, const IonFrameIterator &frame)
}
static void
MarkIonActivation(JSTracer *trc, const IonActivationIterator &activations)
MarkJitActivation(JSTracer *trc, const JitActivationIterator &activations)
{
for (IonFrameIterator frames(activations); !frames.done(); ++frames) {
switch (frames.type()) {
@ -1004,10 +965,10 @@ MarkIonActivation(JSTracer *trc, const IonActivationIterator &activations)
}
void
MarkIonActivations(JSRuntime *rt, JSTracer *trc)
MarkJitActivations(JSRuntime *rt, JSTracer *trc)
{
for (IonActivationIterator activations(rt); activations.more(); ++activations)
MarkIonActivation(trc, activations);
for (JitActivationIterator activations(rt); !activations.done(); ++activations)
MarkJitActivation(trc, activations);
}
void
@ -1020,7 +981,6 @@ AutoTempAllocatorRooter::trace(JSTracer *trc)
void
GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes)
{
JS_ASSERT(cx->fp()->beginsIonActivation());
IonSpew(IonSpew_Snapshots, "Recover PC & Script from the last frame.");
JSRuntime *rt = cx->runtime();
@ -1400,19 +1360,7 @@ IonFrameIterator::isConstructing() const
}
JS_ASSERT(parent.done());
// If entryfp is not set, we entered Ion via a C++ native, like Array.map,
// using FastInvoke. FastInvoke is never used for constructor calls.
if (!activation_->entryfp())
return false;
// If callingIntoIon, we either entered Ion from JM or entered Ion from
// a C++ native using FastInvoke. In both of these cases we don't handle
// constructor calls.
if (activation_->entryfp()->callingIntoIon())
return false;
JS_ASSERT(activation_->entryfp()->runningInIon());
return activation_->entryfp()->isConstructing();
return activation_->firstFrameIsConstructing();
}
unsigned

View File

@ -270,7 +270,7 @@ void HandleParallelFailure(ResumeFromException *rfe);
void EnsureExitFrame(IonCommonFrameLayout *frame);
void MarkIonActivations(JSRuntime *rt, JSTracer *trc);
void MarkJitActivations(JSRuntime *rt, JSTracer *trc);
void MarkIonCompilerRoots(JSTracer *trc);
static inline uint32_t

View File

@ -215,9 +215,10 @@ class MacroAssembler : public MacroAssemblerSpecific
movePtr(ImmWord(GetIonContext()->runtime), dest);
loadPtr(Address(dest, offsetof(JSRuntime, mainThread.ionJSContext)), dest);
}
void loadIonActivation(const Register &dest) {
void loadJitActivation(const Register &dest) {
movePtr(ImmWord(GetIonContext()->runtime), dest);
loadPtr(Address(dest, offsetof(JSRuntime, mainThread.ionActivation)), dest);
size_t offset = offsetof(JSRuntime, mainThread) + PerThreadData::offsetOfActivation();
loadPtr(Address(dest, offset), dest);
}
template<typename T>

View File

@ -4,10 +4,13 @@
* 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 "MIR.h"
#include "mozilla/Casting.h"
#include "BaselineInspector.h"
#include "IonBuilder.h"
#include "LICM.h" // For LinearSum
#include "MIR.h"
#include "MIRGraph.h"
#include "EdgeCaseAnalysis.h"
#include "RangeAnalysis.h"
@ -20,6 +23,8 @@
using namespace js;
using namespace js::ion;
using mozilla::BitwiseCast;
void
MDefinition::PrintOpcodeName(FILE *fp, MDefinition::Opcode op)
{
@ -862,11 +867,10 @@ IsConstant(MDefinition *def, double v)
if (!def->isConstant())
return false;
// Compare as bits to avoid conflating, e.g., -0 and 0.
mozilla::detail::DoublePun lhs, rhs;
lhs.d = def->toConstant()->value().toNumber();
rhs.d = v;
return lhs.u == rhs.u;
// Compare the underlying bits to not equate -0 and +0.
uint64_t lhs = BitwiseCast<uint64_t>(def->toConstant()->value().toNumber());
uint64_t rhs = BitwiseCast<uint64_t>(v);
return lhs == rhs;
}
MDefinition *

View File

@ -6180,6 +6180,10 @@ class MFunctionEnvironment
MDefinition *function() const {
return getOperand(0);
}
TypePolicy *typePolicy() {
return this;
}
};
// Loads the current js::ForkJoinSlice*.

View File

@ -112,7 +112,7 @@ class BailoutStack
} // namespace ion
} // namespace js
IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
BailoutStack *bailout)
: IonFrameIterator(activations),
machine_(bailout->machine())
@ -131,7 +131,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
}
// Compute the snapshot offset from the bailout ID.
IonActivation *activation = activations.activation();
JitActivation *activation = activations.activation()->asJit();
JSCompartment *jsCompartment = activation->compartment();
IonCompartment *ionCompartment = jsCompartment->ionCompartment();
IonCode *code = ionCompartment->getBailoutTable(bailout->frameClass());
@ -148,7 +148,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
snapshotOffset_ = topIonScript_->bailoutToSnapshot(bailoutId);
}
IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
InvalidationBailoutStack *bailout)
: IonFrameIterator(activations),
machine_(bailout->machine())

View File

@ -49,7 +49,7 @@ class BailoutStack
# pragma pack(pop)
#endif
IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
BailoutStack *bailout)
: IonFrameIterator(activations),
machine_(bailout->machineState())
@ -64,7 +64,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
snapshotOffset_ = bailout->snapshotOffset();
}
IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
InvalidationBailoutStack *bailout)
: IonFrameIterator(activations),
machine_(bailout->machine())

View File

@ -65,7 +65,7 @@ class BailoutStack
# pragma pack(pop)
#endif
IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
BailoutStack *bailout)
: IonFrameIterator(activations),
machine_(bailout->machine())
@ -84,7 +84,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
}
// Compute the snapshot offset from the bailout ID.
IonActivation *activation = activations.activation();
JitActivation *activation = activations.activation()->asJit();
JSCompartment *jsCompartment = activation->compartment();
IonCompartment *ionCompartment = jsCompartment->ionCompartment();
IonCode *code = ionCompartment->getBailoutTable(bailout->frameClass());
@ -101,7 +101,7 @@ IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
snapshotOffset_ = topIonScript_->bailoutToSnapshot(bailoutId);
}
IonBailoutIterator::IonBailoutIterator(const IonActivationIterator &activations,
IonBailoutIterator::IonBailoutIterator(const JitActivationIterator &activations,
InvalidationBailoutStack *bailout)
: IonFrameIterator(activations),
machine_(bailout->machine())

View File

@ -30,6 +30,8 @@ assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { retu
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return (+inc() + 1)|0 } return f');
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; inc(i>>>0) } return f');
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc(); return } return f');
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc(inc()) } return f');
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { g(inc()) } function g() {} return f');
assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {});
assertAsmLinkFail(asmCompile('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc()|0 } return f'), null, {inc:0});

View File

@ -0,0 +1,17 @@
// Error().stack (ScriptFrameIter) should not include frames from other contexts.
function g() {
evaluate("function h() {\nstack = Error().stack;\n };\n h();", {newContext: true});
}
function f() {
g();
}
f();
assertEq(stack,
"h@@evaluate:2\n" +
"@@evaluate:4\n");
function k() {
evaluate("stack = Error().stack", {newContext: true});
}
k();
assertEq(stack, "@@evaluate:1\n");

View File

@ -280,7 +280,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
case JSOP_SETALIASEDVAR:
case JSOP_LAMBDA:
usesScopeChain_ = true;
isIonInlineable = false;
break;
case JSOP_DEFFUN:

View File

@ -59,6 +59,7 @@ CPP_SOURCES += [
'testSetProperty.cpp',
'testSourcePolicy.cpp',
'testStringBuffer.cpp',
'testToIntWidth.cpp',
'testTrap.cpp',
'testTypedArrays.cpp',
'testUTF8.cpp',

View File

@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tests.h"
#include <math.h>
#include "vm/NumericConversions.h"
using js::detail::ToIntWidth;
using js::detail::ToUintWidth;
BEGIN_TEST(testToUint8TwiceUint8Range)
{
double d = -256;
uint8_t expected = 0;
do {
CHECK(ToUintWidth<uint8_t>(d) == expected);
d++;
expected++;
} while (d <= 256);
return true;
}
END_TEST(testToUint8TwiceUint8Range)
BEGIN_TEST(testToInt8)
{
double d = -128;
int8_t expected = -128;
do {
CHECK(ToIntWidth<int8_t>(d) == expected);
d++;
expected++;
} while (expected < 127);
return true;
}
END_TEST(testToInt8)
BEGIN_TEST(testToUint32Large)
{
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83)) == 0);
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83) + pow(2.0, 31)) == (1U << 31));
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83) + 2 * pow(2.0, 31)) == 0);
CHECK(ToUintWidth<uint32_t>(pow(2.0, 83) + 3 * pow(2.0, 31)) == (1U << 31));
CHECK(ToUintWidth<uint32_t>(pow(2.0, 84)) == 0);
CHECK(ToUintWidth<uint32_t>(pow(2.0, 84) + pow(2.0, 31)) == 0);
CHECK(ToUintWidth<uint32_t>(pow(2.0, 84) + pow(2.0, 32)) == 0);
return true;
}
END_TEST(testToUint32Large)
BEGIN_TEST(testToUint64Large)
{
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115)) == 0);
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115) + pow(2.0, 63)) == (1ULL << 63));
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115) + 2 * pow(2.0, 63)) == 0);
CHECK(ToUintWidth<uint64_t>(pow(2.0, 115) + 3 * pow(2.0, 63)) == (1ULL << 63));
CHECK(ToUintWidth<uint64_t>(pow(2.0, 116)) == 0);
CHECK(ToUintWidth<uint64_t>(pow(2.0, 116) + pow(2.0, 63)) == 0);
CHECK(ToUintWidth<uint64_t>(pow(2.0, 116) + pow(2.0, 64)) == 0);
return true;
}
END_TEST(testToUint64Large)

View File

@ -716,7 +716,7 @@ PerThreadData::PerThreadData(JSRuntime *runtime)
ionTop(NULL),
ionJSContext(NULL),
ionStackLimit(0),
ionActivation(NULL),
activation_(NULL),
asmJSActivationStack_(NULL),
suppressGC(0)
{}

View File

@ -8,6 +8,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Util.h"
#include <stdlib.h>
@ -43,6 +44,7 @@ using namespace js;
using namespace js::gc;
using namespace js::types;
using mozilla::Abs;
using mozilla::ArrayLength;
using mozilla::DebugOnly;
using mozilla::IsNaN;
@ -1291,19 +1293,6 @@ NumDigitsBase10(uint32_t n)
return t - (n < powersOf10[t]) + 1;
}
static JS_ALWAYS_INLINE uint32_t
NegateNegativeInt32(int32_t i)
{
/*
* We cannot simply return '-i' because this is undefined for INT32_MIN.
* 2s complement does actually give us what we want, however. That is,
* ~0x80000000 + 1 = 0x80000000 which is correct when interpreted as a
* uint32_t. To avoid undefined behavior, we write out 2s complement
* explicitly and rely on the peephole optimizer to generate 'neg'.
*/
return ~uint32_t(i) + 1;
}
inline bool
CompareLexicographicInt32(JSContext *cx, const Value &a, const Value &b, bool *lessOrEqualp)
{
@ -1324,14 +1313,8 @@ CompareLexicographicInt32(JSContext *cx, const Value &a, const Value &b, bool *l
} else if ((aint >= 0) && (bint < 0)) {
*lessOrEqualp = false;
} else {
uint32_t auint, buint;
if (aint >= 0) {
auint = aint;
buint = bint;
} else {
auint = NegateNegativeInt32(aint);
buint = NegateNegativeInt32(bint);
}
uint32_t auint = Abs(aint);
uint32_t buint = Abs(bint);
/*
* ... get number of digits of both integers.

View File

@ -1262,6 +1262,9 @@ JSContext::saveFrameChain()
return false;
}
if (Activation *act = mainThread().activation())
act->saveFrameChain();
if (defaultCompartmentObject_)
setCompartment(defaultCompartmentObject_->compartment());
else
@ -1282,6 +1285,9 @@ JSContext::restoreFrameChain()
stack.restoreFrameChain();
if (Activation *act = mainThread().activation())
act->restoreFrameChain();
if (isExceptionPending())
wrapPendingException();
}

View File

@ -129,7 +129,6 @@ class MathCache;
namespace ion {
class IonRuntime;
class IonActivation;
}
class WeakMapBase;
@ -488,11 +487,6 @@ class PerThreadData : public js::PerThreadDataFriendFields
inline void setIonStackLimit(uintptr_t limit);
/*
* This points to the most recent Ion activation running on the thread.
*/
js::ion::IonActivation *ionActivation;
/*
* asm.js maintains a stack of AsmJSModule activations (see AsmJS.h). This
* stack is used by JSRuntime::triggerOperationCallback to stop long-
@ -502,12 +496,23 @@ class PerThreadData : public js::PerThreadDataFriendFields
* synchronized (by rt->operationCallbackLock).
*/
private:
friend class js::Activation;
friend class js::ActivationIterator;
friend class js::AsmJSActivation;
/*
* Points to the most recent activation running on the thread.
* See Activation comment in vm/Stack.h.
*/
js::Activation *activation_;
/* See AsmJSActivation comment. Protected by rt->operationCallbackLock. */
js::AsmJSActivation *asmJSActivationStack_;
public:
static unsigned offsetOfActivation() {
return offsetof(PerThreadData, activation_);
}
static unsigned offsetOfAsmJSActivationStackReadOnly() {
return offsetof(PerThreadData, asmJSActivationStack_);
}
@ -519,6 +524,16 @@ class PerThreadData : public js::PerThreadDataFriendFields
return asmJSActivationStack_;
}
js::Activation *activation() const {
return activation_;
}
bool currentlyRunningInInterpreter() const {
return activation_->isInterpreter();
}
bool currentlyRunningInJit() const {
return activation_->isJit();
}
/*
* When this flag is non-zero, any attempt to GC will be skipped. It is used
* to suppress GC when reporting an OOM (see js_ReportOutOfMemory) and in

View File

@ -595,21 +595,11 @@ JSCompartment::purge()
bool
JSCompartment::hasScriptsOnStack()
{
for (AllFramesIter afi(rt); !afi.done(); ++afi) {
#ifdef JS_ION
// If this is an Ion frame, check the IonActivation instead
if (afi.isIon())
continue;
#endif
if (afi.interpFrame()->script()->compartment() == this)
for (ActivationIterator iter(rt); !iter.done(); ++iter) {
if (iter.activation()->compartment() == this)
return true;
}
#ifdef JS_ION
for (ion::IonActivationIterator iai(rt); iai.more(); ++iai) {
if (iai.activation()->compartment() == this)
return true;
}
#endif
return false;
}

View File

@ -1059,7 +1059,7 @@ FormatFrame(JSContext *cx, const NonBuiltinScriptFrameIter &iter, char *buf, int
RootedObject callObj(cx);
AutoPropertyDescArray callProps(cx);
if (!iter.isIon() && (showArgs || showLocals)) {
if (!iter.isJit() && (showArgs || showLocals)) {
JSAbstractFramePtr frame(Jsvalify(iter.abstractFramePtr()));
callObj = frame.callObject(cx);
if (callObj)

View File

@ -876,18 +876,15 @@ js_fun_apply(JSContext *cx, unsigned argc, Value *vp)
/*
* Pretend we have been passed the 'arguments' object for the current
* function and read actuals out of the frame.
*
* N.B. Changes here need to be propagated to stubs::SplatApplyArgs.
*/
/* Steps 4-6. */
StackFrame *fp = cx->fp();
#ifdef JS_ION
// We do not want to use ScriptFrameIter to abstract here because this
// is supposed to be a fast path as opposed to ScriptFrameIter which is
// doing complex logic to settle on the next frame twice.
if (fp->beginsIonActivation()) {
ion::IonActivationIterator activations(cx);
if (cx->mainThread().currentlyRunningInJit()) {
ion::JitActivationIterator activations(cx->runtime());
ion::IonFrameIterator frame(activations);
if (frame.isNative()) {
// Stop on the next Ion JS Frame.
@ -931,6 +928,7 @@ js_fun_apply(JSContext *cx, unsigned argc, Value *vp)
} else
#endif
{
StackFrame *fp = cx->fp();
unsigned length = fp->numActualArgs();
JS_ASSERT(length <= StackSpace::ARGS_LENGTH_MAX);

View File

@ -695,16 +695,6 @@ extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc,
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc,
js::types::Type type);
inline bool
UseNewTypeAtEntry(JSContext *cx, StackFrame *fp)
{
if (!fp->isConstructing() || !cx->typeInferenceEnabled() || !fp->prev())
return false;
JSScript *prevScript = fp->prev()->script();
return UseNewType(cx, prevScript, fp->prevpc());
}
inline bool
UseNewTypeForClone(JSFunction *fun)
{
@ -981,14 +971,7 @@ TypeScript::MonitorUnknown(JSContext *cx, JSScript *script, jsbytecode *pc)
/* static */ inline void
TypeScript::GetPcScript(JSContext *cx, JSScript **script, jsbytecode **pc)
{
#ifdef JS_ION
if (cx->fp()->beginsIonActivation()) {
ion::GetPcScript(cx, script, pc);
return;
}
#endif
*script = cx->fp()->script();
*pc = cx->regs().pc;
*script = cx->stack.currentScript(pc);
}
/* static */ inline void

View File

@ -1144,11 +1144,6 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
JS_ASSERT(obj->lastProperty()->slotSpan() == last->slotSpan());
JS_ALWAYS_TRUE(setLastProperty(cx, obj, last));
// Ordinarily ArraySetLength handles this, but we're going behind its
// back right now, so we must do this manually.
if (it == FREEZE && obj->isArray())
obj->getElementsHeader()->setNonwritableArrayLength();
} else {
RootedId id(cx);
for (size_t i = 0; i < props.length(); i++) {
@ -1170,6 +1165,18 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
}
}
// Ordinarily ArraySetLength handles this, but we're going behind its back
// right now, so we must do this manually. Neither the custom property
// tree mutations nor the setGenericAttributes call in the above code will
// do this for us.
//
// ArraySetLength also implements the capacity <= length invariant for
// arrays with non-writable length. We don't need to do anything special
// for that, because capacity was zeroed out by preventExtensions. (See
// the assertion before the if-else above.)
if (it == FREEZE && obj->isArray())
obj->getElementsHeader()->setNonwritableArrayLength();
return true;
}
@ -5221,7 +5228,7 @@ js_DumpStackFrame(JSContext *cx, StackFrame *start)
return;
}
} else {
while (!i.done() && !i.isIon() && i.interpFrame() != start)
while (!i.done() && !i.isJit() && i.interpFrame() != start)
++i;
if (i.done()) {
@ -5232,8 +5239,8 @@ js_DumpStackFrame(JSContext *cx, StackFrame *start)
}
for (; !i.done(); ++i) {
if (i.isIon())
fprintf(stderr, "IonFrame\n");
if (i.isJit())
fprintf(stderr, "JIT frame\n");
else
fprintf(stderr, "StackFrame at %p\n", (void *) i.interpFrame());
@ -5252,10 +5259,10 @@ js_DumpStackFrame(JSContext *cx, StackFrame *start)
fprintf(stderr, " pc = %p\n", pc);
fprintf(stderr, " current op: %s\n", js_CodeName[*pc]);
}
if (!i.isIon())
if (!i.isJit())
MaybeDumpObject("blockChain", i.interpFrame()->maybeBlockChain());
MaybeDumpValue("this", i.thisv());
if (!i.isIon()) {
if (!i.isJit()) {
fprintf(stderr, " rval: ");
dumpValue(i.interpFrame()->returnValue());
fputc('\n', stderr);
@ -5264,13 +5271,13 @@ js_DumpStackFrame(JSContext *cx, StackFrame *start)
fprintf(stderr, " flags:");
if (i.isConstructing())
fprintf(stderr, " constructing");
if (!i.isIon() && i.interpFrame()->isDebuggerFrame())
if (!i.isJit() && i.interpFrame()->isDebuggerFrame())
fprintf(stderr, " debugger");
if (i.isEvalFrame())
fprintf(stderr, " eval");
if (!i.isIon() && i.interpFrame()->isYielding())
if (!i.isJit() && i.interpFrame()->isYielding())
fprintf(stderr, " yielding");
if (!i.isIon() && i.interpFrame()->isGeneratorFrame())
if (!i.isJit() && i.interpFrame()->isGeneratorFrame())
fprintf(stderr, " generator");
fputc('\n', stderr);
@ -5293,7 +5300,7 @@ js_DumpBacktrace(JSContext *cx)
unsigned line = JS_PCToLineNumber(cx, i.script(), i.pc());
JSScript *script = i.script();
sprinter.printf("#%d %14p %s:%d (%p @ %d)\n",
depth, (i.isIon() ? 0 : i.interpFrame()), filename, line,
depth, (i.isJit() ? 0 : i.interpFrame()), filename, line,
script, i.pc() - script->code);
}
fprintf(stdout, "%s", sprinter.string());

View File

@ -1462,10 +1462,10 @@ FindStartPC(JSContext *cx, ScriptFrameIter &iter, int spindex, int skipStackHits
* stack pointer and skewing it from what static analysis in pcstack.init
* would compute.
*
* FIXME: also fall back if iter.isIonOptimizedJS(), since the stack snapshot
* may be for the previous pc (see bug 831120).
* FIXME: also fall back if iter.isIon(), since the stack snapshot may be
* for the previous pc (see bug 831120).
*/
if (iter.isIonOptimizedJS())
if (iter.isIon())
return true;
*valuepc = NULL;

View File

@ -2885,17 +2885,17 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
* assumption of !script->needsArgsObj();
* - type inference data for the script assuming script->needsArgsObj
*/
for (AllFramesIter i(cx->runtime()); !i.done(); ++i) {
for (AllFramesIter i(cx); !i.done(); ++i) {
/*
* We cannot reliably create an arguments object for Ion activations of
* this script. To maintain the invariant that "script->needsArgsObj
* implies fp->hasArgsObj", the Ion bail mechanism will create an
* arguments object right after restoring the StackFrame and before
* entering the interpreter (in ion::ThunkToInterpreter). This delay is
* safe since the engine avoids any observation of a StackFrame when it
* beginsIonActivation (see ScriptFrameIter::interpFrame comment).
* safe since the engine avoids any observation of a StackFrame when it's
* runningInJit (see ScriptFrameIter::interpFrame comment).
*/
if (i.isIonOptimizedJS())
if (i.isIon())
continue;
AbstractFramePtr frame = i.abstractFramePtr();
if (frame.isFunctionFrame() && frame.script() == script) {

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