Bug 551889 - Start Page redesign [r=vingtetun]

This commit is contained in:
Mark Finkle 2010-03-26 11:11:03 -04:00
Родитель 0f06a5a078
Коммит ff09f82f2e
27 изменённых файлов: 1208 добавлений и 18 удалений

Просмотреть файл

@ -2,4 +2,5 @@ chrome.jar:
% content branding %content/branding/
content/branding/about.png (about.png)
content/branding/logoWordmark.png (logoWordmark.png)
content/branding/logo.png (logo.png)
content/branding/favicon32.png (favicon32.png)

Двоичные данные
mobile/branding/nightly/content/logo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 19 KiB

Просмотреть файл

@ -2,4 +2,5 @@ chrome.jar:
% content branding %content/branding/
content/branding/about.png (about.png)
content/branding/logoWordmark.png (logoWordmark.png)
content/branding/logo.png (logo.png)
content/branding/favicon32.png (favicon32.png)

Двоичные данные
mobile/branding/official/content/logo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 19 KiB

Просмотреть файл

@ -0,0 +1,287 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" [
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
%brandDTD;
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd" >
%globalDTD;
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
%browserDTD;
<!ENTITY % aboutDTD SYSTEM "chrome://browser/locale/aboutHome.dtd" >
%aboutDTD;
]>
<!-- ***** 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 Communicator client code, released
- March 31, 1998.
-
- The Initial Developer of the Original Code is
- Netscape Communications Corporation.
- Portions created by the Initial Developer are Copyright (C) 1998-1999
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Mark Finkle <mfinkle@mozilla.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 ***** -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>&urlbar.emptytext;</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0" />
<link rel="icon" type="image/png" href="chrome://branding/content/favicon32.png" />
<link rel="stylesheet" href="chrome://browser/skin/aboutHome.css" type="text/css"/>
<script type="application/javascript;version=1.8"><![CDATA[
let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
let gChromeWin = null;
function getChromeWin() {
if (!gChromeWin) {
gChromeWin = window
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow)
.QueryInterface(Ci.nsIDOMChromeWindow);
}
return gChromeWin;
}
function init() {
initTabs();
initWeave();
initAddons();
}
function _readFile(aFile) {
try {
let stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
stream.init(aFile, 0x01, 0, 0);
let cvstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream);
let fileSize = stream.available();
cvstream.init(stream, "UTF-8", fileSize, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
let data = {};
cvstream.readString(fileSize, data);
let content = data.value;
cvstream.close();
return content.replace(/\r\n?/g, "\n");
}
catch (ex) { Cu.reportError(ex); }
return null;
}
function openTabs(aURLs) {
let BrowserUI = getChromeWin().BrowserUI;
let urls = aURLs.split("|");
for (let i=0; i< urls.length; i++) {
BrowserUI.newTab(urls[i]);
}
}
function initTabs() {
let dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
let session = dirService.get("ProfD", Ci.nsILocalFile);
session.append("sessionstore.bak");
let data = JSON.parse(_readFile(session));
if (!data || data.windows.length == 0)
return;
let chromeWin = getChromeWin();
let allPageURLs = [];
let tabs = data.windows[0].tabs;
let count = Math.min(5, tabs.length);
let list = document.getElementById("recentTabs");
for (let i=0; i<count; i++) {
let url = tabs[i].url;
if (url.indexOf("about:") == 0)
continue;
let title = tabs[i].title;
if (!title)
continue;
let uri = chromeWin.makeURI(url);
let favicon = chromeWin.gFaviconService.getFaviconImageForPage(uri).spec;
let outer = document.createElement("div");
let pageURL = url;
outer.addEventListener("click", function() {
openTabs(pageURL);
}, false);
allPageURLs.push(pageURL);
let img = document.createElement("img");
img.className = "favicon";
img.setAttribute("src", favicon);
outer.appendChild(img);
let inner = document.createElement("div");
inner.className = "inner";
let titlePart = document.createElement("div");
titlePart.textContent = title;
titlePart.className = "title";
inner.appendChild(titlePart);
outer.appendChild(inner);
list.appendChild(outer);
}
if (allPageURLs.length > 0) {
let outer = document.createElement("div");
outer.className = "openall";
outer.textContent = document.getElementById("text-openalltabs").textContent;
outer.addEventListener("click", function() {
openTabs(allPageURLs.join("|"));
}, false);
list.appendChild(outer);
} else {
list.style.display = "none";
}
}
function initWeave() {
let em = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
let weave = em.getItemForID("{340c2bbc-ce74-4362-90b5-7c26312808ef}");
if (!weave || !getChromeWin().WeaveGlue)
document.getElementById("remoteTabs").style.display = "none";
}
function openRemoteTabs() {
getChromeWin().WeaveGlue.openRemoteTabs();
}
function goToAddons(aSearchString) {
let chromeWin = getChromeWin();
let BrowserUI = chromeWin.BrowserUI;
BrowserUI.showPanel("addons-container");
if (aSearchString) {
// ExtensionsView initialization is delayed, so need to delay triggering
// the search as well
setTimeout(function () {
// do the search
chromeWin.ExtensionsView.doSearch(aSearchString);
}, 0);
}
}
var RecommendedSearchResults = {
searchSucceeded: function(aAddons, aAddonCount, aTotalResults) {
let list = document.getElementById("newAddons");
if (aAddons.length == 0) {
list.style.display = "none";
return;
}
for (let i=0; i<aAddons.length; i++) {
let outer = document.createElement("div");
outer.setAttribute("addonID", aAddons[i].id);
let addonName = aAddons[i].name;
outer.addEventListener("click", function() {
goToAddons(addonName);
}, false)
let img = document.createElement("img");
img.className = "favicon";
img.setAttribute("src", aAddons[i].iconURL);
outer.appendChild(img);
let inner = document.createElement("div");
inner.className = "inner";
let titlePart = document.createElement("span");
titlePart.textContent = aAddons[i].name;
titlePart.className = "title";
inner.appendChild(titlePart);
let versionPart = document.createElement("span");
versionPart.textContent = aAddons[i].version;
versionPart.className = "version";
inner.appendChild(versionPart);
outer.appendChild(inner);
list.appendChild(outer);
}
},
searchFailed: function searchFailed() {}
}
const kAddonsMaxDisplay = 2;
function initAddons() {
let repository = "@mozilla.org/extensions/addon-repository;1";
let repo = Cc[repository].createInstance(Ci.nsIAddonRepository);
if (repo.isSearching)
repo.cancelSearch();
repo.retrieveRecommendedAddons(kAddonsMaxDisplay, RecommendedSearchResults);
}
]]></script>
</head>
<body dir="&locale.dir;" onload="init();">
<div id="wrapper">
<div id="header"><div id="logo"><img src="chrome://branding/content/logo.png"/></div><span>&brandShortName; </span><span id="header-suffix">&aboutHome.start;</span></div>
<div id="recentTabs" class="section-box">
<h1>&aboutHome.recentTabs;</h1>
</div>
<div id="remoteTabs" class="section-row" onclick="openRemoteTabs();">
<div>
<img class="favicon" src="chrome://browser/skin/images/remotetabs-32.png"/>
<div>&aboutHome.remoteTabs;</div>
</div>
</div>
<div id="newAddons" class="section-box">
<h1>&aboutHome.recommendedAddons;</h1>
</div>
<div id="about">
<img src="http://mozilla.org/favicon.ico"/> <a href="http://www.mozilla.com/about/">&aboutHome.aboutMozilla;</a>
</div>
</div>
<!-- l10n hack -->
<div style="display: none">
<span id="text-openalltabs">&aboutHome.openAllTabs;</span>
</div>
</body>
</html>

