mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Merge m-c to inbound.
This commit is contained in:
commit
27202e5e77
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;"/>
|
||||
|
@ -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) {
|
||||
|
@ -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 \
|
||||
|
11
browser/base/content/test/blockPluginHard.xml
Normal file
11
browser/base/content/test/blockPluginHard.xml
Normal 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>
|
@ -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");
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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"));
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -44,7 +44,7 @@ BRANDING_FILES := \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||
ifdef MOZ_WIDGET_GTK
|
||||
BRANDING_FILES := \
|
||||
default16.png \
|
||||
default32.png \
|
||||
|
@ -44,7 +44,7 @@ BRANDING_FILES := \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||
ifdef MOZ_WIDGET_GTK
|
||||
BRANDING_FILES := \
|
||||
default16.png \
|
||||
default32.png \
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
]
|
||||
|
@ -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 =
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -13,3 +13,8 @@ CONFIGURE_SUBST_FILES += [
|
||||
'tests/src-simple/Makefile',
|
||||
]
|
||||
|
||||
if CONFIG['HOST_OS_ARCH'] != 'WINNT':
|
||||
HOST_CSRCS += [
|
||||
'nsinstall.c',
|
||||
'pathsub.c',
|
||||
]
|
||||
|
@ -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*
|
||||
|
@ -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 \
|
||||
|
7
content/base/test/chrome/blockNoPlugins.xml
Normal file
7
content/base/test/chrome/blockNoPlugins.xml
Normal 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>
|
11
content/base/test/chrome/blockPluginHard.xml
Normal file
11
content/base/test/chrome/blockPluginHard.xml
Normal 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>
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
||||
|
@ -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',
|
||||
]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
]
|
||||
|
@ -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())
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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_);
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -47,6 +47,9 @@ BuildDominatorTree(MIRGraph &graph);
|
||||
bool
|
||||
BuildPhiReverseMapping(MIRGraph &graph);
|
||||
|
||||
void
|
||||
AssertBasicGraphCoherency(MIRGraph &graph);
|
||||
|
||||
void
|
||||
AssertGraphCoherency(MIRGraph &graph);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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++)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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 *
|
||||
|
@ -6180,6 +6180,10 @@ class MFunctionEnvironment
|
||||
MDefinition *function() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
// Loads the current js::ForkJoinSlice*.
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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});
|
||||
|
17
js/src/jit-test/tests/basic/cross-context-stack-1.js
Normal file
17
js/src/jit-test/tests/basic/cross-context-stack-1.js
Normal 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");
|
@ -280,7 +280,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
case JSOP_SETALIASEDVAR:
|
||||
case JSOP_LAMBDA:
|
||||
usesScopeChain_ = true;
|
||||
isIonInlineable = false;
|
||||
break;
|
||||
|
||||
case JSOP_DEFFUN:
|
||||
|
@ -59,6 +59,7 @@ CPP_SOURCES += [
|
||||
'testSetProperty.cpp',
|
||||
'testSourcePolicy.cpp',
|
||||
'testStringBuffer.cpp',
|
||||
'testToIntWidth.cpp',
|
||||
'testTrap.cpp',
|
||||
'testTypedArrays.cpp',
|
||||
'testUTF8.cpp',
|
||||
|
70
js/src/jsapi-tests/testToIntWidth.cpp
Normal file
70
js/src/jsapi-tests/testToIntWidth.cpp
Normal 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)
|
@ -716,7 +716,7 @@ PerThreadData::PerThreadData(JSRuntime *runtime)
|
||||
ionTop(NULL),
|
||||
ionJSContext(NULL),
|
||||
ionStackLimit(0),
|
||||
ionActivation(NULL),
|
||||
activation_(NULL),
|
||||
asmJSActivationStack_(NULL),
|
||||
suppressGC(0)
|
||||
{}
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user