mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1112304: Update about:tabcrashed to match the new UX spec. r=dao
Uses in-content styles for the tab crash page and adds an overlay to the favicon for crashed tabs. Adds support for closing the crashed tab. The strings here also refer to being able to restore all tabs, that will be implemented and landed at the same time in bug 1109650 to avoid l10n churn.
This commit is contained in:
parent
feb66be0d1
commit
9ddcb19cae
8
browser/base/content/aboutTabCrashed.css
Normal file
8
browser/base/content/aboutTabCrashed.css
Normal file
@ -0,0 +1,8 @@
|
||||
/* 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/. */
|
||||
|
||||
html:not(.crashDumpSubmitted) #reportSent,
|
||||
html:not(.crashDumpAvailable) #report-box {
|
||||
display: none;
|
||||
}
|
@ -12,21 +12,31 @@ function parseQueryString() {
|
||||
|
||||
document.title = parseQueryString();
|
||||
|
||||
addEventListener("DOMContentLoaded", () => {
|
||||
let tryAgain = document.getElementById("tryAgain");
|
||||
let sendCrashReport = document.getElementById("checkSendReport");
|
||||
function shouldSendReport() {
|
||||
if (!document.documentElement.classList.contains("crashDumpAvailable"))
|
||||
return false;
|
||||
return document.getElementById("sendReport").checked;
|
||||
}
|
||||
|
||||
tryAgain.addEventListener("click", () => {
|
||||
let event = new CustomEvent("AboutTabCrashedTryAgain", {
|
||||
bubbles: true,
|
||||
detail: {
|
||||
sendCrashReport: sendCrashReport.checked,
|
||||
},
|
||||
});
|
||||
|
||||
document.dispatchEvent(event);
|
||||
function sendEvent(message) {
|
||||
let event = new CustomEvent("AboutTabCrashedMessage", {
|
||||
bubbles: true,
|
||||
detail: {
|
||||
message,
|
||||
sendCrashReport: shouldSendReport(),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function closeTab() {
|
||||
sendEvent("closeTab");
|
||||
}
|
||||
|
||||
function restoreTab() {
|
||||
sendEvent("restoreTab");
|
||||
}
|
||||
|
||||
// Error pages are loaded as LOAD_BACKGROUND, so they don't get load events.
|
||||
var event = new CustomEvent("AboutTabCrashedLoad", {bubbles:true});
|
||||
|
@ -12,18 +12,19 @@
|
||||
<!ENTITY % globalDTD
|
||||
SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ENTITY % browserDTD
|
||||
SYSTEM "chrome://browser/locale/browser.dtd">
|
||||
%browserDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
|
||||
<!ENTITY % tabCrashedDTD
|
||||
SYSTEM "chrome://browser/locale/aboutTabCrashed.dtd">
|
||||
%tabCrashedDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://global/skin/in-content/info-pages.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/content/aboutTabCrashed.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/skin/aboutTabCrashed.css"/>
|
||||
</head>
|
||||
@ -36,12 +37,17 @@
|
||||
<p>&tabCrashed.message;</p>
|
||||
|
||||
<div id="report-box">
|
||||
<input type="checkbox" id="checkSendReport" checked="checked"/>
|
||||
<label for="checkSendReport">&tabCrashed.checkSendReport;</label>
|
||||
<input type="checkbox" id="sendReport" checked="checked"/>
|
||||
<label for="sendReport">&tabCrashed.sendReport;</label>
|
||||
</div>
|
||||
|
||||
<p id="reportSent">&tabCrashed.reportSent;</p>
|
||||
|
||||
<div class="button-container">
|
||||
<button id="tryAgain">&tabCrashed.tryAgain;</button>
|
||||
<button id="closeTab" onclick="closeTab()">
|
||||
&tabCrashed.closeTab;</button>
|
||||
<button id="restoreTab" onclick="restoreTab()">
|
||||
&tabCrashed.restoreTab;</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -1116,7 +1116,7 @@ var gBrowserInit = {
|
||||
#endif
|
||||
}, false, true);
|
||||
|
||||
gBrowser.addEventListener("AboutTabCrashedTryAgain", function(event) {
|
||||
gBrowser.addEventListener("AboutTabCrashedMessage", function(event) {
|
||||
let ownerDoc = event.originalTarget;
|
||||
|
||||
if (!ownerDoc.documentURI.startsWith("about:tabcrashed")) {
|
||||
@ -1134,8 +1134,16 @@ var gBrowserInit = {
|
||||
TabCrashReporter.submitCrashReport(browser);
|
||||
}
|
||||
#endif
|
||||
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
SessionStore.reviveCrashedTab(tab);
|
||||
switch (event.detail.message) {
|
||||
case "closeTab":
|
||||
gBrowser.removeTab(tab, { animate: true });
|
||||
break;
|
||||
case "restoreTab":
|
||||
SessionStore.reviveCrashedTab(tab);
|
||||
break;
|
||||
}
|
||||
}, false, true);
|
||||
|
||||
let uriToLoad = this._getUriToLoad();
|
||||
|
@ -51,9 +51,10 @@ tabpanels {
|
||||
}
|
||||
}
|
||||
|
||||
.tab-icon-image:not([src]):not([pinned]),
|
||||
.tab-icon-image:not([src]):not([pinned]):not([crashed]),
|
||||
.tab-throbber:not([busy]),
|
||||
.tab-throbber[busy] + .tab-icon-image {
|
||||
.tab-icon-image[busy],
|
||||
.tab-icon-overlay[busy] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -664,9 +664,13 @@
|
||||
// We need to add 2 because loadURIWithFlags may have
|
||||
// cancelled a pending load which would have cleared
|
||||
// its anchor scroll detection temporary increment.
|
||||
if (aWebProgress.isTopLevel)
|
||||
if (aWebProgress.isTopLevel) {
|
||||
this.mBrowser.userTypedClear += 2;
|
||||
|
||||
// If the browser is loading it must not be crashed anymore
|
||||
this.mTab.removeAttribute("crashed");
|
||||
}
|
||||
|
||||
if (this._shouldShowProgress(aRequest)) {
|
||||
if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
|
||||
this.mTab.setAttribute("busy", "true");
|
||||
@ -3579,6 +3583,7 @@
|
||||
browser.docShell.displayLoadError(Cr.NS_ERROR_CONTENT_CRASHED, uri, null);
|
||||
browser.removeAttribute("crashedPageTitle");
|
||||
let tab = this.getTabForBrowser(browser);
|
||||
tab.setAttribute("crashed", true);
|
||||
this.setIcon(tab, icon);
|
||||
]]>
|
||||
</handler>
|
||||
@ -4980,11 +4985,14 @@
|
||||
class="tab-throbber"
|
||||
role="presentation"
|
||||
layer="true" />
|
||||
<xul:image xbl:inherits="src=image,fadein,pinned,selected"
|
||||
<xul:image xbl:inherits="src=image,fadein,pinned,selected,busy,crashed"
|
||||
anonid="tab-icon-image"
|
||||
class="tab-icon-image"
|
||||
validate="never"
|
||||
role="presentation"/>
|
||||
<xul:image xbl:inherits="crashed,busy"
|
||||
class="tab-icon-overlay"
|
||||
role="presentation"/>
|
||||
<xul:label flex="1"
|
||||
anonid="tab-label"
|
||||
xbl:inherits="value=visibleLabel,crop,accesskey,fadein,pinned,selected"
|
||||
|
@ -69,6 +69,7 @@ browser.jar:
|
||||
content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
|
||||
content/browser/aboutSocialError.xhtml (content/aboutSocialError.xhtml)
|
||||
content/browser/aboutProviderDirectory.xhtml (content/aboutProviderDirectory.xhtml)
|
||||
content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css)
|
||||
content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js)
|
||||
content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml)
|
||||
* content/browser/browser.css (content/browser.css)
|
||||
|
@ -6,6 +6,12 @@
|
||||
const PAGE_1 = "data:text/html,<html><body>A%20regular,%20everyday,%20normal%20page.";
|
||||
const PAGE_2 = "data:text/html,<html><body>Another%20regular,%20everyday,%20normal%20page.";
|
||||
|
||||
// Turn off tab animations for testing
|
||||
Services.prefs.setBoolPref("browser.tabs.animate", false);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("browser.tabs.animate");
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns a Promise that resolves once a remote <xul:browser> has experienced
|
||||
* a crash. Also does the job of cleaning up the minidump of the crash.
|
||||
@ -58,6 +64,7 @@ function crashBrowser(browser) {
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(observer, 'ipc:content-shutdown');
|
||||
info("Crash cleaned up");
|
||||
resolve();
|
||||
};
|
||||
|
||||
@ -67,6 +74,7 @@ function crashBrowser(browser) {
|
||||
let aboutTabCrashedLoadPromise = new Promise((resolve, reject) => {
|
||||
browser.addEventListener("AboutTabCrashedLoad", function onCrash() {
|
||||
browser.removeEventListener("AboutTabCrashedLoad", onCrash, false);
|
||||
info("about:tabcrashed loaded");
|
||||
resolve();
|
||||
}, false, true);
|
||||
});
|
||||
@ -75,7 +83,22 @@ function crashBrowser(browser) {
|
||||
// evaluated.
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", false);
|
||||
return Promise.all([crashCleanupPromise, aboutTabCrashedLoadPromise]);
|
||||
return Promise.all([crashCleanupPromise, aboutTabCrashedLoadPromise]).then(() => {
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
is(tab.getAttribute("crashed"), "true", "Tab should be marked as crashed");
|
||||
});
|
||||
}
|
||||
|
||||
function clickButton(browser, id) {
|
||||
info("Clicking " + id);
|
||||
|
||||
let frame_script = (id) => {
|
||||
let button = content.document.getElementById(id);
|
||||
button.click();
|
||||
};
|
||||
|
||||
let mm = browser.messageManager;
|
||||
mm.loadFrameScript("data:,(" + frame_script.toString() + ")('" + id + "');", false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,6 +255,7 @@ add_task(function test_revived_history_from_remote() {
|
||||
// become remote again.
|
||||
browser.loadURI(PAGE_2);
|
||||
yield promiseTabRestored(newTab);
|
||||
ok(!newTab.hasAttribute("crashed"), "Tab shouldn't be marked as crashed anymore.");
|
||||
ok(browser.isRemoteBrowser, "Should be a remote browser");
|
||||
TabState.flush(browser);
|
||||
|
||||
@ -272,6 +296,7 @@ add_task(function test_revived_history_from_non_remote() {
|
||||
// become remote again.
|
||||
browser.loadURI("about:mozilla");
|
||||
yield promiseBrowserLoaded(browser);
|
||||
ok(!newTab.hasAttribute("crashed"), "Tab shouldn't be marked as crashed anymore.");
|
||||
ok(!browser.isRemoteBrowser, "Should not be a remote browser");
|
||||
TabState.flush(browser);
|
||||
|
||||
@ -301,6 +326,14 @@ add_task(function test_revive_tab_from_session_store() {
|
||||
browser.loadURI(PAGE_1);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
|
||||
let newTab2 = gBrowser.addTab();
|
||||
let browser2 = newTab2.linkedBrowser;
|
||||
ok(browser2.isRemoteBrowser, "Should be a remote browser");
|
||||
yield promiseBrowserLoaded(browser2);
|
||||
|
||||
browser.loadURI(PAGE_1);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
|
||||
browser.loadURI(PAGE_2);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
|
||||
@ -308,12 +341,17 @@ add_task(function test_revive_tab_from_session_store() {
|
||||
|
||||
// Crash the tab
|
||||
yield crashBrowser(browser);
|
||||
|
||||
is(newTab2.getAttribute("crashed"), "true", "Second tab should be crashed too.");
|
||||
|
||||
// Flush out any notifications from the crashed browser.
|
||||
TabState.flush(browser);
|
||||
|
||||
// Use SessionStore to revive the tab
|
||||
SessionStore.reviveCrashedTab(newTab);
|
||||
clickButton(browser, "restoreTab");
|
||||
yield promiseBrowserLoaded(browser);
|
||||
ok(!newTab.hasAttribute("crashed"), "Tab shouldn't be marked as crashed anymore.");
|
||||
is(newTab2.getAttribute("crashed"), "true", "Second tab should still be crashed though.");
|
||||
|
||||
// We can't just check browser.currentURI.spec, because from
|
||||
// the outside, a crashed tab has the same URI as the page
|
||||
@ -325,4 +363,35 @@ add_task(function test_revive_tab_from_session_store() {
|
||||
yield promiseHistoryLength(browser, 2);
|
||||
|
||||
gBrowser.removeTab(newTab);
|
||||
});
|
||||
gBrowser.removeTab(newTab2);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Checks that about:tabcrashed can close the current tab
|
||||
*/
|
||||
add_task(function test_close_tab_after_crash() {
|
||||
let newTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = newTab;
|
||||
let browser = newTab.linkedBrowser;
|
||||
ok(browser.isRemoteBrowser, "Should be a remote browser");
|
||||
yield promiseBrowserLoaded(browser);
|
||||
|
||||
browser.loadURI(PAGE_1);
|
||||
yield promiseBrowserLoaded(browser);
|
||||
|
||||
TabState.flush(browser);
|
||||
|
||||
// Crash the tab
|
||||
yield crashBrowser(browser);
|
||||
// Flush out any notifications from the crashed browser.
|
||||
TabState.flush(browser);
|
||||
|
||||
let promise = promiseEvent(gBrowser.tabContainer, "TabClose");
|
||||
|
||||
// Click the close tab button
|
||||
clickButton(browser, "closeTab");
|
||||
yield promise;
|
||||
|
||||
is(gBrowser.tabs.length, 1, "Should have closed the tab");
|
||||
});
|
||||
|
@ -488,15 +488,19 @@ function promiseDelayedStartupFinished(aWindow) {
|
||||
return new Promise(resolve => whenDelayedStartupFinished(aWindow, resolve));
|
||||
}
|
||||
|
||||
function promiseTabRestored(tab) {
|
||||
function promiseEvent(element, eventType, isCapturing = false) {
|
||||
return new Promise(resolve => {
|
||||
tab.addEventListener("SSTabRestored", function onRestored() {
|
||||
tab.removeEventListener("SSTabRestored", onRestored);
|
||||
resolve();
|
||||
});
|
||||
element.addEventListener(eventType, function listener(event) {
|
||||
element.removeEventListener(eventType, listener, isCapturing);
|
||||
resolve(event);
|
||||
}, isCapturing);
|
||||
});
|
||||
}
|
||||
|
||||
function promiseTabRestored(tab) {
|
||||
return promiseEvent(tab, "SSTabRestored");
|
||||
}
|
||||
|
||||
function sendMessage(browser, name, data = {}) {
|
||||
browser.messageManager.sendAsyncMessage(name, data);
|
||||
return promiseContentMessage(browser, name);
|
||||
|
10
browser/locales/en-US/chrome/browser/aboutTabCrashed.dtd
Normal file
10
browser/locales/en-US/chrome/browser/aboutTabCrashed.dtd
Normal file
@ -0,0 +1,10 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<!ENTITY tabCrashed.header "Bad news first: This tab has crashed">
|
||||
<!ENTITY tabCrashed.message "Now for the good news: You can just close this tab, restore it or restore all your crashed tabs.">
|
||||
<!ENTITY tabCrashed.sendReport "Submit a crash report to help prevent more bad news">
|
||||
<!ENTITY tabCrashed.reportSent "Crash report already submitted; thank you for helping make &brandShortName; better!">
|
||||
<!ENTITY tabCrashed.closeTab "Close This Tab">
|
||||
<!ENTITY tabCrashed.restoreTab "Restore This Tab">
|
@ -795,11 +795,6 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
||||
a CSS length value. -->
|
||||
<!ENTITY pluginNotification.width "28em">
|
||||
|
||||
<!ENTITY tabCrashed.header "Tab crashed">
|
||||
<!ENTITY tabCrashed.message "Well, this is embarrassing. We tried to display this Web page, but it's not responding.">
|
||||
<!ENTITY tabCrashed.checkSendReport "Tell &vendorShortName; about this crash so they can fix it.">
|
||||
<!ENTITY tabCrashed.tryAgain "Try Again">
|
||||
|
||||
<!ENTITY uiTour.infoPanel.close "Close">
|
||||
|
||||
<!ENTITY appMenuSidebars.label "Sidebars">
|
||||
|
@ -18,6 +18,7 @@
|
||||
locale/browser/aboutHealthReport.dtd (%chrome/browser/aboutHealthReport.dtd)
|
||||
#endif
|
||||
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
|
||||
locale/browser/aboutTabCrashed.dtd (%chrome/browser/aboutTabCrashed.dtd)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
locale/browser/syncProgress.dtd (%chrome/browser/syncProgress.dtd)
|
||||
locale/browser/syncCustomize.dtd (%chrome/browser/syncCustomize.dtd)
|
||||
|
@ -82,6 +82,7 @@ this.TabCrashReporter = {
|
||||
if (this.browserMap.get(browser) == childID) {
|
||||
this.browserMap.delete(browser);
|
||||
browser.contentDocument.documentElement.classList.remove("crashDumpAvailable");
|
||||
browser.contentDocument.documentElement.classList.add("crashDumpSubmitted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,108 +0,0 @@
|
||||
body {
|
||||
background-color: rgb(241, 244, 248);
|
||||
margin-top: 2em;
|
||||
font: message-box;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
#error-box {
|
||||
background: url('chrome://global/skin/icons/information-24.png') no-repeat left 4px;
|
||||
-moz-padding-start: 30px;
|
||||
}
|
||||
|
||||
#error-box:-moz-locale-dir(rtl) {
|
||||
background-position: right 4px;
|
||||
}
|
||||
|
||||
#main-error-msg {
|
||||
color: #4b4b4b;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#report-box {
|
||||
text-align: center;
|
||||
width: 75%;
|
||||
margin: 0 auto;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.crashDumpAvailable #report-box {
|
||||
display: block
|
||||
}
|
||||
|
||||
#button-box {
|
||||
text-align: center;
|
||||
width: 75%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@media all and (min-width: 300px) {
|
||||
#error-box {
|
||||
max-width: 50%;
|
||||
margin: 0 auto;
|
||||
background-image: url('chrome://global/skin/icons/information-32.png');
|
||||
min-height: 36px;
|
||||
-moz-padding-start: 38px;
|
||||
}
|
||||
|
||||
button {
|
||||
width: auto !important;
|
||||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (min-width: 780px) {
|
||||
#error-box {
|
||||
max-width: 30%;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
font: message-box;
|
||||
font-size: 0.6875em;
|
||||
-moz-appearance: none;
|
||||
-moz-user-select: none;
|
||||
width: 100%;
|
||||
margin: 2px 0;
|
||||
padding: 2px 6px;
|
||||
line-height: 1.2;
|
||||
background-color: hsla(210,30%,95%,.1);
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
|
||||
background-clip: padding-box;
|
||||
border: 1px solid hsla(210,15%,25%,.4);
|
||||
border-color: hsla(210,15%,25%,.3) hsla(210,15%,25%,.35) hsla(210,15%,25%,.4);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.3) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.1);
|
||||
|
||||
transition-property: background-color, border-color, box-shadow;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease;
|
||||
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: hsla(210,30%,95%,.8);
|
||||
border-color: hsla(210,15%,25%,.45) hsla(210,15%,25%,.5) hsla(210,15%,25%,.55);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.3) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.1),
|
||||
0 0 3px hsla(210,15%,25%,.1);
|
||||
transition-property: background-color, border-color, box-shadow;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
button:hover:active {
|
||||
background-color: hsla(210,15%,25%,.2);
|
||||
box-shadow: 0 1px 1px hsla(210,15%,25%,.2) inset,
|
||||
0 0 2px hsla(210,15%,25%,.4) inset;
|
||||
transition-property: background-color, border-color, box-shadow;
|
||||
transition-duration: 10ms;
|
||||
transition-timing-function: linear;
|
||||
}
|
@ -191,6 +191,7 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png)
|
||||
skin/classic/browser/tabbrowser/alltabs-inverted.png (tabbrowser/alltabs-inverted.png)
|
||||
skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)
|
||||
skin/classic/browser/tabbrowser/crashed.svg (../shared/tabbrowser/crashed.svg)
|
||||
skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png)
|
||||
skin/classic/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png)
|
||||
skin/classic/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
|
||||
|
@ -3092,6 +3092,14 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force the overlay to create a new stacking context so it always appears on
|
||||
* top of the icon.
|
||||
*/
|
||||
.tab-icon-overlay {
|
||||
opacity: 0.9999;
|
||||
}
|
||||
|
||||
.tab-label:not([selected="true"]) {
|
||||
opacity: .7;
|
||||
}
|
||||
|
@ -301,6 +301,7 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png (tabbrowser/alltabs-box-bkgnd-icon.png)
|
||||
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted.png (tabbrowser/alltabs-box-bkgnd-icon-inverted.png)
|
||||
skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png (tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png)
|
||||
skin/classic/browser/tabbrowser/crashed.svg (../shared/tabbrowser/crashed.svg)
|
||||
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
|
||||
skin/classic/browser/tabbrowser/newtab@2x.png (tabbrowser/newtab@2x.png)
|
||||
skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* 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/. */
|
||||
|
||||
.title {
|
||||
background-image: url("chrome://browser/skin/tab-crashed.svg");
|
||||
}
|
||||
|
||||
#report-box {
|
||||
display: none;
|
||||
#reportSent {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.crashDumpAvailable #report-box {
|
||||
display: block
|
||||
}
|
16
browser/themes/shared/tabbrowser/crashed.svg
Normal file
16
browser/themes/shared/tabbrowser/crashed.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="22 22 16 16" enable-background="new 22 22 16 16" xml:space="preserve">
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="30" y1="23" x2="30" y2="37">
|
||||
<stop offset="0" style="stop-color:#E63B2E"/>
|
||||
<stop offset="1" style="stop-color:#C33931"/>
|
||||
</linearGradient>
|
||||
<circle fill="url(#SVGID_1_)" cx="30" cy="30" r="7"/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M31.03,33.304c0,0.6-0.479,1.092-1.091,1.092c-0.6,0-1.079-0.492-1.079-1.092
|
||||
c0-0.588,0.479-1.079,1.079-1.079C30.551,32.225,31.03,32.716,31.03,33.304z M29.171,31.133l-0.24-5.253h2.015l-0.24,5.253H29.171z
|
||||
"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 970 B |
@ -65,6 +65,10 @@
|
||||
-moz-padding-start: 9px;
|
||||
}
|
||||
|
||||
.tab-content[pinned] {
|
||||
-moz-padding-end: 3px;
|
||||
}
|
||||
|
||||
.tab-throbber,
|
||||
.tab-icon-image,
|
||||
.tab-close-button {
|
||||
@ -75,12 +79,26 @@
|
||||
.tab-icon-image {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
-moz-margin-end: 6px;
|
||||
}
|
||||
|
||||
.tab-icon-image {
|
||||
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
|
||||
}
|
||||
|
||||
.tab-icon-overlay {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: -16px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[crashed] {
|
||||
display: -moz-box;
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/crashed.svg");
|
||||
}
|
||||
|
||||
.tab-throbber[busy] {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/connecting.png");
|
||||
}
|
||||
@ -89,11 +107,6 @@
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/loading.png");
|
||||
}
|
||||
|
||||
.tab-throbber:not([pinned]),
|
||||
.tab-icon-image:not([pinned]) {
|
||||
-moz-margin-end: 6px;
|
||||
}
|
||||
|
||||
.tab-label {
|
||||
-moz-margin-end: 0;
|
||||
-moz-margin-start: 0;
|
||||
|
@ -219,6 +219,7 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab-XPVista7.png)
|
||||
skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
|
||||
skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)
|
||||
skin/classic/browser/tabbrowser/crashed.svg (../shared/tabbrowser/crashed.svg)
|
||||
skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png)
|
||||
skin/classic/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png)
|
||||
skin/classic/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png)
|
||||
@ -689,6 +690,7 @@ browser.jar:
|
||||
skin/classic/aero/browser/tabbrowser/newtab-XPVista7.png (tabbrowser/newtab-XPVista7.png)
|
||||
skin/classic/aero/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
|
||||
skin/classic/aero/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)
|
||||
skin/classic/aero/browser/tabbrowser/crashed.svg (../shared/tabbrowser/crashed.svg)
|
||||
skin/classic/aero/browser/tabbrowser/loading.png (tabbrowser/loading.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png)
|
||||
|
@ -13,6 +13,7 @@ xul|tab[selected] {
|
||||
}
|
||||
|
||||
xul|button,
|
||||
html|button,
|
||||
xul|colorpicker[type="button"],
|
||||
xul|menulist {
|
||||
margin: 2px 4px;
|
||||
|
@ -15,12 +15,14 @@ xul|tab[selected] {
|
||||
}
|
||||
|
||||
xul|button,
|
||||
html|button,
|
||||
xul|colorpicker[type="button"],
|
||||
xul|menulist {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
xul|button {
|
||||
xul|button,
|
||||
html|button {
|
||||
/* use the same margin of other elements for the alignment */
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
|
@ -29,6 +29,11 @@ html|h1 {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
html|hr {
|
||||
border-style: solid none none none;
|
||||
border-color: #c1c1c1;
|
||||
}
|
||||
|
||||
xul|caption {
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
@ -406,11 +411,29 @@ html|a:hover:active,
|
||||
|
||||
/* Checkboxes and radio buttons */
|
||||
|
||||
/* Hide the actual checkbox */
|
||||
html|input[type="checkbox"] {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* Create a box to style as the checkbox */
|
||||
html|input[type="checkbox"] + html|label:before {
|
||||
display: inline-block;
|
||||
content: "";
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
html|input[type="checkbox"] + html|label {
|
||||
line-height: 0px;
|
||||
}
|
||||
|
||||
xul|checkbox {
|
||||
-moz-margin-start: 0;
|
||||
}
|
||||
|
||||
xul|*.checkbox-check {
|
||||
xul|*.checkbox-check,
|
||||
html|input[type="checkbox"] + html|label:before {
|
||||
-moz-appearance: none;
|
||||
width: 23px;
|
||||
height: 23px;
|
||||
@ -425,7 +448,8 @@ xul|*.checkbox-check {
|
||||
box-shadow: 0 1px 1px 0 #fff, inset 0 2px 0 0 rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
xul|checkbox:not([disabled="true"]):hover > xul|*.checkbox-check {
|
||||
xul|checkbox:not([disabled="true"]):hover > xul|*.checkbox-check,
|
||||
html|input[type="checkbox"]:not(:disabled) + html|label:hover:before {
|
||||
border-color: #0095dd;
|
||||
}
|
||||
|
||||
@ -433,7 +457,12 @@ xul|*.checkbox-check[checked] {
|
||||
list-style-image: url("chrome://global/skin/in-content/check.svg#check");
|
||||
}
|
||||
|
||||
xul|checkbox[disabled="true"] > xul|*.checkbox-check {
|
||||
html|input[type="checkbox"]:checked + html|label:before {
|
||||
background-image: url("chrome://global/skin/in-content/check.svg#check"), linear-gradient(#fff, rgba(255,255,255,0.8)) !important;
|
||||
}
|
||||
|
||||
xul|checkbox[disabled="true"] > xul|*.checkbox-check,
|
||||
html|input[type="checkbox"]:disabled + html|label {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ xul|caption {
|
||||
}
|
||||
|
||||
xul|button,
|
||||
html|button,
|
||||
xul|colorpicker[type="button"],
|
||||
xul|menulist {
|
||||
margin: 2px 4px;
|
||||
|
Loading…
Reference in New Issue
Block a user