Bug 955438 - Add an /about command to open the about:* pages, r=clokep,florian.
This commit is contained in:
Родитель
8c1d9e9e8b
Коммит
44f0b88e39
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<bindings id="aboutPanelBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="aboutPanel">
|
||||
<content flex="1">
|
||||
<xul:browser anonid="aboutBrowser" disablehistory="true" flex="1"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<method name="showAboutPage">
|
||||
<parameter name="aPage"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
let url = aPage.startsWith("about:") ? aPage : "about:" + aPage;
|
||||
this.browser.loadURI(url);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="refreshTitle">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let browser = this.browser;
|
||||
this.tab.setAttribute("label",
|
||||
browser.contentTitle.replace("\0", "", "g") || browser.currentURI.spec);
|
||||
let imageUri = browser.currentURI.spec == "about:addons" ?
|
||||
"chrome://mozapps/skin/extensions/extensionGeneric-16.png" :
|
||||
"chrome://mozapps/skin/places/defaultFavicon.png";
|
||||
this.tab.setAttribute("image", imageUri);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="finishImport">
|
||||
<parameter name="aAboutPanel"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.browser.swapDocShells(aAboutPanel.browser);
|
||||
this.refreshTitle();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="browser" readonly="true">
|
||||
<getter>
|
||||
return document.getAnonymousElementByAttribute(this, "anonid", "aboutBrowser");
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this.browser.addEventListener("DOMTitleChanged", this.refreshTitle.bind(this));
|
||||
// The addon manager does its own link handling using window.open().
|
||||
// We need to override this method to open http links externally.
|
||||
let win = this.browser.contentWindow;
|
||||
let open = win.open;
|
||||
win.open = function(aUrl) {
|
||||
let uri = Services.io.newURI(aUrl, null, null);
|
||||
if (!uri.schemeIs("http") && !uri.schemeIs("https")) {
|
||||
open.apply(this, arguments);
|
||||
}
|
||||
else {
|
||||
Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
|
||||
.getService(Components.interfaces.nsIExternalProtocolService).loadUrl(uri);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</constructor>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="click">
|
||||
<![CDATA[
|
||||
// We only handle middle clicks. We don't handle the addon manager.
|
||||
if (event.button != 1 || this.browser.currentURI.spec == "about:addons")
|
||||
return;
|
||||
|
||||
// The event target may be a descendant of the actual link.
|
||||
let url;
|
||||
for (let elem = event.target; elem; elem = elem.parentNode) {
|
||||
if (elem instanceof HTMLAnchorElement) {
|
||||
url = elem.href;
|
||||
if (url)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!url)
|
||||
return;
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
// If it's an about page, open it.
|
||||
if (url.startsWith("about:")) {
|
||||
let panel = document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"aboutPanel");
|
||||
// addPanel will return null if the window can't accept new tabs.
|
||||
if (window.getTabBrowser().addPanel(panel)) {
|
||||
panel.showAboutPage(url);
|
||||
return;
|
||||
}
|
||||
// If we couldn't add a new tab, load the page in this one.
|
||||
this.showAboutPage(url);
|
||||
return;
|
||||
}
|
||||
// Otherwise open in default browser.
|
||||
// loadUrl can throw if the default browser is misconfigured.
|
||||
Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
|
||||
.getService(Components.interfaces.nsIExternalProtocolService)
|
||||
.loadUrl(Services.io.newURI(url, null, null));
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -6,6 +6,10 @@ conversation {
|
|||
-moz-binding: url("chrome://instantbird/content/conversation.xml#conversation");
|
||||
}
|
||||
|
||||
aboutPanel {
|
||||
-moz-binding: url("chrome://instantbird/content/aboutPanel.xml#aboutPanel");
|
||||
}
|
||||
|
||||
.conv-chat:not([chat]) {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ instantbird.jar:
|
|||
#endif
|
||||
content/instantbird/aboutDialog.css
|
||||
* content/instantbird/aboutDialog.xul
|
||||
content/instantbird/aboutPanel.xml
|
||||
content/instantbird/account.js
|
||||
content/instantbird/accounts.css
|
||||
content/instantbird/accounts.js
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
aboutCommand.help=about <page>: display about:<page> in a new tab.
|
||||
aboutCommand.invalidPageMessage="%S" is not a valid about page.
|
||||
|
||||
startupFailure.title=Instantbird - Start up failure
|
||||
startupFailure.apologize=Instantbird encountered a serious error and cannot start, we apologize for the inconvenience.
|
||||
startupFailure.update=An updated version will probably be available shortly to fix the problem.
|
||||
|
|
|
@ -9,6 +9,7 @@ Cu.import("resource:///modules/imServices.jsm");
|
|||
Cu.import("resource:///modules/imWindows.jsm");
|
||||
Cu.import("resource:///modules/ibNotifications.jsm");
|
||||
Cu.import("resource:///modules/ibSounds.jsm");
|
||||
Cu.import("resource:///modules/imXPCOMUtils.jsm");
|
||||
|
||||
var Core = {
|
||||
_events: [
|
||||
|
@ -17,6 +18,8 @@ var Core = {
|
|||
"quit-application-requested"
|
||||
],
|
||||
|
||||
get bundle() l10nHelper("chrome://instantbird/locale/core.properties"),
|
||||
|
||||
init: function() {
|
||||
try {
|
||||
// Set the Vendor for breakpad only
|
||||
|
@ -66,6 +69,58 @@ var Core = {
|
|||
Services.obs.addObserver(Core, aTopic, false);
|
||||
});
|
||||
|
||||
let self = this;
|
||||
Services.cmd.registerCommand({
|
||||
name: "about",
|
||||
get helpString() self.bundle("aboutCommand.help"),
|
||||
usageContext: Ci.imICommand.CMD_CONTEXT_ALL,
|
||||
priority: Ci.imICommand.CMD_PRIORITY_DEFAULT,
|
||||
run: function(aMsg, aConv) {
|
||||
let page = aMsg.replace(/^about:/, "");
|
||||
let url = "about:" + page;
|
||||
// If the page doesn't exist, we avoid opening a tab.
|
||||
try {
|
||||
Services.io.newChannelFromURI(Services.io.newURI(url, null, null));
|
||||
} catch(e) {
|
||||
if (e.result == Components.results.NS_ERROR_MALFORMED_URI) {
|
||||
Services.conversations.getUIConversation(aConv).systemMessage(
|
||||
self.bundle("aboutCommand.invalidPageMessage", page));
|
||||
return true;
|
||||
}
|
||||
Components.utils.reportError(e); // Log unexpected errors.
|
||||
return false;
|
||||
}
|
||||
// Try to get the most recent conversation window. If no such window exists,
|
||||
// win will be null.
|
||||
let win = Services.wm.getMostRecentWindow("Messenger:convs");
|
||||
// Tries to open an aboutPanel in the specified window.
|
||||
let showPage = function(aWindow, aPage) {
|
||||
// Return false if the window doesn't exist.
|
||||
if (!aWindow)
|
||||
return false;
|
||||
let panel = aWindow.document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"aboutPanel");
|
||||
// Try to add the panel, and return false if the window couldn't accept
|
||||
// it (e.g. tabbed conversations are disabled).
|
||||
if (!aWindow.getTabBrowser().addPanel(panel))
|
||||
return false;
|
||||
panel.showAboutPage(aPage);
|
||||
aWindow.getTabBrowser().selectedTab = panel.tab;
|
||||
panel.focus();
|
||||
return true;
|
||||
}
|
||||
// Try to show the page in win, and open a new window if it didn't work.
|
||||
if (!showPage(win, page)) {
|
||||
win = Services.ww.openWindow(null, "chrome://instantbird/content/instantbird.xul",
|
||||
"_blank", "chrome,toolbar,resizable", null);
|
||||
win.addEventListener("load", showPage.bind(null, win, page));
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
this._showAccountManagerIfNeeded(true);
|
||||
return true;
|
||||
},
|
||||
|
@ -225,15 +280,12 @@ var Core = {
|
|||
},
|
||||
|
||||
_promptError: function(aKeyString, aMessage) {
|
||||
var bundle =
|
||||
Services.strings.createBundle("chrome://instantbird/locale/core.properties");
|
||||
var bundle = this.bundle;
|
||||
|
||||
var title = bundle.GetStringFromName("startupFailure.title");
|
||||
var message =
|
||||
bundle.GetStringFromName("startupFailure.apologize") + "\n\n" +
|
||||
(aMessage ? bundle.formatStringFromName(aKeyString, [aMessage], 1)
|
||||
: bundle.GetStringFromName(aKeyString)) + "\n\n" +
|
||||
bundle.GetStringFromName("startupFailure.update");
|
||||
var title = bundle("startupFailure.title");
|
||||
var message = bundle("startupFailure.apologize") + "\n\n" +
|
||||
(aMessage ? bundle(aKeyString, aMessage)
|
||||
: bundle(aKeyString) + "\n\n" + bundle("startupFailure.update"));
|
||||
const nsIPromptService = Components.interfaces.nsIPromptService;
|
||||
const flags =
|
||||
nsIPromptService.BUTTON_POS_1 * nsIPromptService.BUTTON_TITLE_IS_STRING +
|
||||
|
@ -241,8 +293,8 @@ var Core = {
|
|||
|
||||
var prompts = Services.prompt;
|
||||
if (!prompts.confirmEx(null, title, message, flags,
|
||||
bundle.GetStringFromName("startupFailure.buttonUpdate"),
|
||||
bundle.GetStringFromName("startupFailure.buttonClose"),
|
||||
bundle("startupFailure.buttonUpdate"),
|
||||
bundle("startupFailure.buttonClose"),
|
||||
null, null, {}))
|
||||
this.showUpdates();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче