mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merging cedar with mozilla-central.
This commit is contained in:
commit
8bc1be7f60
@ -72,33 +72,3 @@
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#channelSelector {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#channelSelectorStart {
|
||||
-moz-margin-start: 0;
|
||||
}
|
||||
|
||||
#channelMenulist {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.channel-description {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
#detailsBox,
|
||||
#channelSelector,
|
||||
.channel-description {
|
||||
-moz-transition: opacity 250ms;
|
||||
}
|
||||
|
||||
#contentDeck:not([selectedIndex="0"]) > #detailsBox,
|
||||
#contentDeck:not([selectedIndex="1"]) > #channelSelector,
|
||||
#channelDescriptionDeck:not([selectedIndex="0"]) > #releaseDescription,
|
||||
#channelDescriptionDeck:not([selectedIndex="1"]) > #betaDescription,
|
||||
#channelDescriptionDeck:not([selectedIndex="2"]) > #auroraDescription {
|
||||
opacity: 0;
|
||||
}
|
||||
|
@ -88,7 +88,9 @@ function init(aEvent)
|
||||
gAppUpdater = new appUpdater();
|
||||
#endif
|
||||
|
||||
gChannelSelector.init();
|
||||
let defaults = Services.prefs.getDefaultBranch("");
|
||||
let channelLabel = document.getElementById("currentChannel");
|
||||
channelLabel.value = defaults.getCharPref("app.update.channel");
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// it may not be sized at this point, and we need its width to calculate its position
|
||||
@ -573,72 +575,3 @@ appUpdater.prototype =
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
var gChannelSelector = {
|
||||
validChannels: { release: 1, beta: 1, aurora: 1 },
|
||||
|
||||
init: function() {
|
||||
try {
|
||||
this.channelValue = Services.prefs.getCharPref("app.update.desiredChannel");
|
||||
} catch (e) {
|
||||
let defaults = Services.prefs.getDefaultBranch("");
|
||||
this.channelValue = defaults.getCharPref("app.update.channel");
|
||||
}
|
||||
|
||||
// Only show channel selector UI on valid update channels.
|
||||
if (this.channelValue in this.validChannels) {
|
||||
document.getElementById("currentChannelText").hidden = false;
|
||||
this.setChannelLabel(this.channelValue);
|
||||
this.setChannelMenuitem(this.channelValue);
|
||||
}
|
||||
},
|
||||
|
||||
selectChannel: function(aSelectedItem) {
|
||||
document.getElementById("channelDescriptionDeck").selectedPanel =
|
||||
document.getElementById(aSelectedItem.value + "Description");
|
||||
document.getElementById("channelMenulist").setAttribute("aria-describedby",
|
||||
aSelectedItem.value + "Description");
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this.setChannelMenuitem(this.channelValue);
|
||||
this.hide();
|
||||
},
|
||||
|
||||
apply: function() {
|
||||
this.channelValue = document.getElementById("channelMenulist").selectedItem.value;
|
||||
this.setChannelLabel(this.channelValue);
|
||||
|
||||
// Change app update channel.
|
||||
Services.prefs.setCharPref("app.update.desiredChannel", this.channelValue);
|
||||
|
||||
// Stop any downloads in progress
|
||||
gAppUpdater.aus.pauseDownload();
|
||||
// App updater will look at app.update.desiredChannel for new channel value
|
||||
// and will clear it when the update is complete.
|
||||
gAppUpdater.isChecking = true;
|
||||
gAppUpdater.checker.checkForUpdates(gAppUpdater.updateCheckListener, true);
|
||||
|
||||
this.hide();
|
||||
},
|
||||
|
||||
show: function() {
|
||||
document.getElementById("contentDeck").selectedPanel =
|
||||
document.getElementById("channelSelector");
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
document.getElementById("contentDeck").selectedPanel =
|
||||
document.getElementById("detailsBox");
|
||||
},
|
||||
|
||||
setChannelLabel: function(aValue) {
|
||||
let channelLabel = document.getElementById("currentChannel");
|
||||
channelLabel.value = document.getElementById(aValue + "Menuitem").label;
|
||||
},
|
||||
|
||||
setChannelMenuitem: function(aValue) {
|
||||
document.getElementById("channelMenulist").selectedItem =
|
||||
document.getElementById(aValue + "Menuitem");
|
||||
}
|
||||
}
|
||||
|
@ -80,85 +80,50 @@
|
||||
<label id="distribution" class="text-blurb"/>
|
||||
<label id="distributionId" class="text-blurb"/>
|
||||
|
||||
<!-- Make sure the selectedIndex attribute is always set so that the CSS
|
||||
selectors for transitions work -->
|
||||
<deck id="contentDeck" selectedIndex="0">
|
||||
<vbox id="detailsBox" aria-describedby="communityDesc contributeDesc">
|
||||
<vbox id="updateBox">
|
||||
<vbox id="detailsBox" aria-describedby="communityDesc contributeDesc">
|
||||
<vbox id="updateBox">
|
||||
#ifdef MOZ_UPDATER
|
||||
<deck id="updateDeck" orient="vertical">
|
||||
<hbox id="updateButtonBox" align="center">
|
||||
<button id="updateButton" align="start"
|
||||
oncommand="gAppUpdater.buttonOnCommand();"/>
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="checkingForUpdates" align="center">
|
||||
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
|
||||
</hbox>
|
||||
<hbox id="checkingAddonCompat" align="center">
|
||||
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
|
||||
</hbox>
|
||||
<hbox id="downloading" align="center">
|
||||
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
|
||||
</hbox>
|
||||
<hbox id="downloadFailed" align="center">
|
||||
<label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
|
||||
</hbox>
|
||||
<hbox id="adminDisabled" align="center">
|
||||
<label>&update.adminDisabled;</label>
|
||||
</hbox>
|
||||
<hbox id="noUpdatesFound" align="center">
|
||||
<label>&update.noUpdatesFound;</label>
|
||||
</hbox>
|
||||
<hbox id="manualUpdate" align="center">
|
||||
<label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
|
||||
</hbox>
|
||||
</deck>
|
||||
#endif
|
||||
</vbox>
|
||||
|
||||
<description class="text-blurb" id="currentChannelText" hidden="true">
|
||||
&channel.description.start;<label id="currentChannel"/>&channel.description.end;<label id="channelChangeLink" class="text-link" onclick="gChannelSelector.show();">&channel.change;</label>
|
||||
</description>
|
||||
<description class="text-blurb" id="communityDesc">
|
||||
&community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
|
||||
</description>
|
||||
<description class="text-blurb" id="contributeDesc">
|
||||
&contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
|
||||
</description>
|
||||
</vbox>
|
||||
|
||||
<vbox id="channelSelector">
|
||||
<hbox pack="start" align="center">
|
||||
<label id="channelSelectorStart">&channel.selector.start;</label>
|
||||
<menulist id="channelMenulist" onselect="gChannelSelector.selectChannel(this.selectedItem);" aria-labelledby="channelSelectorStart channelMenulist channelSelectorEnd">
|
||||
<menupopup>
|
||||
<menuitem id="releaseMenuitem" label="Release" value="release"/>
|
||||
<menuitem id="betaMenuitem" label="Beta" value="beta"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="auroraMenuitem" label="Aurora" value="aurora"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<label id="channelSelectorEnd">&channel.selector.end;</label>
|
||||
</hbox>
|
||||
|
||||
<deck id="channelDescriptionDeck" selectedIndex="0">
|
||||
<description id="releaseDescription" class="channel-description">&channel.release.description;</description>
|
||||
<description id="betaDescription" class="channel-description">&channel.beta.description;</description>
|
||||
<description id="auroraDescription" class="channel-description">&channel.aurora.description;</description>
|
||||
<deck id="updateDeck" orient="vertical">
|
||||
<hbox id="updateButtonBox" align="center">
|
||||
<button id="updateButton" align="start"
|
||||
oncommand="gAppUpdater.buttonOnCommand();"/>
|
||||
<spacer flex="1"/>
|
||||
</hbox>
|
||||
<hbox id="checkingForUpdates" align="center">
|
||||
<image class="update-throbber"/><label>&update.checkingForUpdates;</label>
|
||||
</hbox>
|
||||
<hbox id="checkingAddonCompat" align="center">
|
||||
<image class="update-throbber"/><label>&update.checkingAddonCompat;</label>
|
||||
</hbox>
|
||||
<hbox id="downloading" align="center">
|
||||
<image class="update-throbber"/><label>&update.downloading.start;</label><label id="downloadStatus"/><label>&update.downloading.end;</label>
|
||||
</hbox>
|
||||
<hbox id="downloadFailed" align="center">
|
||||
<label>&update.failed.start;</label><label id="failedLink" class="text-link">&update.failed.linkText;</label><label>&update.failed.end;</label>
|
||||
</hbox>
|
||||
<hbox id="adminDisabled" align="center">
|
||||
<label>&update.adminDisabled;</label>
|
||||
</hbox>
|
||||
<hbox id="noUpdatesFound" align="center">
|
||||
<label>&update.noUpdatesFound;</label>
|
||||
</hbox>
|
||||
<hbox id="manualUpdate" align="center">
|
||||
<label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
|
||||
</hbox>
|
||||
</deck>
|
||||
|
||||
<hbox id="channelSelectorButtons" pack="end">
|
||||
#ifdef XP_UNIX
|
||||
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
|
||||
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
|
||||
#else
|
||||
<button oncommand="gChannelSelector.apply();" label="&channel.selector.applyButton;"/>
|
||||
<button oncommand="gChannelSelector.cancel();" label="&channel.selector.cancelButton;"/>
|
||||
#endif
|
||||
</hbox>
|
||||
</vbox>
|
||||
</deck>
|
||||
|
||||
<description class="text-blurb" id="currentChannelText">
|
||||
&channel.description.start;<label id="currentChannel"/>&channel.description.end;
|
||||
</description>
|
||||
<description class="text-blurb" id="communityDesc">
|
||||
&community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end2;
|
||||
</description>
|
||||
<description class="text-blurb" id="contributeDesc">
|
||||
&contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
|
||||
</description>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<vbox id="bottomBox">
|
||||
|
@ -2257,7 +2257,11 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup)
|
||||
}
|
||||
}
|
||||
|
||||
function getShortcutOrURI(aURL, aPostDataRef) {
|
||||
function getShortcutOrURI(aURL, aPostDataRef, aMayInheritPrincipal) {
|
||||
// Initialize outparam to false
|
||||
if (aMayInheritPrincipal)
|
||||
aMayInheritPrincipal.value = false;
|
||||
|
||||
var shortcutURL = null;
|
||||
var keyword = aURL;
|
||||
var param = "";
|
||||
@ -2329,6 +2333,11 @@ function getShortcutOrURI(aURL, aPostDataRef) {
|
||||
return aURL;
|
||||
}
|
||||
|
||||
// This URL came from a bookmark, so it's safe to let it inherit the current
|
||||
// document's principal.
|
||||
if (aMayInheritPrincipal)
|
||||
aMayInheritPrincipal.value = true;
|
||||
|
||||
return shortcutURL;
|
||||
}
|
||||
|
||||
|
@ -608,7 +608,7 @@ iQClass.prototype = {
|
||||
});
|
||||
|
||||
this.css({
|
||||
'-moz-transition-property': 'all', // TODO: just animate the properties we're changing
|
||||
'-moz-transition-property': Object.keys(css).join(", "),
|
||||
'-moz-transition-duration': (duration / 1000) + 's',
|
||||
'-moz-transition-timing-function': easing
|
||||
});
|
||||
|
@ -999,7 +999,7 @@ let UI = {
|
||||
"redo",
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
"preferencesCmdMac", "minimizeWindow",
|
||||
"preferencesCmdMac", "minimizeWindow", "hideThisAppCmdMac",
|
||||
#endif
|
||||
"newNavigator", "newNavigatorTab", "undo", "cut", "copy", "paste",
|
||||
"selectAll", "find"
|
||||
@ -1043,6 +1043,10 @@ let UI = {
|
||||
Keys.meta = true;
|
||||
|
||||
function processBrowserKeys(evt) {
|
||||
// let any keys with alt to pass through
|
||||
if (evt.altKey)
|
||||
return;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (evt.metaKey) {
|
||||
#else
|
||||
@ -1077,6 +1081,7 @@ let UI = {
|
||||
#ifdef XP_MACOSX
|
||||
case self._browserKeys.preferencesCmdMac:
|
||||
case self._browserKeys.minimizeWindow:
|
||||
case self._browserKeys.hideThisAppCmdMac:
|
||||
#endif
|
||||
case self._browserKeys.newNavigator:
|
||||
case self._browserKeys.newNavigatorTab:
|
||||
|
@ -173,6 +173,7 @@ _BROWSER_FILES = \
|
||||
browser_bug647886.js \
|
||||
browser_bug655584.js \
|
||||
browser_findbarClose.js \
|
||||
browser_keywordBookmarklets.js \
|
||||
browser_contextSearchTabPosition.js \
|
||||
browser_ctrlTab.js \
|
||||
browser_customize_popupNotification.js \
|
||||
|
@ -44,6 +44,7 @@ function test() {
|
||||
// Verify that about:addons loads
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
let browser = blanktab.linkedBrowser;
|
||||
is(browser.currentURI.spec, "about:addons", "about:addons should load into blank tab.");
|
||||
gBrowser.removeTab(blanktab);
|
||||
|
@ -11,9 +11,10 @@ function getPostDataString(aIS) {
|
||||
return dataLines[dataLines.length-1];
|
||||
}
|
||||
|
||||
function keywordResult(aURL, aPostData) {
|
||||
function keywordResult(aURL, aPostData, aIsUnsafe) {
|
||||
this.url = aURL;
|
||||
this.postData = aPostData;
|
||||
this.isUnsafe = aIsUnsafe;
|
||||
}
|
||||
|
||||
function keyWordData() {}
|
||||
@ -52,20 +53,20 @@ var testData = [
|
||||
new keywordResult("http://bmget-nosearch/", null)],
|
||||
|
||||
[new searchKeywordData("searchget", "http://searchget/?search={searchTerms}", null, "foo4"),
|
||||
new keywordResult("http://searchget/?search=foo4", null)],
|
||||
new keywordResult("http://searchget/?search=foo4", null, true)],
|
||||
|
||||
[new searchKeywordData("searchpost", "http://searchpost/", "search={searchTerms}", "foo5"),
|
||||
new keywordResult("http://searchpost/", "search=foo5")],
|
||||
new keywordResult("http://searchpost/", "search=foo5", true)],
|
||||
|
||||
[new searchKeywordData("searchpostget", "http://searchpostget/?search1={searchTerms}", "search2={searchTerms}", "foo6"),
|
||||
new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6")],
|
||||
new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6", true)],
|
||||
|
||||
// Bookmark keywords that don't take parameters should not be activated if a
|
||||
// parameter is passed (bug 420328).
|
||||
[new bmKeywordData("bmget-noparam", "http://bmget-noparam/", null, "foo7"),
|
||||
new keywordResult(null, null)],
|
||||
new keywordResult(null, null, true)],
|
||||
[new bmKeywordData("bmpost-noparam", "http://bmpost-noparam/", "not_a=param", "foo8"),
|
||||
new keywordResult(null, null)],
|
||||
new keywordResult(null, null, true)],
|
||||
|
||||
// Test escaping (%s = escaped, %S = raw)
|
||||
// UTF-8 default
|
||||
@ -82,6 +83,12 @@ var testData = [
|
||||
// Explicitly-defined ISO-8859-1
|
||||
[new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "+/@"),
|
||||
new keywordResult("http://bmget/?esc=%2B%2F%40&raw=+/@", null)],
|
||||
|
||||
// Test using a non-bmKeywordData object, to test the behavior of
|
||||
// getShortcutOrURI for non-keywords (setupKeywords only adds keywords for
|
||||
// bmKeywordData objects)
|
||||
[{keyword: "http://gavinsharp.com"},
|
||||
new keywordResult(null, null, true)]
|
||||
];
|
||||
|
||||
function test() {
|
||||
@ -94,12 +101,14 @@ function test() {
|
||||
var query = data.keyword;
|
||||
if (data.searchWord)
|
||||
query += " " + data.searchWord;
|
||||
var url = getShortcutOrURI(query, postData);
|
||||
var mayInheritPrincipal = {};
|
||||
var url = getShortcutOrURI(query, postData, mayInheritPrincipal);
|
||||
|
||||
// null result.url means we should expect the same query we sent in
|
||||
var expected = result.url || query;
|
||||
is(url, expected, "got correct URL for " + data.keyword);
|
||||
is(getPostDataString(postData.value), result.postData, "got correct postData for " + data.keyword);
|
||||
is(mayInheritPrincipal.value, !result.isUnsafe, "got correct mayInheritPrincipal for " + data.keyword);
|
||||
}
|
||||
|
||||
cleanupKeywords();
|
||||
|
38
browser/base/content/test/browser_keywordBookmarklets.js
Normal file
38
browser/base/content/test/browser_keywordBookmarklets.js
Normal file
@ -0,0 +1,38 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let bmFolder = Application.bookmarks.menu.addFolder("keyword-test");
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
registerCleanupFunction (function () {
|
||||
bmFolder.remove();
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
||||
let bm = bmFolder.addBookmark("bookmarklet", makeURI("javascript:1;"));
|
||||
bm.keyword = "bm";
|
||||
|
||||
addPageShowListener(function () {
|
||||
let originalPrincipal = gBrowser.contentPrincipal;
|
||||
|
||||
// Enter bookmarklet keyword in the URL bar
|
||||
gURLBar.value = "bm";
|
||||
gURLBar.focus();
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
|
||||
addPageShowListener(function () {
|
||||
ok(gBrowser.contentPrincipal.equals(originalPrincipal), "javascript bookmarklet should inherit principal");
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function addPageShowListener(func) {
|
||||
gBrowser.selectedBrowser.addEventListener("pageshow", function loadListener() {
|
||||
gBrowser.selectedBrowser.removeEventListener("pageshow", loadListener, false);
|
||||
func();
|
||||
});
|
||||
}
|
@ -260,6 +260,7 @@
|
||||
return; // Do nothing for right clicks
|
||||
|
||||
var url = this.value;
|
||||
var mayInheritPrincipal = false;
|
||||
var postData = null;
|
||||
|
||||
var action = this._parseActionUrl(url);
|
||||
@ -277,7 +278,7 @@
|
||||
}
|
||||
}
|
||||
else {
|
||||
[url, postData] = this._canonizeURL(aTriggeringEvent);
|
||||
[url, postData, mayInheritPrincipal] = this._canonizeURL(aTriggeringEvent);
|
||||
if (!url)
|
||||
return;
|
||||
}
|
||||
@ -293,10 +294,13 @@
|
||||
}
|
||||
|
||||
function loadCurrent() {
|
||||
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
||||
// Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from
|
||||
// inheriting the currently loaded document's principal.
|
||||
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
|
||||
Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
|
||||
// inheriting the currently loaded document's principal, unless this
|
||||
// URL is marked as safe to inherit (e.g. came from a bookmark
|
||||
// keyword).
|
||||
if (!mayInheritPrincipal)
|
||||
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
|
||||
gBrowser.loadURIWithFlags(url, flags, null, null, postData);
|
||||
}
|
||||
|
||||
@ -339,7 +343,7 @@
|
||||
<body><![CDATA[
|
||||
var url = this.value;
|
||||
if (!url)
|
||||
return ["", null];
|
||||
return ["", null, false];
|
||||
|
||||
// Only add the suffix when the URL bar value isn't already "URL-like",
|
||||
// and only if we get a keyboard event, to match user expectations.
|
||||
@ -402,9 +406,10 @@
|
||||
}
|
||||
|
||||
var postData = {};
|
||||
url = getShortcutOrURI(url, postData);
|
||||
var mayInheritPrincipal = { value: false };
|
||||
url = getShortcutOrURI(url, postData, mayInheritPrincipal);
|
||||
|
||||
return [url, postData.value];
|
||||
return [url, postData.value, mayInheritPrincipal.value];
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
@ -6,6 +6,5 @@ browser.jar:
|
||||
content/branding/about-wordmark.png (about-wordmark.png)
|
||||
content/branding/icon48.png (icon48.png)
|
||||
content/branding/icon64.png (icon64.png)
|
||||
content/branding/icon128.png (../mozicon128.png)
|
||||
content/branding/icon16.png (../default16.png)
|
||||
content/branding/aboutDialog.css (aboutDialog.css)
|
||||
|
@ -6,6 +6,5 @@ browser.jar:
|
||||
content/branding/about-wordmark.png (about-wordmark.png)
|
||||
content/branding/icon48.png (icon48.png)
|
||||
content/branding/icon64.png (icon64.png)
|
||||
content/branding/icon128.png (../mozicon128.png)
|
||||
content/branding/icon16.png (../default16.png)
|
||||
content/branding/aboutDialog.css (aboutDialog.css)
|
||||
|
@ -5,6 +5,5 @@ browser.jar:
|
||||
content/branding/about-wordmark.png (about-wordmark.png)
|
||||
content/branding/icon48.png (icon48.png)
|
||||
content/branding/icon64.png (icon64.png)
|
||||
content/branding/icon128.png (../mozicon128.png)
|
||||
content/branding/icon16.png (../default16.png)
|
||||
content/branding/aboutDialog.css (aboutDialog.css)
|
||||
|
@ -6,6 +6,5 @@ browser.jar:
|
||||
content/branding/about-wordmark.png (about-wordmark.png)
|
||||
content/branding/icon48.png (icon48.png)
|
||||
content/branding/icon64.png (icon64.png)
|
||||
content/branding/icon128.png (../mozicon128.png)
|
||||
content/branding/icon16.png (../default16.png)
|
||||
content/branding/aboutDialog.css (aboutDialog.css)
|
||||
|
@ -145,6 +145,15 @@ Site.prototype = {
|
||||
* @return A boolean indicating whether or not a permission is set.
|
||||
*/
|
||||
getPermission: function Site_getPermission(aType, aResultObj) {
|
||||
// Password saving isn't a nsIPermissionManager permission type, so handle
|
||||
// it seperately.
|
||||
if (aType == "password") {
|
||||
aResultObj.value = this.loginSavingEnabled ?
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION :
|
||||
Ci.nsIPermissionManager.DENY_ACTION;
|
||||
return true;
|
||||
}
|
||||
|
||||
let permissionValue;
|
||||
if (TEST_EXACT_PERM_TYPES.indexOf(aType) == -1) {
|
||||
permissionValue = Services.perms.testPermission(this.httpURI, aType);
|
||||
@ -167,6 +176,13 @@ Site.prototype = {
|
||||
* be one of the constants defined in nsIPermissionManager.
|
||||
*/
|
||||
setPermission: function Site_setPermission(aType, aPerm) {
|
||||
// Password saving isn't a nsIPermissionManager permission type, so handle
|
||||
// it seperately.
|
||||
if (aType == "password") {
|
||||
this.loginSavingEnabled = aPerm == Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
return;
|
||||
}
|
||||
|
||||
// Using httpURI is kind of bogus, but the permission manager stores the
|
||||
// permission for the host, so the right thing happens in the end.
|
||||
Services.perms.add(this.httpURI, aType, aPerm);
|
||||
@ -685,14 +701,8 @@ let AboutPermissions = {
|
||||
let permissionMenulist = document.getElementById(aType + "-menulist");
|
||||
let permissionValue;
|
||||
if (!this._selectedSite) {
|
||||
|
||||
// If there is no selected site, we are updating the default permissions interface.
|
||||
permissionValue = PermissionDefaults[aType];
|
||||
} else if (aType == "password") {
|
||||
// Services.logins.getLoginSavingEnabled already looks at the default
|
||||
// permission, so we don't need to.
|
||||
permissionValue = this._selectedSite.loginSavingEnabled ?
|
||||
PermissionDefaults.ALLOW : PermissionDefaults.DENY;
|
||||
} else {
|
||||
let result = {};
|
||||
permissionValue = this._selectedSite.getPermission(aType, result) ?
|
||||
@ -709,9 +719,6 @@ let AboutPermissions = {
|
||||
if (!this._selectedSite) {
|
||||
// If there is no selected site, we are setting the default permission.
|
||||
PermissionDefaults[permissionType] = permissionValue;
|
||||
} else if (permissionType == "password") {
|
||||
let isEnabled = permissionValue == PermissionDefaults.ALLOW;
|
||||
this._selectedSite.loginSavingEnabled = isEnabled;
|
||||
} else {
|
||||
this._selectedSite.setPermission(permissionType, permissionValue);
|
||||
}
|
||||
|
@ -60,21 +60,3 @@
|
||||
example: You are currently on the _Stable_ update channel. -->
|
||||
<!ENTITY channel.description.start "You are currently on the ">
|
||||
<!ENTITY channel.description.end " update channel. ">
|
||||
|
||||
<!ENTITY channel.change "Change">
|
||||
|
||||
<!ENTITY channel.release.description "Enjoy the tried and tested final release being used by hundreds of millions around the world. Stay in control of your online experience with super speed, easy customization and the latest Web technologies.">
|
||||
<!ENTITY channel.beta.description "Experience cutting edge features with more stability. Provide feedback to help refine and polish what will be in the final release.">
|
||||
<!ENTITY channel.aurora.description "Experience the newest innovations in an unstable environment that's not for the faint of heart. Provide feedback on features and performance to help determine what makes the final release.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (channel.selector.start,channel.selector.end): channel.selector.start and
|
||||
channel.selector.end create one sentence, with a channel selection menulist instered in between.
|
||||
This is all in one line, so try to make the localized text short.
|
||||
example: Switch to the [Stable] update channel. -->
|
||||
<!ENTITY channel.selector.start "Switch to the">
|
||||
<!ENTITY channel.selector.end "update channel.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (channel.selector.applyButton): This button applies the user's choice to switch
|
||||
to a new update channel and starts the application update process. -->
|
||||
<!ENTITY channel.selector.applyButton "Apply and Update">
|
||||
<!ENTITY channel.selector.cancelButton "Cancel">
|
||||
|
@ -23,5 +23,5 @@
|
||||
<!ENTITY robots.errorTrailerDescText "And they have a plan.">
|
||||
<!-- TV: Battlestar Galactica (2004 series). Common expletive referring to Cylons. -->
|
||||
<!ENTITY robots.imgtitle "Frakkin' Toasters">
|
||||
<!-- Book: Hitchiker's Guide To The Galaxy. Arthur presses a button and it warns him. -->
|
||||
<!-- Book: Hitchhiker's Guide To The Galaxy. Arthur presses a button and it warns him. -->
|
||||
<!ENTITY robots.dontpress "Please do not press this button again.">
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 98 B |
@ -42,7 +42,6 @@ browser.jar:
|
||||
skin/classic/browser/section_collapsed-rtl.png
|
||||
skin/classic/browser/section_expanded.png
|
||||
skin/classic/browser/Secure-Glyph-White.png
|
||||
skin/classic/browser/Secure-background.gif
|
||||
skin/classic/browser/Toolbar.png
|
||||
skin/classic/browser/toolbarbutton-dropmarker.png
|
||||
skin/classic/browser/urlbar-arrow.png
|
||||
|
@ -555,12 +555,6 @@ nsDOMAttribute::GetIsId(PRBool* aReturn)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMAttribute::GetSchemaTypeInfo(nsIDOM3TypeInfo** aReturn)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDOMAttribute::IsNodeOfType(PRUint32 aFlags) const
|
||||
{
|
||||
|
@ -863,6 +863,9 @@ nsEventStateManager::Init()
|
||||
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE);
|
||||
|
||||
if (sESMInstanceCount == 1) {
|
||||
sKeyCausesActivation =
|
||||
Preferences::GetBool("accessibility.accesskeycausesactivation",
|
||||
sKeyCausesActivation);
|
||||
sLeftClickOnly =
|
||||
Preferences::GetBool("nglayout.events.dispatchLeftClickOnly",
|
||||
sLeftClickOnly);
|
||||
|
@ -22,6 +22,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||
* Ms2ger <ms2ger@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -444,27 +445,7 @@ static const nsAttrValue::EnumTable kDirTable[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetDir(nsAString& aDir)
|
||||
{
|
||||
const nsAttrValue* attr = mAttrsAndChildren.GetAttr(nsGkAtoms::dir);
|
||||
|
||||
if (attr && attr->Type() == nsAttrValue::eEnum) {
|
||||
attr->ToString(aDir);
|
||||
}
|
||||
else {
|
||||
aDir.Truncate();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::SetDir(const nsAString& aDir)
|
||||
{
|
||||
SetAttr(kNameSpaceID_None, nsGkAtoms::dir, aDir, PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsGenericHTMLElement, Dir, dir, NULL)
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetClassName(nsAString& aClassName)
|
||||
@ -2331,7 +2312,7 @@ nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr,
|
||||
|
||||
if (attrVal && attrVal->Type() == nsAttrValue::eEnum) {
|
||||
attrVal->GetEnumString(aResult, PR_TRUE);
|
||||
} else {
|
||||
} else if (aDefault) {
|
||||
AppendASCIItoUTF16(nsDependentCString(aDefault), aResult);
|
||||
}
|
||||
|
||||
|
@ -116,8 +116,8 @@ public:
|
||||
nsresult SetTitle(const nsAString& aTitle);
|
||||
nsresult GetLang(nsAString& aLang);
|
||||
nsresult SetLang(const nsAString& aLang);
|
||||
nsresult GetDir(nsAString& aDir);
|
||||
nsresult SetDir(const nsAString& aDir);
|
||||
NS_IMETHOD GetDir(nsAString& aDir);
|
||||
NS_IMETHOD SetDir(const nsAString& aDir);
|
||||
nsresult GetClassName(nsAString& aClassName);
|
||||
nsresult SetClassName(const nsAString& aClassName);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
* Ms2ger <ms2ger@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -314,8 +315,7 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLBodyElement)
|
||||
NS_IMPL_ELEMENT_CLONE(nsHTMLBodyElement)
|
||||
|
||||
|
||||
NS_IMPL_URI_ATTR(nsHTMLBodyElement, Background, background)
|
||||
|
||||
NS_IMPL_STRING_ATTR(nsHTMLBodyElement, Background, background)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLBodyElement, VLink, vlink)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLBodyElement, ALink, alink)
|
||||
NS_IMPL_STRING_ATTR(nsHTMLBodyElement, Link, link)
|
||||
|
@ -280,6 +280,7 @@ _TEST_FILES = \
|
||||
test_bug658746.html \
|
||||
test_bug659596.html \
|
||||
test_bug659743.xml \
|
||||
test_bug660663.html \
|
||||
test_restore_from_parser_fragment.html \
|
||||
$(NULL)
|
||||
|
||||
|
@ -93,3 +93,47 @@ function reflectUnsignedInt(aElement, aAttr, aNonNull, aDefault)
|
||||
is(aElement[aAttr], 0, "." + aAttr + " should be equals to 0");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aElement Element node to test on
|
||||
* @param aAttr String name of the attribute
|
||||
* @param aSupportedValues Array values we supported
|
||||
* @param aUnsupportedValues Array values we don't support
|
||||
*/
|
||||
function reflectLimitedEnumerated(aElement, aAttr, aSupportedValues,
|
||||
aUnsupportedValues)
|
||||
{
|
||||
aSupportedValues.forEach(function (v) {
|
||||
aElement.setAttribute(aAttr, v);
|
||||
is(aElement[aAttr], v);
|
||||
is(aElement.getAttribute(aAttr), v);
|
||||
aElement.removeAttribute(aAttr);
|
||||
|
||||
aElement.setAttribute(aAttr, v.toUpperCase());
|
||||
is(aElement[aAttr], v);
|
||||
is(aElement.getAttribute(aAttr), v.toUpperCase());
|
||||
aElement.removeAttribute(aAttr);
|
||||
|
||||
aElement[aAttr] = v;
|
||||
is(aElement[aAttr], v);
|
||||
is(aElement.getAttribute(aAttr), v);
|
||||
aElement.removeAttribute(aAttr);
|
||||
|
||||
aElement[aAttr] = v.toUpperCase();
|
||||
is(aElement[aAttr], v);
|
||||
is(aElement.getAttribute(aAttr), v.toUpperCase());
|
||||
aElement.removeAttribute(aAttr);
|
||||
});
|
||||
["cheesecake"].concat(aUnsupportedValues).forEach(function (v) {
|
||||
aElement.setAttribute(aAttr, v);
|
||||
is(aElement[aAttr], "");
|
||||
is(aElement.getAttribute(aAttr), v);
|
||||
aElement.removeAttribute(aAttr);
|
||||
|
||||
aElement[aAttr] = v;
|
||||
is(aElement[aAttr], "");
|
||||
is(aElement.getAttribute(aAttr), v);
|
||||
aElement.removeAttribute(aAttr);
|
||||
});
|
||||
}
|
||||
|
||||
|
29
content/html/content/test/test_bug660663.html
Normal file
29
content/html/content/test/test_bug660663.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=660663
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 660663</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660663">Mozilla Bug 660663</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 660663 **/
|
||||
reflectLimitedEnumerated(document.createElement("div"),
|
||||
"dir",
|
||||
["ltr", "rtl"],
|
||||
["auto"]);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -991,7 +991,7 @@ nsHTMLDocument::StopDocumentLoad()
|
||||
mWriteState = eDocumentClosed;
|
||||
|
||||
// Remove the wyciwyg channel request from the document load group
|
||||
// that we added in OpenCommon().
|
||||
// that we added in Open().
|
||||
NS_ASSERTION(mWyciwygChannel, "nsHTMLDocument::StopDocumentLoad(): "
|
||||
"Trying to remove nonexistent wyciwyg channel!");
|
||||
RemoveWyciwygChannel();
|
||||
@ -1516,33 +1516,50 @@ nsHTMLDocument::SetCookie(const nsAString& aCookie)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
PRBool aReplace)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
|
||||
const nsAString& aReplaceOrName,
|
||||
const nsAString& aFeatures,
|
||||
JSContext* cx, PRUint8 aOptionalArgCount,
|
||||
nsISupports** aReturn)
|
||||
{
|
||||
if (!IsHTML() || mDisableDocWrite) {
|
||||
// No calling document.open() on XHTML
|
||||
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
PRBool loadAsHtml5 = nsHtml5Module::sEnabled;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// If we already have a parser we ignore the document.open call.
|
||||
if (mParser) {
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
|
||||
"XOW should have caught this!");
|
||||
|
||||
if (!aContentType.EqualsLiteral("text/html") &&
|
||||
!aContentType.EqualsLiteral("text/plain")) {
|
||||
NS_WARNING("Unsupported type; fix the caller");
|
||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
// When called with 3 or more arguments, document.open() calls window.open().
|
||||
if (aOptionalArgCount > 2) {
|
||||
nsCOMPtr<nsIDOMWindowInternal> window = GetWindowInternal();
|
||||
if (!window) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIDOMWindow> newWindow;
|
||||
nsresult rv = window->Open(aContentTypeOrUrl, aReplaceOrName, aFeatures,
|
||||
getter_AddRefs(newWindow));
|
||||
*aReturn = newWindow.forget().get();
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!IsHTML() || mDisableDocWrite) {
|
||||
// No calling document.open() on XHTML
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsCAutoString contentType;
|
||||
contentType.AssignLiteral("text/html");
|
||||
if (aOptionalArgCount > 0) {
|
||||
nsAutoString type;
|
||||
ToLowerCase(aContentTypeOrUrl, type);
|
||||
nsCAutoString actualType, dummy;
|
||||
NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
|
||||
if (!actualType.EqualsLiteral("text/html") &&
|
||||
!type.EqualsLiteral("replace")) {
|
||||
contentType.AssignLiteral("text/plain");
|
||||
}
|
||||
}
|
||||
|
||||
// If we already have a parser we ignore the document.open call.
|
||||
if (mParser) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// check whether we're in the middle of unload. If so, ignore this call.
|
||||
@ -1602,7 +1619,7 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
if (thisURI) {
|
||||
thisURI->GetSpec(thisSpec);
|
||||
}
|
||||
printf("nsHTMLDocument::OpenCommon callerDoc %s this %s\n", callerSpec.get(), thisSpec.get());
|
||||
printf("nsHTMLDocument::Open callerDoc %s this %s\n", callerSpec.get(), thisSpec.get());
|
||||
#endif
|
||||
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
@ -1615,9 +1632,7 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
|
||||
if (cv) {
|
||||
PRBool okToUnload;
|
||||
rv = cv->PermitUnload(PR_FALSE, &okToUnload);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
||||
if (NS_SUCCEEDED(cv->PermitUnload(PR_FALSE, &okToUnload)) && !okToUnload) {
|
||||
// We don't want to unload, so stop here, but don't throw an
|
||||
// exception.
|
||||
return NS_OK;
|
||||
@ -1639,7 +1654,7 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsILoadGroup> group = do_QueryReferent(mDocumentLoadGroup);
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, group);
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, group);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
@ -1700,6 +1715,7 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
// resetting the document.
|
||||
mSecurityInfo = securityInfo;
|
||||
|
||||
PRBool loadAsHtml5 = nsHtml5Module::sEnabled;
|
||||
if (loadAsHtml5) {
|
||||
mParser = nsHtml5Module::NewHtml5Parser();
|
||||
rv = NS_OK;
|
||||
@ -1708,7 +1724,7 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
}
|
||||
|
||||
// This will be propagated to the parser when someone actually calls write()
|
||||
SetContentTypeInternal(NS_ConvertUTF16toUTF8(aContentType));
|
||||
SetContentTypeInternal(contentType);
|
||||
|
||||
mWriteState = eDocumentOpened;
|
||||
|
||||
@ -1739,7 +1755,9 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
// so, we need to tell the docshell to not create a new history
|
||||
// entry for this load. Otherwise, make sure that we're doing a normal load,
|
||||
// not whatever type of load was previously done on this docshell.
|
||||
shell->SetLoadType(aReplace ? LOAD_NORMAL_REPLACE : LOAD_NORMAL);
|
||||
shell->SetLoadType(
|
||||
(aOptionalArgCount > 1 && aReplaceOrName.EqualsLiteral("replace"))
|
||||
? LOAD_NORMAL_REPLACE : LOAD_NORMAL);
|
||||
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
shell->GetContentViewer(getter_AddRefs(cv));
|
||||
@ -1749,7 +1767,7 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
}
|
||||
|
||||
// Add a wyciwyg channel request into the document load group
|
||||
NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::OpenCommon(): wyciwyg "
|
||||
NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Open(): wyciwyg "
|
||||
"channel already exists!");
|
||||
|
||||
// In case the editor is listening and will see the new channel
|
||||
@ -1762,46 +1780,7 @@ nsHTMLDocument::OpenCommon(JSContext* cx, const nsAString& aContentType,
|
||||
|
||||
--mWriteLevel;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
|
||||
const nsAString& aReplaceOrName,
|
||||
const nsAString& aFeatures,
|
||||
JSContext* cx, PRUint8 aOptionalArgCount,
|
||||
nsISupports** aReturn)
|
||||
{
|
||||
// When called with 3 or more arguments, document.open() calls window.open().
|
||||
if (aOptionalArgCount > 2) {
|
||||
nsCOMPtr<nsIDOMWindowInternal> window = GetWindowInternal();
|
||||
if (!window) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIDOMWindow> newWindow;
|
||||
nsresult rv = window->Open(aContentTypeOrUrl, aReplaceOrName, aFeatures,
|
||||
getter_AddRefs(newWindow));
|
||||
*aReturn = newWindow.forget().get();
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoString contentType;
|
||||
contentType.AssignLiteral("text/html");
|
||||
if (aOptionalArgCount > 0) {
|
||||
nsAutoString type;
|
||||
ToLowerCase(aContentTypeOrUrl, type);
|
||||
nsCAutoString actualType, dummy;
|
||||
NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
|
||||
if (!actualType.EqualsLiteral("text/html") &&
|
||||
!type.EqualsLiteral("replace")) {
|
||||
contentType.AssignLiteral("text/plain");
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = OpenCommon(cx, contentType,
|
||||
aOptionalArgCount > 1 && aReplaceOrName.EqualsLiteral("replace"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return CallQueryInterface(this, aReturn);
|
||||
}
|
||||
|
||||
|
@ -233,8 +233,6 @@ protected:
|
||||
|
||||
nsresult WriteCommon(JSContext *cx, const nsAString& aText,
|
||||
PRBool aNewlineTerminate);
|
||||
nsresult OpenCommon(JSContext *cx, const nsAString& aContentType,
|
||||
PRBool aReplace);
|
||||
|
||||
nsresult CreateAndAddWyciwygChannel(void);
|
||||
nsresult RemoveWyciwygChannel(void);
|
||||
|
@ -228,7 +228,6 @@
|
||||
#include "nsIDOMComment.h"
|
||||
#include "nsIDOMCDATASection.h"
|
||||
#include "nsIDOMProcessingInstruction.h"
|
||||
#include "nsIDOMNotation.h"
|
||||
#include "nsIDOMNSEvent.h"
|
||||
#include "nsIDOMDataContainerEvent.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
@ -607,8 +606,6 @@ DOMCI_DATA(DOMConstructor, void)
|
||||
DOMCI_DATA(Worker, void)
|
||||
DOMCI_DATA(ChromeWorker, void)
|
||||
|
||||
DOMCI_DATA(Notation, void)
|
||||
|
||||
#define NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _name, _helper, \
|
||||
_flags) \
|
||||
{ #_name, \
|
||||
@ -732,7 +729,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
NS_DEFINE_CLASSINFO_DATA(CDATASection, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(ProcessingInstruction, nsNodeSH,
|
||||
NODE_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(Notation, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(NodeList, nsNodeListSH, ARRAY_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(NamedNodeMap, nsNamedNodeMapSH,
|
||||
ARRAY_SCRIPTABLE_FLAGS)
|
||||
@ -2558,10 +2554,6 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(Notation, nsIDOMNotation)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNotation)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(NodeList, nsIDOMNodeList)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeList)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -63,7 +63,6 @@ DOMCI_CLASS(Text)
|
||||
DOMCI_CLASS(Comment)
|
||||
DOMCI_CLASS(CDATASection)
|
||||
DOMCI_CLASS(ProcessingInstruction)
|
||||
DOMCI_CLASS(Notation)
|
||||
DOMCI_CLASS(NodeList)
|
||||
DOMCI_CLASS(NamedNodeMap)
|
||||
|
||||
|
@ -190,7 +190,7 @@
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPopupManager.h"
|
||||
#include "nsIDOMXULControlElement.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsMenuPopupFrame.h"
|
||||
#endif
|
||||
|
||||
#include "xpcprivate.h"
|
||||
@ -10214,9 +10214,28 @@ nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent)
|
||||
nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElement* aPanel)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetMainWidget();
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
|
||||
// if a panel was supplied, use its widget instead.
|
||||
#ifdef MOZ_XUL
|
||||
if (aPanel) {
|
||||
nsCOMPtr<nsIContent> panel = do_QueryInterface(aPanel);
|
||||
NS_ENSURE_TRUE(panel, NS_ERROR_FAILURE);
|
||||
|
||||
nsIFrame* frame = panel->GetPrimaryFrame();
|
||||
NS_ENSURE_TRUE(frame && frame->GetType() == nsGkAtoms::menuPopupFrame, NS_OK);
|
||||
|
||||
(static_cast<nsMenuPopupFrame*>(frame))->GetWidget(getter_AddRefs(widget));
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
widget = GetMainWidget();
|
||||
#ifdef MOZ_XUL
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!widget) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ interface nsIDOMNSElement;
|
||||
interface nsIDOMNamedNodeMap;
|
||||
interface nsIDOMNode;
|
||||
interface nsIDOMNodeList;
|
||||
interface nsIDOMNotation;
|
||||
interface nsIDOMProcessingInstruction;
|
||||
interface nsIDOMText;
|
||||
interface nsIDOMDOMStringList;
|
||||
|
@ -43,7 +43,7 @@ interface nsIDOMElement;
|
||||
interface nsIDOMEvent;
|
||||
interface nsIChromeFrameMessageManager;
|
||||
|
||||
[scriptable, uuid(ec38cbaf-372f-4874-bc7a-dbf1f0b3d755)]
|
||||
[scriptable, uuid(7cfbc355-cbf9-4408-8e4c-a3c603ff1428)]
|
||||
interface nsIDOMChromeWindow : nsISupports
|
||||
{
|
||||
const unsigned short STATE_MAXIMIZED = 1;
|
||||
@ -84,8 +84,10 @@ interface nsIDOMChromeWindow : nsISupports
|
||||
* start dragging the window. This function will fail unless called
|
||||
* while the left mouse button is held down, callers must check this.
|
||||
*
|
||||
* The optional panel argument should be set when moving a panel.
|
||||
*
|
||||
* Returns NS_ERROR_NOT_IMPLEMENTED (and thus throws in JS) if the OS
|
||||
* doesn't support this.
|
||||
*/
|
||||
void beginWindowMove(in nsIDOMEvent mouseDownEvent);
|
||||
void beginWindowMove(in nsIDOMEvent mouseDownEvent, [optional] in nsIDOMElement panel);
|
||||
};
|
||||
|
@ -60,13 +60,11 @@ SDK_XPIDLSRCS = \
|
||||
nsIDOMNamedNodeMap.idl \
|
||||
nsIDOMNode.idl \
|
||||
nsIDOMNodeList.idl \
|
||||
nsIDOMNotation.idl \
|
||||
nsIDOMProcessingInstruction.idl \
|
||||
nsIDOMText.idl \
|
||||
$(NULL)
|
||||
XPIDLSRCS = \
|
||||
nsIDOM3Node.idl \
|
||||
nsIDOM3TypeInfo.idl \
|
||||
nsIDOM3Attr.idl \
|
||||
nsIDOMDOMStringList.idl \
|
||||
nsIDOMNameList.idl \
|
||||
|
@ -35,13 +35,10 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "domstubs.idl"
|
||||
#include "nsIDOM3TypeInfo.idl"
|
||||
|
||||
[scriptable, uuid(274ef301-065c-450d-a75b-e7673d257293)]
|
||||
[scriptable, uuid(dc3ac0ee-9afb-4d1e-a49c-f5042e5bcf65)]
|
||||
interface nsIDOM3Attr : nsISupports
|
||||
{
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute nsIDOM3TypeInfo schemaTypeInfo;
|
||||
// Introduced in DOM Level 3:
|
||||
readonly attribute boolean isId;
|
||||
};
|
||||
|
@ -603,8 +603,12 @@ PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
|
||||
|
||||
Image::Format format = Image::CAIRO_SURFACE;
|
||||
#ifdef XP_MACOSX
|
||||
if (mIOSurface)
|
||||
if (mIOSurface) {
|
||||
format = Image::MAC_IO_SURFACE;
|
||||
if (!aContainer->Manager()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsRefPtr<Image> image;
|
||||
|
@ -95,9 +95,7 @@ function HTMLBodyElement02() {
|
||||
assertSize("Asize",1,nodeList);
|
||||
testNode = nodeList.item(0);
|
||||
vbackground = testNode.background;
|
||||
// its not clear if this test is valid
|
||||
//assertEquals("backgroundLink","./pix/back1.gif",vbackground);
|
||||
todo_is(vbackground, "./pix/back1.gif", "backgroundLink");
|
||||
assertEquals("backgroundLink","./pix/back1.gif",vbackground);
|
||||
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,20 @@ class Channel : public Message::Sender {
|
||||
//
|
||||
Channel(const std::wstring& channel_id, Mode mode, Listener* listener);
|
||||
|
||||
#if defined(CHROMIUM_MOZILLA_BUILD)
|
||||
// XXX it would nice not to have yet more platform-specific code in
|
||||
// here but it's just not worth the trouble.
|
||||
# if defined(OS_POSIX)
|
||||
// Connect to a pre-created channel |fd| as |mode|.
|
||||
Channel(int fd, Mode mode, Listener* listener);
|
||||
# elif defined(OS_WIN)
|
||||
// Connect to a pre-created channel as |mode|. Clients connect to
|
||||
// the pre-existing server pipe, and servers take over |server_pipe|.
|
||||
Channel(const std::wstring& channel_id, void* server_pipe,
|
||||
Mode mode, Listener* listener);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
~Channel();
|
||||
|
||||
// Connect the pipe. On the server side, this will initiate
|
||||
@ -99,6 +113,16 @@ class Channel : public Message::Sender {
|
||||
// a named FIFO is used as the channel transport mechanism rather than a
|
||||
// socketpair() in which case this method returns -1 for both parameters.
|
||||
void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
|
||||
|
||||
# if defined(CHROMIUM_MOZILLA_BUILD)
|
||||
// Return the server side of the socketpair.
|
||||
int GetServerFileDescriptor() const;
|
||||
# endif
|
||||
#elif defined(OS_WIN)
|
||||
# if defined(CHROMIUM_MOZILLA_BUILD)
|
||||
// Return the server pipe handle.
|
||||
void* GetServerPipeHandle() const;
|
||||
# endif
|
||||
#endif // defined(OS_POSIX)
|
||||
|
||||
private:
|
||||
|
@ -257,18 +257,10 @@ bool SetCloseOnExec(int fd) {
|
||||
|
||||
Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
|
||||
Listener* listener)
|
||||
: mode_(mode),
|
||||
is_blocked_on_write_(false),
|
||||
message_send_bytes_written_(0),
|
||||
uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kIPCUseFIFO)),
|
||||
server_listen_pipe_(-1),
|
||||
pipe_(-1),
|
||||
client_pipe_(-1),
|
||||
listener_(listener),
|
||||
waiting_connect_(true),
|
||||
processing_incoming_(false),
|
||||
factory_(this) {
|
||||
: factory_(this) {
|
||||
Init(mode, listener);
|
||||
uses_fifo_ = CommandLine::ForCurrentProcess()->HasSwitch(switches::kIPCUseFIFO);
|
||||
|
||||
if (!CreatePipe(channel_id, mode)) {
|
||||
// The pipe may have been closed already.
|
||||
LOG(WARNING) << "Unable to create pipe named \"" << channel_id <<
|
||||
@ -277,6 +269,28 @@ Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
|
||||
}
|
||||
}
|
||||
|
||||
Channel::ChannelImpl::ChannelImpl(int fd, Mode mode, Listener* listener)
|
||||
: factory_(this) {
|
||||
Init(mode, listener);
|
||||
pipe_ = fd;
|
||||
waiting_connect_ = (MODE_SERVER == mode);
|
||||
|
||||
EnqueueHelloMessage();
|
||||
}
|
||||
|
||||
void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
|
||||
mode_ = mode;
|
||||
is_blocked_on_write_ = false;
|
||||
message_send_bytes_written_ = 0;
|
||||
uses_fifo_ = false;
|
||||
server_listen_pipe_ = -1;
|
||||
pipe_ = -1;
|
||||
client_pipe_ = -1;
|
||||
listener_ = listener;
|
||||
waiting_connect_ = true;
|
||||
processing_incoming_ = false;
|
||||
}
|
||||
|
||||
bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
|
||||
Mode mode) {
|
||||
DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
|
||||
@ -334,6 +348,10 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
|
||||
}
|
||||
|
||||
// Create the Hello message to be sent when Connect is called
|
||||
return EnqueueHelloMessage();
|
||||
}
|
||||
|
||||
bool Channel::ChannelImpl::EnqueueHelloMessage() {
|
||||
scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
|
||||
HELLO_MESSAGE_TYPE,
|
||||
IPC::Message::PRIORITY_NORMAL));
|
||||
@ -796,6 +814,12 @@ Channel::Channel(const std::wstring& channel_id, Mode mode,
|
||||
: channel_impl_(new ChannelImpl(channel_id, mode, listener)) {
|
||||
}
|
||||
|
||||
#if defined(CHROMIUM_MOZILLA_BUILD)
|
||||
Channel::Channel(int fd, Mode mode, Listener* listener)
|
||||
: channel_impl_(new ChannelImpl(fd, mode, listener)) {
|
||||
}
|
||||
#endif
|
||||
|
||||
Channel::~Channel() {
|
||||
delete channel_impl_;
|
||||
}
|
||||
@ -826,4 +850,10 @@ void Channel::GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const {
|
||||
return channel_impl_->GetClientFileDescriptorMapping(src_fd, dest_fd);
|
||||
}
|
||||
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
int Channel::GetServerFileDescriptor() const {
|
||||
return channel_impl_->GetServerFileDescriptor();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace IPC
|
||||
|
@ -24,6 +24,7 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
|
||||
public:
|
||||
// Mirror methods of Channel, see ipc_channel.h for description.
|
||||
ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
|
||||
ChannelImpl(int fd, Mode mode, Listener* listener);
|
||||
~ChannelImpl() { Close(); }
|
||||
bool Connect();
|
||||
void Close();
|
||||
@ -38,9 +39,17 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher {
|
||||
#endif
|
||||
bool Send(Message* message);
|
||||
void GetClientFileDescriptorMapping(int *src_fd, int *dest_fd) const;
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
int GetServerFileDescriptor() const {
|
||||
DCHECK(mode_ == MODE_SERVER);
|
||||
return pipe_;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
void Init(Mode mode, Listener* listener);
|
||||
bool CreatePipe(const std::wstring& channel_id, Mode mode);
|
||||
bool EnqueueHelloMessage();
|
||||
|
||||
bool ProcessIncomingMessages();
|
||||
bool ProcessOutgoingMessages();
|
||||
|
@ -35,11 +35,9 @@ Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
|
||||
Listener* listener)
|
||||
: ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)),
|
||||
pipe_(INVALID_HANDLE_VALUE),
|
||||
listener_(listener),
|
||||
waiting_connect_(mode == MODE_SERVER),
|
||||
processing_incoming_(false),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
|
||||
Init(mode, listener);
|
||||
|
||||
if (!CreatePipe(channel_id, mode)) {
|
||||
// The pipe may have been closed already.
|
||||
LOG(WARNING) << "Unable to create pipe named \"" << channel_id <<
|
||||
@ -47,6 +45,37 @@ Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CHROMIUM_MOZILLA_BUILD)
|
||||
Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id,
|
||||
HANDLE server_pipe,
|
||||
Mode mode, Listener* listener)
|
||||
: ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
|
||||
Init(mode, listener);
|
||||
|
||||
if (mode == MODE_SERVER) {
|
||||
// Use the existing handle that was dup'd to us
|
||||
pipe_ = server_pipe;
|
||||
EnqueueHelloMessage();
|
||||
} else {
|
||||
// Take the normal init path to connect to the server pipe
|
||||
CreatePipe(channel_id, mode);
|
||||
}
|
||||
}
|
||||
|
||||
void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
|
||||
pipe_ = INVALID_HANDLE_VALUE;
|
||||
listener_ = listener;
|
||||
waiting_connect_ = (mode == MODE_SERVER);
|
||||
processing_incoming_ = false;
|
||||
}
|
||||
|
||||
HANDLE Channel::ChannelImpl::GetServerPipeHandle() const {
|
||||
return pipe_;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Channel::ChannelImpl::Close() {
|
||||
if (thread_check_.get()) {
|
||||
DCHECK(thread_check_->CalledOnValidThread());
|
||||
@ -164,6 +193,10 @@ bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
|
||||
}
|
||||
|
||||
// Create the Hello message to be sent when Connect is called
|
||||
return EnqueueHelloMessage();
|
||||
}
|
||||
|
||||
bool Channel::ChannelImpl::EnqueueHelloMessage() {
|
||||
scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE,
|
||||
HELLO_MESSAGE_TYPE,
|
||||
IPC::Message::PRIORITY_NORMAL));
|
||||
@ -426,6 +459,13 @@ Channel::Channel(const std::wstring& channel_id, Mode mode,
|
||||
: channel_impl_(new ChannelImpl(channel_id, mode, listener)) {
|
||||
}
|
||||
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
Channel::Channel(const std::wstring& channel_id, void* server_pipe,
|
||||
Mode mode, Listener* listener)
|
||||
: channel_impl_(new ChannelImpl(channel_id, server_pipe, mode, listener)) {
|
||||
}
|
||||
#endif
|
||||
|
||||
Channel::~Channel() {
|
||||
delete channel_impl_;
|
||||
}
|
||||
@ -439,6 +479,10 @@ void Channel::Close() {
|
||||
}
|
||||
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
void* Channel::GetServerPipeHandle() const {
|
||||
return channel_impl_->GetServerPipeHandle();
|
||||
}
|
||||
|
||||
Channel::Listener* Channel::set_listener(Listener* listener) {
|
||||
return channel_impl_->set_listener(listener);
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
|
||||
public:
|
||||
// Mirror methods of Channel, see ipc_channel.h for description.
|
||||
ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
|
||||
ChannelImpl(const std::wstring& channel_id, HANDLE server_pipe,
|
||||
Mode mode, Listener* listener);
|
||||
~ChannelImpl() {
|
||||
if (pipe_ != INVALID_HANDLE_VALUE) {
|
||||
Close();
|
||||
@ -28,6 +30,8 @@ class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
|
||||
bool Connect();
|
||||
void Close();
|
||||
#ifdef CHROMIUM_MOZILLA_BUILD
|
||||
HANDLE GetServerPipeHandle() const;
|
||||
|
||||
Listener* set_listener(Listener* listener) {
|
||||
Listener* old = listener_;
|
||||
listener_ = listener;
|
||||
@ -38,8 +42,10 @@ class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
|
||||
#endif
|
||||
bool Send(Message* message);
|
||||
private:
|
||||
void Init(Mode mode, Listener* listener);
|
||||
const std::wstring PipeName(const std::wstring& channel_id) const;
|
||||
bool CreatePipe(const std::wstring& channel_id, Mode mode);
|
||||
bool EnqueueHelloMessage();
|
||||
|
||||
bool ProcessConnection();
|
||||
bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context,
|
||||
|
@ -123,7 +123,7 @@ AsyncChannel::~AsyncChannel()
|
||||
}
|
||||
|
||||
bool
|
||||
AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
|
||||
AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide)
|
||||
{
|
||||
NS_PRECONDITION(!mTransport, "Open() called > once");
|
||||
NS_PRECONDITION(aTransport, "need transport layer");
|
||||
@ -136,8 +136,16 @@ AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
|
||||
// FIXME figure out whether we're in parent or child, grab IO loop
|
||||
// appropriately
|
||||
bool needOpen = true;
|
||||
if(!aIOLoop) {
|
||||
if(aIOLoop) {
|
||||
// We're a child or using the new arguments. Either way, we
|
||||
// need an open.
|
||||
needOpen = true;
|
||||
mChild = (aSide == Unknown) || (aSide == Child);
|
||||
} else {
|
||||
NS_PRECONDITION(aSide == Unknown, "expected default side arg");
|
||||
|
||||
// parent
|
||||
mChild = false;
|
||||
needOpen = false;
|
||||
aIOLoop = XRE_GetIOMessageLoop();
|
||||
// FIXME assuming that the parent waits for the OnConnected event.
|
||||
@ -145,8 +153,6 @@ AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
|
||||
mChannelState = ChannelConnected;
|
||||
}
|
||||
|
||||
mChild = needOpen;
|
||||
|
||||
mIOLoop = aIOLoop;
|
||||
mWorkerLoop = MessageLoop::current();
|
||||
|
||||
@ -241,6 +247,33 @@ AsyncChannel::Send(Message* msg)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AsyncChannel::Echo(Message* msg)
|
||||
{
|
||||
AssertWorkerThread();
|
||||
mMonitor.AssertNotCurrentThreadOwns();
|
||||
NS_ABORT_IF_FALSE(MSG_ROUTING_NONE != msg->routing_id(), "need a route");
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
if (!Connected()) {
|
||||
ReportConnectionError("AsyncChannel");
|
||||
return false;
|
||||
}
|
||||
|
||||
// NB: Go through this OnMessageReceived indirection so that
|
||||
// echoing this message does the right thing for SyncChannel
|
||||
// and RPCChannel too
|
||||
mIOLoop->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this, &AsyncChannel::OnEchoMessage, msg));
|
||||
// OnEchoMessage takes ownership of |msg|
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
AsyncChannel::OnDispatchMessage(const Message& msg)
|
||||
{
|
||||
@ -464,6 +497,14 @@ AsyncChannel::OnMessageReceived(const Message& msg)
|
||||
NewRunnableMethod(this, &AsyncChannel::OnDispatchMessage, msg));
|
||||
}
|
||||
|
||||
void
|
||||
AsyncChannel::OnEchoMessage(Message* msg)
|
||||
{
|
||||
AssertIOThread();
|
||||
OnMessageReceived(*msg);
|
||||
delete msg;
|
||||
}
|
||||
|
||||
void
|
||||
AsyncChannel::OnChannelOpened()
|
||||
{
|
||||
|
@ -42,10 +42,9 @@
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "chrome/common/ipc_channel.h"
|
||||
|
||||
#include "mozilla/Monitor.h"
|
||||
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -66,7 +65,7 @@ struct HasResultCodes
|
||||
};
|
||||
};
|
||||
|
||||
class AsyncChannel : public IPC::Channel::Listener, protected HasResultCodes
|
||||
class AsyncChannel : public Transport::Listener, protected HasResultCodes
|
||||
{
|
||||
protected:
|
||||
typedef mozilla::Monitor Monitor;
|
||||
@ -81,8 +80,8 @@ protected:
|
||||
};
|
||||
|
||||
public:
|
||||
typedef IPC::Channel Transport;
|
||||
typedef IPC::Message Message;
|
||||
typedef mozilla::ipc::Transport Transport;
|
||||
|
||||
class /*NS_INTERFACE_CLASS*/ AsyncListener: protected HasResultCodes
|
||||
{
|
||||
@ -96,6 +95,8 @@ public:
|
||||
virtual void OnChannelConnected(int32 peer_pid) {};
|
||||
};
|
||||
|
||||
enum Side { Parent, Child, Unknown };
|
||||
|
||||
public:
|
||||
//
|
||||
// These methods are called on the "worker" thread
|
||||
@ -108,7 +109,7 @@ public:
|
||||
//
|
||||
// Returns true iff the transport layer was successfully connected,
|
||||
// i.e., mChannelState == ChannelConnected.
|
||||
bool Open(Transport* aTransport, MessageLoop* aIOLoop=0);
|
||||
bool Open(Transport* aTransport, MessageLoop* aIOLoop=0, Side aSide=Unknown);
|
||||
|
||||
// Close the underlying transport channel.
|
||||
void Close();
|
||||
@ -116,6 +117,10 @@ public:
|
||||
// Asynchronously send a message to the other side of the channel
|
||||
virtual bool Send(Message* msg);
|
||||
|
||||
// Asynchronously deliver a message back to this side of the
|
||||
// channel
|
||||
virtual bool Echo(Message* msg);
|
||||
|
||||
// Send OnChannelConnected notification to listeners.
|
||||
void DispatchOnChannelConnected(int32 peer_pid);
|
||||
|
||||
@ -123,7 +128,7 @@ public:
|
||||
// These methods are called on the "IO" thread
|
||||
//
|
||||
|
||||
// Implement the IPC::Channel::Listener interface
|
||||
// Implement the Transport::Listener interface
|
||||
NS_OVERRIDE virtual void OnMessageReceived(const Message& msg);
|
||||
NS_OVERRIDE virtual void OnChannelConnected(int32 peer_pid);
|
||||
NS_OVERRIDE virtual void OnChannelError();
|
||||
@ -176,6 +181,7 @@ protected:
|
||||
void OnChannelOpened();
|
||||
void OnCloseChannel();
|
||||
void PostErrorNotifyTask();
|
||||
void OnEchoMessage(Message* msg);
|
||||
|
||||
// Return true if |msg| is a special message targeted at the IO
|
||||
// thread, in which case it shouldn't be delivered to the worker.
|
||||
@ -190,7 +196,7 @@ protected:
|
||||
MessageLoop* mWorkerLoop; // thread where work is done
|
||||
bool mChild; // am I the child or parent?
|
||||
CancelableTask* mChannelErrorTask; // NotifyMaybeChannelError runnable
|
||||
IPC::Channel::Listener* mExistingListener; // channel's previous listener
|
||||
Transport::Listener* mExistingListener; // channel's previous listener
|
||||
};
|
||||
|
||||
|
||||
|
@ -84,6 +84,12 @@ using mozilla::ipc::GeckoChildProcessHost;
|
||||
static const int kMagicAndroidSystemPropFd = 5;
|
||||
#endif
|
||||
|
||||
static bool
|
||||
ShouldHaveDirectoryService()
|
||||
{
|
||||
return GeckoProcessType_Default == XRE_GetProcessType();
|
||||
}
|
||||
|
||||
template<>
|
||||
struct RunnableMethodTraits<GeckoChildProcessHost>
|
||||
{
|
||||
@ -139,15 +145,20 @@ void GetPathToBinary(FilePath& exePath)
|
||||
exePath = exePath.DirName();
|
||||
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
|
||||
#elif defined(OS_POSIX)
|
||||
nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCString path;
|
||||
greDir->GetNativePath(path);
|
||||
exePath = FilePath(path.get());
|
||||
if (ShouldHaveDirectoryService()) {
|
||||
nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
NS_ASSERTION(directoryService, "Expected XPCOM to be available");
|
||||
if (directoryService) {
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCString path;
|
||||
greDir->GetNativePath(path);
|
||||
exePath = FilePath(path.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (exePath.empty()) {
|
||||
exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
|
||||
exePath = exePath.DirName();
|
||||
}
|
||||
@ -421,41 +432,50 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_MACOSX)
|
||||
base::environment_map newEnvVars;
|
||||
nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCString path;
|
||||
greDir->GetNativePath(path);
|
||||
#ifdef OS_LINUX
|
||||
#ifdef ANDROID
|
||||
path += "/lib";
|
||||
#endif
|
||||
newEnvVars["LD_LIBRARY_PATH"] = path.get();
|
||||
#elif OS_MACOSX
|
||||
newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
|
||||
// XXX DYLD_INSERT_LIBRARIES should only be set when launching a plugin
|
||||
// process, and has no effect on other subprocesses (the hooks in
|
||||
// libplugin_child_interpose.dylib become noops). But currently it
|
||||
// gets set when launching any kind of subprocess.
|
||||
//
|
||||
// Trigger "dyld interposing" for the dylib that contains
|
||||
// plugin_child_interpose.mm. This allows us to hook OS calls in the
|
||||
// plugin process (ones that don't work correctly in a background
|
||||
// process). Don't break any other "dyld interposing" that has already
|
||||
// been set up by whatever may have launched the browser.
|
||||
const char* prevInterpose = PR_GetEnv("DYLD_INSERT_LIBRARIES");
|
||||
nsCString interpose;
|
||||
if (prevInterpose) {
|
||||
interpose.Assign(prevInterpose);
|
||||
interpose.AppendLiteral(":");
|
||||
// XPCOM may not be initialized in some subprocesses. We don't want
|
||||
// to initialize XPCOM just for the directory service, especially
|
||||
// since LD_LIBRARY_PATH is already set correctly in subprocesses
|
||||
// (meaning that we don't need to set that up in the environment).
|
||||
if (ShouldHaveDirectoryService()) {
|
||||
nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
NS_ASSERTION(directoryService, "Expected XPCOM to be available");
|
||||
if (directoryService) {
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(greDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCString path;
|
||||
greDir->GetNativePath(path);
|
||||
# ifdef OS_LINUX
|
||||
# ifdef ANDROID
|
||||
path += "/lib";
|
||||
# endif // ANDROID
|
||||
newEnvVars["LD_LIBRARY_PATH"] = path.get();
|
||||
# elif OS_MACOSX
|
||||
newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
|
||||
// XXX DYLD_INSERT_LIBRARIES should only be set when launching a plugin
|
||||
// process, and has no effect on other subprocesses (the hooks in
|
||||
// libplugin_child_interpose.dylib become noops). But currently it
|
||||
// gets set when launching any kind of subprocess.
|
||||
//
|
||||
// Trigger "dyld interposing" for the dylib that contains
|
||||
// plugin_child_interpose.mm. This allows us to hook OS calls in the
|
||||
// plugin process (ones that don't work correctly in a background
|
||||
// process). Don't break any other "dyld interposing" that has already
|
||||
// been set up by whatever may have launched the browser.
|
||||
const char* prevInterpose = PR_GetEnv("DYLD_INSERT_LIBRARIES");
|
||||
nsCString interpose;
|
||||
if (prevInterpose) {
|
||||
interpose.Assign(prevInterpose);
|
||||
interpose.AppendLiteral(":");
|
||||
}
|
||||
interpose.Append(path.get());
|
||||
interpose.AppendLiteral("/libplugin_child_interpose.dylib");
|
||||
newEnvVars["DYLD_INSERT_LIBRARIES"] = interpose.get();
|
||||
# endif // OS_LINUX
|
||||
}
|
||||
}
|
||||
interpose.Append(path.get());
|
||||
interpose.AppendLiteral("/libplugin_child_interpose.dylib");
|
||||
newEnvVars["DYLD_INSERT_LIBRARIES"] = interpose.get();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif // OS_LINUX || OS_MACOSX
|
||||
|
||||
FilePath exePath;
|
||||
GetPathToBinary(exePath);
|
||||
@ -509,18 +529,20 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
||||
|
||||
childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end());
|
||||
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsCAutoString path;
|
||||
nsCOMPtr<nsIFile> file = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
|
||||
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
|
||||
childArgv.push_back("-greomni");
|
||||
childArgv.push_back(path.get());
|
||||
}
|
||||
file = mozilla::Omnijar::GetPath(mozilla::Omnijar::APP);
|
||||
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
|
||||
childArgv.push_back("-appomni");
|
||||
childArgv.push_back(path.get());
|
||||
if (Omnijar::IsInitialized()) {
|
||||
// Make sure that child processes can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsCAutoString path;
|
||||
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
|
||||
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
|
||||
childArgv.push_back("-greomni");
|
||||
childArgv.push_back(path.get());
|
||||
}
|
||||
file = Omnijar::GetPath(Omnijar::APP);
|
||||
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
|
||||
childArgv.push_back("-appomni");
|
||||
childArgv.push_back(path.get());
|
||||
}
|
||||
}
|
||||
|
||||
childArgv.push_back(pidstring);
|
||||
@ -624,18 +646,20 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
||||
|
||||
cmdLine.AppendLooseValue(std::wstring(mGroupId.get()));
|
||||
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsAutoString path;
|
||||
nsCOMPtr<nsIFile> file = mozilla::Omnijar::GetPath(mozilla::Omnijar::GRE);
|
||||
if (file && NS_SUCCEEDED(file->GetPath(path))) {
|
||||
cmdLine.AppendLooseValue(UTF8ToWide("-greomni"));
|
||||
cmdLine.AppendLooseValue(path.get());
|
||||
}
|
||||
file = mozilla::Omnijar::GetPath(mozilla::Omnijar::APP);
|
||||
if (file && NS_SUCCEEDED(file->GetPath(path))) {
|
||||
cmdLine.AppendLooseValue(UTF8ToWide("-appomni"));
|
||||
cmdLine.AppendLooseValue(path.get());
|
||||
if (Omnijar::IsInitialized()) {
|
||||
// Make sure the child process can find the omnijar
|
||||
// See XRE_InitCommandLine in nsAppRunner.cpp
|
||||
nsAutoString path;
|
||||
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
|
||||
if (file && NS_SUCCEEDED(file->GetPath(path))) {
|
||||
cmdLine.AppendLooseValue(UTF8ToWide("-greomni"));
|
||||
cmdLine.AppendLooseValue(path.get());
|
||||
}
|
||||
file = Omnijar::GetPath(Omnijar::APP);
|
||||
if (file && NS_SUCCEEDED(file->GetPath(path))) {
|
||||
cmdLine.AppendLooseValue(UTF8ToWide("-appomni"));
|
||||
cmdLine.AppendLooseValue(path.get());
|
||||
}
|
||||
}
|
||||
|
||||
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
|
||||
|
@ -68,8 +68,20 @@ EXPORTS_mozilla/ipc = \
|
||||
Shmem.h \
|
||||
SyncChannel.h \
|
||||
ScopedXREEmbed.h \
|
||||
Transport.h \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT) #{
|
||||
EXPORTS_mozilla/ipc += \
|
||||
Transport_win.h \
|
||||
$(NULL)
|
||||
else
|
||||
# POSIX
|
||||
EXPORTS_mozilla/ipc += \
|
||||
Transport_posix.h \
|
||||
$(NULL)
|
||||
endif #}
|
||||
|
||||
ifeq ($(OS_TARGET),Android)
|
||||
# Android has its own,
|
||||
# almost-but-not-quite-compatible-with-POSIX-or-/dev/shm shared memory
|
||||
@ -85,6 +97,7 @@ CPPSRCS += \
|
||||
GeckoChildProcessHost.cpp \
|
||||
MessagePump.cpp \
|
||||
ProcessChild.cpp \
|
||||
ProtocolUtils.cpp \
|
||||
RPCChannel.cpp \
|
||||
ScopedXREEmbed.cpp \
|
||||
SharedMemory.cpp \
|
||||
@ -93,15 +106,19 @@ CPPSRCS += \
|
||||
SyncChannel.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifeq ($(OS_ARCH),WINNT) #{
|
||||
CPPSRCS += \
|
||||
SharedMemory_windows.cpp \
|
||||
Transport_win.cpp \
|
||||
WindowsMessageLoop.cpp \
|
||||
$(NULL)
|
||||
else
|
||||
# This generic code works on android.
|
||||
CPPSRCS += SharedMemory_posix.cpp
|
||||
endif
|
||||
# POSIX
|
||||
CPPSRCS += \
|
||||
SharedMemory_posix.cpp \
|
||||
Transport_posix.cpp \
|
||||
$(NULL)
|
||||
endif #}
|
||||
|
||||
ifeq ($(OS_TARGET),Android)
|
||||
CPPSRCS += SharedMemoryBasic_android.cpp
|
||||
|
161
ipc/glue/ProtocolUtils.cpp
Normal file
161
ipc/glue/ProtocolUtils.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "base/process_util.h"
|
||||
|
||||
#include "mozilla/ipc/AsyncChannel.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace IPC;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class ChannelOpened : public IPC::Message
|
||||
{
|
||||
public:
|
||||
ChannelOpened(TransportDescriptor aDescriptor,
|
||||
ProcessId aOtherProcess,
|
||||
ProtocolId aProtocol)
|
||||
: IPC::Message(MSG_ROUTING_CONTROL, // these only go to top-level actors
|
||||
CHANNEL_OPENED_MESSAGE_TYPE,
|
||||
PRIORITY_NORMAL)
|
||||
{
|
||||
IPC::WriteParam(this, aDescriptor);
|
||||
IPC::WriteParam(this, aOtherProcess);
|
||||
IPC::WriteParam(this, static_cast<uint32>(aProtocol));
|
||||
}
|
||||
|
||||
static bool Read(const IPC::Message& aMsg,
|
||||
TransportDescriptor* aDescriptor,
|
||||
ProcessId* aOtherProcess,
|
||||
ProtocolId* aProtocol)
|
||||
{
|
||||
void* iter = nsnull;
|
||||
if (!IPC::ReadParam(&aMsg, &iter, aDescriptor) ||
|
||||
!IPC::ReadParam(&aMsg, &iter, aOtherProcess) ||
|
||||
!IPC::ReadParam(&aMsg, &iter, reinterpret_cast<uint32*>(aProtocol))) {
|
||||
return false;
|
||||
}
|
||||
aMsg.EndRead(iter);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
Bridge(const PrivateIPDLInterface&,
|
||||
AsyncChannel* aParentChannel, ProcessHandle aParentProcess,
|
||||
AsyncChannel* aChildChannel, ProcessHandle aChildProcess,
|
||||
ProtocolId aProtocol)
|
||||
{
|
||||
ProcessId parentId = GetProcId(aParentProcess);
|
||||
ProcessId childId = GetProcId(aChildProcess);
|
||||
if (!parentId || !childId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TransportDescriptor parentSide, childSide;
|
||||
if (!CreateTransport(aParentProcess, aChildProcess,
|
||||
&parentSide, &childSide)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aParentChannel->Send(new ChannelOpened(parentSide,
|
||||
childId,
|
||||
aProtocol)) ||
|
||||
!aChildChannel->Send(new ChannelOpened(childSide,
|
||||
parentId,
|
||||
aProtocol))) {
|
||||
CloseDescriptor(parentSide);
|
||||
CloseDescriptor(childSide);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Open(const PrivateIPDLInterface&,
|
||||
AsyncChannel* aOpenerChannel, ProcessHandle aOtherProcess,
|
||||
Transport::Mode aOpenerMode,
|
||||
ProtocolId aProtocol)
|
||||
{
|
||||
bool isParent = (Transport::MODE_SERVER == aOpenerMode);
|
||||
ProcessHandle thisHandle = GetCurrentProcessHandle();
|
||||
ProcessHandle parentHandle = isParent ? thisHandle : aOtherProcess;
|
||||
ProcessHandle childHandle = !isParent ? thisHandle : aOtherProcess;
|
||||
ProcessId parentId = GetProcId(parentHandle);
|
||||
ProcessId childId = GetProcId(childHandle);
|
||||
if (!parentId || !childId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TransportDescriptor parentSide, childSide;
|
||||
if (!CreateTransport(parentHandle, childHandle,
|
||||
&parentSide, &childSide)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Message* parentMsg = new ChannelOpened(parentSide, childId, aProtocol);
|
||||
Message* childMsg = new ChannelOpened(childSide, parentId, aProtocol);
|
||||
nsAutoPtr<Message> messageForUs(isParent ? parentMsg : childMsg);
|
||||
nsAutoPtr<Message> messageForOtherSide(!isParent ? parentMsg : childMsg);
|
||||
if (!aOpenerChannel->Echo(messageForUs.forget()) ||
|
||||
!aOpenerChannel->Send(messageForOtherSide.forget())) {
|
||||
CloseDescriptor(parentSide);
|
||||
CloseDescriptor(childSide);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
UnpackChannelOpened(const PrivateIPDLInterface&,
|
||||
const Message& aMsg,
|
||||
TransportDescriptor* aTransport,
|
||||
ProcessId* aOtherProcess,
|
||||
ProtocolId* aProtocol)
|
||||
{
|
||||
return ChannelOpened::Read(aMsg, aTransport, aOtherProcess, aProtocol);
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
@ -46,12 +46,21 @@
|
||||
|
||||
#include "prenv.h"
|
||||
|
||||
#include "IPCMessageStart.h"
|
||||
#include "mozilla/ipc/Shmem.h"
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
// WARNING: this takes into account the private, special-message-type
|
||||
// enum in ipc_channel.h. They need to be kept in sync.
|
||||
namespace {
|
||||
// XXX the max message ID is actually kuint32max now ... when this
|
||||
// changed, the assumptions of the special message IDs changed in that
|
||||
// they're not carving out messages from likely-unallocated space, but
|
||||
// rather carving out messages from the end of space allocated to
|
||||
// protocol 0. Oops! We can get away with this until protocol 0
|
||||
// starts approaching its 65,536th message.
|
||||
enum {
|
||||
CHANNEL_OPENED_MESSAGE_TYPE = kuint16max - 6,
|
||||
SHMEM_DESTROYED_MESSAGE_TYPE = kuint16max - 5,
|
||||
UNBLOCK_CHILD_MESSAGE_TYPE = kuint16max - 4,
|
||||
BLOCK_CHILD_MESSAGE_TYPE = kuint16max - 3,
|
||||
@ -63,6 +72,7 @@ enum {
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class AsyncChannel;
|
||||
|
||||
// Used to pass references to protocol actors across the wire.
|
||||
// Actors created on the parent-side have a positive ID, and actors
|
||||
@ -117,8 +127,9 @@ public:
|
||||
virtual bool IsTrackingSharedMemory(Shmem::SharedMemory*) = 0;
|
||||
virtual bool DestroySharedMemory(Shmem&) = 0;
|
||||
|
||||
// XXX odd duck, acknowledged
|
||||
// XXX odd ducks, acknowledged
|
||||
virtual ProcessHandle OtherProcess() const = 0;
|
||||
virtual AsyncChannel* GetIPCChannel() = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -133,6 +144,25 @@ LoggingEnabled()
|
||||
}
|
||||
|
||||
|
||||
typedef IPCMessageStart ProtocolId;
|
||||
|
||||
struct PrivateIPDLInterface {};
|
||||
|
||||
bool
|
||||
Bridge(const PrivateIPDLInterface&,
|
||||
AsyncChannel*, base::ProcessHandle, AsyncChannel*, base::ProcessHandle,
|
||||
ProtocolId);
|
||||
|
||||
bool
|
||||
Open(const PrivateIPDLInterface&,
|
||||
AsyncChannel*, base::ProcessHandle, Transport::Mode,
|
||||
ProtocolId);
|
||||
|
||||
bool
|
||||
UnpackChannelOpened(const PrivateIPDLInterface&,
|
||||
const IPC::Message&,
|
||||
TransportDescriptor*, base::ProcessId*, ProtocolId*);
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
@ -11,18 +14,19 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Alexander J. Vincent <ajvincent@gmail.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
@ -34,22 +38,33 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "domstubs.idl"
|
||||
#ifndef mozilla_ipc_Transport_h
|
||||
#define mozilla_ipc_Transport_h 1
|
||||
|
||||
// Introduced in DOM Level 3:
|
||||
[scriptable, uuid(2a1088c7-499a-49a7-9d3b-1970d21532ab)]
|
||||
interface nsIDOM3TypeInfo : nsISupports
|
||||
{
|
||||
readonly attribute DOMString typeName;
|
||||
readonly attribute DOMString typeNamespace;
|
||||
#include "base/process_util.h"
|
||||
#include "chrome/common/ipc_channel.h"
|
||||
|
||||
// DerivationMethods
|
||||
const unsigned long DERIVATION_RESTRICTION = 0x00000001;
|
||||
const unsigned long DERIVATION_EXTENSION = 0x00000002;
|
||||
const unsigned long DERIVATION_UNION = 0x00000004;
|
||||
const unsigned long DERIVATION_LIST = 0x00000008;
|
||||
#ifdef OS_POSIX
|
||||
# include "mozilla/ipc/Transport_posix.h"
|
||||
#elif OS_WIN
|
||||
# include "mozilla/ipc/Transport_win.h"
|
||||
#endif
|
||||
|
||||
boolean isDerivedFrom(in DOMString typeNamespaceArg,
|
||||
in DOMString typeNameArg,
|
||||
in unsigned long derivationMethod);
|
||||
};
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
|
||||
typedef IPC::Channel Transport;
|
||||
|
||||
bool CreateTransport(base::ProcessHandle aProcOne, base::ProcessHandle aProcTwo,
|
||||
TransportDescriptor* aOne, TransportDescriptor* aTwo);
|
||||
|
||||
Transport* OpenDescriptor(const TransportDescriptor& aTd,
|
||||
Transport::Mode aMode);
|
||||
|
||||
void CloseDescriptor(const TransportDescriptor& aTd);
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_Transport_h
|
98
ipc/glue/Transport_posix.cpp
Normal file
98
ipc/glue/Transport_posix.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "chrome/common/child_process_info.h"
|
||||
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
bool
|
||||
CreateTransport(ProcessHandle /*unused*/, ProcessHandle /*unused*/,
|
||||
TransportDescriptor* aOne, TransportDescriptor* aTwo)
|
||||
{
|
||||
// Gecko doesn't care about this random ID, and the argument to this
|
||||
// function isn't really necessary, it can be just any random
|
||||
// pointer value
|
||||
wstring id = ChildProcessInfo::GenerateRandomChannelID(aOne);
|
||||
// Use MODE_SERVER to force creation of the socketpair
|
||||
Transport t(id, Transport::MODE_SERVER, nsnull);
|
||||
int fd1 = t.GetServerFileDescriptor();
|
||||
int fd2, dontcare;
|
||||
t.GetClientFileDescriptorMapping(&fd2, &dontcare);
|
||||
if (fd1 < 0 || fd2 < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The Transport closes these fds when it goes out of scope, so we
|
||||
// dup them here
|
||||
fd1 = dup(fd1);
|
||||
fd2 = dup(fd2);
|
||||
if (fd1 < 0 || fd2 < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOne->mFd = FileDescriptor(fd1, true/*close after sending*/);
|
||||
aTwo->mFd = FileDescriptor(fd2, true/*close after sending*/);
|
||||
return true;
|
||||
}
|
||||
|
||||
Transport*
|
||||
OpenDescriptor(const TransportDescriptor& aTd, Transport::Mode aMode)
|
||||
{
|
||||
return new Transport(aTd.mFd.fd, aMode, nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
CloseDescriptor(const TransportDescriptor& aTd)
|
||||
{
|
||||
close(aTd.mFd.fd);
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
@ -1,10 +1,12 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
@ -12,20 +14,19 @@
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Vidur Apparao <vidur@netscape.com> (original author)
|
||||
* Johnny Stenback <jst@netscape.com>
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
@ -37,20 +38,41 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMNode.idl"
|
||||
#ifndef mozilla_ipc_Transport_posix_h
|
||||
#define mozilla_ipc_Transport_posix_h 1
|
||||
|
||||
/**
|
||||
* The nsIDOMNotation interface represents a notation declared in the DTD.
|
||||
* A notation either declares, by name, the format of an unparsed entity,
|
||||
* or is used for formal declaration of processing instruction targets.
|
||||
*
|
||||
* For more information on this interface please see
|
||||
* http://www.w3.org/TR/DOM-Level-2-Core/
|
||||
*/
|
||||
#include "IPC/IPCMessageUtils.h"
|
||||
|
||||
[scriptable, uuid(43658ade-a157-447a-8dcd-aa7fc824ef0a)]
|
||||
interface nsIDOMNotation : nsIDOMNode
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
struct TransportDescriptor
|
||||
{
|
||||
readonly attribute DOMString publicId;
|
||||
readonly attribute DOMString systemId;
|
||||
base::FileDescriptor mFd;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::ipc::TransportDescriptor>
|
||||
{
|
||||
typedef mozilla::ipc::TransportDescriptor paramType;
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mFd);
|
||||
}
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->mFd);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
|
||||
#endif // mozilla_ipc_Transport_posix_h
|
101
ipc/glue/Transport_win.cpp
Normal file
101
ipc/glue/Transport_win.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "chrome/common/child_process_info.h"
|
||||
|
||||
#include "mozilla/ipc/Transport.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
bool
|
||||
CreateTransport(ProcessHandle aProcOne, ProcessHandle /*unused*/,
|
||||
TransportDescriptor* aOne, TransportDescriptor* aTwo)
|
||||
{
|
||||
// This id is used to name the IPC pipe. The pointer passed to this
|
||||
// function isn't significant.
|
||||
wstring id = ChildProcessInfo::GenerateRandomChannelID(aOne);
|
||||
// Use MODE_SERVER to force creation of the pipe
|
||||
Transport t(id, Transport::MODE_SERVER, nsnull);
|
||||
HANDLE serverPipe = t.GetServerPipeHandle();
|
||||
if (!serverPipe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// NB: we create the server pipe immediately, instead of just
|
||||
// grabbing an ID, on purpose. In the current setup, the client
|
||||
// needs to connect to an existing server pipe, so to prevent race
|
||||
// conditions, we create the server side here and then dup it to the
|
||||
// eventual server process.
|
||||
HANDLE serverDup;
|
||||
DWORD access = 0;
|
||||
DWORD options = DUPLICATE_SAME_ACCESS;
|
||||
if (!DuplicateHandle(GetCurrentProcess(), serverPipe, aProcOne,
|
||||
&serverDup,
|
||||
access,
|
||||
FALSE/*not inheritable*/,
|
||||
options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOne->mPipeName = aTwo->mPipeName = id;
|
||||
aOne->mServerPipe = serverDup;
|
||||
aTwo->mServerPipe = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
Transport*
|
||||
OpenDescriptor(const TransportDescriptor& aTd, Transport::Mode aMode)
|
||||
{
|
||||
return new Transport(aTd.mPipeName, aTd.mServerPipe, aMode, nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
CloseDescriptor(const TransportDescriptor& aTd)
|
||||
{
|
||||
CloseHandle(aTd.mServerPipe);
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
83
ipc/glue/Transport_win.h
Normal file
83
ipc/glue/Transport_win.h
Normal file
@ -0,0 +1,83 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef mozilla_ipc_Transport_win_h
|
||||
#define mozilla_ipc_Transport_win_h 1
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "IPC/IPCMessageUtils.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
struct TransportDescriptor
|
||||
{
|
||||
std::wstring mPipeName;
|
||||
HANDLE mServerPipe;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::ipc::TransportDescriptor>
|
||||
{
|
||||
typedef mozilla::ipc::TransportDescriptor paramType;
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mPipeName);
|
||||
WriteParam(aMsg, aParam.mServerPipe);
|
||||
}
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return (ReadParam(aMsg, aIter, &aResult->mPipeName) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mServerPipe));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
|
||||
#endif // mozilla_ipc_Transport_win_h
|
@ -97,6 +97,7 @@ $(foreach IPDLDIR,$(IPDLDIRS),$(eval $(ADD_IPDLDIR)))
|
||||
CPPSRCS = \
|
||||
$(PROTOCOLS:%.ipdl=%Parent.cpp) \
|
||||
$(PROTOCOLS:%.ipdl=%Child.cpp) \
|
||||
$(PROTOCOLS:%.ipdl=%.cpp) \
|
||||
$(NULL)
|
||||
|
||||
GARBAGE += $(CPPSRCS)
|
||||
|
@ -75,14 +75,19 @@ log(2, 'Generated C++ sources will be generated in "%s"', cppdir)
|
||||
|
||||
allprotocols = []
|
||||
|
||||
def normalizedFilename(f):
|
||||
if f == '-':
|
||||
return '<stdin>'
|
||||
return f
|
||||
|
||||
# First pass: parse and type-check all protocols
|
||||
for f in files:
|
||||
log(1, os.path.basename(f))
|
||||
filename = normalizedFilename(f)
|
||||
if f == '-':
|
||||
fd = sys.stdin
|
||||
filename = '<stdin>'
|
||||
else:
|
||||
fd = open(f)
|
||||
filename = f
|
||||
|
||||
specstring = fd.read()
|
||||
fd.close()
|
||||
@ -92,8 +97,6 @@ for f in files:
|
||||
print >>sys.stderr, 'Specification could not be parsed.'
|
||||
sys.exit(1)
|
||||
|
||||
allprotocols.append('%sMsgStart' % ast.protocol.name)
|
||||
|
||||
log(2, 'checking types')
|
||||
if not ipdl.typecheck(ast):
|
||||
print >>sys.stderr, 'Specification is not well typed.'
|
||||
@ -103,7 +106,14 @@ for f in files:
|
||||
log(3, ' pretty printed code:')
|
||||
ipdl.genipdl(ast, codedir)
|
||||
|
||||
# Second pass: generate code
|
||||
for f in files:
|
||||
# Read from parser cache
|
||||
filename = normalizedFilename(f)
|
||||
ast = ipdl.parse(None, filename, includedirs=includedirs)
|
||||
ipdl.gencxx(filename, ast, headersdir, cppdir)
|
||||
|
||||
allprotocols.append('%sMsgStart' % ast.protocol.name)
|
||||
|
||||
allprotocols.sort()
|
||||
|
||||
|
@ -77,6 +77,8 @@ class Visitor:
|
||||
spawns.accept(self)
|
||||
for bridges in p.bridgesStmts:
|
||||
bridges.accept(self)
|
||||
for opens in p.opensStmts:
|
||||
opens.accept(self)
|
||||
for mgr in p.managers:
|
||||
mgr.accept(self)
|
||||
for managed in p.managesStmts:
|
||||
@ -95,6 +97,9 @@ class Visitor:
|
||||
def visitBridgesStmt(self, bridges):
|
||||
pass
|
||||
|
||||
def visitOpensStmt(self, opens):
|
||||
pass
|
||||
|
||||
def visitManager(self, mgr):
|
||||
pass
|
||||
|
||||
@ -269,6 +274,7 @@ class Protocol(NamespacedNode):
|
||||
self.sendSemantics = ASYNC
|
||||
self.spawnsStmts = [ ]
|
||||
self.bridgesStmts = [ ]
|
||||
self.opensStmts = [ ]
|
||||
self.managers = [ ]
|
||||
self.managesStmts = [ ]
|
||||
self.messageDecls = [ ]
|
||||
@ -304,6 +310,12 @@ class BridgesStmt(Node):
|
||||
self.parentSide = parentSide
|
||||
self.childSide = childSide
|
||||
|
||||
class OpensStmt(Node):
|
||||
def __init__(self, loc, side, proto):
|
||||
Node.__init__(self, loc)
|
||||
self.side = side
|
||||
self.proto = proto
|
||||
|
||||
class Manager(Node):
|
||||
def __init__(self, loc, managerName):
|
||||
Node.__init__(self, loc)
|
||||
|
@ -110,6 +110,12 @@ class Visitor:
|
||||
meth.decl.accept(self)
|
||||
self.visitBlock(meth)
|
||||
|
||||
def visitFunctionDecl(self, fun):
|
||||
self.visitMethodDecl(fun)
|
||||
|
||||
def visitFunctionDefn(self, fd):
|
||||
self.visitMethodDefn(fd)
|
||||
|
||||
def visitConstructorDecl(self, ctor):
|
||||
self.visitMethodDecl(ctor)
|
||||
|
||||
@ -509,6 +515,20 @@ class MethodDefn(Block):
|
||||
Block.__init__(self)
|
||||
self.decl = decl
|
||||
|
||||
class FunctionDecl(MethodDecl):
|
||||
def __init__(self, name, params=[ ], ret=Type('void'),
|
||||
static=0, warn_unused=0,
|
||||
inline=0, force_inline=0,
|
||||
T=None):
|
||||
MethodDecl.__init__(self, name, params=params, ret=ret,
|
||||
static=static, warn_unused=warn_unused,
|
||||
inline=inline, force_inline=force_inline,
|
||||
T=T)
|
||||
|
||||
class FunctionDefn(MethodDefn):
|
||||
def __init__(self, decl):
|
||||
MethodDefn.__init__(self, decl)
|
||||
|
||||
class ConstructorDecl(MethodDecl):
|
||||
def __init__(self, name, params=[ ], explicit=0, force_inline=0):
|
||||
MethodDecl.__init__(self, name, params=params, ret=None,
|
||||
|
@ -35,7 +35,7 @@ from copy import deepcopy
|
||||
|
||||
import ipdl.ast
|
||||
from ipdl.cxx.ast import *
|
||||
from ipdl.type import TypeVisitor
|
||||
from ipdl.type import ActorType, ProcessGraph, TypeVisitor
|
||||
|
||||
# FIXME/cjones: the chromium Message logging code doesn't work on
|
||||
# gcc/POSIX, because it wprintf()s across the chromium/mozilla
|
||||
@ -55,8 +55,8 @@ lowered form of |tu|'''
|
||||
|
||||
pname = tu.protocol.name
|
||||
|
||||
pheader = File(pname +'.h')
|
||||
_GenerateProtocolHeader().lower(tu, pheader)
|
||||
pheader, pcpp = File(pname +'.h'), File(pname +'.cpp')
|
||||
_GenerateProtocolCode().lower(tu, pheader, pcpp)
|
||||
|
||||
parentheader, parentcpp = File(pname +'Parent.h'), File(pname +'Parent.cpp')
|
||||
_GenerateProtocolParentCode().lower(
|
||||
@ -66,7 +66,7 @@ lowered form of |tu|'''
|
||||
_GenerateProtocolChildCode().lower(
|
||||
tu, pname+'Child', childheader, childcpp)
|
||||
|
||||
return [ pheader, parentheader, childheader ], [ parentcpp, childcpp ]
|
||||
return [ pheader, parentheader, childheader ], [ pcpp, parentcpp, childcpp ]
|
||||
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
@ -76,6 +76,14 @@ lowered form of |tu|'''
|
||||
_NULL_ACTOR_ID = ExprLiteral.ZERO
|
||||
_FREED_ACTOR_ID = ExprLiteral.ONE
|
||||
|
||||
_DISCLAIMER = Whitespace('''//
|
||||
// Automatically generated by ipdlc.
|
||||
// Edit at your own risk
|
||||
//
|
||||
|
||||
''')
|
||||
|
||||
|
||||
class _struct: pass
|
||||
|
||||
def _protocolHeaderName(p, side=''):
|
||||
@ -134,6 +142,9 @@ def _actorManager(actor):
|
||||
def _actorState(actor):
|
||||
return ExprSelect(actor, '->', 'mState')
|
||||
|
||||
def _backstagePass():
|
||||
return ExprCall(ExprVar('mozilla::ipc::PrivateIPDLInterface'))
|
||||
|
||||
def _nullState(proto=None):
|
||||
pfx = ''
|
||||
if proto is not None: pfx = proto.name() +'::'
|
||||
@ -346,6 +357,11 @@ def _otherSide(side):
|
||||
if side == 'parent': return 'child'
|
||||
assert 0
|
||||
|
||||
def _sideToTransportMode(side):
|
||||
if side == 'parent': mode = 'SERVER'
|
||||
elif side == 'child': mode = 'CLIENT'
|
||||
return ExprVar('mozilla::ipc::Transport::MODE_'+ mode)
|
||||
|
||||
def _ifLogging(stmts):
|
||||
iflogging = StmtIf(ExprCall(ExprVar('mozilla::ipc::LoggingEnabled')))
|
||||
iflogging.addifstmts(stmts)
|
||||
@ -1052,6 +1068,21 @@ class Protocol(ipdl.ast.Protocol):
|
||||
def otherProcessMethod(self):
|
||||
return ExprVar('OtherProcess')
|
||||
|
||||
def callOtherProcess(self, actorThis=None):
|
||||
fn = self.otherProcessMethod()
|
||||
if actorThis is not None:
|
||||
fn = ExprSelect(actorThis, '->', fn.name)
|
||||
return ExprCall(fn)
|
||||
|
||||
def getChannelMethod(self):
|
||||
return ExprVar('GetIPCChannel')
|
||||
|
||||
def callGetChannel(self, actorThis=None):
|
||||
fn = self.getChannelMethod()
|
||||
if actorThis is not None:
|
||||
fn = ExprSelect(actorThis, '->', fn.name)
|
||||
return ExprCall(fn)
|
||||
|
||||
def processingErrorVar(self):
|
||||
assert self.decl.type.isToplevel()
|
||||
return ExprVar('ProcessingError')
|
||||
@ -1311,46 +1342,58 @@ with some new IPDL/C++ nodes that are tuned for C++ codegen."""
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
|
||||
class _GenerateProtocolHeader(ipdl.ast.Visitor):
|
||||
'''Creates a header containing code common to both the parent and
|
||||
child actors.'''
|
||||
class _GenerateProtocolCode(ipdl.ast.Visitor):
|
||||
'''Creates code common to both the parent and child actors.'''
|
||||
def __init__(self):
|
||||
self.protocol = None # protocol we're generating a class for
|
||||
self.file = None # File stuff is stuck in
|
||||
self.hdrfile = None # what will become Protocol.h
|
||||
self.cppfile = None # what will become Protocol.cpp
|
||||
self.cppIncludeHeaders = []
|
||||
self.structUnionDefns = []
|
||||
self.funcDefns = []
|
||||
|
||||
def lower(self, tu, outcxxfile):
|
||||
def lower(self, tu, cxxHeaderFile, cxxFile):
|
||||
self.protocol = tu.protocol
|
||||
self.file = outcxxfile
|
||||
self.hdrfile = cxxHeaderFile
|
||||
self.cppfile = cxxFile
|
||||
tu.accept(self)
|
||||
|
||||
def visitTranslationUnit(self, tu):
|
||||
f = self.file
|
||||
hf = self.hdrfile
|
||||
|
||||
f.addthing(Whitespace('''//
|
||||
// Automatically generated by the IPDL compiler.
|
||||
// Edit at your own risk
|
||||
//
|
||||
|
||||
'''))
|
||||
f.addthings(_includeGuardStart(f))
|
||||
f.addthing(Whitespace.NL)
|
||||
hf.addthing(_DISCLAIMER)
|
||||
hf.addthings(_includeGuardStart(hf))
|
||||
hf.addthing(Whitespace.NL)
|
||||
|
||||
ipdl.ast.Visitor.visitTranslationUnit(self, tu)
|
||||
|
||||
f.addthings(self.structUnionDefns)
|
||||
hf.addthing(Whitespace.NL)
|
||||
hf.addthings(_includeGuardEnd(hf))
|
||||
|
||||
f.addthing(Whitespace.NL)
|
||||
f.addthings(_includeGuardEnd(f))
|
||||
cf = self.cppfile
|
||||
cf.addthings((
|
||||
[ _DISCLAIMER, Whitespace.NL ]
|
||||
+ [ CppDirective('include','"'+h+'.h"')
|
||||
for h in self.cppIncludeHeaders ]
|
||||
+ [ Whitespace.NL ]
|
||||
))
|
||||
|
||||
# construct the namespace into which we'll stick all our defns
|
||||
ns = Namespace(self.protocol.name)
|
||||
cf.addthing(_putInNamespaces(ns, self.protocol.namespaces))
|
||||
ns.addstmts(([ Whitespace.NL]
|
||||
+ self.funcDefns
|
||||
+[ Whitespace.NL ]))
|
||||
cf.addthings(self.structUnionDefns)
|
||||
|
||||
|
||||
def visitCxxInclude(self, inc):
|
||||
self.file.addthing(CppDirective('include', '"'+ inc.file +'"'))
|
||||
self.hdrfile.addthing(CppDirective('include', '"'+ inc.file +'"'))
|
||||
|
||||
def processStructOrUnionClass(self, su, which, forwarddecls, cls):
|
||||
clsdecl, methoddefns = _splitClassDeclDefn(cls, inlinedefns=1)
|
||||
clsdecl, methoddefns = _splitClassDeclDefn(cls)
|
||||
|
||||
self.file.addthings(
|
||||
self.hdrfile.addthings(
|
||||
[ Whitespace.NL ]
|
||||
+ forwarddecls
|
||||
+ [ Whitespace("""
|
||||
@ -1379,7 +1422,29 @@ child actors.'''
|
||||
*_generateCxxUnion(ud))
|
||||
|
||||
def visitProtocol(self, p):
|
||||
self.file.addthing(Whitespace("""
|
||||
self.cppIncludeHeaders.append(_protocolHeaderName(self.protocol, ''))
|
||||
bridges = ProcessGraph.bridgesOf(p.decl.type)
|
||||
for bridge in bridges:
|
||||
ppt, pside = bridge.parent.ptype, _otherSide(bridge.parent.side)
|
||||
cpt, cside = bridge.child.ptype, _otherSide(bridge.child.side)
|
||||
self.hdrfile.addthings([
|
||||
Whitespace.NL,
|
||||
_makeForwardDeclForActor(ppt, pside),
|
||||
_makeForwardDeclForActor(cpt, cside)
|
||||
])
|
||||
self.cppIncludeHeaders.append(_protocolHeaderName(ppt._p, pside))
|
||||
self.cppIncludeHeaders.append(_protocolHeaderName(cpt._p, cside))
|
||||
|
||||
opens = ProcessGraph.opensOf(p.decl.type)
|
||||
for o in opens:
|
||||
optype, oside = o.opener.ptype, o.opener.side
|
||||
self.hdrfile.addthings([
|
||||
Whitespace.NL,
|
||||
_makeForwardDeclForActor(optype, oside)
|
||||
])
|
||||
self.cppIncludeHeaders.append(_protocolHeaderName(optype._p, oside))
|
||||
|
||||
self.hdrfile.addthing(Whitespace("""
|
||||
//-----------------------------------------------------------------------------
|
||||
// Code common to %sChild and %sParent
|
||||
//
|
||||
@ -1387,9 +1452,22 @@ child actors.'''
|
||||
|
||||
# construct the namespace into which we'll stick all our decls
|
||||
ns = Namespace(self.protocol.name)
|
||||
self.file.addthing(_putInNamespaces(ns, p.namespaces))
|
||||
self.hdrfile.addthing(_putInNamespaces(ns, p.namespaces))
|
||||
ns.addstmt(Whitespace.NL)
|
||||
|
||||
# user-facing methods for connecting two process with a new channel
|
||||
for bridge in bridges:
|
||||
bdecl, bdefn = _splitFuncDeclDefn(self.genBridgeFunc(bridge))
|
||||
ns.addstmts([ bdecl, Whitespace.NL ])
|
||||
self.funcDefns.append(bdefn)
|
||||
|
||||
# user-facing methods for opening a new channel across two
|
||||
# existing endpoints
|
||||
for o in opens:
|
||||
odecl, odefn = _splitFuncDeclDefn(self.genOpenFunc(o))
|
||||
ns.addstmts([ odecl, Whitespace.NL ])
|
||||
self.funcDefns.append(odefn)
|
||||
|
||||
# state information
|
||||
stateenum = TypeEnum('State')
|
||||
# NB: __Dead is the first state on purpose, so that it has
|
||||
@ -1421,7 +1499,9 @@ child actors.'''
|
||||
msgenum.addId(self.protocol.name +'End')
|
||||
ns.addstmts([ StmtDecl(Decl(msgenum, '')), Whitespace.NL ])
|
||||
|
||||
ns.addstmts([ self.genTransitionFunc(), Whitespace.NL ])
|
||||
tfDecl, tfDefn = _splitFuncDeclDefn(self.genTransitionFunc())
|
||||
ns.addstmts([ tfDecl, Whitespace.NL ])
|
||||
self.funcDefns.append(tfDefn)
|
||||
|
||||
typedefs = self.protocol.decl.cxxtypedefs
|
||||
for md in p.messageDecls:
|
||||
@ -1439,6 +1519,50 @@ child actors.'''
|
||||
ns.addstmts([ Whitespace.NL, Whitespace.NL ])
|
||||
|
||||
|
||||
def genBridgeFunc(self, bridge):
|
||||
p = self.protocol
|
||||
parentHandleType = _cxxBareType(ActorType(bridge.parent.ptype),
|
||||
_otherSide(bridge.parent.side))
|
||||
parentvar = ExprVar('parentHandle')
|
||||
|
||||
childHandleType = _cxxBareType(ActorType(bridge.child.ptype),
|
||||
_otherSide(bridge.child.side))
|
||||
childvar = ExprVar('childHandle')
|
||||
|
||||
bridgefunc = MethodDefn(MethodDecl(
|
||||
'Bridge',
|
||||
params=[ Decl(parentHandleType, parentvar.name),
|
||||
Decl(childHandleType, childvar.name) ],
|
||||
ret=Type.BOOL))
|
||||
bridgefunc.addstmt(StmtReturn(ExprCall(
|
||||
ExprVar('mozilla::ipc::Bridge'),
|
||||
args=[ _backstagePass(),
|
||||
p.callGetChannel(parentvar), p.callOtherProcess(parentvar),
|
||||
p.callGetChannel(childvar), p.callOtherProcess(childvar),
|
||||
_protocolId(p.decl.type)
|
||||
])))
|
||||
return bridgefunc
|
||||
|
||||
|
||||
def genOpenFunc(self, o):
|
||||
p = self.protocol
|
||||
localside = o.opener.side
|
||||
openertype = _cxxBareType(ActorType(o.opener.ptype), o.opener.side)
|
||||
openervar = ExprVar('opener')
|
||||
openfunc = MethodDefn(MethodDecl(
|
||||
'Open',
|
||||
params=[ Decl(openertype, openervar.name) ],
|
||||
ret=Type.BOOL))
|
||||
openfunc.addstmt(StmtReturn(ExprCall(
|
||||
ExprVar('mozilla::ipc::Open'),
|
||||
args=[ _backstagePass(),
|
||||
p.callGetChannel(openervar), p.callOtherProcess(openervar),
|
||||
_sideToTransportMode(localside),
|
||||
_protocolId(p.decl.type)
|
||||
])))
|
||||
return openfunc
|
||||
|
||||
|
||||
def genTransitionFunc(self):
|
||||
ptype = self.protocol.decl.type
|
||||
usesend, sendvar = set(), ExprVar('__Send')
|
||||
@ -1466,13 +1590,12 @@ child actors.'''
|
||||
msgexpr = ExprSelect(triggervar, '.', 'mMsg')
|
||||
actionexpr = ExprSelect(triggervar, '.', 'mAction')
|
||||
|
||||
transitionfunc = MethodDefn(MethodDecl(
|
||||
transitionfunc = FunctionDefn(FunctionDecl(
|
||||
'Transition',
|
||||
params=[ Decl(Type('State'), fromvar.name),
|
||||
Decl(Type('mozilla::ipc::Trigger'), triggervar.name),
|
||||
Decl(Type('State', ptr=1), nextvar.name) ],
|
||||
ret=Type.BOOL,
|
||||
inline=1))
|
||||
ret=Type.BOOL))
|
||||
|
||||
fromswitch = StmtSwitch(fromvar)
|
||||
|
||||
@ -2244,6 +2367,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
Typedef(Type(self.protocol.channelName()), 'Channel'),
|
||||
Typedef(Type(self.protocol.fqListenerName()), 'ChannelListener'),
|
||||
Typedef(Type('base::ProcessHandle'), 'ProcessHandle'),
|
||||
Typedef(Type('mozilla::ipc::AsyncChannel'), 'AsyncChannel'),
|
||||
Typedef(Type('mozilla::ipc::SharedMemory'), 'SharedMemory'),
|
||||
Typedef(Type('mozilla::ipc::Trigger'), 'Trigger')
|
||||
]
|
||||
@ -2255,15 +2379,9 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
hf = self.hdrfile
|
||||
cf = self.cppfile
|
||||
|
||||
disclaimer = Whitespace('''//
|
||||
// Automatically generated by ipdlc.
|
||||
// Edit at your own risk
|
||||
//
|
||||
|
||||
''')
|
||||
# make the C++ header
|
||||
hf.addthings(
|
||||
[ disclaimer ]
|
||||
[ _DISCLAIMER ]
|
||||
+ _includeGuardStart(hf)
|
||||
+[
|
||||
Whitespace.NL,
|
||||
@ -2318,7 +2436,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
|
||||
# make the .cpp file
|
||||
cf.addthings([
|
||||
disclaimer,
|
||||
_DISCLAIMER,
|
||||
Whitespace.NL,
|
||||
CppDirective(
|
||||
'include',
|
||||
@ -2396,6 +2514,10 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
Inherit(p.managerInterfaceType(), viz='protected') ],
|
||||
abstract=True)
|
||||
|
||||
bridgeActorsCreated = ProcessGraph.bridgeEndpointsOf(ptype, self.side)
|
||||
opensActorsCreated = ProcessGraph.opensEndpointsOf(ptype, self.side)
|
||||
channelOpenedActors = bridgeActorsCreated + opensActorsCreated
|
||||
|
||||
friends = _FindFriends().findFriends(ptype)
|
||||
if ptype.isManaged():
|
||||
friends.update(ptype.managers)
|
||||
@ -2417,11 +2539,27 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
self.prettyside)),
|
||||
Whitespace.NL ])
|
||||
|
||||
for actor in channelOpenedActors:
|
||||
self.hdrfile.addthings([
|
||||
Whitespace.NL,
|
||||
_makeForwardDeclForActor(actor.ptype, actor.side),
|
||||
Whitespace.NL
|
||||
])
|
||||
|
||||
self.cls.addstmt(Label.PROTECTED)
|
||||
for typedef in p.cxxTypedefs():
|
||||
self.cls.addstmt(typedef)
|
||||
for typedef in self.includedActorTypedefs:
|
||||
self.cls.addstmt(typedef)
|
||||
# XXX these don't really fit in the other lists; just include
|
||||
# them here for now
|
||||
self.cls.addstmts([
|
||||
Typedef(Type('base::ProcessId'), 'ProcessId'),
|
||||
Typedef(Type('mozilla::ipc::ProtocolId'), 'ProtocolId'),
|
||||
Typedef(Type('mozilla::ipc::Transport'), 'Transport'),
|
||||
Typedef(Type('mozilla::ipc::TransportDescriptor'), 'TransportDescriptor')
|
||||
])
|
||||
|
||||
self.cls.addstmt(Whitespace.NL)
|
||||
|
||||
self.cls.addstmts([ Typedef(p.fqStateType(), 'State'), Whitespace.NL ])
|
||||
@ -2467,6 +2605,17 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
ret=Type.BOOL,
|
||||
virtual=1, pure=1)))
|
||||
|
||||
for actor in channelOpenedActors:
|
||||
# add the Alloc interface for actors created when a
|
||||
# new channel is opened
|
||||
actortype = _cxxBareType(actor.asType(), actor.side)
|
||||
self.cls.addstmt(StmtDecl(MethodDecl(
|
||||
_allocMethod(actor.ptype).name,
|
||||
params=[ Decl(Type('Transport', ptr=1), 'transport'),
|
||||
Decl(Type('ProcessId'), 'otherProcess') ],
|
||||
ret=actortype,
|
||||
virtual=1, pure=1)))
|
||||
|
||||
# optional ActorDestroy() method; default is no-op
|
||||
self.cls.addstmts([
|
||||
Whitespace.NL,
|
||||
@ -2551,6 +2700,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
aTransportVar = ExprVar('aTransport')
|
||||
aThreadVar = ExprVar('aThread')
|
||||
processvar = ExprVar('aOtherProcess')
|
||||
sidevar = ExprVar('aSide')
|
||||
openmeth = MethodDefn(
|
||||
MethodDecl(
|
||||
'Open',
|
||||
@ -2559,13 +2709,16 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
Decl(Type('ProcessHandle'), processvar.name),
|
||||
Param(Type('MessageLoop', ptr=True),
|
||||
aThreadVar.name,
|
||||
default=ExprLiteral.NULL) ],
|
||||
default=ExprLiteral.NULL),
|
||||
Param(Type('AsyncChannel::Side'),
|
||||
sidevar.name,
|
||||
default=ExprVar('Channel::Unknown')) ],
|
||||
ret=Type.BOOL))
|
||||
|
||||
openmeth.addstmts([
|
||||
StmtExpr(ExprAssn(p.otherProcessVar(), processvar)),
|
||||
StmtReturn(ExprCall(ExprSelect(p.channelVar(), '.', 'Open'),
|
||||
[ aTransportVar, aThreadVar ]))
|
||||
[ aTransportVar, aThreadVar, sidevar ]))
|
||||
])
|
||||
self.cls.addstmts([
|
||||
openmeth,
|
||||
@ -2656,6 +2809,11 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
for md in p.messageDecls:
|
||||
self.visitMessageDecl(md)
|
||||
|
||||
# Handlers for the creation of actors when a new channel is
|
||||
# opened
|
||||
if len(channelOpenedActors):
|
||||
self.makeChannelOpenedHandlers(channelOpenedActors)
|
||||
|
||||
# add default cases
|
||||
default = StmtBlock()
|
||||
default.addstmt(StmtReturn(_Result.NotKnown))
|
||||
@ -2939,8 +3097,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
Whitespace.NL
|
||||
])
|
||||
|
||||
ifkill = StmtIf(ExprNot(
|
||||
_killProcess(ExprCall(p.otherProcessMethod()))))
|
||||
ifkill = StmtIf(ExprNot(_killProcess(p.callOtherProcess())))
|
||||
ifkill.addifstmt(
|
||||
_printErrorMessage(" may have failed to kill child!"))
|
||||
fatalerror.addstmt(ifkill)
|
||||
@ -3178,6 +3335,10 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
ret=Type('ProcessHandle'),
|
||||
const=1,
|
||||
virtual=1))
|
||||
getchannel = MethodDefn(MethodDecl(
|
||||
p.getChannelMethod().name,
|
||||
ret=Type('AsyncChannel', ptr=1),
|
||||
virtual=1))
|
||||
|
||||
if p.decl.type.isToplevel():
|
||||
tmpvar = ExprVar('tmp')
|
||||
@ -3230,7 +3391,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
p.nextShmemIdExpr(self.side) ]),
|
||||
StmtDecl(Decl(Type('Message', ptr=1), descriptorvar.name),
|
||||
init=_shmemShareTo(shmemvar,
|
||||
ExprCall(p.otherProcessMethod()),
|
||||
p.callOtherProcess(),
|
||||
p.routingId()))
|
||||
])
|
||||
failif = StmtIf(ExprNot(descriptorvar))
|
||||
@ -3271,7 +3432,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
p.nextShmemIdExpr(self.side) ]),
|
||||
StmtDecl(Decl(Type('Message', ptr=1), descriptorvar.name),
|
||||
init=_shmemShareTo(shmemvar,
|
||||
ExprCall(p.otherProcessMethod()),
|
||||
p.callOtherProcess(),
|
||||
p.routingId()))
|
||||
])
|
||||
failif = StmtIf(ExprNot(descriptorvar))
|
||||
@ -3325,7 +3486,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
StmtDecl(Decl(Type('Message', ptr=1), descriptorvar.name),
|
||||
init=_shmemUnshareFrom(
|
||||
shmemvar,
|
||||
ExprCall(p.otherProcessMethod()),
|
||||
p.callOtherProcess(),
|
||||
p.routingId())),
|
||||
Whitespace.NL,
|
||||
StmtExpr(p.removeShmemId(idvar)),
|
||||
@ -3360,6 +3521,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
CaseLabel('SHMEM_DESTROYED_MESSAGE_TYPE'), abort)
|
||||
|
||||
otherprocess.addstmt(StmtReturn(p.otherProcessVar()))
|
||||
getchannel.addstmt(StmtReturn(ExprAddrOf(p.channelVar())))
|
||||
else:
|
||||
# delegate registration to manager
|
||||
register.addstmt(StmtReturn(ExprCall(
|
||||
@ -3390,9 +3552,9 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
destroyshmem.addstmt(StmtReturn(ExprCall(
|
||||
ExprSelect(p.managerVar(), '->', p.destroySharedMemory().name),
|
||||
[ shmemvar ])))
|
||||
otherprocess.addstmt(StmtReturn(ExprCall(
|
||||
ExprSelect(p.managerVar(), '->',
|
||||
p.otherProcessMethod().name))))
|
||||
otherprocess.addstmt(StmtReturn(
|
||||
p.callOtherProcess(p.managerVar())))
|
||||
getchannel.addstmt(StmtReturn(p.channelVar()))
|
||||
|
||||
# all protocols share the "same" RemoveManagee() implementation
|
||||
pvar = ExprVar('aProtocolId')
|
||||
@ -3445,6 +3607,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
istracking,
|
||||
destroyshmem,
|
||||
otherprocess,
|
||||
getchannel,
|
||||
Whitespace.NL ]
|
||||
|
||||
def makeShmemIface(self):
|
||||
@ -3635,6 +3798,68 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
||||
return case
|
||||
|
||||
|
||||
def makeChannelOpenedHandlers(self, actors):
|
||||
handlers = StmtBlock()
|
||||
|
||||
# unpack the transport descriptor et al.
|
||||
msgvar = self.msgvar
|
||||
tdvar = ExprVar('td')
|
||||
pidvar = ExprVar('pid')
|
||||
pvar = ExprVar('p')
|
||||
iffail = StmtIf(ExprNot(ExprCall(
|
||||
ExprVar('mozilla::ipc::UnpackChannelOpened'),
|
||||
args=[ _backstagePass(),
|
||||
msgvar,
|
||||
ExprAddrOf(tdvar), ExprAddrOf(pidvar), ExprAddrOf(pvar) ])))
|
||||
iffail.addifstmt(StmtReturn(_Result.PayloadError))
|
||||
handlers.addstmts([
|
||||
StmtDecl(Decl(Type('TransportDescriptor'), tdvar.name)),
|
||||
StmtDecl(Decl(Type('ProcessId'), pidvar.name)),
|
||||
StmtDecl(Decl(Type('ProtocolId'), pvar.name)),
|
||||
iffail,
|
||||
Whitespace.NL
|
||||
])
|
||||
|
||||
def makeHandlerCase(actor):
|
||||
case = StmtBlock()
|
||||
modevar = _sideToTransportMode(actor.side)
|
||||
tvar = ExprVar('t')
|
||||
iffailopen = StmtIf(ExprNot(ExprAssn(
|
||||
tvar,
|
||||
ExprCall(ExprVar('mozilla::ipc::OpenDescriptor'),
|
||||
args=[ tdvar, modevar ]))))
|
||||
iffailopen.addifstmt(StmtReturn(_Result.ValuError))
|
||||
|
||||
iffailalloc = StmtIf(ExprNot(ExprCall(
|
||||
_allocMethod(actor.ptype),
|
||||
args=[ tvar, pidvar ])))
|
||||
iffailalloc.addifstmt(StmtReturn(_Result.ProcessingError))
|
||||
|
||||
case.addstmts([
|
||||
StmtDecl(Decl(Type('Transport', ptr=1), tvar.name)),
|
||||
iffailopen,
|
||||
iffailalloc,
|
||||
StmtBreak()
|
||||
])
|
||||
return CaseLabel(_protocolId(actor.ptype).name), case
|
||||
|
||||
pswitch = StmtSwitch(pvar)
|
||||
for actor in actors:
|
||||
label, case = makeHandlerCase(actor)
|
||||
pswitch.addcase(label, case)
|
||||
|
||||
die = Block()
|
||||
die.addstmts([ _runtimeAbort('Invalid protocol'),
|
||||
StmtReturn(_Result.ValuError) ])
|
||||
pswitch.addcase(DefaultLabel(), die)
|
||||
|
||||
handlers.addstmts([
|
||||
pswitch,
|
||||
StmtReturn(_Result.Processed)
|
||||
])
|
||||
self.asyncSwitch.addcase(CaseLabel('CHANNEL_OPENED_MESSAGE_TYPE'),
|
||||
handlers)
|
||||
|
||||
##-------------------------------------------------------------------------
|
||||
## The next few functions are the crux of the IPDL code generator.
|
||||
## They generate code for all the nasty work of message
|
||||
@ -4684,7 +4909,7 @@ class _GenerateProtocolChildCode(_GenerateProtocolActorCode):
|
||||
## Utility passes
|
||||
##
|
||||
|
||||
def _splitClassDeclDefn(cls, inlinedefns=0):
|
||||
def _splitClassDeclDefn(cls):
|
||||
"""Destructively split |cls| methods into declarations and
|
||||
definitions (if |not methodDecl.force_inline|). Return classDecl,
|
||||
methodDefns."""
|
||||
@ -4692,25 +4917,29 @@ methodDefns."""
|
||||
|
||||
for i, stmt in enumerate(cls.stmts):
|
||||
if isinstance(stmt, MethodDefn) and not stmt.decl.force_inline:
|
||||
decl, defn = _splitMethodDefn(stmt, cls.name, inlinedefns)
|
||||
decl, defn = _splitMethodDefn(stmt, cls.name)
|
||||
cls.stmts[i] = StmtDecl(decl)
|
||||
defns.addstmts([ defn, Whitespace.NL ])
|
||||
|
||||
return cls, defns
|
||||
|
||||
def _splitMethodDefn(md, clsname, inlinedefn):
|
||||
def _splitMethodDefn(md, clsname):
|
||||
saveddecl = deepcopy(md.decl)
|
||||
md.decl.name = (clsname +'::'+ md.decl.name)
|
||||
md.decl.virtual = 0
|
||||
md.decl.static = 0
|
||||
md.decl.warn_unused = 0
|
||||
md.decl.inline = inlinedefn
|
||||
for param in md.decl.params:
|
||||
if isinstance(param, Param):
|
||||
param.default = None
|
||||
return saveddecl, md
|
||||
|
||||
|
||||
def _splitFuncDeclDefn(fun):
|
||||
assert not fun.decl.inline
|
||||
return StmtDecl(fun.decl), fun
|
||||
|
||||
|
||||
# XXX this is tantalizingly similar to _splitClassDeclDefn, but just
|
||||
# different enough that I don't see the need to define
|
||||
# _GenerateSkeleton in terms of that
|
||||
|
@ -155,6 +155,7 @@ reserved = set((
|
||||
'manages',
|
||||
'namespace',
|
||||
'nullable',
|
||||
'opens',
|
||||
'or',
|
||||
'parent',
|
||||
'protocol',
|
||||
@ -343,7 +344,7 @@ def p_ProtocolBody(p):
|
||||
p[0] = p[1]
|
||||
|
||||
##--------------------
|
||||
## spawns/bridges stmts
|
||||
## spawns/bridges/opens stmts
|
||||
|
||||
def p_SpawnsStmtsOpt(p):
|
||||
"""SpawnsStmtsOpt : SpawnsStmt SpawnsStmtsOpt
|
||||
@ -370,7 +371,7 @@ def p_AsOpt(p):
|
||||
|
||||
def p_BridgesStmtsOpt(p):
|
||||
"""BridgesStmtsOpt : BridgesStmt BridgesStmtsOpt
|
||||
| ManagersStmtOpt"""
|
||||
| OpensStmtsOpt"""
|
||||
if 2 == len(p):
|
||||
p[0] = p[1]
|
||||
else:
|
||||
@ -381,6 +382,20 @@ def p_BridgesStmt(p):
|
||||
"""BridgesStmt : BRIDGES ID ',' ID ';'"""
|
||||
p[0] = BridgesStmt(locFromTok(p, 1), p[2], p[4])
|
||||
|
||||
def p_OpensStmtsOpt(p):
|
||||
"""OpensStmtsOpt : OpensStmt OpensStmtsOpt
|
||||
| ManagersStmtOpt"""
|
||||
if 2 == len(p):
|
||||
p[0] = p[1]
|
||||
else:
|
||||
p[2].opensStmts.insert(0, p[1])
|
||||
p[0] = p[2]
|
||||
|
||||
def p_OpensStmt(p):
|
||||
"""OpensStmt : PARENT OPENS ID ';'
|
||||
| CHILD OPENS ID ';'"""
|
||||
p[0] = OpensStmt(locFromTok(p, 1), p[1], p[3])
|
||||
|
||||
##--------------------
|
||||
## manager/manages stmts
|
||||
|
||||
|
@ -294,7 +294,7 @@ class ProtocolType(IPDLType):
|
||||
self.qname = qname
|
||||
self.sendSemantics = sendSemantics
|
||||
self.spawns = set() # ProtocolType
|
||||
self.bridges = set() # [ Bridge ]
|
||||
self.opens = set() # ProtocolType
|
||||
self.managers = set() # ProtocolType
|
||||
self.manages = [ ]
|
||||
self.stateless = stateless
|
||||
@ -314,8 +314,9 @@ class ProtocolType(IPDLType):
|
||||
assert self.isToplevel() and ptype.isToplevel()
|
||||
self.spawns.add(ptype)
|
||||
|
||||
def addBridge(self, parentPType, childPType):
|
||||
self.bridges.add(Bridge(parentPType, childPType))
|
||||
def addOpen(self, ptype):
|
||||
assert self.isToplevel() and ptype.isToplevel()
|
||||
self.opens.add(ptype)
|
||||
|
||||
def managedBy(self, mgr):
|
||||
self.managers = mgr
|
||||
@ -777,6 +778,9 @@ class GatherDecls(TcheckVisitor):
|
||||
for bridges in p.bridgesStmts:
|
||||
bridges.accept(self)
|
||||
|
||||
for opens in p.opensStmts:
|
||||
opens.accept(self)
|
||||
|
||||
seenmgrs = set()
|
||||
for mgr in p.managers:
|
||||
if mgr.name in seenmgrs:
|
||||
@ -927,6 +931,14 @@ class GatherDecls(TcheckVisitor):
|
||||
bridges.parentSide = lookup(bridges.parentSide)
|
||||
bridges.childSide = lookup(bridges.childSide)
|
||||
|
||||
def visitOpensStmt(self, opens):
|
||||
pname = opens.proto
|
||||
opens.proto = self.symtab.lookup(pname)
|
||||
if opens.proto is None:
|
||||
self.error(opens.loc,
|
||||
"opened protocol `%s' has not been declared",
|
||||
pname)
|
||||
|
||||
|
||||
def visitManager(self, mgr):
|
||||
mgrdecl = self.symtab.lookup(mgr.name)
|
||||
@ -1234,6 +1246,11 @@ class CheckTypes(TcheckVisitor):
|
||||
"protocol `%s' is not top-level and so cannot declare |bridges|",
|
||||
pname)
|
||||
|
||||
if len(p.opensStmts) and not ptype.isToplevel():
|
||||
self.error(p.decl.loc,
|
||||
"protocol `%s' is not top-level and so cannot declare |opens|",
|
||||
pname)
|
||||
|
||||
for mgrtype in ptype.managers:
|
||||
if mgrtype is not None and ptype.needsMoreJuiceThan(mgrtype):
|
||||
self.error(
|
||||
@ -1300,8 +1317,23 @@ class CheckTypes(TcheckVisitor):
|
||||
self.error(bridges.loc,
|
||||
"cannot bridge non-top-level-protocol(s) `%s' and `%s'",
|
||||
parentType.name(), childType.name())
|
||||
|
||||
|
||||
def visitOpensStmt(self, opens):
|
||||
if not self.ptype.isToplevel():
|
||||
self.error(opens.loc,
|
||||
"only top-level protocols can have |opens| statements; `%s' cannot",
|
||||
self.ptype.name())
|
||||
return
|
||||
|
||||
openedType = opens.proto.type
|
||||
if not (openedType.isIPDL() and openedType.isProtocol()
|
||||
and openedType.isToplevel()):
|
||||
self.error(opens.loc,
|
||||
"cannot open non-top-level-protocol `%s'",
|
||||
openedType.name())
|
||||
else:
|
||||
self.ptype.addBridge(parentType, childType)
|
||||
self.ptype.addOpen(openedType)
|
||||
|
||||
|
||||
def visitManagesStmt(self, mgs):
|
||||
@ -1442,6 +1474,8 @@ class Actor:
|
||||
self.ptype = ptype
|
||||
self.side = side
|
||||
|
||||
def asType(self):
|
||||
return ActorType(self.ptype)
|
||||
def other(self):
|
||||
return Actor(self.ptype, _otherside(self.side))
|
||||
|
||||
@ -1471,11 +1505,20 @@ class BridgeEdge:
|
||||
self.parent, self.bridgeProto.name(), self.child)
|
||||
def __str__(self): return repr(self)
|
||||
|
||||
class OpensEdge:
|
||||
def __init__(self, opener, openedProto):
|
||||
self.opener = opener # Actor
|
||||
self.openedProto = openedProto # ProtocolType
|
||||
def __repr__(self):
|
||||
return '(%r)--opens-->(%s)'% (self.opener, self.openedProto.name())
|
||||
def __str__(self): return repr(self)
|
||||
|
||||
# "singleton" class with state that persists across type checking of
|
||||
# all protocols
|
||||
class ProcessGraph:
|
||||
processes = set() # set(Process)
|
||||
bridges = { } # ProtocolType -> BridgeEdge
|
||||
bridges = { } # ProtocolType -> [ BridgeEdge ]
|
||||
opens = { } # ProtocolType -> [ OpensEdge ]
|
||||
actorToProcess = { } # Actor -> Process
|
||||
visitedSpawns = set() # set(ActorType)
|
||||
visitedBridges = set() # set(ActorType)
|
||||
@ -1493,6 +1536,48 @@ class ProcessGraph:
|
||||
cls.actorToProcess[actor] = p
|
||||
return cls.actorToProcess[actor]
|
||||
|
||||
@classmethod
|
||||
def bridgesOf(cls, bridgeP):
|
||||
return cls.bridges.get(bridgeP, [])
|
||||
|
||||
@classmethod
|
||||
def bridgeEndpointsOf(cls, ptype, side):
|
||||
actor = Actor(ptype, side)
|
||||
endpoints = []
|
||||
for b in cls.iterbridges():
|
||||
if b.parent == actor:
|
||||
endpoints.append(Actor(b.bridgeProto, 'parent'))
|
||||
elif b.child == actor:
|
||||
endpoints.append(Actor(b.bridgeProto, 'child'))
|
||||
return endpoints
|
||||
|
||||
@classmethod
|
||||
def iterbridges(cls):
|
||||
for edges in cls.bridges.itervalues():
|
||||
for bridge in edges:
|
||||
yield bridge
|
||||
|
||||
@classmethod
|
||||
def opensOf(cls, openedP):
|
||||
return cls.opens.get(openedP, [])
|
||||
|
||||
@classmethod
|
||||
def opensEndpointsOf(cls, ptype, side):
|
||||
actor = Actor(ptype, side)
|
||||
endpoints = []
|
||||
for o in cls.iteropens():
|
||||
if actor == o.opener:
|
||||
endpoints.append(Actor(o.openedProto, o.opener.side))
|
||||
elif actor == o.opener.other():
|
||||
endpoints.append(Actor(o.openedProto, o.opener.other().side))
|
||||
return endpoints
|
||||
|
||||
@classmethod
|
||||
def iteropens(cls):
|
||||
for edges in cls.opens.itervalues():
|
||||
for opens in edges:
|
||||
yield opens
|
||||
|
||||
@classmethod
|
||||
def spawn(cls, spawner, remoteSpawn):
|
||||
localSpawn = remoteSpawn.other()
|
||||
@ -1502,7 +1587,26 @@ class ProcessGraph:
|
||||
|
||||
@classmethod
|
||||
def bridge(cls, parent, child, bridgeP):
|
||||
cls.bridges[bridgeP] = BridgeEdge(bridgeP, parent, child)
|
||||
bridgeParent = Actor(bridgeP, 'parent')
|
||||
parentProcess = ProcessGraph.getProcess(parent)
|
||||
parentProcess.merge(ProcessGraph.getProcess(bridgeParent))
|
||||
bridgeChild = Actor(bridgeP, 'child')
|
||||
childProcess = ProcessGraph.getProcess(child)
|
||||
childProcess.merge(ProcessGraph.getProcess(bridgeChild))
|
||||
if bridgeP not in cls.bridges:
|
||||
cls.bridges[bridgeP] = [ ]
|
||||
cls.bridges[bridgeP].append(BridgeEdge(bridgeP, parent, child))
|
||||
|
||||
@classmethod
|
||||
def open(cls, opener, opened, openedP):
|
||||
remoteOpener, remoteOpened, = opener.other(), opened.other()
|
||||
openerProcess = ProcessGraph.getProcess(opener)
|
||||
openerProcess.merge(ProcessGraph.getProcess(opened))
|
||||
remoteOpenerProcess = ProcessGraph.getProcess(remoteOpener)
|
||||
remoteOpenerProcess.merge(ProcessGraph.getProcess(remoteOpened))
|
||||
if openedP not in cls.opens:
|
||||
cls.opens[openedP] = [ ]
|
||||
cls.opens[openedP].append(OpensEdge(opener, openedP))
|
||||
|
||||
|
||||
class BuildProcessGraph(TcheckVisitor):
|
||||
@ -1610,6 +1714,22 @@ class BuildProcessGraph(TcheckVisitor):
|
||||
|
||||
ProcessGraph.bridge(parentSideActor, childSideActor, bridgeProto)
|
||||
|
||||
def visitOpensStmt(self, opens):
|
||||
openedP = opens.proto.type
|
||||
opener = Actor(self.visiting, opens.side)
|
||||
opened = Actor(openedP, opens.side)
|
||||
|
||||
# The picture here is:
|
||||
# [ opener | opened ] (process 1)
|
||||
# | |
|
||||
# | |
|
||||
# [ remoteOpener | remoteOpened ] (process 2)
|
||||
#
|
||||
# An opens stmt tells us that the pairs |opener|/|opened|
|
||||
# and |remoteOpener|/|remoteOpened| are each in the same
|
||||
# process.
|
||||
ProcessGraph.open(opener, opened, openedP)
|
||||
|
||||
|
||||
class CheckProcessGraph(TcheckVisitor):
|
||||
def __init__(self, errors):
|
||||
@ -1625,8 +1745,13 @@ class CheckProcessGraph(TcheckVisitor):
|
||||
for edge in process.iteredges():
|
||||
print ' ', edge
|
||||
print 'Bridges'
|
||||
for bridge in ProcessGraph.bridges.itervalues():
|
||||
print ' ', bridge
|
||||
for bridgeList in ProcessGraph.bridges.itervalues():
|
||||
for bridge in bridgeList:
|
||||
print ' ', bridge
|
||||
print 'Opens'
|
||||
for opensList in ProcessGraph.opens.itervalues():
|
||||
for opens in opensList:
|
||||
print ' ', opens
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -59,6 +59,7 @@ EXPORT_LIBRARY = 1
|
||||
|
||||
IPDLTESTS = \
|
||||
TestBlockChild \
|
||||
TestBridgeMain \
|
||||
TestCrashCleanup \
|
||||
TestDataStructures \
|
||||
TestDesc \
|
||||
@ -69,6 +70,7 @@ IPDLTESTS = \
|
||||
TestManyChildAllocs \
|
||||
TestMultiMgrs \
|
||||
TestNestedLoops \
|
||||
TestOpens \
|
||||
TestRPCErrorCleanup \
|
||||
TestRPCRaces \
|
||||
TestRPCShutdownRace \
|
||||
@ -89,6 +91,10 @@ ifeq ($(OS_ARCH),Linux)
|
||||
IPDLTESTS += TestSysVShmem
|
||||
endif
|
||||
|
||||
EXTRA_PROTOCOLS = \
|
||||
TestBridgeSub \
|
||||
$(NULL)
|
||||
|
||||
IPDLTESTSRCS = $(addsuffix .cpp,$(IPDLTESTS))
|
||||
IPDLTESTHDRS = $(addprefix $(srcdir)/,$(addsuffix .h,$(IPDLTESTS)))
|
||||
|
||||
@ -110,7 +116,7 @@ include $(topsrcdir)/config/rules.mk
|
||||
IPDLUNITTEST_BIN = $(DEPTH)/dist/bin/ipdlunittest$(BIN_SUFFIX)
|
||||
|
||||
IPDLUnitTests.cpp : Makefile.in $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTHDRS)
|
||||
$(PYTHON) $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTS) > $@
|
||||
$(PYTHON) $(GENTESTER) $(TESTER_TEMPLATE) -t $(IPDLTESTS) -e $(EXTRA_PROTOCOLS) > $@
|
||||
|
||||
check::
|
||||
@$(EXIT_ON_ERROR) \
|
||||
|
24
ipc/ipdl/test/cxx/PTestBridgeMain.ipdl
Normal file
24
ipc/ipdl/test/cxx/PTestBridgeMain.ipdl
Normal file
@ -0,0 +1,24 @@
|
||||
include protocol PTestBridgeSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestBridgeMain {
|
||||
child spawns PTestBridgeSub;
|
||||
|
||||
child:
|
||||
Start();
|
||||
|
||||
parent:
|
||||
__delete__();
|
||||
|
||||
state START:
|
||||
send Start goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
33
ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl
Normal file
33
ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl
Normal file
@ -0,0 +1,33 @@
|
||||
include protocol PTestBridgeMain;
|
||||
include protocol PTestBridgeSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
// (Bridge protocols can have different semantics than the endpoints
|
||||
// they bridge)
|
||||
rpc protocol PTestBridgeMainSub {
|
||||
bridges PTestBridgeMain, PTestBridgeSub;
|
||||
|
||||
child:
|
||||
Hi();
|
||||
rpc HiRpc();
|
||||
|
||||
parent:
|
||||
Hello();
|
||||
sync HelloSync();
|
||||
rpc HelloRpc();
|
||||
__delete__();
|
||||
|
||||
state START: recv Hello goto HI;
|
||||
state HI: send Hi goto HELLO_SYNC;
|
||||
state HELLO_SYNC: recv HelloSync goto HELLO_RPC;
|
||||
state HELLO_RPC: answer HelloRpc goto HI_RPC;
|
||||
state HI_RPC: call HiRpc goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
24
ipc/ipdl/test/cxx/PTestBridgeSub.ipdl
Normal file
24
ipc/ipdl/test/cxx/PTestBridgeSub.ipdl
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestBridgeSub {
|
||||
child:
|
||||
Ping();
|
||||
|
||||
parent:
|
||||
BridgeEm();
|
||||
__delete__();
|
||||
|
||||
state START:
|
||||
send Ping goto BRIDGEEM;
|
||||
state BRIDGEEM:
|
||||
recv BridgeEm goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
25
ipc/ipdl/test/cxx/PTestOpens.ipdl
Normal file
25
ipc/ipdl/test/cxx/PTestOpens.ipdl
Normal file
@ -0,0 +1,25 @@
|
||||
include protocol PTestOpensOpened;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestOpens {
|
||||
// This channel is opened and parked on a non-main thread
|
||||
child opens PTestOpensOpened;
|
||||
|
||||
child:
|
||||
Start();
|
||||
|
||||
parent:
|
||||
__delete__();
|
||||
|
||||
state START:
|
||||
send Start goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
28
ipc/ipdl/test/cxx/PTestOpensOpened.ipdl
Normal file
28
ipc/ipdl/test/cxx/PTestOpensOpened.ipdl
Normal file
@ -0,0 +1,28 @@
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
// (Opens protocols can have different semantics than the endpoints
|
||||
// that opened them)
|
||||
rpc protocol PTestOpensOpened {
|
||||
child:
|
||||
Hi();
|
||||
rpc HiRpc();
|
||||
|
||||
parent:
|
||||
Hello();
|
||||
sync HelloSync();
|
||||
rpc HelloRpc();
|
||||
__delete__();
|
||||
|
||||
state START: recv Hello goto HI;
|
||||
state HI: send Hi goto HELLO_SYNC;
|
||||
state HELLO_SYNC: recv HelloSync goto HELLO_RPC;
|
||||
state HELLO_RPC: answer HelloRpc goto HI_RPC;
|
||||
state HI_RPC: call HiRpc goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
252
ipc/ipdl/test/cxx/TestBridgeMain.cpp
Normal file
252
ipc/ipdl/test/cxx/TestBridgeMain.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
#include "TestBridgeMain.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
#include "IPDLUnitTestSubprocess.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
template<>
|
||||
struct RunnableMethodTraits<mozilla::_ipdltest::TestBridgeMainSubChild>
|
||||
{
|
||||
static void RetainCallee(mozilla::_ipdltest::TestBridgeMainSubChild* obj) { }
|
||||
static void ReleaseCallee(mozilla::_ipdltest::TestBridgeMainSubChild* obj) { }
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// main process
|
||||
void
|
||||
TestBridgeMainParent::Main()
|
||||
{
|
||||
if (!SendStart())
|
||||
fail("sending Start");
|
||||
}
|
||||
|
||||
PTestBridgeMainSubParent*
|
||||
TestBridgeMainParent::AllocPTestBridgeMainSub(Transport* transport,
|
||||
ProcessId otherProcess)
|
||||
{
|
||||
ProcessHandle h;
|
||||
if (!base::OpenProcessHandle(otherProcess, &h)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsAutoPtr<TestBridgeMainSubParent> a(new TestBridgeMainSubParent(transport));
|
||||
if (!a->Open(transport, h, XRE_GetIOMessageLoop(), AsyncChannel::Parent)) {
|
||||
return nsnull;
|
||||
}
|
||||
return a.forget();
|
||||
}
|
||||
|
||||
void
|
||||
TestBridgeMainParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeMainSubParent::RecvHello()
|
||||
{
|
||||
return SendHi();
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeMainSubParent::RecvHelloSync()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeMainSubParent::AnswerHelloRpc()
|
||||
{
|
||||
return CallHiRpc();
|
||||
}
|
||||
|
||||
void
|
||||
TestBridgeMainSubParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
|
||||
// ActorDestroy() is just a callback from IPDL-generated code,
|
||||
// which needs the top-level actor (this) to stay alive a little
|
||||
// longer so other things can be cleaned up.
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<TestBridgeMainSubParent>(this));
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<Transport>(mTransport));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// sub process --- child of main
|
||||
TestBridgeMainChild* gBridgeMainChild;
|
||||
|
||||
TestBridgeMainChild::TestBridgeMainChild()
|
||||
: mSubprocess(nsnull)
|
||||
{
|
||||
gBridgeMainChild = this;
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeMainChild::RecvStart()
|
||||
{
|
||||
vector<string> subsubArgs;
|
||||
subsubArgs.push_back("TestBridgeSub");
|
||||
|
||||
mSubprocess = new IPDLUnitTestSubprocess();
|
||||
if (!mSubprocess->SyncLaunch(subsubArgs))
|
||||
fail("problem launching subprocess");
|
||||
|
||||
IPC::Channel* transport = mSubprocess->GetChannel();
|
||||
if (!transport)
|
||||
fail("no transport");
|
||||
|
||||
TestBridgeSubParent* bsp = new TestBridgeSubParent();
|
||||
bsp->Open(transport, mSubprocess->GetChildProcessHandle());
|
||||
|
||||
bsp->Main();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestBridgeMainChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
// NB: this is kosher because QuitChild() joins with the IO thread
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<IPDLUnitTestSubprocess>(mSubprocess));
|
||||
QuitChild();
|
||||
}
|
||||
|
||||
void
|
||||
TestBridgeSubParent::Main()
|
||||
{
|
||||
if (!SendPing())
|
||||
fail("sending Ping");
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeSubParent::RecvBridgeEm()
|
||||
{
|
||||
if (!PTestBridgeMainSub::Bridge(gBridgeMainChild, this))
|
||||
fail("bridging Main and Sub");
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestBridgeSubParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
gBridgeMainChild->Close();
|
||||
|
||||
// ActorDestroy() is just a callback from IPDL-generated code,
|
||||
// which needs the top-level actor (this) to stay alive a little
|
||||
// longer so other things can be cleaned up.
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<TestBridgeSubParent>(this));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// subsub process --- child of sub
|
||||
|
||||
static TestBridgeSubChild* gBridgeSubChild;
|
||||
|
||||
TestBridgeSubChild::TestBridgeSubChild()
|
||||
{
|
||||
gBridgeSubChild = this;
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeSubChild::RecvPing()
|
||||
{
|
||||
if (!SendBridgeEm())
|
||||
fail("sending BridgeEm");
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestBridgeMainSubChild*
|
||||
TestBridgeSubChild::AllocPTestBridgeMainSub(Transport* transport,
|
||||
ProcessId otherProcess)
|
||||
{
|
||||
ProcessHandle h;
|
||||
if (!base::OpenProcessHandle(otherProcess, &h)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsAutoPtr<TestBridgeMainSubChild> a(new TestBridgeMainSubChild(transport));
|
||||
if (!a->Open(transport, h, XRE_GetIOMessageLoop(), AsyncChannel::Child)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!a->SendHello())
|
||||
fail("sending Hello");
|
||||
|
||||
return a.forget();
|
||||
}
|
||||
|
||||
void
|
||||
TestBridgeSubChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeMainSubChild::RecvHi()
|
||||
{
|
||||
if (!SendHelloSync())
|
||||
fail("sending HelloSync");
|
||||
if (!CallHelloRpc())
|
||||
fail("calling HelloRpc");
|
||||
if (!mGotHi)
|
||||
fail("didn't answer HiRpc");
|
||||
|
||||
// Need to close the channel without message-processing frames on
|
||||
// the C++ stack
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this, &TestBridgeMainSubChild::Close));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestBridgeMainSubChild::AnswerHiRpc()
|
||||
{
|
||||
mGotHi = true; // d00d
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestBridgeMainSubChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
|
||||
gBridgeSubChild->Close();
|
||||
|
||||
// ActorDestroy() is just a callback from IPDL-generated code,
|
||||
// which needs the top-level actor (this) to stay alive a little
|
||||
// longer so other things can be cleaned up.
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<TestBridgeMainSubChild>(this));
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<Transport>(mTransport));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
152
ipc/ipdl/test/cxx/TestBridgeMain.h
Normal file
152
ipc/ipdl/test/cxx/TestBridgeMain.h
Normal file
@ -0,0 +1,152 @@
|
||||
#ifndef mozilla__ipdltest_TestBridgeMain_h
|
||||
#define mozilla__ipdltest_TestBridgeMain_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestBridgeMainParent.h"
|
||||
#include "mozilla/_ipdltest/PTestBridgeMainChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestBridgeSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestBridgeSubChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestBridgeMainSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestBridgeMainSubChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Main" process
|
||||
//
|
||||
class TestBridgeMainParent :
|
||||
public PTestBridgeMainParent
|
||||
{
|
||||
public:
|
||||
TestBridgeMainParent() {}
|
||||
virtual ~TestBridgeMainParent() {}
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual PTestBridgeMainSubParent*
|
||||
AllocPTestBridgeMainSub(Transport* transport,
|
||||
ProcessId otherProcess);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
class TestBridgeMainSubParent :
|
||||
public PTestBridgeMainSubParent
|
||||
{
|
||||
public:
|
||||
TestBridgeMainSubParent(Transport* aTransport)
|
||||
: mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestBridgeMainSubParent() {}
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvHello();
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvHelloSync();
|
||||
NS_OVERRIDE
|
||||
virtual bool AnswerHelloRpc();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
Transport* mTransport;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Sub" process --- child of "main"
|
||||
//
|
||||
class TestBridgeSubParent;
|
||||
|
||||
class TestBridgeMainChild :
|
||||
public PTestBridgeMainChild
|
||||
{
|
||||
public:
|
||||
TestBridgeMainChild();
|
||||
virtual ~TestBridgeMainChild() {}
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvStart();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
IPDLUnitTestSubprocess* mSubprocess;
|
||||
};
|
||||
|
||||
class TestBridgeSubParent :
|
||||
public PTestBridgeSubParent
|
||||
{
|
||||
public:
|
||||
TestBridgeSubParent() {}
|
||||
virtual ~TestBridgeSubParent() {}
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvBridgeEm();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Subsub" process --- child of "sub"
|
||||
//
|
||||
class TestBridgeSubChild :
|
||||
public PTestBridgeSubChild
|
||||
{
|
||||
public:
|
||||
TestBridgeSubChild();
|
||||
virtual ~TestBridgeSubChild() {}
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvPing();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual PTestBridgeMainSubChild*
|
||||
AllocPTestBridgeMainSub(Transport* transport,
|
||||
ProcessId otherProcess);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
class TestBridgeMainSubChild :
|
||||
public PTestBridgeMainSubChild
|
||||
{
|
||||
public:
|
||||
TestBridgeMainSubChild(Transport* aTransport)
|
||||
: mGotHi(false)
|
||||
, mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestBridgeMainSubChild() {}
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvHi();
|
||||
NS_OVERRIDE
|
||||
virtual bool AnswerHiRpc();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
bool mGotHi;
|
||||
Transport* mTransport;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestBridgeMain_h
|
266
ipc/ipdl/test/cxx/TestOpens.cpp
Normal file
266
ipc/ipdl/test/cxx/TestOpens.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
#include "base/thread.h"
|
||||
|
||||
#include "TestOpens.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
template<>
|
||||
struct RunnableMethodTraits<mozilla::_ipdltest::TestOpensChild>
|
||||
{
|
||||
static void RetainCallee(mozilla::_ipdltest::TestOpensChild* obj) { }
|
||||
static void ReleaseCallee(mozilla::_ipdltest::TestOpensChild* obj) { }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct RunnableMethodTraits<mozilla::_ipdltest::TestOpensOpenedChild>
|
||||
{
|
||||
static void RetainCallee(mozilla::_ipdltest::TestOpensOpenedChild* obj) { }
|
||||
static void ReleaseCallee(mozilla::_ipdltest::TestOpensOpenedChild* obj) { }
|
||||
};
|
||||
|
||||
using namespace base;
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
static MessageLoop* gMainThread;
|
||||
|
||||
static void
|
||||
AssertNotMainThread()
|
||||
{
|
||||
if (!gMainThread)
|
||||
fail("gMainThread is not initialized");
|
||||
if (MessageLoop::current() == gMainThread)
|
||||
fail("unexpectedly called on the main thread");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
// Thread on which TestOpensOpenedParent runs
|
||||
static Thread* gParentThread;
|
||||
|
||||
void
|
||||
TestOpensParent::Main()
|
||||
{
|
||||
if (!SendStart())
|
||||
fail("sending Start");
|
||||
}
|
||||
|
||||
static void
|
||||
OpenParent(TestOpensOpenedParent* aParent,
|
||||
Transport* aTransport, ProcessHandle aOtherProcess)
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
// Open the actor on the off-main thread to park it there.
|
||||
// Messages will be delivered to this thread's message loop
|
||||
// instead of the main thread's.
|
||||
if (!aParent->Open(aTransport, aOtherProcess,
|
||||
XRE_GetIOMessageLoop(), AsyncChannel::Parent))
|
||||
fail("opening Parent");
|
||||
}
|
||||
|
||||
PTestOpensOpenedParent*
|
||||
TestOpensParent::AllocPTestOpensOpened(Transport* transport,
|
||||
ProcessId otherProcess)
|
||||
{
|
||||
gMainThread = MessageLoop::current();
|
||||
|
||||
ProcessHandle h;
|
||||
if (!base::OpenProcessHandle(otherProcess, &h)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
gParentThread = new Thread("ParentThread");
|
||||
if (!gParentThread->Start())
|
||||
fail("starting parent thread");
|
||||
|
||||
TestOpensOpenedParent* a = new TestOpensOpenedParent(transport);
|
||||
gParentThread->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(OpenParent, a, transport, h));
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
TestOpensParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
// Stops the thread and joins it
|
||||
delete gParentThread;
|
||||
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestOpensOpenedParent::RecvHello()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
return SendHi();
|
||||
}
|
||||
|
||||
bool
|
||||
TestOpensOpenedParent::RecvHelloSync()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestOpensOpenedParent::AnswerHelloRpc()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
return CallHiRpc();
|
||||
}
|
||||
|
||||
void
|
||||
TestOpensOpenedParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
|
||||
// ActorDestroy() is just a callback from IPDL-generated code,
|
||||
// which needs the top-level actor (this) to stay alive a little
|
||||
// longer so other things can be cleaned up.
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<TestOpensOpenedParent>(this));
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<Transport>(mTransport));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
static TestOpensChild* gOpensChild;
|
||||
// Thread on which TestOpensOpenedChild runs
|
||||
static Thread* gChildThread;
|
||||
|
||||
TestOpensChild::TestOpensChild()
|
||||
{
|
||||
gOpensChild = this;
|
||||
}
|
||||
|
||||
bool
|
||||
TestOpensChild::RecvStart()
|
||||
{
|
||||
if (!PTestOpensOpened::Open(this))
|
||||
fail("opening PTestOpensOpened");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
OpenChild(TestOpensOpenedChild* aChild,
|
||||
Transport* aTransport, ProcessHandle aOtherProcess)
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
// Open the actor on the off-main thread to park it there.
|
||||
// Messages will be delivered to this thread's message loop
|
||||
// instead of the main thread's.
|
||||
if (!aChild->Open(aTransport, aOtherProcess,
|
||||
XRE_GetIOMessageLoop(), AsyncChannel::Child))
|
||||
fail("opening Child");
|
||||
|
||||
// Kick off the unit tests
|
||||
if (!aChild->SendHello())
|
||||
fail("sending Hello");
|
||||
}
|
||||
|
||||
PTestOpensOpenedChild*
|
||||
TestOpensChild::AllocPTestOpensOpened(Transport* transport,
|
||||
ProcessId otherProcess)
|
||||
{
|
||||
gMainThread = MessageLoop::current();
|
||||
|
||||
ProcessHandle h;
|
||||
if (!base::OpenProcessHandle(otherProcess, &h)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
gChildThread = new Thread("ChildThread");
|
||||
if (!gChildThread->Start())
|
||||
fail("starting child thread");
|
||||
|
||||
TestOpensOpenedChild* a = new TestOpensOpenedChild(transport);
|
||||
gChildThread->message_loop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(OpenChild, a, transport, h));
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
TestOpensChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
// Stops the thread and joins it
|
||||
delete gChildThread;
|
||||
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestOpensOpenedChild::RecvHi()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
if (!SendHelloSync())
|
||||
fail("sending HelloSync");
|
||||
if (!CallHelloRpc())
|
||||
fail("calling HelloRpc");
|
||||
if (!mGotHi)
|
||||
fail("didn't answer HiRpc");
|
||||
|
||||
// Need to close the channel without message-processing frames on
|
||||
// the C++ stack
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this, &TestOpensOpenedChild::Close));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestOpensOpenedChild::AnswerHiRpc()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
mGotHi = true; // d00d
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestOpensOpenedChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
|
||||
// ActorDestroy() is just a callback from IPDL-generated code,
|
||||
// which needs the top-level actor (this) to stay alive a little
|
||||
// longer so other things can be cleaned up.
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<TestOpensOpenedChild>(this));
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
new DeleteTask<Transport>(mTransport));
|
||||
|
||||
// Kick off main-thread shutdown.
|
||||
gMainThread->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(gOpensChild, &TestOpensChild::Close));
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
104
ipc/ipdl/test/cxx/TestOpens.h
Normal file
104
ipc/ipdl/test/cxx/TestOpens.h
Normal file
@ -0,0 +1,104 @@
|
||||
#ifndef mozilla__ipdltest_TestOpens_h
|
||||
#define mozilla__ipdltest_TestOpens_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestOpensParent.h"
|
||||
#include "mozilla/_ipdltest/PTestOpensChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestOpensOpenedParent.h"
|
||||
#include "mozilla/_ipdltest/PTestOpensOpenedChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
// parent process
|
||||
|
||||
class TestOpensParent : public PTestOpensParent
|
||||
{
|
||||
public:
|
||||
TestOpensParent() {}
|
||||
virtual ~TestOpensParent() {}
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual PTestOpensOpenedParent*
|
||||
AllocPTestOpensOpened(Transport* transport, ProcessId otherProcess);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
class TestOpensOpenedParent : public PTestOpensOpenedParent
|
||||
{
|
||||
public:
|
||||
TestOpensOpenedParent(Transport* aTransport)
|
||||
: mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestOpensOpenedParent() {}
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvHello();
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvHelloSync();
|
||||
NS_OVERRIDE
|
||||
virtual bool AnswerHelloRpc();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
Transport* mTransport;
|
||||
};
|
||||
|
||||
|
||||
// child process
|
||||
|
||||
class TestOpensChild : public PTestOpensChild
|
||||
{
|
||||
public:
|
||||
TestOpensChild();
|
||||
virtual ~TestOpensChild() {}
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvStart();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual PTestOpensOpenedChild*
|
||||
AllocPTestOpensOpened(Transport* transport, ProcessId otherProcess);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
class TestOpensOpenedChild : public PTestOpensOpenedChild
|
||||
{
|
||||
public:
|
||||
TestOpensOpenedChild(Transport* aTransport)
|
||||
: mGotHi(false)
|
||||
, mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestOpensOpenedChild() {}
|
||||
|
||||
protected:
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvHi();
|
||||
NS_OVERRIDE
|
||||
virtual bool AnswerHiRpc();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
bool mGotHi;
|
||||
Transport* mTransport;
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestOpens_h
|
@ -37,30 +37,50 @@
|
||||
|
||||
import string, sys
|
||||
|
||||
def usage():
|
||||
print >>sys.stderr, """
|
||||
%s template_file -t unit_tests... -e extra_protocols...
|
||||
|
||||
TEMPLATE_FILE is used to generate to generate the unit-tester .cpp
|
||||
UNIT_TESTS are the top-level protocols defining unit tests
|
||||
EXTRA_PROTOCOLS are top-level protocols for subprocesses that can be
|
||||
spawned in tests but are not unit tests in and of
|
||||
themselves
|
||||
"""% (sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
def main(argv):
|
||||
template = argv[1]
|
||||
unittests = argv[2:]
|
||||
|
||||
if argv[2] != '-t': usage()
|
||||
i = 3
|
||||
unittests = []
|
||||
while argv[i] != '-e':
|
||||
unittests.append(argv[i])
|
||||
i += 1
|
||||
|
||||
extras = argv[(i+1):]
|
||||
|
||||
includes = '\n'.join([
|
||||
'#include "%s.h"'% (t) for t in unittests ])
|
||||
|
||||
|
||||
enum_values = '\n'.join([
|
||||
' %s,'% (t) for t in unittests ])
|
||||
' %s,'% (t) for t in unittests+extras ])
|
||||
last_enum = unittests[-1]
|
||||
|
||||
|
||||
string_to_enums = '\n'.join([
|
||||
''' else if (!strcmp(aString, "%s"))
|
||||
return %s;'''% (t, t) for t in unittests ])
|
||||
return %s;'''% (t, t) for t in unittests+extras ])
|
||||
|
||||
enum_to_strings = '\n'.join([
|
||||
''' case %s:
|
||||
return "%s";'''%(t, t) for t in unittests ])
|
||||
return "%s";'''%(t, t) for t in unittests+extras ])
|
||||
|
||||
parent_delete_cases = '\n'.join([
|
||||
''' case %s: {
|
||||
delete reinterpret_cast<mozilla::_ipdltest::%sParent*>(gParentActor);
|
||||
delete reinterpret_cast<%sParent*>(gParentActor);
|
||||
return;
|
||||
}
|
||||
'''% (t, t) for t in unittests ])
|
||||
@ -77,10 +97,10 @@ def main(argv):
|
||||
|
||||
child_delete_cases = '\n'.join([
|
||||
''' case %s: {
|
||||
delete reinterpret_cast<mozilla::_ipdltest::%sChild*>(gChildActor);
|
||||
delete reinterpret_cast<%sChild*>(gChildActor);
|
||||
return;
|
||||
}
|
||||
'''% (t, t) for t in unittests ])
|
||||
'''% (t, t) for t in unittests+extras ])
|
||||
|
||||
|
||||
child_init_cases = '\n'.join([
|
||||
@ -91,7 +111,7 @@ def main(argv):
|
||||
(*child)->Open(transport, parent, worker);
|
||||
return;
|
||||
}
|
||||
'''% (t, t, t, t) for t in unittests ])
|
||||
'''% (t, t, t, t) for t in unittests+extras ])
|
||||
|
||||
templatefile = open(template, 'r')
|
||||
sys.stdout.write(
|
||||
|
@ -1,5 +1,8 @@
|
||||
IPDLSRCS = \
|
||||
PTestBlockChild.ipdl \
|
||||
PTestBridgeMain.ipdl \
|
||||
PTestBridgeSub.ipdl \
|
||||
PTestBridgeMainSub.ipdl \
|
||||
PTestCrashCleanup.ipdl \
|
||||
PTestDataStructures.ipdl \
|
||||
PTestDataStructuresSub.ipdl \
|
||||
@ -20,6 +23,8 @@ IPDLSRCS = \
|
||||
PTestMultiMgrsRight.ipdl \
|
||||
PTestMultiMgrsBottom.ipdl \
|
||||
PTestNestedLoops.ipdl \
|
||||
PTestOpens.ipdl \
|
||||
PTestOpensOpened.ipdl \
|
||||
PTestRaceDeferral.ipdl \
|
||||
PTestRacyReentry.ipdl \
|
||||
PTestRacyRPCReplies.ipdl \
|
||||
|
6
ipc/ipdl/test/ipdl/error/opensNonexistent.ipdl
Normal file
6
ipc/ipdl/test/ipdl/error/opensNonexistent.ipdl
Normal file
@ -0,0 +1,6 @@
|
||||
protocol opensNonexistent {
|
||||
parent opens Unicorn;
|
||||
|
||||
child: __delete__();
|
||||
state DEAD: send __delete__;
|
||||
};
|
13
ipc/ipdl/test/ipdl/error/opensSubprotocol.ipdl
Normal file
13
ipc/ipdl/test/ipdl/error/opensSubprotocol.ipdl
Normal file
@ -0,0 +1,13 @@
|
||||
include protocol subprotocolOpens;
|
||||
|
||||
protocol opensSubprotocol {
|
||||
child opens subprotocolOpens;
|
||||
|
||||
manages subprotocolOpens;
|
||||
|
||||
child:
|
||||
subprotocolOpens();
|
||||
__delete__();
|
||||
|
||||
state DEAD: send __delete__;
|
||||
};
|
10
ipc/ipdl/test/ipdl/error/subprotocolOpens.ipdl
Normal file
10
ipc/ipdl/test/ipdl/error/subprotocolOpens.ipdl
Normal file
@ -0,0 +1,10 @@
|
||||
include protocol opensSubprotocol;
|
||||
|
||||
protocol subprotocolOpens {
|
||||
parent opens opensSubprotocol;
|
||||
|
||||
manager opensSubprotocol;
|
||||
|
||||
child: __delete__();
|
||||
state DEAD: send __delete__;
|
||||
};
|
@ -1,11 +1,13 @@
|
||||
include protocol compositor;
|
||||
include protocol jetpack;
|
||||
include protocol media;
|
||||
include protocol plugin;
|
||||
|
||||
sync protocol content {
|
||||
parent spawns compositor as parent;
|
||||
parent spawns jetpack;
|
||||
child spawns plugin;
|
||||
child opens media;
|
||||
|
||||
child:
|
||||
__delete__();
|
||||
|
7
ipc/ipdl/test/ipdl/ok/media.ipdl
Normal file
7
ipc/ipdl/test/ipdl/ok/media.ipdl
Normal file
@ -0,0 +1,7 @@
|
||||
sync protocol media {
|
||||
child:
|
||||
__delete__();
|
||||
|
||||
state DEAD:
|
||||
send __delete__;
|
||||
};
|
@ -282,14 +282,14 @@ HTTP(../..) == inline--position-relative--01.xhtml inline--position-relative-
|
||||
# tests do not have any width or height on the <object> element so they should
|
||||
# be sized purely by the embedded SVG's intrinsic size.
|
||||
|
||||
== object--auto-auto--0-0.html pass-empty.svg # XXX add border
|
||||
== object--auto-auto--0-pct.html object--auto-auto--0-pct--ref.html
|
||||
== object--auto-auto--0-px.html object--auto-auto--0-px--ref.html
|
||||
== object--auto-auto--pct-0.html object--auto-auto--pct-0--ref.html
|
||||
random-if(Android) == object--auto-auto--0-0.html pass-empty.svg # XXX add border
|
||||
random-if(Android) == object--auto-auto--0-pct.html object--auto-auto--0-pct--ref.html
|
||||
random-if(Android) == object--auto-auto--0-px.html object--auto-auto--0-px--ref.html
|
||||
random-if(Android) == object--auto-auto--pct-0.html object--auto-auto--pct-0--ref.html
|
||||
# The following four commented out tests fail post bug 428023:
|
||||
#== object--auto-auto--pct-pct.html object--auto-auto--pct-pct--ref.html
|
||||
#== object--auto-auto--pct-px.html object--auto-auto--pct-px--ref.html
|
||||
== object--auto-auto--px-0.html object--auto-auto--px-0--ref.html
|
||||
random-if(Android) == object--auto-auto--px-0.html object--auto-auto--px-0--ref.html
|
||||
#== object--auto-auto--px-pct.html object--auto-auto--px-pct--ref.html
|
||||
random-if(Android) == object--auto-auto--px-px.html object--auto-auto--px-px--ref.html
|
||||
#== object--pct-pct--0-0.html pass.svg
|
||||
|
@ -42,8 +42,9 @@
|
||||
interface nsIDOMElement;
|
||||
interface nsIDOMNode;
|
||||
interface nsIDOMEvent;
|
||||
interface nsIDOMClientRect;
|
||||
|
||||
[scriptable, uuid(548a9e3f-af78-42b0-a260-035ece15c19f)]
|
||||
[scriptable, uuid(6AD1B199-95D3-448B-98D7-896BCE3A1DCD)]
|
||||
interface nsIPopupBoxObject : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -183,6 +184,12 @@ interface nsIPopupBoxObject : nsISupports
|
||||
* menu, the parent menu.
|
||||
*/
|
||||
readonly attribute nsIDOMElement anchorNode;
|
||||
|
||||
/*
|
||||
* Retrieve the screen rectangle of the popup, including the area occupied by
|
||||
* any titlebar or borders present.
|
||||
*/
|
||||
nsIDOMClientRect getOuterScreenRect();
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsMenuPopupFrame.h"
|
||||
#include "nsClientRect.h"
|
||||
|
||||
class nsPopupBoxObject : public nsBoxObject,
|
||||
public nsIPopupBoxObject
|
||||
@ -290,6 +291,39 @@ nsPopupBoxObject::GetAnchorNode(nsIDOMElement** aAnchor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPopupBoxObject::GetOuterScreenRect(nsIDOMClientRect** aRect)
|
||||
{
|
||||
nsClientRect* rect = new nsClientRect();
|
||||
if (!rect)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aRect = rect);
|
||||
|
||||
nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
|
||||
if (!menuPopupFrame)
|
||||
return NS_OK;
|
||||
|
||||
// Return an empty rectangle if the popup is not open.
|
||||
nsPopupState state = menuPopupFrame->PopupState();
|
||||
if (state != ePopupOpen && state != ePopupOpenAndVisible)
|
||||
return NS_OK;
|
||||
|
||||
nsIView* view = menuPopupFrame->GetView();
|
||||
if (view) {
|
||||
nsIWidget* widget = view->GetWidget();
|
||||
if (widget) {
|
||||
nsIntRect screenRect;
|
||||
widget->GetScreenBounds(screenRect);
|
||||
|
||||
PRInt32 pp = menuPopupFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
rect->SetLayoutRect(screenRect.ToAppUnits(pp));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Creation Routine ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
|
@ -531,9 +531,11 @@ var BrowserUI = {
|
||||
DownloadsView.init();
|
||||
ConsoleView.init();
|
||||
|
||||
// Pre-start the content process
|
||||
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
|
||||
.ensureContentProcess();
|
||||
if (Services.prefs.getBoolPref("browser.tabs.remote")) {
|
||||
// Pre-start the content process
|
||||
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
|
||||
.ensureContentProcess();
|
||||
}
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
// Init the sync system
|
||||
|
@ -23,31 +23,31 @@ documenttab {
|
||||
}
|
||||
|
||||
settings {
|
||||
-moz-binding: url("chrome://browser/content/bindings/setting.xml#settings");
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#settings");
|
||||
}
|
||||
|
||||
setting[type="bool"] {
|
||||
-moz-binding: url("chrome://browser/content/bindings/setting.xml#setting-bool");
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-bool");
|
||||
}
|
||||
|
||||
setting[type="bool"][localized="true"] {
|
||||
-moz-binding: url("chrome://browser/content/bindings/setting.xml#setting-localized-bool");
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-localized-bool");
|
||||
}
|
||||
|
||||
setting[type="boolint"] {
|
||||
-moz-binding: url("chrome://browser/content/bindings/setting.xml#setting-boolint");
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-boolint");
|
||||
}
|
||||
|
||||
setting[type="integer"] {
|
||||
-moz-binding: url("chrome://browser/content/bindings/setting.xml#setting-integer");
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-integer");
|
||||
}
|
||||
|
||||
setting[type="control"] {
|
||||
-moz-binding: url("chrome://browser/content/bindings/setting.xml#setting-control");
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-control");
|
||||
}
|
||||
|
||||
setting[type="string"] {
|
||||
-moz-binding: url("chrome://browser/content/bindings/setting.xml#setting-string");
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/setting.xml#setting-string");
|
||||
}
|
||||
|
||||
#browsers > notificationbox {
|
||||
|
@ -2731,7 +2731,8 @@ Tab.prototype = {
|
||||
|
||||
try {
|
||||
let flags = aParams.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||
browser.loadURIWithFlags(aURI, flags, aParams.referrerURI, aParams.charset, aParams.postData);
|
||||
let postData = aParams.postData ? aParams.postData.value : null;
|
||||
browser.loadURIWithFlags(aURI, flags, aParams.referrerURI, aParams.charset, postData);
|
||||
} catch(e) {
|
||||
dump("Error: " + e + "\n");
|
||||
}
|
||||
|
@ -534,7 +534,7 @@
|
||||
</hbox>
|
||||
<separator class="prompt-line"/>
|
||||
<vbox id="syncsetup-simple" class="syncsetup-page" flex="1">
|
||||
<scrollbox class="prompt-message" orient="vertical" flex="1">
|
||||
<scrollbox id="sync-message" class="prompt-message" orient="vertical" flex="1">
|
||||
<description class="syncsetup-desc syncsetup-center" flex="1">&sync.setup.jpake;</description>
|
||||
<description class="syncsetup-center syncsetup-link" flex="1" onclick="WeaveGlue.openTutorial();">&sync.setup.tutorial;</description>
|
||||
<separator/>
|
||||
|
@ -885,8 +885,11 @@ var FormHelperUI = {
|
||||
|
||||
doAutoComplete: function formHelperDoAutoComplete(aElement) {
|
||||
// Suggestions are only in <label>s. Ignore the rest.
|
||||
if (aElement instanceof Ci.nsIDOMXULLabelElement)
|
||||
this._currentBrowser.messageManager.sendAsyncMessage("FormAssist:AutoComplete", { value: aElement.getAttribute("data") });
|
||||
if (!(aElement instanceof Ci.nsIDOMXULLabelElement))
|
||||
return;
|
||||
|
||||
this._currentBrowser.messageManager.sendAsyncMessage("FormAssist:AutoComplete", { value: aElement.getAttribute("data") });
|
||||
ContentPopupHelper.popup = null;
|
||||
},
|
||||
|
||||
get _open() {
|
||||
|
@ -256,13 +256,13 @@ var ViewConfig = {
|
||||
row.setAttribute("default", aPref.default);
|
||||
|
||||
let label = document.createElement("label");
|
||||
label.setAttribute("class", "preftitle");
|
||||
label.setAttribute("class", "preferences-title");
|
||||
label.setAttribute("value", aPref.name);
|
||||
label.setAttribute("crop", "end");
|
||||
row.appendChild(label);
|
||||
|
||||
label = document.createElement("label");
|
||||
label.setAttribute("class", "prefvalue");
|
||||
label.setAttribute("class", "preferences-value");
|
||||
label.setAttribute("value", aPref.value);
|
||||
label.setAttribute("crop", "end");
|
||||
row.appendChild(label);
|
||||
|
@ -636,8 +636,11 @@ let Content = {
|
||||
}
|
||||
|
||||
if (isTouchClick) {
|
||||
let rect = rects[0];
|
||||
let point = (new Rect(rect.left, rect.top, rect.width, rect.height)).center();
|
||||
let rect = new Rect(rects[0]);
|
||||
if (rect.isEmpty())
|
||||
return;
|
||||
|
||||
let point = rect.center();
|
||||
aX = point.x;
|
||||
aY = point.y;
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ chrome.jar:
|
||||
content/bindings/console.xml (content/bindings/console.xml)
|
||||
content/bindings/dialog.xml (content/bindings/dialog.xml)
|
||||
content/bindings/pageaction.xml (content/bindings/pageaction.xml)
|
||||
content/bindings/setting.xml (content/bindings/setting.xml)
|
||||
content/bindings/arrowbox.xml (content/bindings/arrowbox.xml)
|
||||
content/browser.css (content/browser.css)
|
||||
content/cursor.css (content/cursor.css)
|
||||
|
@ -81,8 +81,10 @@ SessionStore.prototype = {
|
||||
// Get file references
|
||||
this._sessionFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
this._sessionFileBackup = this._sessionFile.clone();
|
||||
this._sessionCache = this._sessionFile.clone();
|
||||
this._sessionFile.append("sessionstore.js");
|
||||
this._sessionFileBackup.append("sessionstore.bak");
|
||||
this._sessionCache.append("sessionstoreCache");
|
||||
|
||||
this._loadState = STATE_STOPPED;
|
||||
|
||||
@ -91,6 +93,7 @@ SessionStore.prototype = {
|
||||
this._shouldRestore = true;
|
||||
this._sessionFileBackup.remove(false);
|
||||
}
|
||||
|
||||
if (this._sessionFile.exists()) {
|
||||
// Disable crash recovery if we have exceeded the timeout
|
||||
this._lastSessionTime = this._sessionFile.lastModifiedTime;
|
||||
@ -101,6 +104,9 @@ SessionStore.prototype = {
|
||||
|
||||
this._sessionFile.copyTo(null, this._sessionFileBackup.leafName);
|
||||
}
|
||||
|
||||
if (!this._sessionCache.exists() || !this._sessionCache.isDirectory())
|
||||
this._sessionCache.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex); // file was write-locked?
|
||||
}
|
||||
@ -130,6 +136,37 @@ SessionStore.prototype = {
|
||||
this._sessionFileBackup.remove(false);
|
||||
} catch (ex) { dump(ex + '\n'); } // couldn't remove the file - what now?
|
||||
}
|
||||
|
||||
this._clearCache();
|
||||
},
|
||||
|
||||
_clearCache: function ss_clearCache() {
|
||||
// First, let's get a list of files we think should be active
|
||||
let activeFiles = [];
|
||||
this._forEachBrowserWindow(function(aWindow) {
|
||||
let tabs = aWindow.Browser.tabs;
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
let browser = tabs[i].browser;
|
||||
if (browser.__SS_extdata && "thumbnail" in browser.__SS_extdata)
|
||||
activeFiles.push(browser.__SS_extdata.thumbnail);
|
||||
}
|
||||
});
|
||||
|
||||
// Now, let's find the stale files in the cache folder
|
||||
let staleFiles = [];
|
||||
let cacheFiles = this._sessionCache.directoryEntries;
|
||||
while (cacheFiles.hasMoreElements()) {
|
||||
let file = cacheFiles.getNext().QueryInterface(Ci.nsILocalFile);
|
||||
let fileURI = Services.io.newFileURI(file);
|
||||
if (activeFiles.indexOf(fileURI) == -1)
|
||||
staleFiles.push(file);
|
||||
}
|
||||
|
||||
// Remove the stale files in a separate step to keep the enumerator from
|
||||
// messing up if we remove the files as we collect them.
|
||||
staleFiles.forEach(function(aFile) {
|
||||
aFile.remove(false);
|
||||
})
|
||||
},
|
||||
|
||||
observe: function ss_observe(aSubject, aTopic, aData) {
|
||||
@ -289,8 +326,10 @@ SessionStore.prototype = {
|
||||
this._lastSaveTime = Date.now();
|
||||
|
||||
// Nothing to restore, notify observers things are complete
|
||||
if (!this._shouldRestore)
|
||||
if (!this._shouldRestore) {
|
||||
this._clearCache();
|
||||
Services.obs.notifyObservers(null, "sessionstore-windows-restored", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Add tab change listeners to all already existing tabs
|
||||
@ -482,8 +521,8 @@ SessionStore.prototype = {
|
||||
|
||||
let tabs = aWindow.Browser.tabs;
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
if (tabs[i].browser.__SS_data) {
|
||||
let browser = tabs[i].browser;
|
||||
let browser = tabs[i].browser;
|
||||
if (browser.__SS_data) {
|
||||
let tabData = browser.__SS_data;
|
||||
if (browser.__SS_extdata)
|
||||
tabData.extData = browser.__SS_extdata;
|
||||
@ -616,6 +655,23 @@ SessionStore.prototype = {
|
||||
|
||||
setTabValue: function ss_setTabValue(aTab, aKey, aStringValue) {
|
||||
let browser = aTab.linkedBrowser;
|
||||
|
||||
// Thumbnails are actually stored in the cache, so do the save and update the URI
|
||||
if (aKey == "thumbnail") {
|
||||
let file = this._sessionCache.clone();
|
||||
file.append("thumbnail-" + browser.contentWindowId);
|
||||
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
|
||||
|
||||
let source = Services.io.newURI(aStringValue, "UTF8", null);
|
||||
let target = Services.io.newFileURI(file)
|
||||
|
||||
let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist);
|
||||
persist.persistFlags = Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES | Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
persist.saveURI(source, null, null, null, null, file);
|
||||
|
||||
aStringValue = target.spec;
|
||||
}
|
||||
|
||||
if (!browser.__SS_extdata)
|
||||
browser.__SS_extdata = {};
|
||||
browser.__SS_extdata[aKey] = aStringValue;
|
||||
@ -636,18 +692,17 @@ SessionStore.prototype = {
|
||||
|
||||
restoreLastSession: function ss_restoreLastSession(aBringToFront) {
|
||||
// The previous session data has already been renamed to the backup file
|
||||
let dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
let session = dirService.get("ProfD", Ci.nsILocalFile);
|
||||
session.append("sessionstore.bak");
|
||||
if (!session.exists())
|
||||
if (!this._sessionFileBackup.exists())
|
||||
return;
|
||||
|
||||
let self = this;
|
||||
function notifyObservers() {
|
||||
self._clearCache();
|
||||
Services.obs.notifyObservers(null, "sessionstore-windows-restored", "");
|
||||
}
|
||||
|
||||
try {
|
||||
let channel = NetUtil.newChannel(session);
|
||||
let channel = NetUtil.newChannel(this._sessionFileBackup);
|
||||
channel.contentType = "application/json";
|
||||
NetUtil.asyncFetch(channel, function(aStream, aResult) {
|
||||
if (!Components.isSuccessCode(aResult)) {
|
||||
|
@ -1216,37 +1216,41 @@ pageaction:not([image]) > hbox >.pageaction-image {
|
||||
border-bottom: @border_width_tiny@ solid #cacdd5;
|
||||
}
|
||||
|
||||
/* XXX should be a richlistitem */
|
||||
.prefbox {
|
||||
setting {
|
||||
padding: @padding_xsmall@;
|
||||
border-bottom: @border_width_tiny@ solid rgb(207,207,207);
|
||||
min-height: @touch_row@; /* row size */
|
||||
-moz-box-align: center;
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
||||
.setting-group > .prefbox {
|
||||
.setting-label {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
.setting-group > setting {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.setting-subgroup > .prefbox {
|
||||
.setting-subgroup > setting {
|
||||
border-bottom: none;
|
||||
-moz-margin-start: @margin_xxxnormal@;
|
||||
}
|
||||
|
||||
.setting-subgroup + :not(.setting-subgroup) > .prefbox {
|
||||
.setting-subgroup + :not(.setting-subgroup) > setting {
|
||||
border-top: @border_width_tiny@ solid rgb(207,207,207);
|
||||
}
|
||||
|
||||
/* Put setting textboxes on a separate row in portrait */
|
||||
@media (@orientation@: portrait) {
|
||||
.setting-integer,
|
||||
.setting-string {
|
||||
setting[type="integer"],
|
||||
setting[type="string"] {
|
||||
-moz-box-align: start;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
.setting-integer > .setting-input > textbox,
|
||||
.setting-string > .setting-input > textbox {
|
||||
setting[type="integer"] > .setting-input > textbox,
|
||||
setting[type="string"] > .setting-input > textbox {
|
||||
width: 499px; /* textboxes seem to need a width in order to flex */
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
@ -1256,17 +1260,17 @@ pageaction:not([image]) > hbox >.pageaction-image {
|
||||
-moz-margin-start: 28px; /* sized based on the 32px addon image */
|
||||
}
|
||||
|
||||
.options-box > setting:last-child > .prefbox {
|
||||
.options-box > setting:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
/* XXX should be a richlistitem description.title */
|
||||
.preftitle {
|
||||
.preferences-title {
|
||||
font-size: @font_normal@ !important;
|
||||
}
|
||||
|
||||
/* XXX should be a richlistitem description.normal */
|
||||
.prefdesc {
|
||||
.preferences-description {
|
||||
font-size: @font_small@ !important;
|
||||
color: grey;
|
||||
}
|
||||
@ -1461,6 +1465,10 @@ pageaction:not([image]) > hbox >.pageaction-image {
|
||||
-moz-margin-start: @margin_xnormal@;
|
||||
}
|
||||
|
||||
#sync-message {
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
/* content scrollbars */
|
||||
.scroller {
|
||||
opacity: 0;
|
||||
|
@ -44,7 +44,7 @@ richlistitem {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
richlistitem .preftitle {
|
||||
richlistitem .preferences-title {
|
||||
pointer-events: none;
|
||||
min-width: 200px;
|
||||
-moz-box-flex: 1;
|
||||
@ -52,7 +52,7 @@ richlistitem .preftitle {
|
||||
}
|
||||
|
||||
/* XXX look + sync */
|
||||
richlistitem[default="false"] .preftitle {
|
||||
richlistitem[default="false"] .preferences-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@ -98,11 +98,11 @@ richlistitem .prefvalue {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#editor[default="false"] .preftitle {
|
||||
#editor[default="false"] .preferences-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#editor-setting .prefbox {
|
||||
#editor-setting setting {
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
|
@ -1195,37 +1195,41 @@ pageaction:not([image]) > hbox >.pageaction-image {
|
||||
border-bottom: @border_width_tiny@ solid #cacdd5;
|
||||
}
|
||||
|
||||
/* XXX should be a richlistitem */
|
||||
.prefbox {
|
||||
setting {
|
||||
padding: @padding_xsmall@;
|
||||
border-bottom: @border_width_tiny@ solid @color_divider_border@;
|
||||
min-height: @touch_row@; /* row size */
|
||||
-moz-box-align: center;
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
|
||||
.setting-group > .prefbox {
|
||||
.setting-label {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
.setting-group > setting {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.setting-subgroup > .prefbox {
|
||||
.setting-subgroup > setting {
|
||||
border-bottom: none;
|
||||
-moz-margin-start: @margin_xxxnormal@;
|
||||
}
|
||||
|
||||
.setting-subgroup + :not(.setting-subgroup) > .prefbox {
|
||||
.setting-subgroup + :not(.setting-subgroup) > setting {
|
||||
border-top: @border_width_tiny@ solid rgb(207,207,207);
|
||||
}
|
||||
|
||||
/* Put setting textboxes on a separate row in portrait */
|
||||
@media (@orientation@: portrait) {
|
||||
.setting-integer,
|
||||
.setting-string {
|
||||
setting[type="integer"],
|
||||
setting[type="string"] {
|
||||
-moz-box-align: start;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
.setting-integer > .setting-input > textbox,
|
||||
.setting-string > .setting-input > textbox {
|
||||
setting[type="integer"] > .setting-input > textbox,
|
||||
setting[type="string"] > .setting-input > textbox {
|
||||
width: 499px; /* textboxes seem to need a width in order to flex */
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
@ -1235,17 +1239,17 @@ pageaction:not([image]) > hbox >.pageaction-image {
|
||||
-moz-margin-start: 28px; /* sized based on the 32px addon image */
|
||||
}
|
||||
|
||||
.options-box > setting:last-child > .prefbox {
|
||||
.options-box > setting:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
/* XXX should be a richlistitem description.title */
|
||||
.preftitle {
|
||||
.preferences-title {
|
||||
font-size: @font_normal@ !important;
|
||||
}
|
||||
|
||||
/* XXX should be a richlistitem description.normal */
|
||||
.prefdesc {
|
||||
.preferences-description {
|
||||
font-size: @font_small@ !important;
|
||||
color: @color_subtext_default@;
|
||||
}
|
||||
|
@ -1824,7 +1824,7 @@ pref("gfx.font_rendering.cleartype_params.rendering_mode", -1);
|
||||
// of gfx.font_rendering.cleartype_params.rendering_mode.
|
||||
// Currently we apply this setting to the sans-serif Microsoft "core Web fonts".
|
||||
pref("gfx.font_rendering.cleartype_params.force_gdi_classic_for_families",
|
||||
"Arial,Courier New,Tahoma,Trebuchet MS,Verdana");
|
||||
"Arial,Courier New,Segoe UI,Tahoma,Trebuchet MS,Verdana");
|
||||
// The maximum size at which we will force GDI classic mode using
|
||||
// force_gdi_classic_for_families.
|
||||
pref("gfx.font_rendering.cleartype_params.force_gdi_classic_max_size", 15);
|
||||
|
@ -102,18 +102,6 @@ static PRLogModuleInfo *webSocketLog = nsnull;
|
||||
// An implementation of draft-ietf-hybi-thewebsocketprotocol-07
|
||||
#define SEC_WEBSOCKET_VERSION "7"
|
||||
|
||||
/*
|
||||
* About using rand() without a srand() or initstate()
|
||||
*
|
||||
* rand() is commonly called throughout the codebase with the assumption
|
||||
* that it has been seeded securely. That does indeed happen in
|
||||
* the initialization of the nsUUIDGenerator sevice - getting secure
|
||||
* seed information from PR_GetRandomNoise() and giving that to
|
||||
* initstate(). We won't repeat that here "just in case" because
|
||||
* it is easy to drain some systems of their true random sources.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* About SSL unsigned certificates
|
||||
*
|
||||
@ -1162,7 +1150,18 @@ nsWebSocketHandler::PrimeNewOutgoingMessage()
|
||||
|
||||
// Perfom the sending mask. never use a zero mask
|
||||
PRUint32 mask;
|
||||
while (!(mask = (PRUint32) rand()));
|
||||
do {
|
||||
PRUint8 *buffer;
|
||||
nsresult rv = mRandomGenerator->GenerateRandomBytes(4, &buffer);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("WebSocketHandler:: PrimeNewOutgoingMessage() "
|
||||
"GenerateRandomBytes failure %x\n", rv));
|
||||
StopSession(rv);
|
||||
return;
|
||||
}
|
||||
mask = * reinterpret_cast<PRUint32 *>(buffer);
|
||||
NS_Free(buffer);
|
||||
} while (!mask);
|
||||
*(((PRUint32 *)payload) - 1) = PR_htonl(mask);
|
||||
|
||||
LOG(("WebSocketHandler:: PrimeNewOutgoingMessage() "
|
||||
@ -1475,13 +1474,13 @@ nsWebSocketHandler::SetupRequest()
|
||||
NS_LITERAL_CSTRING("Sec-WebSocket-Extensions"),
|
||||
NS_LITERAL_CSTRING("deflate-stream"), PR_FALSE);
|
||||
|
||||
PRUint32 secKey[4];
|
||||
PRUint8 *secKey;
|
||||
nsCAutoString secKeyString;
|
||||
secKey[0] = (PRUint32) rand();
|
||||
secKey[1] = (PRUint32) rand();
|
||||
secKey[2] = (PRUint32) rand();
|
||||
secKey[3] = (PRUint32) rand();
|
||||
|
||||
rv = mRandomGenerator->GenerateRandomBytes(16, &secKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
char* b64 = PL_Base64Encode((const char *)secKey, 16, nsnull);
|
||||
NS_Free(secKey);
|
||||
if (!b64) return NS_ERROR_OUT_OF_MEMORY;
|
||||
secKeyString.Assign(b64);
|
||||
PR_Free(b64);
|
||||
@ -1633,7 +1632,7 @@ nsWebSocketHandler::AsyncOnChannelRedirect(
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("nsWebSocketHandler Redirect could not QI to HTTP\n"));
|
||||
callback->OnRedirectVerifyCallback(NS_ERROR_FAILURE);
|
||||
callback->OnRedirectVerifyCallback(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1642,17 +1641,22 @@ nsWebSocketHandler::AsyncOnChannelRedirect(
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("nsWebSocketHandler Redirect could not QI to HTTP Upgrade\n"));
|
||||
callback->OnRedirectVerifyCallback(NS_ERROR_FAILURE);
|
||||
callback->OnRedirectVerifyCallback(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The redirect is OK
|
||||
// The redirect is likely OK
|
||||
|
||||
newChannel->SetNotificationCallbacks(this);
|
||||
mURI = newuri;
|
||||
mHttpChannel = newHttpChannel;
|
||||
mChannel = newUpgradeChannel;
|
||||
SetupRequest();
|
||||
rv = SetupRequest();
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("nsWebSocketHandler Redirect could not SetupRequest()\n"));
|
||||
callback->OnRedirectVerifyCallback(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We cannot just tell the callback OK right now due to the 1 connect at
|
||||
// a time policy. First we need to complete the old location and then
|
||||
@ -1667,7 +1671,7 @@ nsWebSocketHandler::AsyncOnChannelRedirect(
|
||||
rv = ApplyForAdmission();
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("nsWebSocketHandler Redirect failed due to DNS failure\n"));
|
||||
callback->OnRedirectVerifyCallback(NS_ERROR_FAILURE);
|
||||
callback->OnRedirectVerifyCallback(rv);
|
||||
mRedirectCallback = nsnull;
|
||||
}
|
||||
|
||||
@ -1851,6 +1855,13 @@ nsWebSocketHandler::AsyncOpen(nsIURI *aURI,
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRandomGenerator = do_GetService("@mozilla.org/security/random-generator;1",
|
||||
&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("unable to continue without random number generator");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefService;
|
||||
prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsIStringStream.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIRandomGenerator.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
@ -196,6 +197,7 @@ private:
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsICancelable> mDNSRequest;
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
nsCOMPtr<nsIRandomGenerator> mRandomGenerator;
|
||||
|
||||
nsCString mProtocol;
|
||||
nsCString mOrigin;
|
||||
|
43
netwerk/test/unit/test_double_content_length.js
Normal file
43
netwerk/test/unit/test_double_content_length.js
Normal file
@ -0,0 +1,43 @@
|
||||
do_load_httpd_js();
|
||||
|
||||
var httpserver = new nsHttpServer();
|
||||
var index = 0;
|
||||
|
||||
function setupChannel(url)
|
||||
{
|
||||
var ios = Components.classes["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
var chan = ios.newChannel("http://localhost:4444" + url, "", null);
|
||||
var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel);
|
||||
return httpChan;
|
||||
}
|
||||
|
||||
function completeTest1(request, data, ctx)
|
||||
{
|
||||
httpserver.stop(do_test_finished);
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
httpserver.registerPathHandler("/2xcl", handler);
|
||||
httpserver.start(4444);
|
||||
|
||||
var channel = setupChannel("/2xcl");
|
||||
channel.asyncOpen(new ChannelListener(completeTest1,
|
||||
channel, CL_EXPECT_FAILURE), null);
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function handler(metadata, response)
|
||||
{
|
||||
var body = "012345678901234567890123456789";
|
||||
response.seizePower();
|
||||
response.write("HTTP/1.0 200 OK\r\n");
|
||||
response.write("Content-Type: text/plain\r\n");
|
||||
response.write("Content-Length: 20\r\n");
|
||||
response.write("Content-Length: 30\r\n");
|
||||
response.write("\r\n");
|
||||
response.write(body);
|
||||
response.finish();
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ tail =
|
||||
[test_cookie_header.js]
|
||||
[test_data_protocol.js]
|
||||
[test_dns_service.js]
|
||||
[test_double_content_length.js]
|
||||
[test_event_sink.js]
|
||||
[test_extract_charset_from_content_type.js]
|
||||
[test_fallback_no-cache-entry_canceled.js]
|
||||
|
@ -35,93 +35,92 @@
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = toolkit/components/passwordmgr/test
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = toolkit/components/passwordmgr/test
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
ifneq (mobile,$(MOZ_BUILD_APP))
|
||||
DIRS = \
|
||||
browser \
|
||||
$(NULL)
|
||||
browser \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
# Module name for xpcshell tests.
|
||||
MODULE = test_passwordmgr
|
||||
MODULE = test_passwordmgr
|
||||
XPCSHELL_TESTS = unit
|
||||
|
||||
# Mochitest tests
|
||||
MOCHI_TESTS = \
|
||||
test_basic_form.html \
|
||||
test_basic_form_html5.html \
|
||||
test_basic_form_2.html \
|
||||
test_basic_form_0pw.html \
|
||||
test_basic_form_1pw.html \
|
||||
test_basic_form_1pw_2.html \
|
||||
test_basic_form_2pw_1.html \
|
||||
test_basic_form_2pw_2.html \
|
||||
test_basic_form_3pw_1.html \
|
||||
test_basic_form_autocomplete.html \
|
||||
test_basic_form_observer_autofillForms.html \
|
||||
test_basic_form_observer_autocomplete.html \
|
||||
test_basic_form_observer_foundLogins.html \
|
||||
test_basic_form_pwonly.html \
|
||||
test_bug_227640.html \
|
||||
test_bug_242956.html \
|
||||
test_bug_360493_1.html \
|
||||
test_bug_360493_2.html \
|
||||
test_bug_391514.html \
|
||||
test_bug_427033.html \
|
||||
test_bug_444968.html \
|
||||
test_master_password.html \
|
||||
test_master_password_cleanup.html \
|
||||
test_prompt_async.html \
|
||||
test_xhr.html \
|
||||
test_xml_load.html \
|
||||
test_zzz_finish.html \
|
||||
$(NULL)
|
||||
test_basic_form.html \
|
||||
test_basic_form_html5.html \
|
||||
test_basic_form_2.html \
|
||||
test_basic_form_0pw.html \
|
||||
test_basic_form_1pw.html \
|
||||
test_basic_form_1pw_2.html \
|
||||
test_basic_form_2pw_1.html \
|
||||
test_basic_form_2pw_2.html \
|
||||
test_basic_form_3pw_1.html \
|
||||
test_basic_form_autocomplete.html \
|
||||
test_basic_form_observer_autofillForms.html \
|
||||
test_basic_form_observer_autocomplete.html \
|
||||
test_basic_form_observer_foundLogins.html \
|
||||
test_basic_form_pwonly.html \
|
||||
test_bug_227640.html \
|
||||
test_bug_242956.html \
|
||||
test_bug_360493_1.html \
|
||||
test_bug_360493_2.html \
|
||||
test_bug_391514.html \
|
||||
test_bug_427033.html \
|
||||
test_bug_444968.html \
|
||||
test_master_password.html \
|
||||
test_master_password_cleanup.html \
|
||||
test_prompt_async.html \
|
||||
test_xhr.html \
|
||||
test_xml_load.html \
|
||||
test_zzz_finish.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHI_CONTENT = \
|
||||
pwmgr_common.js \
|
||||
prompt_common.js \
|
||||
notification_common.js \
|
||||
authenticate.sjs \
|
||||
formsubmit.sjs \
|
||||
subtst_privbrowsing_1.html \
|
||||
subtst_privbrowsing_2.html \
|
||||
subtst_privbrowsing_3.html \
|
||||
subtst_privbrowsing_4.html \
|
||||
subtst_master_pass.html \
|
||||
subtst_notifications_1.html \
|
||||
subtst_notifications_2.html \
|
||||
subtst_notifications_3.html \
|
||||
subtst_notifications_4.html \
|
||||
subtst_notifications_5.html \
|
||||
subtst_notifications_6.html \
|
||||
subtst_notifications_7.html \
|
||||
subtst_notifications_8.html \
|
||||
subtst_notifications_9.html \
|
||||
subtst_notifications_10.html \
|
||||
subtst_prompt_async.html \
|
||||
$(NULL)
|
||||
pwmgr_common.js \
|
||||
prompt_common.js \
|
||||
notification_common.js \
|
||||
authenticate.sjs \
|
||||
formsubmit.sjs \
|
||||
subtst_privbrowsing_1.html \
|
||||
subtst_privbrowsing_2.html \
|
||||
subtst_privbrowsing_3.html \
|
||||
subtst_privbrowsing_4.html \
|
||||
subtst_master_pass.html \
|
||||
subtst_notifications_1.html \
|
||||
subtst_notifications_2.html \
|
||||
subtst_notifications_3.html \
|
||||
subtst_notifications_4.html \
|
||||
subtst_notifications_5.html \
|
||||
subtst_notifications_6.html \
|
||||
subtst_notifications_7.html \
|
||||
subtst_notifications_8.html \
|
||||
subtst_notifications_9.html \
|
||||
subtst_notifications_10.html \
|
||||
subtst_prompt_async.html \
|
||||
$(NULL)
|
||||
|
||||
# Don't run these tests in suite
|
||||
ifndef MOZ_SUITE
|
||||
MOCHI_TESTS += \
|
||||
test_privbrowsing.html \
|
||||
test_prompt.html \
|
||||
test_notifications.html \
|
||||
$(NULL)
|
||||
test_privbrowsing.html \
|
||||
test_prompt.html \
|
||||
test_notifications.html \
|
||||
$(NULL)
|
||||
else
|
||||
$(warning test_prompt.html is disabled until doorhanger notfications work. Bug 598360)
|
||||
$(warning test_notifications.html is disabled until doorhanger notfications work. Bug 598360)
|
||||
$(warning test_privbrowsing.html is disabled due to doorhangers, Bug 598360, and no privatebrowsing support)
|
||||
endif
|
||||
|
||||
XPCSHELL_TESTS = unit
|
||||
|
||||
# This test doesn't pass because we can't ensure a cross-platform
|
||||
# event that occurs between DOMContentLoaded and Pageload
|
||||
# test_bug_221634.html
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user