Просмотреть файл

@ -82,6 +82,11 @@ const TOOLBARSTATE_LOADED = 2;
"@mozilla.org/focus-manager;1",
[Ci.nsIFocusManager]
],
[
"gWindowMediator",
"@mozilla.org/appshell/window-mediator;1",
[Ci.nsIWindowMediator]
],
[
"gObserverService",
"@mozilla.org/observer-service;1",

Просмотреть файл

@ -336,7 +336,7 @@ var Browser = {
pageScrollboxScroller: null,
styles: {},
startup: function() {
startup: function startup() {
var self = this;
let needOverride = Util.needHomepageOverride();
@ -488,14 +488,14 @@ var Browser = {
Util.forceOnline();
// Command line arguments/initial homepage
let whereURI = "about:blank";
let whereURI = this.getHomePage();
switch (needOverride) {
case "new profile":
whereURI = "about:firstrun";
break;
case "new version":
case "none":
whereURI = "about:blank";
whereURI = this.getHomePage();
break;
}
@ -566,7 +566,32 @@ var Browser = {
window.dispatchEvent(event);
},
shutdown: function() {
closing: function closing() {
// Prompt if we have multiple tabs before closing window
// TODO: bug 545395
// Figure out if there's at least one other browser window around.
let lastBrowser = true;
let e = gWindowMediator.getEnumerator("navigator:browser");
while (e.hasMoreElements() && lastBrowser) {
let win = e.getNext();
if (win != window && win.toolbar.visible)
lastBrowser = false;
}
if (!lastBrowser)
return true;
// Let everyone know we are closing the last browser window
let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
gObserverService.notifyObservers(closingCanceled, "browser-lastwindow-close-requested", null);
if (closingCanceled.data)
return false;
gObserverService.notifyObservers(null, "browser-lastwindow-close-granted", null);
return true;
},
shutdown: function shutdown() {
this._browserView.uninit();
BrowserUI.uninit();
this._pluginObserver.stop();
@ -583,6 +608,15 @@ var Browser = {
initNewProfile: function initNewProfile() {
},
getHomePage: function () {
let url = "about:home";
try {
url = gPrefService.getComplexValue("browser.startup.homepage", Ci.nsIPrefLocalizedString).data;
} catch (e) { }
return url;
},
get browsers() {
return this._tabs.map(function(tab) { return tab.browser; });
@ -636,6 +670,10 @@ var Browser = {
return this._selectedTab.browser;
},
get tabs() {
return this._tabs;
},
getTabForDocument: function(aDocument) {
let tabs = this._tabs;
for (let i = 0; i < tabs.length; i++) {

Просмотреть файл

@ -54,6 +54,7 @@
<window id="main-window"
onload="Browser.startup();"
onunload="Browser.shutdown();"
onclose="return Browser.closing();"
windowtype="navigator:browser"
title="&brandShortName;"
#ifdef WINCE
@ -222,6 +223,7 @@
maxrows="6"
completeselectedindex="true"
minresultsforpopup="0"
emptytext="&urlbar.emptytext;"
flex="1"
ontextentered="BrowserUI.goToURI();"
clickSelectsAll="true"/>
@ -396,6 +398,15 @@
&defaultBrowser.description;
</setting>
#endif
<setting id="prefs-homepage" title="&homepage.title;" type="control">
<menulist id="prefs-homepage-options" oncommand="PreferencesView.updateHomePage();">
<menupopup>
<menuitem id="prefs-homepage-default" label="&homepage.default;" value="default"/>
<menuitem id="prefs-homepage-none" label="&homepage.none;" value="none"/>
<menuitem id="prefs-homepage-currentpage" label="&homepage.currentpage;" value="custom"/>
</menupopup>
</menulist>
</setting>
<settings id="prefs-content" label="&content.title;">
<setting pref="permissions.default.image" title="&showImages.title;" type="boolint" on="1" off="2"/>
<setting pref="javascript.enabled" type="bool" title="&enableJavaScript.title;"/>

Просмотреть файл

@ -37,7 +37,7 @@
var PreferencesView = {
_currentLocale: null,
_list: null,
_languages: null,
_msg: null,
_restartCount: 0,
@ -115,7 +115,7 @@ var PreferencesView = {
},
_delayedInit: function ev__delayedInit() {
if (this._list)
if (this._languages)
return;
#ifdef WINCE
@ -123,8 +123,10 @@ var PreferencesView = {
document.getElementById("prefs-default-browser").value = phone.isDefaultBrowser(false);
#endif
this._list = document.getElementById("prefs-languages");
this._languages = document.getElementById("prefs-languages");
this._loadLocales();
this._loadHomePage();
},
_loadLocales: function _loadLocales() {
@ -148,7 +150,7 @@ var PreferencesView = {
} catch (e) {
label = locale;
}
let item = this._list.appendItem(label, locale);
let item = this._languages.appendItem(label, locale);
if (locale == selectedLocale) {
this._currentLocale = locale;
selectedItem = item;
@ -165,9 +167,9 @@ var PreferencesView = {
// Highlight current locale (or auto-detect entry)
if (autoDetect)
this._list.selectedItem = document.getElementById("prefs-languages-auto");
this._languages.selectedItem = document.getElementById("prefs-languages-auto");
else
this._list.selectedItem = selectedItem;
this._languages.selectedItem = selectedItem;
// Hide the setting if we only have one locale
if (localeCount == 1)
@ -176,7 +178,7 @@ var PreferencesView = {
updateLocale: function updateLocale() {
// Which locale did the user select?
let newLocale = this._list.selectedItem.value;
let newLocale = this._languages.selectedItem.value;
if (newLocale == "auto") {
if (gPrefService.prefHasUserValue("general.useragent.locale"))
@ -192,5 +194,74 @@ var PreferencesView = {
this.hideRestart();
else
this.showRestart();
}
},
_loadHomePage: function _loadHomePage() {
let url = Browser.getHomePage();
let value = "default";
let display = url;
switch (url) {
case "about:blank":
value = "none";
display = "";
break;
case "about:home":
value = "default";
display = "";
break;
default:
value = "custom";
break;
}
// Show or hide the URL of the custom homepage
document.getElementById("prefs-homepage").setAttribute("desc", display);
// Select the homepage option
let options = document.getElementById("prefs-homepage-options");
if (value == "custom") {
// Make sure nothing is selected and just use a label to show the state
options.selectedIndex = -1;
options.setAttribute("label", Elements.browserBundle.getString("homepage.custom"));
} else {
// Select the right menulist item
options.value = value;
}
},
updateHomePage: function updateHomePage() {
let url = "about:home";
let options = document.getElementById("prefs-homepage-options");
let value = options.selectedItem.value;
let display = "";
switch (value) {
case "none":
url = "about:blank";
break;
case "default":
url = "about:home";
break;
case "custom":
url = Browser.selectedBrowser.currentURI.spec;
display = url;
break;
}
// Show or hide the URL of the custom homepage
document.getElementById("prefs-homepage").setAttribute("desc", display);
let options = document.getElementById("prefs-homepage-options");
if (value == "custom") {
// Make sure nothing is selected and just use a label to show the state
options.selectedIndex = -1;
options.setAttribute("label", Elements.browserBundle.getString("homepage.custom"));
}
// Save the homepage URL to a preference
let pls = Cc["@mozilla.org/pref-localizedstring;1"].createInstance(Ci.nsIPrefLocalizedString);
pls.data = url;
gPrefService.setComplexValue("browser.startup.homepage", Ci.nsIPrefLocalizedString, pls);
}
};

Просмотреть файл

@ -7,6 +7,7 @@ chrome.jar:
content/config.js (content/config.js)
content/aboutCertError.xhtml (content/aboutCertError.xhtml)
content/aboutCertError.css (content/aboutCertError.css)
content/aboutHome.xhtml (content/aboutHome.xhtml)
content/languages.properties (content/languages.properties)
* content/browser.xul (content/browser.xul)
* content/browser.js (content/browser.js)

Просмотреть файл

@ -63,6 +63,10 @@ let modules = {
certerror: {
uri: "chrome://browser/content/aboutCertError.xhtml",
privileged: true
},
home: {
uri: "chrome://browser/content/aboutHome.xhtml",
privileged: true
}
}
@ -141,6 +145,15 @@ AboutCertError.prototype = {
classID: Components.ID("{972efe64-8ac0-4e91-bdb0-22835d987815}")
}
function AboutHome() {}
AboutHome.prototype = {
__proto__: AboutGeneric.prototype,
classDescription: "About Home",
contractID: "@mozilla.org/network/protocol/about;1?what=home",
classID: Components.ID("{b071364f-ab68-4669-a9db-33fca168271a}")
}
function NSGetModule(compMgr, fileSpec)
XPCOMUtils.generateModule([AboutFirstrun, AboutFennec, AboutRights,
AboutCertError, AboutFirefox]);
AboutCertError, AboutFirefox, AboutHome]);

Просмотреть файл

@ -11,7 +11,7 @@
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Alerts Service.
* The Original Code is Download Manager UI.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009

Просмотреть файл

@ -64,6 +64,7 @@ EXTRA_COMPONENTS = \
ContentDispatchChooser.js \
AutoCompleteCache.js \
AddonUpdateService.js \
SessionStore.js \
$(NULL)
DIRS = protocols \

Просмотреть файл

@ -0,0 +1,389 @@
/* ***** 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 Session Store.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.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 ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gObserverService",
"@mozilla.org/observer-service;1",
"nsIObserverService");
XPCOMUtils.defineLazyServiceGetter(this, "gWindowMediator",
"@mozilla.org/appshell/window-mediator;1",
"nsIWindowMediator");
XPCOMUtils.defineLazyServiceGetter(this, "gPrefService",
"@mozilla.org/preferences-service;1",
"nsIPrefBranch2");
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
Cu.import("resource://gre/modules/NetUtil.jsm");
return NetUtil;
});
// -----------------------------------------------------------------------
// Session Store
// -----------------------------------------------------------------------
const STATE_STOPPED = 0;
const STATE_RUNNING = 1;
const STATE_QUITTING = -1;
function SessionStore() { }
SessionStore.prototype = {
classDescription: "Browser Session Store",
contractID: "@mozilla.org/browser/sessionstore;1",
classID: Components.ID("{90c3dfaf-4245-46d3-9bc1-1d8251ff8c01}"),
_xpcom_categories: [{ category: "app-startup", service: true }],
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, Ci.nsIObserver, Ci.nsISupportsWeakReference]),
_windows: {},
_lastSaveTime: 0,
_interval: 15000,
init: function ss_init() {
// Get file references
let dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
this._sessionFile = dirService.get("ProfD", Ci.nsILocalFile);
this._sessionFileBackup = this._sessionFile.clone();
this._sessionFile.append("sessionstore.js");
this._sessionFileBackup.append("sessionstore.bak");
this._loadState = STATE_STOPPED;
try {
if (this._sessionFileBackup.exists())
this._sessionFileBackup.remove(false);
if (this._sessionFile.exists())
this._sessionFile.copyTo(null, this._sessionFileBackup.leafName);
} catch (ex) {
Cu.reportError(ex); // file was write-locked?
}
try {
this._interval = gPrefService.getIntPref("sessionstore.interval");
} catch (e) {}
},
observe: function ss_observe(aSubject, aTopic, aData) {
let self = this;
switch (aTopic) {
case "app-startup":
gObserverService.addObserver(this, "final-ui-startup", true);
gObserverService.addObserver(this, "domwindowopened", true);
gObserverService.addObserver(this, "domwindowclosed", true);
gObserverService.addObserver(this, "browser-lastwindow-close-granted", true);
gObserverService.addObserver(this, "quit-application-requested", true);
gObserverService.addObserver(this, "quit-application-granted", true);
gObserverService.addObserver(this, "quit-application", true);
break;
case "final-ui-startup":
gObserverService.removeObserver(this, "final-ui-startup");
this.init();
break;
case "domwindowopened":
let window = aSubject;
window.addEventListener("load", function() {
self.onWindowOpen(window);
window.removeEventListener("load", arguments.callee, false);
}, false);
break;
case "domwindowclosed": // catch closed windows
this.onWindowClose(aSubject);
break;
case "browser-lastwindow-close-granted":
// Force and open timer to save state
if (this._saveTimer) {
this._saveTimer.cancel();
this._saveTimer = null;
this.saveState();
}
// Freeze the data at what we've got (ignoring closing windows)
this._loadState = STATE_QUITTING;
break;
case "quit-application-requested":
// Get a current snapshot of all windows
this._forEachBrowserWindow(function(aWindow) {
self._collectWindowData(aWindow);
});
break;
case "quit-application-granted":
case "quit-application":
// Freeze the data at what we've got (ignoring closing windows)
this._loadState = STATE_QUITTING;
gObserverService.removeObserver(this, "domwindowopened");
gObserverService.removeObserver(this, "domwindowclosed");
gObserverService.removeObserver(this, "browser-lastwindow-close-granted");
gObserverService.removeObserver(this, "quit-application-requested");
gObserverService.removeObserver(this, "quit-application-granted");
gObserverService.removeObserver(this, "quit-application");
// Make sure to break our cycle with the save timer
if (this._saveTimer) {
this._saveTimer.cancel();
this._saveTimer = null;
}
break;
case "timer-callback":
// Timer call back for delayed saving
this._saveTimer = null;
this.saveState();
break;
}
},
handleEvent: function ss_handleEvent(aEvent) {
let window = aEvent.currentTarget.ownerDocument.defaultView;
switch (aEvent.type) {
case "load":
case "pageshow":
this.onTabLoad(window, aEvent.currentTarget, aEvent);
break;
case "TabOpen":
case "TabClose":
let browser = window.Browser.getTabFromChrome(aEvent.originalTarget).browser;
if (aEvent.type == "TabOpen") {
this.onTabAdd(window, browser);
}
else {
this.onTabClose(window, aEvent.originalTarget);
this.onTabRemove(window, browser);
}
break;
case "TabSelect":
this.onTabSelect(window);
break;
}
},
onWindowOpen: function ss_onWindowOpen(aWindow) {
// Return if window has already been initialized
if (aWindow && aWindow.__SSID && this._windows[aWindow.__SSID])
return;
// Ignore non-browser windows and windows opened while shutting down
if (aWindow.document.documentElement.getAttribute("windowtype") != "navigator:browser" || this._loadState == STATE_QUITTING)
return;
// Assign it a unique identifier (timestamp) and create its data object
aWindow.__SSID = "window" + Date.now();
this._windows[aWindow.__SSID] = { tabs: [], selected: 0 };
// Perform additional initialization when the first window is loading
if (this._loadState == STATE_STOPPED) {
this._loadState = STATE_RUNNING;
this._lastSaveTime = Date.now();
}
// Add tab change listeners to all already existing tabs
let tabs = aWindow.Browser.tabs;
for (let i = 0; i < tabs.length; i++)
this.onTabAdd(aWindow, tabs[i].browser, true);
// Notification of tab add/remove/selection
let tabContainer = aWindow.document.getElementById("tabs");
tabContainer.addEventListener("TabOpen", this, true);
tabContainer.addEventListener("TabClose", this, true);
tabContainer.addEventListener("TabSelect", this, true);
},
onWindowClose: function ss_onWindowClose(aWindow) {
// Ignore windows not tracked by SessionStore
if (!aWindow.__SSID || !this._windows[aWindow.__SSID])
return;
let tabContainer = aWindow.document.getElementById("tabs");
tabContainer.removeEventListener("TabOpen", this, true);
tabContainer.removeEventListener("TabClose", this, true);
tabContainer.removeEventListener("TabSelect", this, true);
if (this._loadState == STATE_RUNNING) {
// Update all window data for a last time
this._collectWindowData(aWindow);
// Clear this window from the list
delete this._windows[aWindow.__SSID];
// Save the state without this window to disk
this.saveStateDelayed();
}
let tabs = aWindow.Browser.tabs;
for (let i = 0; i < tabs.length; i++)
this.onTabRemove(aWindow, tabs[i].browser, true);
delete aWindow.__SSID;
},
onTabAdd: function ss_onTabAdd(aWindow, aBrowser, aNoNotification) {
aBrowser.addEventListener("load", this, true);
aBrowser.addEventListener("pageshow", this, true);
if (!aNoNotification) {
this.saveStateDelayed(aWindow);
}
},
onTabRemove: function ss_onTabRemove(aWindow, aBrowser, aNoNotification) {
aBrowser.removeEventListener("load", this, true);
aBrowser.removeEventListener("pageshow", this, true);
delete aBrowser.__SS_data;
if (!aNoNotification) {
this.saveStateDelayed(aWindow);
}
},
onTabClose: function ss_onTabClose(aWindow, aTab) {
},
onTabLoad: function ss_onTabLoad(aWindow, aBrowser, aEvent) {
// react on "load" and solitary "pageshow" events (the first "pageshow"
// following "load" is too late for deleting the data caches)
if (aEvent.type != "load" && !aEvent.persisted) {
return;
}
delete aBrowser.__SS_data;
this._collectTabData(aBrowser);
this.saveStateDelayed(aWindow);
},
onTabSelect: function ss_onTabSelect(aWindow) {
},
saveStateDelayed: function ss_saveStateDelayed() {
if (!this._saveTimer) {
// Interval until the next disk operation is allowed
let minimalDelay = this._lastSaveTime + this._interval - Date.now();
// If we have to wait, set a timer, otherwise saveState directly
let delay = Math.max(minimalDelay, 2000);
if (delay > 0) {
this._saveTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._saveTimer.init(this, delay, Ci.nsITimer.TYPE_ONE_SHOT);
}
else {
this.saveState();
}
}
},
saveState: function ss_saveState() {
let self = this;
this._forEachBrowserWindow(function(aWindow) {
self._collectWindowData(aWindow);
});
let data = { windows: [] };
let index;
for (index in this._windows)
data.windows.push(this._windows[index]);
this._writeFile(this._sessionFile, JSON.stringify(data));
this._lastSaveTime = Date.now();
},
_collectTabData: function ss__collectTabData(aBrowser) {
let tabData = { url: aBrowser.currentURI.spec, title: aBrowser.contentDocument.title };
aBrowser.__SS_data = tabData;
},
_collectWindowData: function ss__collectWindowData(aWindow) {
// Ignore windows not tracked by SessionStore
if (!aWindow.__SSID || !this._windows[aWindow.__SSID])
return;
let winData = this._windows[aWindow.__SSID];
winData.tabs = [];
let tabs = aWindow.Browser.tabs;
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].browser.__SS_data)
winData.tabs.push(tabs[i].browser.__SS_data);
}
},
_forEachBrowserWindow: function ss_forEachBrowserWindow(aFunc) {
let windowsEnum = gWindowMediator.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
let window = windowsEnum.getNext();
if (window.__SSID && !window.closed)
aFunc.call(this, window);
}
},
_writeFile: function ss_writeFile(aFile, aData) {
let stateString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
stateString.data = aData;
gObserverService.notifyObservers(stateString, "sessionstore-state-write", "");
// Don't touch the file if an observer has deleted all state data
if (!stateString.data)
return;
// Initialize the file output stream.
let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, 0);
// Obtain a converter to convert our data to a UTF-8 encoded input stream.
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
// Asynchronously copy the data to the file.
let istream = converter.convertToInputStream(aData);
NetUtil.asyncCopy(istream, ostream, function(rc) {
if (Components.isSuccessCode(rc)) {
gObserverService.notifyObservers(null, "sessionstore-state-write-complete", "");
}
});
}
};
function NSGetModule(aCompMgr, aFileSpec) {
return XPCOMUtils.generateModule([SessionStore]);
}

Просмотреть файл

@ -0,0 +1,6 @@
<!ENTITY aboutHome.start "Start">
<!ENTITY aboutHome.recentTabs "Your tabs from last time">
<!ENTITY aboutHome.remoteTabs "Tabs from your other computers">
<!ENTITY aboutHome.recommendedAddons "Add-ons for your Firefox">
<!ENTITY aboutHome.aboutMozilla "About Mozilla">
<!ENTITY aboutHome.openAllTabs "Open all in tabs">

Просмотреть файл

@ -1,3 +1,5 @@
<!ENTITY urlbar.emptytext "Enter Search or Address">
<!ENTITY back.label "Back">
<!ENTITY forward.label "Forward">
<!ENTITY reload.label "Reload">

Просмотреть файл

@ -120,6 +120,9 @@ offlineApps.notNow=Not Now
# Bookmark List
bookmarkList.desktop=Desktop Bookmarks
# Homepage
homepage.custom=Custom
# Page Actions
pageactions.search.addNew=Add Search Engine
pageactions.password.forget=Forget Password

Просмотреть файл

@ -14,3 +14,8 @@
<!ENTITY language.auto "Auto-detect">
<!ENTITY defaultBrowser.title "Default Browser">
<!ENTITY defaultBrowser.description "Make &brandShortName; your default browser">
<!ENTITY homepage.title "Start page">
<!ENTITY homepage.none "Blank">
<!ENTITY homepage.default "&brandShortName; Start">
<!ENTITY homepage.currentpage "Use Current Page">
<!ENTITY homepage.custom "Custom Page">

Просмотреть файл

@ -4,6 +4,7 @@
% locale browser @AB_CD@ %locale/@AB_CD@/browser/
locale/@AB_CD@/browser/about.dtd (%chrome/about.dtd)
locale/@AB_CD@/browser/aboutCertError.dtd (%chrome/aboutCertError.dtd)
locale/@AB_CD@/browser/aboutHome.dtd (%chrome/aboutHome.dtd)
locale/@AB_CD@/browser/browser.dtd (%chrome/browser.dtd)
locale/@AB_CD@/browser/browser.properties (%chrome/browser.properties)
locale/@AB_CD@/browser/config.dtd (%chrome/config.dtd)

Просмотреть файл

@ -0,0 +1,178 @@
/* ***** 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 Mobile Browser.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.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 ***** */
html {
background: white;
font-family: "Nokia Sans", Tahoma, sans-serif !important;
font-size: 24px;
margin: 0px 20px;
}
#wrapper {
max-width: 600px;
margin: 0 auto;
}
#logo {
float: right;
margin-top: -24px;
margin-right: -34px;
}
#header {
font-weight: bold;
color: white;
background: transparent -moz-linear-gradient(top, rgba(57,89,117,1) 0%, rgba(30,66,98,1) 50%, rgba(24,54,82,1) 90%);
-moz-border-radius: 6px;
padding: 12px;
padding-bottom: 14px;
margin-bottom: 12px;
margin-top: 20px;
-moz-box-shadow: inset rgba(0, 0, 0, 0.2) 0 -3px 0px, rgba(0, 0, 0, 0.1) 0px 2px 0px;
}
#header-suffix {
color: rgb(112,136,156);
}
.section-box {
background-color: white;
padding: 0;
margin-bottom: 8px;
-moz-border-radius: 8px;
border: 1px solid rgba(0,0,0,0.3);
-moz-box-shadow:
inset rgba(255, 255, 255, 0.5) 0 1px 0px,
inset rgba(0, 0, 0, 0.1) 0 -3px 0px,
rgba(0, 0, 0, 0.1) 0px 2px 0px;
}
.section-box > h1 {
font-size: 18px;
font-weight: normal;
color: black;
background: transparent -moz-linear-gradient(top, rgba(235,235,235,0.2) 0%, rgba(235,235,235,1) 90%);
margin: 0;
padding: 4px 12px 8px 12px;
-moz-border-radius: 8px 8px 0 0;
}
.section-box > div {
border-bottom: 1px solid rgba(0,0,0,0.1);
padding: 8px;
padding-bottom: 12px;
position: relative;
}
.section-box > div:last-child {
border-bottom: 0;
}
/* Make room for the image */
.section-box > div > div,
.section-row > div > div {
margin-left: 48px;
}
.section-box .title {
color: black;
}
.section-box .openall {
text-align: right;
font-size: 18px;
padding: 12px 8px;
color: black;
}
.section-box .version {
margin-left: 12px;
font-size: 18px;
color: gray;
}
.section-box .favicon {
border: none;
top: 8px;
left: 12px;
width: 32px;
height: 32px;
position: absolute;
}
#newAddons > div {
background: url("images/arrowright-16.png") right center no-repeat;
margin-right: 8px;
}
.section-row {
color: black;
background: transparent -moz-linear-gradient(top, rgba(235,235,235,0.2) 0%, rgba(235,235,235,1) 90%);
padding: 8px;
padding-bottom: 12px;
-moz-border-radius: 8px;
border: 1px solid rgba(0,0,0,0.3);
-moz-box-shadow:
inset rgba(255, 255, 255, 0.5) 0 1px 0px,
inset rgba(0, 0, 0, 0.1) 0 -3px 0px,
rgba(0, 0, 0, 0.1) 0px 2px 0px;
margin: 24px auto;
}
.section-row > div {
position: relative;
}
.section-row .favicon {
border: none;
top: 0;
left: 4px;
width: 32px;
height: 32px;
position: absolute;
}
#about {
font-size: 12px;
text-align: center;
margin-top: 24px;
}
#about > img {
vertical-align: middle;
margin: 4px;
}

Просмотреть файл

@ -189,8 +189,6 @@ toolbarbutton.urlbar-cap-button {
-moz-appearance: none !important;
padding: 0px !important;
border: none !important;
color: #000;
background-color: #fff;
}
/* make sure this endcap matches the other endcap */

Двоичные данные
mobile/themes/hildon/images/remotetabs-32.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 213 B

Просмотреть файл

@ -5,6 +5,7 @@ chrome.jar:
aboutCertError.css (aboutCertError.css)
aboutPage.css (aboutPage.css)
about.css (about.css)
aboutHome.css (aboutHome.css)
config.css (config.css)
firstRun.css (firstRun.css)
header.css (header.css)
@ -62,6 +63,7 @@ chrome.jar:
images/console-active-64.png (images/console-active-64.png)
images/newtab-default-64.png (images/newtab-default-64.png)
images/newtab-active-64.png (images/newtab-active-64.png)
images/remotetabs-32.png (images/remotetabs-32.png)
images/leftcap-default-64.png (images/leftcap-default-64.png)
images/leftcap-active-64.png (images/leftcap-active-64.png)
images/leftcapEV-default-64.png (images/leftcapEV-default-64.png)

Просмотреть файл

@ -0,0 +1,178 @@
/* ***** 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 Mobile Browser.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.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 ***** */
html {
background: white;
font-family: "Nokia Sans", Tahoma, sans-serif !important;
font-size: 24px;
margin: 0px 20px;
}
#wrapper {
max-width: 600px;
margin: 0 auto;
}
#logo {
float: right;
margin-top: -24px;
margin-right: -34px;
}
#header {
font-weight: bold;
color: white;
background: transparent -moz-linear-gradient(top, rgba(57,89,117,1) 0%, rgba(30,66,98,1) 50%, rgba(24,54,82,1) 90%);
-moz-border-radius: 6px;
padding: 12px;
padding-bottom: 14px;
margin-bottom: 12px;
margin-top: 20px;
-moz-box-shadow: inset rgba(0, 0, 0, 0.2) 0 -3px 0px, rgba(0, 0, 0, 0.1) 0px 2px 0px;
}
#header-suffix {
color: rgb(112,136,156);
}
.section-box {
background-color: white;
padding: 0;
margin-bottom: 8px;
-moz-border-radius: 8px;
border: 1px solid rgba(0,0,0,0.3);
-moz-box-shadow:
inset rgba(255, 255, 255, 0.5) 0 1px 0px,
inset rgba(0, 0, 0, 0.1) 0 -3px 0px,
rgba(0, 0, 0, 0.1) 0px 2px 0px;
}
.section-box > h1 {
font-size: 18px;
font-weight: normal;
color: black;
background: transparent -moz-linear-gradient(top, rgba(235,235,235,0.2) 0%, rgba(235,235,235,1) 90%);
margin: 0;
padding: 4px 12px 8px 12px;
-moz-border-radius: 8px 8px 0 0;
}
.section-box > div {
border-bottom: 1px solid rgba(0,0,0,0.1);
padding: 8px;
padding-bottom: 12px;
position: relative;
}
.section-box > div:last-child {
border-bottom: 0;
}
/* Make room for the image */
.section-box > div > div,
.section-row > div > div {
margin-left: 48px;
}
.section-box .title {
color: black;
}
.section-box .openall {
text-align: right;
font-size: 18px;
padding: 12px 8px;
color: black;
}
.section-box .version {
margin-left: 12px;
font-size: 18px;
color: gray;
}
.section-box .favicon {
border: none;
top: 8px;
left: 12px;
width: 32px;
height: 32px;
position: absolute;
}
#newAddons > div {
background: url("images/arrowright-16.png") right center no-repeat;
margin-right: 8px;
}
.section-row {
color: black;
background: transparent -moz-linear-gradient(top, rgba(235,235,235,0.2) 0%, rgba(235,235,235,1) 90%);
padding: 8px;
padding-bottom: 12px;
-moz-border-radius: 8px;
border: 1px solid rgba(0,0,0,0.3);
-moz-box-shadow:
inset rgba(255, 255, 255, 0.5) 0 1px 0px,
inset rgba(0, 0, 0, 0.1) 0 -3px 0px,
rgba(0, 0, 0, 0.1) 0px 2px 0px;
margin: 24px auto;
}
.section-row > div {
position: relative;
}
.section-row .favicon {
border: none;
top: 0;
left: 4px;
width: 32px;
height: 32px;
position: absolute;
}
#about {
font-size: 12px;
text-align: center;
margin-top: 24px;
}
#about > img {
vertical-align: middle;
margin: 4px;
}

Просмотреть файл

@ -102,8 +102,6 @@ toolbarbutton.urlbar-cap-button {
-moz-appearance: none !important;
padding: 0px !important;
border: none !important;
color: #000;
background-color: #fff;
}
/* right toolbar (browser controls) ---------------------------------------- */

Двоичные данные
mobile/themes/wince/images/remotetabs-32.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 213 B

Просмотреть файл

@ -59,6 +59,7 @@ chrome.jar:
images/console-active-64.png (images/console-active-64.png)
images/newtab-default-64.png (images/newtab-default-64.png)
images/newtab-active-64.png (images/newtab-active-64.png)
images/remotetabs-32.png (images/remotetabs-32.png)
images/leftcap-default-64.png (images/leftcap-default-64.png)
images/leftcap-active-64.png (images/leftcap-active-64.png)
images/leftcapEV-default-64.png (images/leftcapEV-default-64.png)