--- a/MozillaFirefox/MozillaFirefox.changes Sat Nov 11 10:08:36 2017 +0100
+++ b/MozillaFirefox/MozillaFirefox.changes Wed Jan 10 22:27:13 2018 +0100
@@ -1,15 +1,123 @@
-------------------------------------------------------------------
-Thu Nov 9 15:01:30 UTC 2017 - wr@rosenauer.org
-
-- update to Firefox 57.0b14
+Tue Jan 9 18:48:02 UTC 2018 - wr@rosenauer.org
+
+- fixed build with latest rust (mozilla-rust-1.23.patch)
+
+-------------------------------------------------------------------
+Thu Jan 4 12:23:41 UTC 2018 - wr@rosenauer.org
+
+- update to Firefox 57.0.4
+ MFSA 2018-1: Speculative execution side-channel attack ("Spectre")
+ (boo#1074723)
+
+-------------------------------------------------------------------
+Wed Jan 3 08:29:38 UTC 2018 - wr@rosenauer.org
+
+- fixed regression introduced Oct 10th which made Firefox crash
+ when cancelling the KDE file dialog (boo#1069962)
+
+-------------------------------------------------------------------
+Fri Dec 29 19:52:34 UTC 2017 - astieger@suse.com
+
+- Mozilla Firefox 57.0.3:
+ * Fix a crash reporting issue that inadvertently sends background
+ tab crash reports to Mozilla without user opt-in (bmo#1427111,
+ bsc#1074235)
+- Includes changes from 57.0.2:
+ * fixes for platforms other than GNU/Linux
+
+-------------------------------------------------------------------
+Fri Dec 8 15:52:17 UTC 2017 - dimstar@opensuse.org
+
+- Explicitly buildrequires python2-xml: The build system relies on
+ it. We wrongly relied on other packages pulling it in for us.
+
+-------------------------------------------------------------------
+Thu Dec 7 11:12:31 UTC 2017 - dimstar@opensuse.org
+
+- Escape the usage of %{VERSION} when calling out to rpm.
+ RPM 4.14 has %{VERSION} defined as 'the main packages version'.
+
+-------------------------------------------------------------------
+Wed Nov 29 23:45:03 UTC 2017 - wr@rosenauer.org
+
+- update to Firefox 57.0.1
+ * CVE-2017-7843: Web worker in Private Browsing mode can write
+ IndexedDB data (bsc#1072034, bmo#1410106)
+ * CVE-2017-7844: Visited history information leak through SVG
+ image (bsc#1072036, bmo#1420001)
+ * Fix a video color distortion issue on YouTube and other video
+ sites with some AMD devices (bmo#1417442)
+ * Fix an issue with prefs.js when the profile path has non-ascii
+ characters (bmo#1420427)
+
+-------------------------------------------------------------------
+Tue Nov 21 09:00:48 UTC 2017 - christophe@krop.fr
+
+- Add mozilla-bmo1360278.patch
+ Starting with Firefox 57, the context menu appears on key press.
+ This patch creates a config entry to restore the
+ old behaviour. Without the patch, the mouse gesture extensions
+ require 2 clicks to work (bmo#1360278).
+ The new config entry is named ui.context_menus.after_mouseup
+ (default : false).
+
+-------------------------------------------------------------------
+Sat Nov 18 08:35:21 UTC 2017 - wr@rosenauer.org
+
+- Allow experimental CSD for Gtk3 (bmo#1399611) if available and enabled
+ widget.allow-client-side-decoration=true
+ (mozilla-bmo1399611-csd.patch)
+
+-------------------------------------------------------------------
+Wed Nov 15 06:46:06 UTC 2017 - wr@rosenauer.org
+
+- update to Firefox 57.0 (boo#1068101)
* Firefox Quantum
* Photon UI
+ * Unified address and search bar
* AMD VP9 hardware video decoder support
* Added support for Date/Time input
* stricter security sandbox blocking filesystem reading and
writing on Linux systems
* middle mouse paste in the content area no longer navigates to
URLs by default on Unix systems
+ MFSA 2017-24
+ * CVE-2017-7828 (bmo#1406750. bmo#1412252)
+ Use-after-free of PressShell while restyling layout
+ * CVE-2017-7830 (bmo#1408990)
+ Cross-origin URL information leak through Resource Timing API
+ * CVE-2017-7831 (bmo#1392026)
+ Information disclosure of exposed properties on JavaScript proxy
+ objects
+ * CVE-2017-7832 (bmo#1408782)
+ Domain spoofing through use of dotless 'i' character followed
+ by accent markers
+ * CVE-2017-7833 (bmo#1370497)
+ Domain spoofing with Arabic and Indic vowel marker characters
+ * CVE-2017-7834 (bmo#1358009)
+ data: URLs opened in new tabs bypass CSP protections
+ * CVE-2017-7835 (bmo#1402363)
+ Mixed content blocking incorrectly applies with redirects
+ * CVE-2017-7836 (bmo#1401339)
+ Pingsender dynamically loads libcurl on Linux and OS X
+ * CVE-2017-7837 (bmo#1325923)
+ SVG loaded as <img> can use meta tags to set cookies
+ * CVE-2017-7838 (bmo#1399540)
+ Failure of individual decoding of labels in international domain
+ names triggers punycode display of entire IDN
+ * CVE-2017-7839 (bmo#1402896)
+ Control characters before javascript: URLs defeats self-XSS
+ prevention mechanism
+ * CVE-2017-7840 (bmo#1366420)
+ Exported bookmarks do not strip script elements from user-supplied
+ tags
+ * CVE-2017-7842 (bmo#1397064)
+ Referrer Policy is not always respected for <link> elements
+ * CVE-2017-7827
+ Memory safety bugs fixed in Firefox 57
+ * CVE-2017-7826
+ Memory safety bugs fixed in Firefox 57 and Firefox ESR 52.5
- requires NSPR 4.17, NSS 3.33 and rustc 1.19
- rebased patches
- added mozilla-bindgen-systemlibs.patch to allow stylo build
--- a/MozillaFirefox/MozillaFirefox.spec Sat Nov 11 10:08:36 2017 +0100
+++ b/MozillaFirefox/MozillaFirefox.spec Wed Jan 10 22:27:13 2018 +0100
@@ -1,8 +1,8 @@
#
# spec file for package MozillaFirefox
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
-# 2006-2017 Wolfgang Rosenauer
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# 2006-2018 Wolfgang Rosenauer
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,11 +18,11 @@
# changed with every update
-%define major 56
+%define major 57
%define mainver %major.99
%define update_channel beta
%define branding 1
-%define releasedate 20171102181127
+%define releasedate 20180108140638
# PIE, full relro (x86_64 for now)
%define build_hardened 1
@@ -75,6 +75,7 @@
BuildRequires: mozilla-nspr-devel >= 4.17
BuildRequires: mozilla-nss-devel >= 3.33
BuildRequires: python-devel
+BuildRequires: python2-xml
BuildRequires: rust >= 1.19
BuildRequires: rust-std
BuildRequires: startup-notification-devel
@@ -153,6 +154,9 @@
Patch6: mozilla-reduce-files-per-UnifiedBindings.patch
Patch7: mozilla-aarch64-startup-crash.patch
Patch8: mozilla-bindgen-systemlibs.patch
+Patch9: mozilla-bmo1360278.patch
+Patch10: mozilla-bmo1399611-csd.patch
+Patch11: mozilla-rust-1.23.patch
# Firefox/browser
Patch101: firefox-kde.patch
Patch102: firefox-no-default-ualocale.patch
@@ -164,8 +168,8 @@
%if %branding
Requires: %{name}-branding > 44.0
%endif
-Requires: mozilla-nspr >= %(rpm -q --queryformat '%{VERSION}' mozilla-nspr)
-Requires: mozilla-nss >= %(rpm -q --queryformat '%{VERSION}' mozilla-nss)
+Requires: mozilla-nspr >= %(rpm -q --queryformat '%%{VERSION}' mozilla-nspr)
+Requires: mozilla-nss >= %(rpm -q --queryformat '%%{VERSION}' mozilla-nss)
Recommends: libcanberra0
Recommends: libpulse0
# addon leads to startup crash (bnc#908892)
@@ -264,6 +268,9 @@
%endif
%patch7 -p1
%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
# Firefox
%patch101 -p1
%patch102 -p1
--- a/MozillaFirefox/create-tar.sh Sat Nov 11 10:08:36 2017 +0100
+++ b/MozillaFirefox/create-tar.sh Wed Jan 10 22:27:13 2018 +0100
@@ -7,8 +7,8 @@
CHANNEL="beta"
BRANCH="releases/mozilla-$CHANNEL"
-RELEASE_TAG="FIREFOX_57_0b14_RELEASE"
-VERSION="56.99"
+RELEASE_TAG="FIREFOX_58_0b15_RELEASE"
+VERSION="57.99
# mozilla
if [ -d mozilla ]; then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MozillaFirefox/mozilla-bmo1360278.patch Wed Jan 10 22:27:13 2018 +0100
@@ -0,0 +1,1 @@
+../mozilla-bmo1360278.patch
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MozillaFirefox/mozilla-bmo1399611-csd.patch Wed Jan 10 22:27:13 2018 +0100
@@ -0,0 +1,1 @@
+../mozilla-bmo1399611-csd.patch
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MozillaFirefox/mozilla-rust-1.23.patch Wed Jan 10 22:27:13 2018 +0100
@@ -0,0 +1,1 @@
+../mozilla-rust-1.23.patch
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mozilla-bmo1360278.patch Wed Jan 10 22:27:13 2018 +0100
@@ -0,0 +1,260 @@
+
+# HG changeset patch
+# User Robin Grenet <robin.grenet@wanadoo.fr>
+# Date 1510835758 -3600
+# Node ID f540f9e801cb2e0be5259baea13dfce953ccb520
+# Parent 0abbf75bd0ecfa99ab4386f551a622983f5f27ea
+Bug 1360278 - Add preference to trigger context menu on mouse up for GTK+ and macOS, r=mstange,smaug
+
+MozReview-Commit-ID: Bg60bD8jIg6
+
+diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
+--- a/modules/libpref/init/all.js
++++ b/modules/libpref/init/all.js
+@@ -229,16 +229,20 @@ pref("dom.script_loader.bytecode_cache.e
+ pref("dom.script_loader.bytecode_cache.strategy", 0);
+
+ // Fastback caching - if this pref is negative, then we calculate the number
+ // of content viewers to cache based on the amount of available memory.
+ pref("browser.sessionhistory.max_total_viewers", -1);
+
+ pref("ui.use_native_colors", true);
+ pref("ui.click_hold_context_menus", false);
++
++// Pop up context menu on mouseup instead of mousedown, if that's the OS default.
++// Note: ignored on Windows (context menus always use mouseup)
++pref("ui.context_menus.after_mouseup", false);
+ // Duration of timeout of incremental search in menus (ms). 0 means infinite.
+ pref("ui.menu.incremental_search.timeout", 1000);
+ // If true, all popups won't hide automatically on blur
+ pref("ui.popup.disable_autohide", false);
+
+ pref("browser.display.use_document_fonts", 1); // 0 = never, 1 = quick, 2 = always
+ // 0 = default: always, except in high contrast mode
+ // 1 = always
+diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm
+--- a/widget/cocoa/nsChildView.mm
++++ b/widget/cocoa/nsChildView.mm
+@@ -4695,18 +4695,20 @@ NSEvent* gLastDragMouseDownEvent = nil;
+ [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
+ geckoEvent.button = WidgetMouseEvent::eRightButton;
+ geckoEvent.mClickCount = [theEvent clickCount];
+
+ mGeckoChild->DispatchInputEvent(&geckoEvent);
+ if (!mGeckoChild)
+ return;
+
+- // Let the superclass do the context menu stuff.
+- [super rightMouseDown:theEvent];
++ if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) {
++ // Let the superclass do the context menu stuff.
++ [super rightMouseDown:theEvent];
++ }
+
+ NS_OBJC_END_TRY_ABORT_BLOCK;
+ }
+
+ - (void)rightMouseUp:(NSEvent *)theEvent
+ {
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+
+@@ -4719,16 +4721,33 @@ NSEvent* gLastDragMouseDownEvent = nil;
+ WidgetMouseEvent geckoEvent(true, eMouseUp, mGeckoChild,
+ WidgetMouseEvent::eReal);
+ [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
+ geckoEvent.button = WidgetMouseEvent::eRightButton;
+ geckoEvent.mClickCount = [theEvent clickCount];
+
+ nsAutoRetainCocoaObject kungFuDeathGrip(self);
+ mGeckoChild->DispatchInputEvent(&geckoEvent);
++ if (!mGeckoChild)
++ return;
++
++ if (nsBaseWidget::ShowContextMenuAfterMouseUp()) {
++ // Let the superclass do the context menu stuff, but pretend it's rightMouseDown.
++ NSEvent *dupeEvent = [NSEvent mouseEventWithType:NSRightMouseDown
++ location:theEvent.locationInWindow
++ modifierFlags:theEvent.modifierFlags
++ timestamp:theEvent.timestamp
++ windowNumber:theEvent.windowNumber
++ context:theEvent.context
++ eventNumber:theEvent.eventNumber
++ clickCount:theEvent.clickCount
++ pressure:theEvent.pressure];
++
++ [super rightMouseDown:dupeEvent];
++ }
+
+ NS_OBJC_END_TRY_ABORT_BLOCK;
+ }
+
+ - (void)rightMouseDragged:(NSEvent*)theEvent
+ {
+ if (!mGeckoChild)
+ return;
+diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
+--- a/widget/gtk/nsWindow.cpp
++++ b/widget/gtk/nsWindow.cpp
+@@ -2733,16 +2733,29 @@ nsWindow::InitButtonEvent(WidgetMouseEve
+ }
+
+ static guint ButtonMaskFromGDKButton(guint button)
+ {
+ return GDK_BUTTON1_MASK << (button - 1);
+ }
+
+ void
++nsWindow::DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
++ GdkEventButton *aEvent)
++{
++ if (domButton == WidgetMouseEvent::eRightButton && MOZ_LIKELY(!mIsDestroyed)) {
++ WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
++ WidgetMouseEvent::eReal);
++ InitButtonEvent(contextMenuEvent, aEvent);
++ contextMenuEvent.pressure = mLastMotionPressure;
++ DispatchInputEvent(&contextMenuEvent);
++ }
++}
++
++void
+ nsWindow::OnButtonPressEvent(GdkEventButton *aEvent)
+ {
+ LOG(("Button %u press on %p\n", aEvent->button, (void *)this));
+
+ // If you double click in GDK, it will actually generate a second
+ // GDK_BUTTON_PRESS before sending the GDK_2BUTTON_PRESS, and this is
+ // different than the DOM spec. GDK puts this in the queue
+ // programatically, so it's safe to assume that if there's a
+@@ -2801,23 +2814,18 @@ nsWindow::OnButtonPressEvent(GdkEventBut
+ WidgetMouseEvent event(true, eMouseDown, this, WidgetMouseEvent::eReal);
+ event.button = domButton;
+ InitButtonEvent(event, aEvent);
+ event.pressure = mLastMotionPressure;
+
+ DispatchInputEvent(&event);
+
+ // right menu click on linux should also pop up a context menu
+- if (domButton == WidgetMouseEvent::eRightButton &&
+- MOZ_LIKELY(!mIsDestroyed)) {
+- WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
+- WidgetMouseEvent::eReal);
+- InitButtonEvent(contextMenuEvent, aEvent);
+- contextMenuEvent.pressure = mLastMotionPressure;
+- DispatchInputEvent(&contextMenuEvent);
++ if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) {
++ DispatchContextMenuEventFromMouseEvent(domButton, aEvent);
+ }
+ }
+
+ void
+ nsWindow::OnButtonReleaseEvent(GdkEventButton *aEvent)
+ {
+ LOG(("Button %u release on %p\n", aEvent->button, (void *)this));
+
+@@ -2843,16 +2851,21 @@ nsWindow::OnButtonReleaseEvent(GdkEventB
+ event.button = domButton;
+ InitButtonEvent(event, aEvent);
+ gdouble pressure = 0;
+ gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
+ event.pressure = pressure ? pressure : mLastMotionPressure;
+
+ DispatchInputEvent(&event);
+ mLastMotionPressure = pressure;
++
++ // right menu click on linux should also pop up a context menu
++ if (nsBaseWidget::ShowContextMenuAfterMouseUp()) {
++ DispatchContextMenuEventFromMouseEvent(domButton, aEvent);
++ }
+ }
+
+ void
+ nsWindow::OnContainerFocusInEvent(GdkEventFocus *aEvent)
+ {
+ LOGFOCUS(("OnContainerFocusInEvent [%p]\n", (void *)this));
+
+ // Unset the urgency hint, if possible
+diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
+--- a/widget/gtk/nsWindow.h
++++ b/widget/gtk/nsWindow.h
+@@ -240,16 +240,18 @@ private:
+ LayoutDeviceIntSize GetSafeWindowSize(LayoutDeviceIntSize aSize);
+
+ void EnsureGrabs (void);
+ void GrabPointer (guint32 aTime);
+ void ReleaseGrabs (void);
+
+ void UpdateClientOffset();
+
++ void DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
++ GdkEventButton *aEvent);
+ public:
+ void ThemeChanged(void);
+ void OnDPIChanged(void);
+ void OnCheckResize(void);
+ void OnCompositedChanged(void);
+
+ #ifdef MOZ_X11
+ Window mOldFocusWindow;
+diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp
+--- a/widget/nsBaseWidget.cpp
++++ b/widget/nsBaseWidget.cpp
+@@ -1213,16 +1213,32 @@ nsBaseWidget::DispatchEventToAPZOnly(moz
+ if (mAPZC) {
+ MOZ_ASSERT(APZThreadUtils::IsControllerThread());
+ uint64_t inputBlockId = 0;
+ ScrollableLayerGuid guid;
+ mAPZC->ReceiveInputEvent(*aEvent, &guid, &inputBlockId);
+ }
+ }
+
++// static
++bool
++nsBaseWidget::ShowContextMenuAfterMouseUp()
++{
++ static bool gContextMenuAfterMouseUp = false;
++ static bool gContextMenuAfterMouseUpCached = false;
++ if (!gContextMenuAfterMouseUpCached) {
++ Preferences::AddBoolVarCache(&gContextMenuAfterMouseUp,
++ "ui.context_menus.after_mouseup",
++ false);
++
++ gContextMenuAfterMouseUpCached = true;
++ }
++ return gContextMenuAfterMouseUp;
++}
++
+ nsIDocument*
+ nsBaseWidget::GetDocument() const
+ {
+ if (mWidgetListener) {
+ if (nsIPresShell* presShell = mWidgetListener->GetPresShell()) {
+ return presShell->GetDocument();
+ }
+ }
+diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h
+--- a/widget/nsBaseWidget.h
++++ b/widget/nsBaseWidget.h
+@@ -412,16 +412,22 @@ public:
+ void NotifyLiveResizeStopped();
+
+ #if defined(MOZ_WIDGET_ANDROID)
+ void RecvToolbarAnimatorMessageFromCompositor(int32_t) override {};
+ void UpdateRootFrameMetrics(const ScreenPoint& aScrollOffset, const CSSToScreenScale& aZoom) override {};
+ void RecvScreenPixels(mozilla::ipc::Shmem&& aMem, const ScreenIntSize& aSize) override {};
+ #endif
+
++ /**
++ * Whether context menus should only appear on mouseup instead of mousedown,
++ * on OSes where they normally appear on mousedown (macOS, *nix).
++ */
++ static bool ShowContextMenuAfterMouseUp();
++
+ protected:
+ // These are methods for CompositorWidgetWrapper, and should only be
+ // accessed from that class. Derived widgets can choose which methods to
+ // implement, or none if supporting out-of-process compositing.
+ virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) {
+ return true;
+ }
+ virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mozilla-bmo1399611-csd.patch Wed Jan 10 22:27:13 2018 +0100
@@ -0,0 +1,1744 @@
+diff -up firefox-57.0b8/browser/app/profile/firefox.js.1399611 firefox-57.0b8/browser/app/profile/firefox.js
+--- firefox-57.0b8/browser/app/profile/firefox.js.1399611 2017-10-16 12:11:45.364240654 +0200
++++ firefox-57.0b8/browser/app/profile/firefox.js 2017-10-16 12:28:03.860720910 +0200
+@@ -457,11 +457,7 @@ pref("browser.tabs.loadBookmarksInBackgr
+ pref("browser.tabs.loadBookmarksInTabs", false);
+ pref("browser.tabs.tabClipWidth", 140);
+ pref("browser.tabs.tabMinWidth", 76);
+-#ifdef UNIX_BUT_NOT_MAC
+-pref("browser.tabs.drawInTitlebar", false);
+-#else
+ pref("browser.tabs.drawInTitlebar", true);
+-#endif
+
+ // Offer additional drag space to the user. The drag space
+ // will only be shown if browser.tabs.drawInTitlebar is true.
+diff -up firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js.1399611 firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js
+--- firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js.1399611 2017-10-09 22:17:13.000000000 +0200
++++ firefox-57.0b8/browser/base/content/browser-tabsintitlebar.js 2017-10-16 12:11:45.364240654 +0200
+@@ -14,6 +14,11 @@ var TabsInTitlebar = {
+ this._readPref();
+ Services.prefs.addObserver(this._prefName, this);
+
++ // Always disable on unsupported GTK versions.
++ if (AppConstants.MOZ_WIDGET_TOOLKIT == "gtk3") {
++ this.allowedBy("gtk", window.matchMedia("(-moz-gtk-csd-available)"));
++ }
++
+ // We need to update the appearance of the titlebar when the menu changes
+ // from the active to the inactive state. We can't, however, rely on
+ // DOMMenuBarInactive, because the menu fires this event and then removes
+diff -up firefox-57.0b8/browser/base/moz.build.1399611 firefox-57.0b8/browser/base/moz.build
+--- firefox-57.0b8/browser/base/moz.build.1399611 2017-09-29 18:16:45.000000000 +0200
++++ firefox-57.0b8/browser/base/moz.build 2017-10-16 12:11:45.364240654 +0200
+@@ -57,7 +57,7 @@ DEFINES['APP_LICENSE_BLOCK'] = '%s/conte
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
+ DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1
+
+-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
++if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
+ DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
+diff -up firefox-57.0b8/browser/themes/linux/browser.css.1399611 firefox-57.0b8/browser/themes/linux/browser.css
+--- firefox-57.0b8/browser/themes/linux/browser.css.1399611 2017-10-05 06:17:37.000000000 +0200
++++ firefox-57.0b8/browser/themes/linux/browser.css 2017-10-16 12:11:45.365240651 +0200
+@@ -556,7 +556,9 @@ html|span.ac-emphasize-text-url {
+
+ #nav-bar,
+ #toolbar-menubar:not([autohide="true"]):not(:-moz-lwtheme):-moz-system-metric(menubar-drag),
+-#TabsToolbar:not(:-moz-lwtheme):-moz-system-metric(menubar-drag) {
++#TabsToolbar:not(:-moz-lwtheme):-moz-system-metric(menubar-drag),
++#main-window[tabsintitlebar] #toolbar-menubar:not([autohide="true"]),
++#main-window[tabsintitlebar] #TabsToolbar {
+ -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-drag");
+ }
+
+@@ -713,3 +715,85 @@ html|span.ac-emphasize-text-url {
+ .restore-tabs-button:hover:active:not([disabled="true"]) {
+ padding: 3px;
+ }
++
++@media not all and (-moz-gtk-csd-available) {
++ #main-window > #titlebar {
++ /* We need to hide the titlebar explicitly on versions of GTK without CSD. */
++ display: none;
++ }
++}
++
++/* Titlebar/CSD */
++@media (-moz-gtk-csd-available) {
++ #main-window[tabsintitlebar][sizemode="normal"] > #titlebar {
++ min-height: calc(var(--tab-min-height) + 12px);
++ }
++
++ #main-window[tabsintitlebar] #titlebar:-moz-lwtheme {
++ visibility: hidden;
++ }
++ #main-window[tabsintitlebar] #titlebar-content:-moz-lwtheme {
++ visibility: visible;
++ }
++
++ #main-window[tabsintitlebar][sizemode="normal"] > #titlebar {
++ -moz-appearance: -moz-window-titlebar;
++ }
++ #main-window[tabsintitlebar][sizemode="maximized"] > #titlebar {
++ -moz-appearance: -moz-window-titlebar-maximized;
++ }
++
++ /* The button box must appear on top of the navigator-toolbox in order for
++ * click and hover mouse events to work properly for the button in the restored
++ * window state. Otherwise, elements in the navigator-toolbox, like the menubar,
++ * can swallow those events.
++ */
++ #titlebar-buttonbox {
++ z-index: 1;
++ }
++
++ /* titlebar command buttons */
++ /* Use full scale icons here as the Gtk+ does. */
++ @media (-moz-gtk-csd-minimize-button) {
++ #titlebar-min {
++ list-style-image: url("moz-icon://stock/window-minimize-symbolic");
++ -moz-appearance: -moz-window-button-minimize;
++ }
++ }
++ @media not all and (-moz-gtk-csd-minimize-button) {
++ #titlebar-min {
++ display: none;
++ }
++ }
++
++ @media (-moz-gtk-csd-maximize-button) {
++ #titlebar-max {
++ list-style-image: url("moz-icon://stock/window-maximize-symbolic");
++ -moz-appearance: -moz-window-button-maximize;
++ }
++ #main-window[sizemode="maximized"] #titlebar-max {
++ list-style-image: url("moz-icon://stock/window-restore-symbolic");
++ -moz-appearance: -moz-window-button-restore;
++ }
++ }
++ @media not all and (-moz-gtk-csd-maximize-button) {
++ #titlebar-max {
++ display: none;
++ }
++ #main-window[sizemode="maximized"] #titlebar-max {
++ display: none;
++ }
++ }
++
++ @media (-moz-gtk-csd-close-button) {
++ #titlebar-close {
++ list-style-image: url("moz-icon://stock/window-close-symbolic");
++ -moz-appearance: -moz-window-button-close;
++ }
++ }
++ @media not all and (-moz-gtk-csd-close-button) {
++ #titlebar-close {
++ display: none;
++ }
++ }
++}
+diff -up firefox-57.0b8/dom/base/nsGkAtomList.h.1399611 firefox-57.0b8/dom/base/nsGkAtomList.h
+--- firefox-57.0b8/dom/base/nsGkAtomList.h.1399611 2017-09-15 06:15:41.000000000 +0200
++++ firefox-57.0b8/dom/base/nsGkAtomList.h 2017-10-16 12:11:45.365240651 +0200
+@@ -2270,6 +2270,10 @@ GK_ATOM(touch_enabled, "touch-enabled")
+ GK_ATOM(menubar_drag, "menubar-drag")
+ GK_ATOM(swipe_animation_enabled, "swipe-animation-enabled")
+ GK_ATOM(physical_home_button, "physical-home-button")
++GK_ATOM(gtk_csd_available, "gtk-csd-available")
++GK_ATOM(gtk_csd_minimize_button, "gtk-csd-minimize-button")
++GK_ATOM(gtk_csd_maximize_button, "gtk-csd-maximize-button")
++GK_ATOM(gtk_csd_close_button, "gtk-csd-close-button")
+
+ // windows theme selector metrics
+ GK_ATOM(windows_classic, "windows-classic")
+@@ -2306,6 +2310,10 @@ GK_ATOM(_moz_device_orientation, "-moz-d
+ GK_ATOM(_moz_is_resource_document, "-moz-is-resource-document")
+ GK_ATOM(_moz_swipe_animation_enabled, "-moz-swipe-animation-enabled")
+ GK_ATOM(_moz_physical_home_button, "-moz-physical-home-button")
++GK_ATOM(_moz_gtk_csd_available, "-moz-gtk-csd-available")
++GK_ATOM(_moz_gtk_csd_minimize_button, "-moz-gtk-csd-minimize-button")
++GK_ATOM(_moz_gtk_csd_maximize_button, "-moz-gtk-csd-maximize-button")
++GK_ATOM(_moz_gtk_csd_close_button, "-moz-gtk-csd-close-button")
+
+ // application commands
+ GK_ATOM(Back, "Back")
+diff -up firefox-57.0b8/gfx/src/nsThemeConstants.h.1399611 firefox-57.0b8/gfx/src/nsThemeConstants.h
+--- firefox-57.0b8/gfx/src/nsThemeConstants.h.1399611 2017-06-12 18:37:10.000000000 +0200
++++ firefox-57.0b8/gfx/src/nsThemeConstants.h 2017-10-16 12:11:45.365240651 +0200
+@@ -299,6 +299,7 @@ enum ThemeWidgetType : uint8_t {
+ NS_THEME_MAC_SOURCE_LIST,
+ NS_THEME_MAC_SOURCE_LIST_SELECTION,
+ NS_THEME_MAC_ACTIVE_SOURCE_LIST_SELECTION,
++ NS_THEME_GTK_WINDOW_DECORATION,
+
+ ThemeWidgetType_COUNT
+ };
+diff -up firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp.1399611 firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp
+--- firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp.1399611 2017-08-02 14:27:54.000000000 +0200
++++ firefox-57.0b8/layout/style/nsCSSRuleProcessor.cpp 2017-10-16 12:11:45.365240651 +0200
+@@ -1180,6 +1180,30 @@ nsCSSRuleProcessor::InitSystemMetrics()
+ sSystemMetrics->AppendElement(nsGkAtoms::physical_home_button);
+ }
+
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_available);
++ }
++
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDMinimizeButton,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_minimize_button);
++ }
++
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDMaximizeButton,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_maximize_button);
++ }
++
++ rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDCloseButton,
++ &metricResult);
++ if (NS_SUCCEEDED(rv) && metricResult) {
++ sSystemMetrics->AppendElement(nsGkAtoms::gtk_csd_close_button);
++ }
++
+ #ifdef XP_WIN
+ if (NS_SUCCEEDED(
+ LookAndFeel::GetInt(LookAndFeel::eIntID_WindowsThemeIdentifier,
+diff -up firefox-57.0b8/layout/style/nsMediaFeatures.cpp.1399611 firefox-57.0b8/layout/style/nsMediaFeatures.cpp
+--- firefox-57.0b8/layout/style/nsMediaFeatures.cpp.1399611 2017-09-15 06:15:42.000000000 +0200
++++ firefox-57.0b8/layout/style/nsMediaFeatures.cpp 2017-10-16 12:11:45.366240647 +0200
+@@ -788,6 +788,42 @@ nsMediaFeatures::features[] = {
+ GetSystemMetric
+ },
+
++ {
++ &nsGkAtoms::_moz_gtk_csd_available,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_available },
++ GetSystemMetric
++ },
++
++ {
++ &nsGkAtoms::_moz_gtk_csd_minimize_button,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_minimize_button },
++ GetSystemMetric
++ },
++
++ {
++ &nsGkAtoms::_moz_gtk_csd_maximize_button,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_maximize_button },
++ GetSystemMetric
++ },
++
++ {
++ &nsGkAtoms::_moz_gtk_csd_close_button,
++ nsMediaFeature::eMinMaxNotAllowed,
++ nsMediaFeature::eBoolInteger,
++ nsMediaFeature::eNoRequirements,
++ { &nsGkAtoms::gtk_csd_close_button },
++ GetSystemMetric
++ },
++
+ // Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
+ // Internal because it is really only useful in the user agent anyway
+ // and therefore not worth standardizing.
+diff -up firefox-57.0b8/modules/libpref/init/all.js.1399611 firefox-57.0b8/modules/libpref/init/all.js
+--- firefox-57.0b8/modules/libpref/init/all.js.1399611 2017-10-12 18:12:09.000000000 +0200
++++ firefox-57.0b8/modules/libpref/init/all.js 2017-10-16 12:11:45.366240647 +0200
+@@ -4911,6 +4911,7 @@ pref("gfx.apitrace.enabled",false);
+ pref("gfx.xrender.enabled",false);
+ pref("widget.chrome.allow-gtk-dark-theme", false);
+ pref("widget.content.allow-gtk-dark-theme", false);
++pref("widget.allow-client-side-decoration", false);
+ #endif
+ #endif
+
+diff -up firefox-57.0b8/toolkit/modules/moz.build.1399611 firefox-57.0b8/toolkit/modules/moz.build
+--- firefox-57.0b8/toolkit/modules/moz.build.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/toolkit/modules/moz.build 2017-10-16 12:11:45.366240647 +0200
+@@ -259,7 +259,7 @@ EXTRA_JS_MODULES.sessionstore += [
+ ]
+
+ DEFINES['INSTALL_COMPACT_THEMES'] = 1
+-if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
++if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa', 'gtk3'):
+ DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
+diff -up firefox-57.0b8/widget/gtk/gtk3drawing.cpp.1399611 firefox-57.0b8/widget/gtk/gtk3drawing.cpp
+--- firefox-57.0b8/widget/gtk/gtk3drawing.cpp.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/widget/gtk/gtk3drawing.cpp 2017-10-16 12:11:45.367240644 +0200
+@@ -17,6 +17,7 @@
+ #include "WidgetStyleCache.h"
+
+ #include <math.h>
++#include <dlfcn.h>
+
+ static gboolean checkbox_check_state;
+ static gboolean notebook_has_tab_gap;
+@@ -39,9 +40,25 @@ static gint
+ moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
+ GtkWidgetState* state, GtkTextDirection direction);
+
++static void
++moz_gtk_add_style_margin(GtkStyleContext* style,
++ gint* left, gint* top, gint* right, gint* bottom);
++static void
++moz_gtk_add_style_border(GtkStyleContext* style,
++ gint* left, gint* top, gint* right, gint* bottom);
++static void
++moz_gtk_add_style_padding(GtkStyleContext* style,
++ gint* left, gint* top, gint* right, gint* bottom);
++static void moz_gtk_add_margin_border_padding(GtkStyleContext *style,
++ gint* left, gint* top,
++ gint* right, gint* bottom);
++static void moz_gtk_add_border_padding(GtkStyleContext *style,
++ gint* left, gint* top,
++ gint* right, gint* bottom);
+ static GtkBorder
+ GetMarginBorderPadding(GtkStyleContext* aStyle);
+
++
+ // GetStateFlagsFromGtkWidgetState() can be safely used for the specific
+ // GtkWidgets that set both prelight and active flags. For other widgets,
+ // either the GtkStateFlags or Gecko's GtkWidgetState need to be carefully
+@@ -233,6 +250,43 @@ moz_gtk_splitter_get_metrics(gint orient
+ return MOZ_GTK_SUCCESS;
+ }
+
++void
++moz_gtk_get_window_border(gint* top, gint* right, gint* bottom, gint* left)
++{
++ MOZ_ASSERT(gtk_check_version(3, 20, 0) == nullptr,
++ "Window decorations are only supported on GTK 3.20+.");
++
++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW);
++
++ *top = *right = *bottom = *left = 0;
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
++ GtkBorder windowMargin;
++ gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &windowMargin);
++
++ style = GetStyleContext(MOZ_GTK_WINDOW_DECORATION);
++
++ // Available on GTK 3.20+.
++ static auto sGtkRenderBackgroundGetClip =
++ (void (*)(GtkStyleContext*, gdouble, gdouble, gdouble, gdouble, GdkRectangle*))
++ dlsym(RTLD_DEFAULT, "gtk_render_background_get_clip");
++
++ GdkRectangle shadowClip;
++ sGtkRenderBackgroundGetClip(style, 0, 0, 0, 0, &shadowClip);
++
++ // Transfer returned inset rectangle to GtkBorder
++ GtkBorder shadowBorder = {
++ static_cast<gint16>(-shadowClip.x), // left
++ static_cast<gint16>(shadowClip.width + shadowClip.x), // right
++ static_cast<gint16>(-shadowClip.y), // top
++ static_cast<gint16>(shadowClip.height + shadowClip.y), // bottom
++ };
++
++ *left += MAX(windowMargin.left, shadowBorder.left);
++ *right += MAX(windowMargin.right, shadowBorder.right);
++ *top += MAX(windowMargin.top, shadowBorder.top);
++ *bottom += MAX(windowMargin.bottom, shadowBorder.bottom);
++}
++
+ static gint
+ moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+@@ -302,6 +356,24 @@ moz_gtk_button_paint(cairo_t *cr, GdkRec
+ }
+
+ static gint
++moz_gtk_header_bar_button_paint(cairo_t *cr, GdkRectangle* rect,
++ GtkWidgetState* state,
++ GtkReliefStyle relief, GtkWidget* widget,
++ GtkTextDirection direction)
++{
++ GtkBorder margin;
++ GtkStyleContext* style = gtk_widget_get_style_context(widget);
++ gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin);
++
++ rect->x += margin.left;
++ rect->y += margin.top;
++ rect->width -= margin.left + margin.right;
++ rect->height -= margin.top + margin.bottom;
++
++ return moz_gtk_button_paint(cr, rect, state, relief, widget, direction);
++}
++
++static gint
+ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkWidgetState* state,
+ gboolean selected, gboolean inconsistent,
+@@ -1948,6 +2020,38 @@ moz_gtk_info_bar_paint(cairo_t *cr, GdkR
+ return MOZ_GTK_SUCCESS;
+ }
+
++static gint
++moz_gtk_header_bar_paint(WidgetNodeType widgetType,
++ cairo_t *cr, GdkRectangle* rect, GtkWidgetState* state)
++{
++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
++ GtkStyleContext *style;
++
++ style = GetStyleContext(widgetType, GTK_TEXT_DIR_LTR,
++ state_flags);
++ InsetByMargin(rect, style);
++ gtk_render_background(style, cr, rect->x, rect->y, rect->width,
++ rect->height);
++ gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
++
++ return MOZ_GTK_SUCCESS;
++}
++
++void
++moz_gtk_header_bar_paint(cairo_t *cr, GdkRectangle* rect)
++{
++ static GtkWidgetState state;
++ moz_gtk_header_bar_paint(MOZ_GTK_HEADER_BAR, cr, rect, &state);
++}
++
++void
++moz_gtk_get_header_bar_border(gint* top, gint* right, gint* bottom, gint* left)
++{
++ *left = *top = *right = *bottom = 0;
++ moz_gtk_add_border_padding(GetStyleContext(MOZ_GTK_HEADER_BAR),
++ left, top, right, bottom);
++}
++
+ static void
+ moz_gtk_add_style_margin(GtkStyleContext* style,
+ gint* left, gint* top, gint* right, gint* bottom)
+@@ -1999,6 +2103,14 @@ static void moz_gtk_add_margin_border_pa
+ moz_gtk_add_style_padding(style, left, top, right, bottom);
+ }
+
++static void moz_gtk_add_border_padding(GtkStyleContext *style,
++ gint* left, gint* top,
++ gint* right, gint* bottom)
++{
++ moz_gtk_add_style_border(style, left, top, right, bottom);
++ moz_gtk_add_style_padding(style, left, top, right, bottom);
++}
++
+ static GtkBorder
+ GetMarginBorderPadding(GtkStyleContext* aStyle)
+ {
+@@ -2054,8 +2166,7 @@ moz_gtk_get_widget_border(WidgetNodeType
+ // XXX: Subtract 1 pixel from the padding to account for the default
+ // padding in forms.css. See bug 1187385.
+ *left = *top = *right = *bottom = -1;
+- moz_gtk_add_style_padding(style, left, top, right, bottom);
+- moz_gtk_add_style_border(style, left, top, right, bottom);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
+
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -2076,10 +2187,8 @@ moz_gtk_get_widget_border(WidgetNodeType
+ *left = *top = *right = *bottom =
+ gtk_container_get_border_width(GTK_CONTAINER(
+ GetWidget(MOZ_GTK_TREE_HEADER_CELL)));
+-
+ style = GetStyleContext(MOZ_GTK_TREE_HEADER_CELL);
+- moz_gtk_add_style_border(style, left, top, right, bottom);
+- moz_gtk_add_style_padding(style, left, top, right, bottom);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_TREE_HEADER_SORTARROW:
+@@ -2105,8 +2214,7 @@ moz_gtk_get_widget_border(WidgetNodeType
+ gtk_container_get_border_width(GTK_CONTAINER(
+ GetWidget(MOZ_GTK_COMBOBOX_BUTTON)));
+ style = GetStyleContext(MOZ_GTK_COMBOBOX_BUTTON);
+- moz_gtk_add_style_padding(style, left, top, right, bottom);
+- moz_gtk_add_style_border(style, left, top, right, bottom);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
+
+ /* If there is no separator, don't try to count its width. */
+ separator_width = 0;
+@@ -2160,10 +2268,8 @@ moz_gtk_get_widget_border(WidgetNodeType
+ style = gtk_widget_get_style_context(w);
+
+ *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(w));
+- moz_gtk_add_style_border(style,
+- left, top, right, bottom);
+- moz_gtk_add_style_padding(style,
+- left, top, right, bottom);
++ moz_gtk_add_border_padding(style,
++ left, top, right, bottom);
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_MENUPOPUP:
+@@ -2210,6 +2316,21 @@ moz_gtk_get_widget_border(WidgetNodeType
+
+ return MOZ_GTK_SUCCESS;
+ }
++ case MOZ_GTK_HEADER_BAR:
++ case MOZ_GTK_HEADER_BAR_MAXIMIZED:
++ {
++ style = GetStyleContext(widget);
++ moz_gtk_add_border_padding(style, left, top, right, bottom);
++ return MOZ_GTK_SUCCESS;
++ }
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ {
++ style = GetStyleContext(widget);
++ moz_gtk_add_margin_border_padding(style, left, top, right, bottom);
++ return MOZ_GTK_SUCCESS;
++ }
+
+ /* These widgets have no borders, since they are not containers. */
+ case MOZ_GTK_CHECKBUTTON_LABEL:
+@@ -2646,6 +2767,36 @@ GetScrollbarMetrics(GtkOrientation aOrie
+ return metrics;
+ }
+
++void
++moz_gtk_window_decoration_paint(cairo_t *cr, GdkRectangle* rect)
++{
++ gint top, right, bottom, left;
++ moz_gtk_get_window_border(&top, &right, &bottom, &left);
++
++ cairo_save(cr);
++ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
++ cairo_rectangle(cr, rect->x, rect->y, left, rect->height);
++ cairo_fill(cr);
++ cairo_rectangle(cr, rect->x+rect->width-right, rect->y, right, rect->height);
++ cairo_fill(cr);
++ cairo_rectangle(cr, rect->x, rect->y, rect->width, top);
++ cairo_fill(cr);
++ cairo_rectangle(cr, rect->x, rect->height-bottom, rect->width, bottom);
++ cairo_fill(cr);
++ cairo_restore(cr);
++
++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW_DECORATION,
++ GTK_TEXT_DIR_NONE);
++ rect->x += left;
++ rect->y += top;
++ rect->width -= left + right;
++ rect->height -= top + bottom;
++
++ gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
++ gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
++}
++
++
+ /* cairo_t *cr argument has to be a system-cairo. */
+ gint
+ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr,
+@@ -2671,6 +2822,14 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ GetWidget(MOZ_GTK_BUTTON),
+ direction);
+ break;
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ return moz_gtk_header_bar_button_paint(cr, rect, state,
++ (GtkReliefStyle) flags,
++ GetWidget(widget),
++ direction);
++ break;
+ case MOZ_GTK_CHECKBUTTON:
+ case MOZ_GTK_RADIOBUTTON:
+ return moz_gtk_toggle_paint(cr, rect, state,
+@@ -2877,6 +3036,10 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ case MOZ_GTK_INFO_BAR:
+ return moz_gtk_info_bar_paint(cr, rect, state);
+ break;
++ case MOZ_GTK_HEADER_BAR:
++ case MOZ_GTK_HEADER_BAR_MAXIMIZED:
++ return moz_gtk_header_bar_paint(widget, cr, rect, state);
++ break;
+ default:
+ g_warning("Unknown widget type: %d", widget);
+ }
+diff -up firefox-57.0b8/widget/gtk/gtkdrawing.h.1399611 firefox-57.0b8/widget/gtk/gtkdrawing.h
+--- firefox-57.0b8/widget/gtk/gtkdrawing.h.1399611 2017-06-12 18:37:20.000000000 +0200
++++ firefox-57.0b8/widget/gtk/gtkdrawing.h 2017-10-16 12:11:45.367240644 +0200
+@@ -268,8 +268,14 @@ typedef enum {
+ MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL,
+ /* Paints the background of a window, dialog or page. */
+ MOZ_GTK_WINDOW,
++ /* Used only as a container for MOZ_GTK_HEADER_BAR_MAXIMIZED. */
++ MOZ_GTK_WINDOW_MAXIMIZED,
+ /* Window container for all widgets */
+ MOZ_GTK_WINDOW_CONTAINER,
++ /* Window with the 'csd' style class. */
++ MOZ_GTK_WINDOW_CSD,
++ /* Client-side window decoration node. Available on GTK 3.20+. */
++ MOZ_GTK_WINDOW_DECORATION,
+ /* Paints a GtkInfoBar, for notifications. */
+ MOZ_GTK_INFO_BAR,
+ /* Used for widget tree construction. */
+@@ -290,6 +296,14 @@ typedef enum {
+ MOZ_GTK_COMBOBOX_ENTRY_ARROW,
+ /* Used for scrolled window shell. */
+ MOZ_GTK_SCROLLED_WINDOW,
++ /* Paints a GtkHeaderBar */
++ MOZ_GTK_HEADER_BAR,
++ /* Paints a GtkHeaderBar in maximized state */
++ MOZ_GTK_HEADER_BAR_MAXIMIZED,
++ /* Paints a GtkHeaderBar title buttons */
++ MOZ_GTK_HEADER_BAR_BUTTON_CLOSE,
++ MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE,
++ MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE,
+
+ MOZ_GTK_WIDGET_NODE_COUNT
+ } WidgetNodeType;
+@@ -542,6 +556,32 @@ gint moz_gtk_get_menu_separator_height(g
+ */
+ gint moz_gtk_splitter_get_metrics(gint orientation, gint* size);
+
++#if (MOZ_WIDGET_GTK == 3)
++/**
++ * Gets the margins to be used for window decorations, typically the extra space
++ * required to draw a drop shadow (obtained from gtk_render_background_get_clip).
++ * Only available on GTK 3.20+.
++ */
++void moz_gtk_get_window_border(gint* top, gint* right, gint* bottom, gint* left);
++
++/**
++ * Draw window decorations, typically a shadow.
++ * Only available on GTK 3.20+.
++ */
++void moz_gtk_window_decoration_paint(cairo_t *cr, GdkRectangle* rect);
++
++/**
++ * Gets the border of window header bar, only available on GTK 3.20+.
++ */
++void moz_gtk_get_header_bar_border(gint* top, gint* right, gint* bottom, gint* left);
++
++/**
++ * Draw window header bar, only available on GTK 3.20+.
++ */
++void moz_gtk_header_bar_paint(cairo_t *cr, GdkRectangle* rect);
++
++#endif
++
+ /**
+ * Get the YTHICKNESS of a tab (notebook extension).
+ */
+diff -up firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c.1399611 firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c
+--- firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c.1399611 2017-10-09 22:17:13.000000000 +0200
++++ firefox-57.0b8/widget/gtk/mozgtk/mozgtk.c 2017-10-16 12:11:45.367240644 +0200
+@@ -580,6 +580,8 @@ STUB(gtk_style_context_set_state)
+ STUB(gtk_style_properties_lookup_property)
+ STUB(gtk_tree_view_column_get_button)
+ STUB(gtk_widget_get_preferred_size)
++STUB(gtk_widget_get_preferred_width)
++STUB(gtk_widget_get_preferred_height)
+ STUB(gtk_widget_get_state_flags)
+ STUB(gtk_widget_get_style_context)
+ STUB(gtk_widget_path_append_type)
+@@ -589,6 +591,10 @@ STUB(gtk_widget_path_iter_add_class)
+ STUB(gtk_widget_path_get_object_type)
+ STUB(gtk_widget_path_new)
+ STUB(gtk_widget_path_unref)
++STUB(gtk_widget_set_margin_left)
++STUB(gtk_widget_set_margin_right)
++STUB(gtk_widget_set_margin_top)
++STUB(gtk_widget_set_margin_bottom)
+ STUB(gtk_widget_set_visual)
+ STUB(gtk_app_chooser_dialog_new_for_content_type)
+ STUB(gtk_app_chooser_get_type)
+@@ -601,6 +607,7 @@ STUB(gtk_color_chooser_get_type)
+ STUB(gtk_color_chooser_set_rgba)
+ STUB(gtk_color_chooser_get_rgba)
+ STUB(gtk_color_chooser_set_use_alpha)
++STUB(gtk_window_get_size)
+ #endif
+
+ #ifdef GTK2_SYMBOLS
+diff -up firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp.1399611 firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp
+--- firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp.1399611 2017-09-21 06:10:10.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsLookAndFeel.cpp 2017-10-16 12:11:45.367240644 +0200
+@@ -642,6 +642,22 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
+ case eIntID_ContextMenuOffsetHorizontal:
+ aResult = 2;
+ break;
++ case eIntID_GTKCSDAvailable:
++ EnsureInit();
++ aResult = sCSDAvailable;
++ break;
++ case eIntID_GTKCSDMaximizeButton:
++ EnsureInit();
++ aResult = sCSDMaximizeButton;
++ break;
++ case eIntID_GTKCSDMinimizeButton:
++ EnsureInit();
++ aResult = sCSDMinimizeButton;
++ break;
++ case eIntID_GTKCSDCloseButton:
++ EnsureInit();
++ aResult = sCSDCloseButton;
++ break;
+ default:
+ aResult = 0;
+ res = NS_ERROR_FAILURE;
+@@ -1048,6 +1064,40 @@ nsLookAndFeel::EnsureInit()
+
+ gtk_widget_destroy(window);
+ g_object_unref(labelWidget);
++
++ // Require GTK 3.20 for client-side decoration support.
++ // 3.20 exposes gtk_render_background_get_clip, which is required for
++ // calculating shadow metrics for decorated windows.
++ sCSDAvailable = gtk_check_version(3, 20, 0) == nullptr;
++ if (sCSDAvailable) {
++ sCSDAvailable =
++ mozilla::Preferences::GetBool("widget.allow-client-side-decoration",
++ false);
++ }
++
++ const gchar* decorationLayout = nullptr;
++ if (gtk_check_version(3, 12, 0) == nullptr) {
++ static auto sGtkHeaderBarGetDecorationLayoutPtr =
++ (const gchar* (*)(GtkWidget*))
++ dlsym(RTLD_DEFAULT, "gtk_header_bar_get_decoration_layout");
++
++ GtkWidget* headerBar = GetWidget(MOZ_GTK_HEADER_BAR);
++ decorationLayout = sGtkHeaderBarGetDecorationLayoutPtr(headerBar);
++ if (!decorationLayout) {
++ g_object_get(settings, "gtk-decoration-layout", &decorationLayout,
++ nullptr);
++ }
++ }
++
++ if (decorationLayout) {
++ sCSDCloseButton = (strstr(decorationLayout, "close") != nullptr);
++ sCSDMaximizeButton = (strstr(decorationLayout, "maximize") != nullptr);
++ sCSDMinimizeButton = (strstr(decorationLayout, "minimize") != nullptr);
++ } else {
++ sCSDCloseButton = true;
++ sCSDMaximizeButton = true;
++ sCSDMinimizeButton = true;
++ }
+ }
+
+ // virtual
+diff -up firefox-57.0b8/widget/gtk/nsLookAndFeel.h.1399611 firefox-57.0b8/widget/gtk/nsLookAndFeel.h
+--- firefox-57.0b8/widget/gtk/nsLookAndFeel.h.1399611 2017-09-21 06:10:10.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsLookAndFeel.h 2017-10-16 12:11:45.367240644 +0200
+@@ -32,6 +32,8 @@ public:
+ virtual char16_t GetPasswordCharacterImpl();
+ virtual bool GetEchoPasswordImpl();
+
++ bool IsCSDAvailable() const { return sCSDAvailable; }
++
+ protected:
+
+ // Cached fonts
+@@ -82,6 +84,10 @@ protected:
+ char16_t sInvisibleCharacter;
+ float sCaretRatio;
+ bool sMenuSupportsDrag;
++ bool sCSDAvailable;
++ bool sCSDMaximizeButton;
++ bool sCSDMinimizeButton;
++ bool sCSDCloseButton;
+ bool mInitialized;
+
+ void EnsureInit();
+diff -up firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp.1399611 firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp
+--- firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp.1399611 2017-09-19 06:18:28.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsNativeThemeGTK.cpp 2017-10-16 12:11:45.368240640 +0200
+@@ -23,6 +23,7 @@
+ #include "nsIDOMHTMLInputElement.h"
+ #include "nsGkAtoms.h"
+ #include "nsAttrValueInlines.h"
++#include "nsWindow.h"
+
+ #include "mozilla/EventStates.h"
+ #include "mozilla/Services.h"
+@@ -703,6 +704,24 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
+ case NS_THEME_GTK_INFO_BAR:
+ aGtkWidgetType = MOZ_GTK_INFO_BAR;
+ break;
++ case NS_THEME_WINDOW_TITLEBAR:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR;
++ break;
++ case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_MAXIMIZED;
++ break;
++ case NS_THEME_WINDOW_BUTTON_CLOSE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_CLOSE;
++ break;
++ case NS_THEME_WINDOW_BUTTON_MINIMIZE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE;
++ break;
++ case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
++ break;
++ case NS_THEME_WINDOW_BUTTON_RESTORE:
++ aGtkWidgetType = MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE;
++ break;
+ default:
+ return false;
+ }
+@@ -1627,6 +1646,10 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
+ case NS_THEME_MENULIST:
+ case NS_THEME_TOOLBARBUTTON:
+ case NS_THEME_TREEHEADERCELL:
++ case NS_THEME_WINDOW_BUTTON_CLOSE:
++ case NS_THEME_WINDOW_BUTTON_MINIMIZE:
++ case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
++ case NS_THEME_WINDOW_BUTTON_RESTORE:
+ {
+ if (aWidgetType == NS_THEME_MENULIST) {
+ // Include the arrow size.
+@@ -1892,9 +1915,21 @@ nsNativeThemeGTK::ThemeSupportsWidget(ns
+ case NS_THEME_DIALOG:
+ #if (MOZ_WIDGET_GTK == 3)
+ case NS_THEME_GTK_INFO_BAR:
++ case NS_THEME_GTK_WINDOW_DECORATION:
+ #endif
+ return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
+
++ case NS_THEME_WINDOW_BUTTON_CLOSE:
++ case NS_THEME_WINDOW_BUTTON_MINIMIZE:
++ case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
++ case NS_THEME_WINDOW_BUTTON_RESTORE:
++ case NS_THEME_WINDOW_TITLEBAR:
++ case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
++ // GtkHeaderBar is available on GTK 3.10+, which is used for styling
++ // title bars and title buttons.
++ return gtk_check_version(3, 10, 0) == nullptr &&
++ !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
++
+ case NS_THEME_MENULIST_BUTTON:
+ if (aFrame && aFrame->GetWritingMode().IsVertical()) {
+ return false;
+@@ -1978,6 +2013,13 @@ nsNativeThemeGTK::GetWidgetTransparency(
+ #else
+ return eTransparent;
+ #endif
++ case NS_THEME_GTK_WINDOW_DECORATION:
++ {
++ nsWindow* window = static_cast<nsWindow*>(aFrame->GetNearestWidget());
++ if (window)
++ return window->IsComposited() ? eTransparent : eOpaque;
++ return eOpaque;
++ }
+ }
+
+ return eUnknownTransparency;
+diff -up firefox-57.0b8/widget/gtk/nsWindow.cpp.1399611 firefox-57.0b8/widget/gtk/nsWindow.cpp
+--- firefox-57.0b8/widget/gtk/nsWindow.cpp.1399611 2017-10-16 12:11:45.361240666 +0200
++++ firefox-57.0b8/widget/gtk/nsWindow.cpp 2017-10-16 12:11:45.369240636 +0200
+@@ -85,6 +85,7 @@
+ #include "nsIPropertyBag2.h"
+ #include "GLContext.h"
+ #include "gfx2DGlue.h"
++#include "nsLookAndFeel.h"
+
+ #ifdef ACCESSIBILITY
+ #include "mozilla/a11y/Accessible.h"
+@@ -139,6 +140,8 @@ using namespace mozilla::widget;
+
+ #include "mozilla/layers/APZCTreeManager.h"
+
++#include "gtkdrawing.h"
++
+ using namespace mozilla;
+ using namespace mozilla::gfx;
+ using namespace mozilla::widget;
+@@ -186,6 +189,8 @@ static gboolean expose_event_cb
+ #else
+ static gboolean expose_event_cb (GtkWidget *widget,
+ cairo_t *rect);
++static gboolean expose_event_decoration_draw_cb (GtkWidget *widget,
++ cairo_t *cr);
+ #endif
+ static gboolean configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event);
+@@ -231,7 +236,6 @@ static void screen_composited_change
+ gpointer user_data);
+ static void widget_composited_changed_cb (GtkWidget* widget,
+ gpointer user_data);
+-
+ #if (MOZ_WIDGET_GTK == 3)
+ static void scale_changed_cb (GtkWidget* widget,
+ GParamSpec* aPSpec,
+@@ -440,6 +444,7 @@ nsWindow::nsWindow()
+
+ mContainer = nullptr;
+ mGdkWindow = nullptr;
++ mIsCSDEnabled = false;
+ mShell = nullptr;
+ mCompositorWidgetDelegate = nullptr;
+ mHasMappedToplevel = false;
+@@ -481,6 +486,9 @@ nsWindow::nsWindow()
+ mLastScrollEventTime = GDK_CURRENT_TIME;
+ #endif
+ mPendingConfigures = 0;
++ mDrawWindowDecoration = false;
++ mDecorationSize = {0,0,0,0};
++ mCSDSupportLevel = CSD_SUPPORT_UNKNOWN;
+ }
+
+ nsWindow::~nsWindow()
+@@ -1479,8 +1487,8 @@ LayoutDeviceIntRect
+ nsWindow::GetScreenBounds()
+ {
+ LayoutDeviceIntRect rect;
+- if (mIsTopLevel && mContainer) {
+- // use the point including window decorations
++ if (mIsTopLevel && mContainer && !IsClientDecorated()) {
++ // use the point including default Gtk+ window decorations
+ gint x, y;
+ gdk_window_get_root_origin(gtk_widget_get_window(GTK_WIDGET(mContainer)), &x, &y);
+ rect.MoveTo(GdkPointToDevicePixels({ x, y }));
+@@ -1606,6 +1614,10 @@ nsWindow::SetCursor(nsCursor aCursor)
+ return;
+
+ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), newCursor);
++ if (IsClientDecorated()) {
++ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mShell)),
++ newCursor);
++ }
+ }
+ }
+ }
+@@ -1662,6 +1674,10 @@ nsWindow::SetCursor(imgIContainer* aCurs
+ if (cursor) {
+ if (mContainer) {
+ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), cursor);
++ if (IsClientDecorated()) {
++ gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mShell)),
++ cursor);
++ }
+ rv = NS_OK;
+ }
+ #if (MOZ_WIDGET_GTK == 3)
+@@ -2176,6 +2192,12 @@ nsWindow::OnExposeEvent(cairo_t *cr)
+ return TRUE;
+ }
+
++ // Clip upper part of the mContainer to get visible rounded corners
++ // of GtkHeaderBar which is renderd to mShell.
++ if (mIsCSDEnabled) {
++ ApplyCSDClipping();
++ }
++
+ // If this widget uses OMTC...
+ if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT ||
+ GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR) {
+@@ -2586,6 +2608,53 @@ nsWindow::OnMotionNotifyEvent(GdkEventMo
+ }
+ }
+ #endif /* MOZ_X11 */
++ // Client is decorated and we're getting the motion event for mShell
++ // window which draws the CSD decorations around mContainer.
++ if (IsClientDecorated()) {
++ if (aEvent->window == gtk_widget_get_window(mShell)) {
++ GdkWindowEdge edge;
++ LayoutDeviceIntPoint refPoint =
++ GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
++ if (CheckResizerEdge(refPoint, edge)) {
++ nsCursor cursor = eCursor_none;
++ switch (edge) {
++ case GDK_WINDOW_EDGE_NORTH:
++ cursor = eCursor_n_resize;
++ break;
++ case GDK_WINDOW_EDGE_NORTH_WEST:
++ cursor = eCursor_nw_resize;
++ break;
++ case GDK_WINDOW_EDGE_NORTH_EAST:
++ cursor = eCursor_ne_resize;
++ break;
++ case GDK_WINDOW_EDGE_WEST:
++ cursor = eCursor_w_resize;
++ break;
++ case GDK_WINDOW_EDGE_EAST:
++ cursor = eCursor_e_resize;
++ break;
++ case GDK_WINDOW_EDGE_SOUTH:
++ cursor = eCursor_s_resize;
++ break;
++ case GDK_WINDOW_EDGE_SOUTH_WEST:
++ cursor = eCursor_sw_resize;
++ break;
++ case GDK_WINDOW_EDGE_SOUTH_EAST:
++ cursor = eCursor_se_resize;
++ break;
++ }
++ SetCursor(cursor);
++ return;
++ }
++ }
++ // We're not on resize handle - check if we need to reset cursor back.
++ if (mCursor == eCursor_n_resize || mCursor == eCursor_nw_resize ||
++ mCursor == eCursor_ne_resize || mCursor == eCursor_w_resize ||
++ mCursor == eCursor_e_resize || mCursor == eCursor_s_resize ||
++ mCursor == eCursor_sw_resize || mCursor == eCursor_se_resize) {
++ SetCursor(eCursor_standard);
++ }
++ }
+
+ WidgetMouseEvent event(true, eMouseMove, this, WidgetMouseEvent::eReal);
+
+@@ -2756,6 +2825,20 @@ nsWindow::OnButtonPressEvent(GdkEventBut
+ if (CheckForRollup(aEvent->x_root, aEvent->y_root, false, false))
+ return;
+
++ if (IsClientDecorated() && aEvent->window == gtk_widget_get_window(mShell)) {
++ // Check to see if the event is within our window's resize region
++ GdkWindowEdge edge;
++ LayoutDeviceIntPoint refPoint =
++ GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
++ if (CheckResizerEdge(refPoint, edge)) {
++ gdk_window_begin_resize_drag(gtk_widget_get_window(mShell),
++ edge, aEvent->button,
++ aEvent->x_root, aEvent->y_root,
++ aEvent->time);
++ return;
++ }
++ }
++
+ gdouble pressure = 0;
+ gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
+ mLastMotionPressure = pressure;
+@@ -3341,6 +3424,8 @@ nsWindow::OnWindowStateEvent(GtkWidget *
+ #endif //ACCESSIBILITY
+ }
+
++ UpdateClientDecorations();
++
+ if (mWidgetListener) {
+ mWidgetListener->SizeModeChanged(mSizeState);
+ if (aEvent->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
+@@ -3405,6 +3490,7 @@ nsWindow::OnCompositedChanged()
+ presShell->ThemeChanged();
+ }
+ }
++ UpdateClientDecorations();
+ }
+
+ void
+@@ -3593,7 +3679,8 @@ nsWindow::Create(nsIWidget* aParent,
+ GtkWindow *topLevelParent = nullptr;
+ nsWindow *parentnsWindow = nullptr;
+ GtkWidget *eventWidget = nullptr;
+- bool shellHasCSD = false;
++ GtkWidget *drawWidget = nullptr;
++ bool drawToContainer = false;
+
+ if (aParent) {
+ parentnsWindow = static_cast<nsWindow*>(aParent);
+@@ -3640,29 +3727,47 @@ nsWindow::Create(nsIWidget* aParent,
+ GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
+ mShell = gtk_window_new(type);
+
+- bool useAlphaVisual = (mWindowType == eWindowType_popup &&
+- aInitData->mSupportTranslucency);
++ bool useAlphaVisual = false;
++#if (MOZ_WIDGET_GTK == 3)
++ // When CSD is available we can emulate it for toplevel windows.
++ // Content is rendered to mContainer and transparent decorations to mShell.
++ if (GetCSDSupportLevel() != CSD_SUPPORT_NONE &&
++ mWindowType == eWindowType_toplevel) {
++ int32_t isCSDAvailable = false;
++ nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
++ &isCSDAvailable);
++ if (NS_SUCCEEDED(rv)) {
++ mIsCSDEnabled = useAlphaVisual = isCSDAvailable;
++ }
++ } else
++#endif
++ if (mWindowType == eWindowType_popup) {
++ useAlphaVisual = aInitData->mSupportTranslucency;
++ }
+
+ // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false
+ // to allow experimentation
+ if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false))
+ useAlphaVisual = true;
+
++ // An ARGB visual is only useful if we are on a compositing
++ // window manager.
++ GdkScreen *screen = gtk_widget_get_screen(mShell);
++ if (useAlphaVisual && !gdk_screen_is_composited(screen)) {
++ useAlphaVisual = false;
++ }
++
+ // We need to select an ARGB visual here instead of in
+ // SetTransparencyMode() because it has to be done before the
+- // widget is realized. An ARGB visual is only useful if we
+- // are on a compositing window manager.
++ // widget is realized.
+ if (useAlphaVisual) {
+- GdkScreen *screen = gtk_widget_get_screen(mShell);
+- if (gdk_screen_is_composited(screen)) {
+ #if (MOZ_WIDGET_GTK == 2)
+- GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
+- gtk_widget_set_colormap(mShell, colormap);
++ GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
++ gtk_widget_set_colormap(mShell, colormap);
+ #else
+- GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
+- gtk_widget_set_visual(mShell, visual);
++ GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
++ gtk_widget_set_visual(mShell, visual);
+ #endif
+- }
+ }
+
+ // We only move a general managed toplevel window if someone has
+@@ -3756,24 +3861,56 @@ nsWindow::Create(nsIWidget* aParent,
+ mContainer = MOZ_CONTAINER(container);
+
+ #if (MOZ_WIDGET_GTK == 3)
+- // "csd" style is set when widget is realized so we need to call
+- // it explicitly now.
+- gtk_widget_realize(mShell);
+-
+- // We can't draw directly to top-level window when client side
+- // decorations are enabled. We use container with GdkWindow instead.
+- GtkStyleContext* style = gtk_widget_get_style_context(mShell);
+- shellHasCSD = gtk_style_context_has_class(style, "csd");
+-#endif
+- if (!shellHasCSD) {
+- // Use mShell's window for drawing and events.
+- gtk_widget_set_has_window(container, FALSE);
+- // Prevent GtkWindow from painting a background to flicker.
+- gtk_widget_set_app_paintable(mShell, TRUE);
+- }
+- // Set up event widget
+- eventWidget = shellHasCSD ? container : mShell;
++ /* There are tree possible situations here:
++ *
++ * 1) We're running on Gtk+ < 3.20 without any decorations. Content
++ * is rendered to mShell window and we listen Gtk+ events on mShell.
++ * 2) We're running on Gtk+ > 3.20 and window decorations are drawn
++ * by default by Gtk+. Content is rendered to mContainer,
++ * we listen events on mContainer. mShell contains default Gtk+
++ * window decorations rendered by Gtk+.
++ * 3) We're running on Gtk+ > 3.20 and both window decorations and
++ * content is rendered by gecko. We emulate Gtk+ decoration rendering
++ * to mShell and we need to listen Gtk events on both mShell
++ * and mContainer.
++ */
++
++ // When client side decorations are enabled (rendered by us or by Gtk+)
++ // the decoration is rendered to mShell (toplevel) window and
++ // we draw our content to mContainer.
++ if (mIsCSDEnabled) {
++ drawToContainer = true;
++ } else {
++ // mIsCSDEnabled can be disabled by preference so look at actual
++ // toplevel window style to to detect active "csd" style.
++ // The "csd" style is set when widget is realized so we need to call
++ // it explicitly now.
++ gtk_widget_realize(mShell);
++
++ GtkStyleContext* style = gtk_widget_get_style_context(mShell);
++ drawToContainer = gtk_style_context_has_class(style, "csd");
++ }
++#endif
++ drawWidget = (drawToContainer) ? container : mShell;
++ // When we draw decorations on our own we need to handle resize events
++ // because Gtk+ does not provide resizers for undecorated windows.
++ // The CSD on mShell borders act as resize handlers
++ // so we need to listen there.
++ eventWidget = (drawToContainer && !mIsCSDEnabled) ? container : mShell;
++
+ gtk_widget_add_events(eventWidget, kEvents);
++ if (eventWidget != drawWidget) {
++ // CSD is rendered by us (not by Gtk+) so we also need to listen
++ // at mShell window for events.
++ gtk_widget_add_events(drawWidget, kEvents);
++ }
++
++ // Prevent GtkWindow from painting a background to flicker.
++ gtk_widget_set_app_paintable(drawWidget, TRUE);
++
++ // gtk_container_add() realizes the child widget so we need to
++ // set it now.
++ gtk_widget_set_has_window(container, drawToContainer);
+
+ gtk_container_add(GTK_CONTAINER(mShell), container);
+ gtk_widget_realize(container);
+@@ -3783,7 +3920,7 @@ nsWindow::Create(nsIWidget* aParent,
+ gtk_widget_grab_focus(container);
+
+ // the drawing window
+- mGdkWindow = gtk_widget_get_window(eventWidget);
++ mGdkWindow = gtk_widget_get_window(drawWidget);
+
+ if (mWindowType == eWindowType_popup) {
+ // gdk does not automatically set the cursor for "temporary"
+@@ -3856,6 +3993,11 @@ nsWindow::Create(nsIWidget* aParent,
+
+ // label the drawing window with this object so we can find our way home
+ g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
++ if (mIsCSDEnabled) {
++ // label the CSD window with this object so we can find our way home
++ g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)),
++ "nsWindow", this);
++ }
+
+ if (mContainer)
+ g_object_set_data(G_OBJECT(mContainer), "nsWindow", this);
+@@ -3893,6 +4035,10 @@ nsWindow::Create(nsIWidget* aParent,
+ g_signal_connect_after(default_settings,
+ "notify::gtk-font-name",
+ G_CALLBACK(theme_changed_cb), this);
++ if (mIsCSDEnabled) {
++ g_signal_connect(G_OBJECT(mShell), "draw",
++ G_CALLBACK(expose_event_decoration_draw_cb), nullptr);
++ }
+ }
+
+ if (mContainer) {
+@@ -3943,7 +4089,7 @@ nsWindow::Create(nsIWidget* aParent,
+ G_CALLBACK(drag_data_received_event_cb), nullptr);
+
+ GtkWidget *widgets[] = { GTK_WIDGET(mContainer),
+- !shellHasCSD ? mShell : nullptr };
++ !drawToContainer ? mShell : nullptr };
+ for (size_t i = 0; i < ArrayLength(widgets) && widgets[i]; ++i) {
+ // Visibility events are sent to the owning widget of the relevant
+ // window but do not propagate to parent widgets so connect on
+@@ -3973,7 +4119,6 @@ nsWindow::Create(nsIWidget* aParent,
+ // Don't let GTK mess with the shapes of our GdkWindows
+ GTK_PRIVATE_SET_FLAG(eventWidget, GTK_HAS_SHAPE_MASK);
+ #endif
+-
+ // These events are sent to the owning widget of the relevant window
+ // and propagate up to the first widget that handles the events, so we
+ // need only connect on mShell, if it exists, to catch events on its
+@@ -4110,6 +4255,12 @@ nsWindow::NativeResize()
+ size.width, size.height));
+
+ if (mIsTopLevel) {
++ // When we draw decorations add extra space to draw shadows
++ // around the main window.
++ if (mDrawWindowDecoration) {
++ size.width += mDecorationSize.left + mDecorationSize.right;
++ size.height += mDecorationSize.top + mDecorationSize.bottom;
++ }
+ gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
+ }
+ else if (mContainer) {
+@@ -4166,6 +4317,11 @@ nsWindow::NativeMoveResize()
+ if (mIsTopLevel) {
+ // x and y give the position of the window manager frame top-left.
+ gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y);
++
++ if (mDrawWindowDecoration) {
++ size.width += mDecorationSize.left + mDecorationSize.right;
++ size.height += mDecorationSize.top + mDecorationSize.bottom;
++ }
+ // This sets the client window size.
+ gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
+ }
+@@ -5524,6 +5680,33 @@ expose_event_cb(GtkWidget *widget, cairo
+
+ return FALSE;
+ }
++
++/* static */
++gboolean
++expose_event_decoration_draw_cb(GtkWidget *widget, cairo_t *cr)
++{
++ GdkWindow* gdkWindow = gtk_widget_get_window(widget);
++ if (gtk_cairo_should_draw_window(cr, gdkWindow)) {
++ RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
++ if (!window) {
++ NS_WARNING("Cannot get nsWindow from GtkWidget");
++ }
++ else if (window->IsClientDecorated()) {
++ cairo_save(cr);
++ gtk_cairo_transform_to_window(cr, widget, gdkWindow);
++
++ GdkRectangle rect = {0,0,0,0};
++ gtk_window_get_size(GTK_WINDOW(widget), &rect.width, &rect.height);
++ moz_gtk_window_decoration_paint(cr, &rect);
++
++ rect.height = 40;
++ moz_gtk_header_bar_paint(cr, &rect);
++ cairo_restore(cr);
++ }
++ }
++ return TRUE;
++}
++
+ #endif //MOZ_WIDGET_GTK == 2
+
+ static gboolean
+@@ -6576,6 +6759,28 @@ nsWindow::ClearCachedResources()
+ }
+ }
+
++NS_IMETHODIMP
++nsWindow::SetNonClientMargins(LayoutDeviceIntMargin &aMargins)
++{
++ SetDrawsInTitlebar(aMargins.top == 0);
++ return NS_OK;
++}
++
++void
++nsWindow::SetDrawsInTitlebar(bool aState)
++{
++ if (!mIsCSDEnabled || aState == mDrawWindowDecoration)
++ return;
++
++ if (mShell) {
++ gtk_window_set_decorated(GTK_WINDOW(mShell), !aState);
++ gtk_widget_set_app_paintable(mShell, aState);
++ }
++
++ mDrawWindowDecoration = aState;
++ UpdateClientDecorations();
++}
++
+ gint
+ nsWindow::GdkScaleFactor()
+ {
+@@ -6846,6 +7051,157 @@ nsWindow::SynthesizeNativeTouchPoint(uin
+ }
+ #endif
+
++bool
++nsWindow::IsClientDecorated() const
++{
++ return mDrawWindowDecoration && mSizeState == nsSizeMode_Normal;
++}
++
++int
++nsWindow::GetClientResizerSize()
++{
++ if (!mShell)
++ return 0;
++
++ // GTK uses a default size of 20px as of 3.20.
++ gint size = 20;
++ gtk_widget_style_get(mShell, "decoration-resize-handle", &size, nullptr);
++
++ return GdkCoordToDevicePixels(size);
++}
++
++nsWindow::CSDSupportLevel
++nsWindow::GetCSDSupportLevel() {
++ if (mCSDSupportLevel != CSD_SUPPORT_UNKNOWN) {
++ return mCSDSupportLevel;
++ }
++ // TODO: MATE
++ const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
++ if (currentDesktop) {
++ if (strcmp(currentDesktop, "GNOME") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FULL;
++ } else if (strcmp(currentDesktop, "XFCE") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FULL;
++ } else if (strcmp(currentDesktop, "X-Cinnamon") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FULL;
++ } else if (strcmp(currentDesktop, "KDE") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FLAT;
++ } else if (strcmp(currentDesktop, "LXDE") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FLAT;
++ } else if (strcmp(currentDesktop, "openbox") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_FLAT;
++ } else if (strcmp(currentDesktop, "i3") == 0) {
++ mCSDSupportLevel = CSD_SUPPORT_NONE;
++ } else {
++ mCSDSupportLevel = CSD_SUPPORT_NONE;
++ }
++ }
++ return mCSDSupportLevel;
++}
++
++void
++nsWindow::UpdateClientDecorations()
++{
++ // When the CSD is not fully supported by window manager (ie. WM is not
++ // expecting that application is going to draw window shadows) we can't
++ // add shadows widths to the window margin. That would lead to completely
++ // opaque black border of the window.
++ if (!mDrawWindowDecoration || GetCSDSupportLevel() != CSD_SUPPORT_FULL)
++ return;
++
++ gint top = 0, right = 0, bottom = 0, left = 0;
++ if (mSizeState == nsSizeMode_Normal) {
++ moz_gtk_get_window_border(&top, &right, &bottom, &left);
++ }
++
++ static auto sGdkWindowSetShadowWidth =
++ (void (*)(GdkWindow*, gint, gint, gint, gint))
++ dlsym(RTLD_DEFAULT, "gdk_window_set_shadow_width");
++ sGdkWindowSetShadowWidth(gtk_widget_get_window(mShell),
++ left, right, top, bottom);
++
++ mDecorationSize.left = left;
++ mDecorationSize.right = right;
++ mDecorationSize.top = top;
++ mDecorationSize.bottom = bottom;
++
++ // Gtk+ doesn't like when we set mContainer margin bigger than actual
++ // mContainer window size. That happens when we're called early and the
++ // mShell/mContainer is not allocated/resized yet and has default 1x1 size.
++ // Just resize to some minimal value which will be changed
++ // by Gecko soon.
++ GtkAllocation allocation;
++ gtk_widget_get_allocation(GTK_WIDGET(mContainer), &allocation);
++ if (allocation.width < left + right || allocation.height < top + bottom) {
++ gtk_widget_get_preferred_width(GTK_WIDGET(mContainer), nullptr,
++ &allocation.width);
++ gtk_widget_get_preferred_height(GTK_WIDGET(mContainer), nullptr,
++ &allocation.height);
++ allocation.width += left + right + 1;
++ allocation.height += top + bottom + 1;
++ gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
++ }
++
++ gtk_widget_set_margin_left(GTK_WIDGET(mContainer), mDecorationSize.left);
++ gtk_widget_set_margin_right(GTK_WIDGET(mContainer), mDecorationSize.right);
++ gtk_widget_set_margin_top(GTK_WIDGET(mContainer), mDecorationSize.top);
++ gtk_widget_set_margin_bottom(GTK_WIDGET(mContainer), mDecorationSize.bottom);
++}
++
++void
++nsWindow::ApplyCSDClipping()
++{
++ if (IsClientDecorated()) {
++ gint top, right, bottom, left;
++ moz_gtk_get_header_bar_border(&top, &right, &bottom, &left);
++ cairo_rectangle_int_t rect = { 0, top, mBounds.width, mBounds.height};
++ cairo_region_t *region = cairo_region_create_rectangle(&rect);
++ gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
++ cairo_region_destroy(region);
++ } else {
++ gdk_window_shape_combine_region(mGdkWindow, nullptr, 0, 0);
++ }
++}
++
++bool
++nsWindow::CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge)
++{
++ gint scale = GdkScaleFactor();
++ gint left = scale * mDecorationSize.left;
++ gint top = scale * mDecorationSize.top;
++ gint right = scale * mDecorationSize.right;
++ gint bottom = scale * mDecorationSize.bottom;
++
++ int resizerSize = GetClientResizerSize();
++ int topDist = aPoint.y;
++ int leftDist = aPoint.x;
++ int rightDist = mBounds.width - aPoint.x;
++ int bottomDist = mBounds.height - aPoint.y;
++
++ //TODO -> wrong sizes
++
++ if (leftDist <= resizerSize && topDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_NORTH_WEST;
++ } else if (rightDist <= resizerSize && topDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_NORTH_EAST;
++ } else if (leftDist <= resizerSize && bottomDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_SOUTH_WEST;
++ } else if (rightDist <= resizerSize && bottomDist <= resizerSize) {
++ aOutEdge = GDK_WINDOW_EDGE_SOUTH_EAST;
++ } else if (topDist <= top) {
++ aOutEdge = GDK_WINDOW_EDGE_NORTH;
++ } else if (leftDist <= left) {
++ aOutEdge = GDK_WINDOW_EDGE_WEST;
++ } else if (rightDist <= right) {
++ aOutEdge = GDK_WINDOW_EDGE_EAST;
++ } else if (bottomDist <= bottom) {
++ aOutEdge = GDK_WINDOW_EDGE_SOUTH;
++ } else {
++ return false;
++ }
++ return true;
++}
++
+ int32_t
+ nsWindow::RoundsWidgetCoordinatesTo()
+ {
+diff -up firefox-57.0b8/widget/gtk/nsWindow.h.1399611 firefox-57.0b8/widget/gtk/nsWindow.h
+--- firefox-57.0b8/widget/gtk/nsWindow.h.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/widget/gtk/nsWindow.h 2017-10-16 12:11:45.369240636 +0200
+@@ -123,6 +123,7 @@ public:
+ double aHeight,
+ bool aRepaint) override;
+ virtual bool IsEnabled() const override;
++ bool IsComposited() const;
+
+ void SetZIndex(int32_t aZIndex) override;
+ virtual void SetSizeMode(nsSizeMode aMode) override;
+@@ -351,6 +352,9 @@ public:
+ #endif
+ virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
+
++ NS_IMETHOD SetNonClientMargins(LayoutDeviceIntMargin& aMargins) override;
++ void SetDrawsInTitlebar(bool aState) override;
++
+ // HiDPI scale conversion
+ gint GdkScaleFactor();
+
+@@ -367,6 +371,9 @@ public:
+ LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect);
+
+ virtual bool WidgetTypeSupportsAcceleration() override;
++
++ // Decorations
++ bool IsClientDecorated() const;
+ protected:
+ virtual ~nsWindow();
+
+@@ -384,6 +391,16 @@ protected:
+
+ virtual void RegisterTouchWindow() override;
+
++ int GetClientResizerSize();
++
++ // Informs the window manager about the size of the shadows surrounding
++ // a client-side decorated window.
++ void UpdateClientDecorations();
++
++ // Returns true if the given point (in device pixels) is within a resizer
++ // region of the window. Only used when drawing decorations client side.
++ bool CheckResizerEdge(LayoutDeviceIntPoint aPoint, GdkWindowEdge& aOutEdge);
++
+ nsCOMPtr<nsIWidget> mParent;
+ // Is this a toplevel window?
+ bool mIsTopLevel;
+@@ -432,12 +449,12 @@ private:
+ gint* aRootX, gint* aRootY);
+ void ClearCachedResources();
+ nsIWidgetListener* GetListener();
+- bool IsComposited() const;
+-
++ void ApplyCSDClipping();
+
+ GtkWidget *mShell;
+ MozContainer *mContainer;
+ GdkWindow *mGdkWindow;
++ bool mIsCSDEnabled;
+ PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
+
+
+@@ -536,6 +553,10 @@ private:
+ // leaving fullscreen
+ nsSizeMode mLastSizeMode;
+
++ // If true, draw our own window decorations (where supported).
++ bool mDrawWindowDecoration;
++ GtkBorder mDecorationSize;
++
+ static bool DragInProgress(void);
+
+ void DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent);
+@@ -567,6 +588,17 @@ private:
+ RefPtr<mozilla::widget::IMContextWrapper> mIMContext;
+
+ mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter;
++ typedef enum { CSD_SUPPORT_FULL, // CSD including shadows
++ CSD_SUPPORT_FLAT, // CSD without shadows
++ CSD_SUPPORT_NONE, // WM does not support CSD at all
++ CSD_SUPPORT_UNKNOWN
++ } CSDSupportLevel;
++ /**
++ * Get the support of Client Side Decoration by checking
++ * the XDG_CURRENT_DESKTOP environment variable.
++ */
++ CSDSupportLevel GetCSDSupportLevel();
++ CSDSupportLevel mCSDSupportLevel;
+ };
+
+ #endif /* __nsWindow_h__ */
+diff -up firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp.1399611 firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp
+--- firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp.1399611 2017-09-15 06:15:40.000000000 +0200
++++ firefox-57.0b8/widget/gtk/WidgetStyleCache.cpp 2017-10-16 12:11:45.369240636 +0200
+@@ -26,10 +26,14 @@ static GtkStyleContext*
+ GetCssNodeStyleInternal(WidgetNodeType aNodeType);
+
+ static GtkWidget*
+-CreateWindowWidget()
++CreateWindowWidget(WidgetNodeType type)
+ {
+ GtkWidget *widget = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_set_name(widget, "MozillaGtkWidget");
++ if (type == MOZ_GTK_WINDOW_CSD) {
++ GtkStyleContext* style = gtk_widget_get_style_context(widget);
++ gtk_style_context_add_class(style, "csd");
++ }
+ return widget;
+ }
+
+@@ -101,7 +105,7 @@ CreateTooltipWidget()
+ {
+ MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr,
+ "CreateTooltipWidget should be used for Gtk < 3.20 only.");
+- GtkWidget* widget = CreateWindowWidget();
++ GtkWidget* widget = CreateWindowWidget(MOZ_GTK_WINDOW);
+ GtkStyleContext* style = gtk_widget_get_style_context(widget);
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
+ return widget;
+@@ -529,11 +533,82 @@ CreateNotebookWidget()
+ }
+
+ static GtkWidget*
++CreateHeaderBar(bool aMaximized)
++{
++ MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
++ "GtkHeaderBar is only available on GTK 3.10+.");
++ if (gtk_check_version(3, 10, 0) != nullptr)
++ return nullptr;
++
++ static auto sGtkHeaderBarNewPtr = (GtkWidget* (*)())
++ dlsym(RTLD_DEFAULT, "gtk_header_bar_new");
++ static const char* MOZ_GTK_STYLE_CLASS_TITLEBAR = "titlebar";
++
++ GtkWidget* headerbar = sGtkHeaderBarNewPtr();
++ if (aMaximized) {
++ GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
++ gtk_widget_set_name(window, "MozillaMaximizedGtkWidget");
++ GtkStyleContext* style = gtk_widget_get_style_context(window);
++ gtk_style_context_add_class(style, "maximized");
++ GtkWidget *fixed = gtk_fixed_new();
++ gtk_container_add(GTK_CONTAINER(window), fixed);
++ gtk_container_add(GTK_CONTAINER(fixed), headerbar);
++ // Save the window container so we don't leak it.
++ sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED] = window;
++ } else {
++ AddToWindowContainer(headerbar);
++ }
++
++ // Emulate what create_titlebar() at gtkwindow.c does.
++ GtkStyleContext* style = gtk_widget_get_style_context(headerbar);
++ gtk_style_context_add_class(style, MOZ_GTK_STYLE_CLASS_TITLEBAR);
++ gtk_style_context_add_class(style, "default-decoration");
++
++ return headerbar;
++}
++
++// TODO - Also return style for buttons located at Maximized toolbar.
++static GtkWidget*
++CreateHeaderBarButton(WidgetNodeType aWidgetType)
++{
++ MOZ_ASSERT(gtk_check_version(3, 10, 0) == nullptr,
++ "GtkHeaderBar is only available on GTK 3.10+.");
++
++ if (gtk_check_version(3, 10, 0) != nullptr)
++ return nullptr;
++
++ static const char* MOZ_GTK_STYLE_CLASS_TITLEBUTTON = "titlebutton";
++
++ GtkWidget* widget = gtk_button_new();
++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_HEADER_BAR)), widget);
++
++ GtkStyleContext* style = gtk_widget_get_style_context(widget);
++ gtk_style_context_add_class(style, MOZ_GTK_STYLE_CLASS_TITLEBUTTON);
++
++ switch (aWidgetType) {
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ gtk_style_context_add_class(style, "close");
++ break;
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ gtk_style_context_add_class(style, "minimize");
++ break;
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ gtk_style_context_add_class(style, "maximize");
++ break;
++ default:
++ break;
++ }
++
++ return widget;
++}
++
++static GtkWidget*
+ CreateWidget(WidgetNodeType aWidgetType)
+ {
+ switch (aWidgetType) {
+ case MOZ_GTK_WINDOW:
+- return CreateWindowWidget();
++ case MOZ_GTK_WINDOW_CSD:
++ return CreateWindowWidget(aWidgetType);
+ case MOZ_GTK_WINDOW_CONTAINER:
+ return CreateWindowContainerWidget();
+ case MOZ_GTK_CHECKBUTTON_CONTAINER:
+@@ -610,6 +685,13 @@ CreateWidget(WidgetNodeType aWidgetType)
+ return CreateComboBoxEntryButtonWidget();
+ case MOZ_GTK_COMBOBOX_ENTRY_ARROW:
+ return CreateComboBoxEntryArrowWidget();
++ case MOZ_GTK_HEADER_BAR:
++ case MOZ_GTK_HEADER_BAR_MAXIMIZED:
++ return CreateHeaderBar(aWidgetType == MOZ_GTK_HEADER_BAR_MAXIMIZED);
++ case MOZ_GTK_HEADER_BAR_BUTTON_CLOSE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MINIMIZE:
++ case MOZ_GTK_HEADER_BAR_BUTTON_MAXIMIZE:
++ return CreateHeaderBarButton(aWidgetType);
+ default:
+ /* Not implemented */
+ return nullptr;
+@@ -1049,6 +1131,10 @@ GetCssNodeStyleInternal(WidgetNodeType a
+ GtkWidget* widget = GetWidget(MOZ_GTK_NOTEBOOK);
+ return gtk_widget_get_style_context(widget);
+ }
++ case MOZ_GTK_WINDOW_DECORATION:
++ style = CreateChildCSSNode("decoration",
++ MOZ_GTK_WINDOW_CSD);
++ break;
+ default:
+ return GetWidgetRootStyle(aNodeType);
+ }
+@@ -1214,6 +1300,8 @@ ResetWidgetCache(void)
+ /* This will destroy all of our widgets */
+ if (sWidgetStorage[MOZ_GTK_WINDOW])
+ gtk_widget_destroy(sWidgetStorage[MOZ_GTK_WINDOW]);
++ if (sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED])
++ gtk_widget_destroy(sWidgetStorage[MOZ_GTK_WINDOW_MAXIMIZED]);
+
+ /* Clear already freed arrays */
+ mozilla::PodArrayZero(sWidgetStorage);
+diff -up firefox-57.0b8/widget/LookAndFeel.h.1399611 firefox-57.0b8/widget/LookAndFeel.h
+--- firefox-57.0b8/widget/LookAndFeel.h.1399611 2017-09-16 18:22:54.000000000 +0200
++++ firefox-57.0b8/widget/LookAndFeel.h 2017-10-16 12:11:45.369240636 +0200
+@@ -405,6 +405,30 @@ public:
+ eIntID_PhysicalHomeButton,
+
+ /*
++ * A boolean value indicating whether client-side decorations are
++ * supported by the user's GTK version.
++ */
++ eIntID_GTKCSDAvailable,
++
++ /*
++ * A boolean value indicating whether client-side decorations should
++ * contain a minimize button.
++ */
++ eIntID_GTKCSDMinimizeButton,
++
++ /*
++ * A boolean value indicating whether client-side decorations should
++ * contain a maximize button.
++ */
++ eIntID_GTKCSDMaximizeButton,
++
++ /*
++ * A boolean value indicating whether client-side decorations should
++ * contain a close button.
++ */
++ eIntID_GTKCSDCloseButton,
++
++ /*
+ * Controls whether overlay scrollbars display when the user moves
+ * the mouse in a scrollable frame.
+ */
--- a/mozilla-kde.patch Sat Nov 11 10:08:36 2017 +0100
+++ b/mozilla-kde.patch Wed Jan 10 22:27:13 2018 +0100
@@ -1,5 +1,5 @@
# HG changeset patch
-# Parent 87a32e5d11e9d652e331a5f852bb951069b20c4a
+# Parent 2504512f9a9ba7b52dd99745d15f049f2a03f4f4
Description: Add KDE integration to Firefox (toolkit parts)
Author: Wolfgang Rosenauer <wolfgang@rosenauer.org>
Author: Lubos Lunak <lunak@suse.com>
@@ -3275,7 +3275,7 @@
mFilters.AppendElement(filter);
mFilterNames.AppendElement(name);
-@@ -371,16 +375,37 @@ nsFilePicker::Show(int16_t *aReturn)
+@@ -371,16 +375,39 @@ nsFilePicker::Show(int16_t *aReturn)
NS_IMETHODIMP
nsFilePicker::Open(nsIFilePickerShownCallback *aCallback)
@@ -3288,6 +3288,7 @@
+ if( nsKDEUtils::kdeSupport()) {
+ mCallback = aCallback;
+ mRunning = true;
++ NS_ADDREF_THIS();
+ g_idle_add([](gpointer data) -> gboolean {
+ nsFilePicker* queuedPicker = (nsFilePicker*) data;
+ int16_t result;
@@ -3299,6 +3300,7 @@
+ queuedPicker->mResult = result;
+ }
+ queuedPicker->mRunning = false;
++ NS_RELEASE(queuedPicker);
+ return G_SOURCE_REMOVE;
+ }, this);
+
@@ -3313,7 +3315,7 @@
GtkFileChooserAction action = GetGtkFileChooserAction(mMode);
-@@ -603,8 +628,233 @@ nsFilePicker::Done(GtkWidget* file_choos
+@@ -603,8 +630,233 @@ nsFilePicker::Done(GtkWidget* file_choos
if (mCallback) {
mCallback->Done(result);
mCallback = nullptr;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mozilla-rust-1.23.patch Wed Jan 10 22:27:13 2018 +0100
@@ -0,0 +1,1083 @@
+
+# HG changeset patch
+# User Simon Sapin <simon.sapin@exyr.org>
+# Date 1510231769 21600
+# Node ID 3242ac6fdb3879f723145e6b07fff04a5c960d1e
+# Parent bf63b9d8f2410464d5f2526588e380f934e937cc
+servo: Merge #19162 - Allow unused imports for AsciiExt in style code (from emilio:ascii-ext); r=emilio
+
+See #19128, this part is cherry-picked so Gecko can build with rust nightly.
+
+Source-Repo: https://github.com/servo/servo
+Source-Revision: e7a654dd13f589e127193267bcb576ffd661c11d
+
+diff --git a/servo/components/gfx/font.rs b/servo/components/gfx/font.rs
+--- a/servo/components/gfx/font.rs
++++ b/servo/components/gfx/font.rs
+@@ -5,17 +5,17 @@
+ use app_units::Au;
+ use euclid::{Point2D, Rect, Size2D};
+ use font_template::FontTemplateDescriptor;
+ use ordered_float::NotNaN;
+ use platform::font::{FontHandle, FontTable};
+ use platform::font_context::FontContextHandle;
+ use platform::font_template::FontTemplateData;
+ use smallvec::SmallVec;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::ToOwned;
+ use std::cell::RefCell;
+ use std::collections::HashMap;
+ use std::rc::Rc;
+ use std::str;
+ use std::sync::Arc;
+ use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
+ use style::computed_values::{font_stretch, font_variant_caps, font_weight};
+diff --git a/servo/components/net/fetch/cors_cache.rs b/servo/components/net/fetch/cors_cache.rs
+--- a/servo/components/net/fetch/cors_cache.rs
++++ b/servo/components/net/fetch/cors_cache.rs
+@@ -7,17 +7,17 @@
+ //! For stuff involving `<img>`, `<iframe>`, `<form>`, etc please check what
+ //! the request mode should be and compare with the fetch spec
+ //! This library will eventually become the core of the Fetch crate
+ //! with CORSRequest being expanded into FetchRequest (etc)
+
+ use hyper::method::Method;
+ use net_traits::request::{CredentialsMode, Origin, Request};
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use time::{self, Timespec};
+
+ /// Union type for CORS cache entries
+ ///
+ /// Each entry might pertain to a header or method
+ #[derive(Clone, Debug)]
+ pub enum HeaderOrMethod {
+ HeaderData(String),
+diff --git a/servo/components/net/fetch/methods.rs b/servo/components/net/fetch/methods.rs
+--- a/servo/components/net/fetch/methods.rs
++++ b/servo/components/net/fetch/methods.rs
+@@ -16,17 +16,17 @@ use hyper::method::Method;
+ use hyper::mime::{Mime, SubLevel, TopLevel};
+ use hyper::status::StatusCode;
+ use mime_guess::guess_mime_type;
+ use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy};
+ use net_traits::request::{CredentialsMode, Referrer, Request, RequestMode, ResponseTainting};
+ use net_traits::request::{Type, Origin, Window};
+ use net_traits::response::{Response, ResponseBody, ResponseType};
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::Cow;
+ use std::fmt;
+ use std::fs::File;
+ use std::io::Read;
+ use std::mem;
+ use std::str;
+ use std::sync::Arc;
+ use std::sync::mpsc::{Sender, Receiver};
+diff --git a/servo/components/net/http_loader.rs b/servo/components/net/http_loader.rs
+--- a/servo/components/net/http_loader.rs
++++ b/servo/components/net/http_loader.rs
+@@ -34,17 +34,17 @@ use log;
+ use msg::constellation_msg::PipelineId;
+ use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
+ use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin};
+ use net_traits::request::{RedirectMode, Referrer, Request, RequestMode};
+ use net_traits::request::{ResponseTainting, ServiceWorkersMode, Type};
+ use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
+ use resource_thread::AuthCache;
+ use servo_url::{ImmutableOrigin, ServoUrl};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::collections::HashSet;
+ use std::error::Error;
+ use std::io::{self, Read, Write};
+ use std::iter::FromIterator;
+ use std::mem;
+ use std::ops::Deref;
+ use std::sync::RwLock;
+ use std::sync::mpsc::{channel, Sender};
+diff --git a/servo/components/net/websocket_loader.rs b/servo/components/net/websocket_loader.rs
+--- a/servo/components/net/websocket_loader.rs
++++ b/servo/components/net/websocket_loader.rs
+@@ -14,17 +14,17 @@ use hyper::http::h1::{LINE_ENDING, parse
+ use hyper::method::Method;
+ use hyper::net::HttpStream;
+ use hyper::status::StatusCode;
+ use hyper::version::HttpVersion;
+ use net_traits::{CookieSource, MessageData, NetworkError, WebSocketCommunicate, WebSocketConnectData};
+ use net_traits::{WebSocketDomAction, WebSocketNetworkEvent};
+ use net_traits::request::{Destination, Type};
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::io::{self, Write};
+ use std::net::TcpStream;
+ use std::sync::{Arc, Mutex};
+ use std::sync::atomic::{AtomicBool, Ordering};
+ use std::thread;
+ use url::Position;
+ use websocket::{Message, Receiver as WSReceiver, Sender as WSSender};
+ use websocket::header::{Origin, WebSocketAccept, WebSocketKey, WebSocketProtocol, WebSocketVersion};
+diff --git a/servo/components/net_traits/response.rs b/servo/components/net_traits/response.rs
+--- a/servo/components/net_traits/response.rs
++++ b/servo/components/net_traits/response.rs
+@@ -4,17 +4,17 @@
+
+ //! The [Response](https://fetch.spec.whatwg.org/#responses) object
+ //! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
+ use {FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
+ use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
+ use hyper::status::StatusCode;
+ use hyper_serde::Serde;
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::sync::{Arc, Mutex};
+
+ /// [Response type](https://fetch.spec.whatwg.org/#concept-response-type)
+ #[derive(Clone, Debug, Deserialize, HeapSizeOf, PartialEq, Serialize)]
+ pub enum ResponseType {
+ Basic,
+ Cors,
+ Default,
+diff --git a/servo/components/script/dom/bindings/str.rs b/servo/components/script/dom/bindings/str.rs
+--- a/servo/components/script/dom/bindings/str.rs
++++ b/servo/components/script/dom/bindings/str.rs
+@@ -2,17 +2,17 @@
+ * 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/. */
+
+ //! The `ByteString` struct.
+
+ use cssparser::CowRcStr;
+ use html5ever::{LocalName, Namespace};
+ use servo_atoms::Atom;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::{Borrow, Cow, ToOwned};
+ use std::fmt;
+ use std::hash::{Hash, Hasher};
+ use std::marker::PhantomData;
+ use std::ops;
+ use std::ops::{Deref, DerefMut};
+ use std::str;
+ use std::str::{Bytes, FromStr};
+diff --git a/servo/components/script/dom/blob.rs b/servo/components/script/dom/blob.rs
+--- a/servo/components/script/dom/blob.rs
++++ b/servo/components/script/dom/blob.rs
+@@ -11,17 +11,17 @@ use dom::bindings::js::{JS, Root};
+ use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
+ use dom::bindings::str::DOMString;
+ use dom::globalscope::GlobalScope;
+ use dom_struct::dom_struct;
+ use ipc_channel::ipc;
+ use net_traits::{CoreResourceMsg, IpcSend};
+ use net_traits::blob_url_store::{BlobBuf, get_blob_origin};
+ use net_traits::filemanager_thread::{FileManagerThreadMsg, ReadFileProgress, RelativePos};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::mem;
+ use std::ops::Index;
+ use std::path::PathBuf;
+ use uuid::Uuid;
+
+ /// File-based blob
+ #[derive(JSTraceable)]
+ pub struct FileBlob {
+diff --git a/servo/components/script/dom/cssstyledeclaration.rs b/servo/components/script/dom/cssstyledeclaration.rs
+--- a/servo/components/script/dom/cssstyledeclaration.rs
++++ b/servo/components/script/dom/cssstyledeclaration.rs
+@@ -11,17 +11,17 @@ use dom::bindings::reflector::{DomObject
+ use dom::bindings::str::DOMString;
+ use dom::cssrule::CSSRule;
+ use dom::element::Element;
+ use dom::node::{Node, window_from_node, document_from_node};
+ use dom::window::Window;
+ use dom_struct::dom_struct;
+ use servo_arc::Arc;
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use style::attr::AttrValue;
+ use style::properties::{Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId};
+ use style::properties::{parse_one_declaration_into, parse_style_attribute, SourcePropertyDeclaration};
+ use style::selector_parser::PseudoElement;
+ use style::shared_lock::Locked;
+ use style_traits::{PARSING_MODE_DEFAULT, ToCss};
+
+ // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
+diff --git a/servo/components/script/dom/document.rs b/servo/components/script/dom/document.rs
+--- a/servo/components/script/dom/document.rs
++++ b/servo/components/script/dom/document.rs
+@@ -118,17 +118,17 @@ use script_traits::{AnimationState, Comp
+ use script_traits::{MouseButton, MouseEventType, MozBrowserEvent};
+ use script_traits::{MsDuration, ScriptMsg, TouchpadPressurePhase};
+ use script_traits::{TouchEventType, TouchId};
+ use script_traits::UntrustedNodeAddress;
+ use servo_arc::Arc;
+ use servo_atoms::Atom;
+ use servo_config::prefs::PREFS;
+ use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::ToOwned;
+ use std::cell::{Cell, Ref, RefMut};
+ use std::collections::{HashMap, HashSet, VecDeque};
+ use std::collections::hash_map::Entry::{Occupied, Vacant};
+ use std::default::Default;
+ use std::iter::once;
+ use std::mem;
+ use std::rc::Rc;
+diff --git a/servo/components/script/dom/element.rs b/servo/components/script/dom/element.rs
+--- a/servo/components/script/dom/element.rs
++++ b/servo/components/script/dom/element.rs
+@@ -90,17 +90,17 @@ use script_layout_interface::message::Re
+ use script_thread::ScriptThread;
+ use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
+ use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode};
+ use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
+ use selectors::matching::{RelevantLinkStatus, matches_selector_list};
+ use selectors::sink::Push;
+ use servo_arc::Arc;
+ use servo_atoms::Atom;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::Cow;
+ use std::cell::{Cell, Ref};
+ use std::convert::TryFrom;
+ use std::default::Default;
+ use std::fmt;
+ use std::mem;
+ use std::rc::Rc;
+ use style::CaseSensitivityExt;
+diff --git a/servo/components/script/dom/htmlelement.rs b/servo/components/script/dom/htmlelement.rs
+--- a/servo/components/script/dom/htmlelement.rs
++++ b/servo/components/script/dom/htmlelement.rs
+@@ -25,17 +25,17 @@ use dom::htmlhtmlelement::HTMLHtmlElemen
+ use dom::htmlinputelement::HTMLInputElement;
+ use dom::htmllabelelement::HTMLLabelElement;
+ use dom::node::{Node, SEQUENTIALLY_FOCUSABLE};
+ use dom::node::{document_from_node, window_from_node};
+ use dom::nodelist::NodeList;
+ use dom::virtualmethods::VirtualMethods;
+ use dom_struct::dom_struct;
+ use html5ever::{LocalName, Prefix};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::default::Default;
+ use std::rc::Rc;
+ use style::attr::AttrValue;
+ use style::element_state::*;
+
+ #[dom_struct]
+ pub struct HTMLElement {
+ element: Element,
+diff --git a/servo/components/script/dom/htmllinkelement.rs b/servo/components/script/dom/htmllinkelement.rs
+--- a/servo/components/script/dom/htmllinkelement.rs
++++ b/servo/components/script/dom/htmllinkelement.rs
+@@ -21,17 +21,17 @@ use dom::htmlelement::HTMLElement;
+ use dom::node::{Node, UnbindContext, document_from_node, window_from_node};
+ use dom::stylesheet::StyleSheet as DOMStyleSheet;
+ use dom::virtualmethods::VirtualMethods;
+ use dom_struct::dom_struct;
+ use html5ever::{LocalName, Prefix};
+ use net_traits::ReferrerPolicy;
+ use script_traits::{MozBrowserEvent, ScriptMsg};
+ use servo_arc::Arc;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::ToOwned;
+ use std::cell::Cell;
+ use std::default::Default;
+ use style::attr::AttrValue;
+ use style::media_queries::parse_media_query_list;
+ use style::parser::ParserContext as CssParserContext;
+ use style::str::HTML_SPACE_CHARACTERS;
+ use style::stylesheets::{CssRuleType, Stylesheet};
+diff --git a/servo/components/script/dom/htmlmetaelement.rs b/servo/components/script/dom/htmlmetaelement.rs
+--- a/servo/components/script/dom/htmlmetaelement.rs
++++ b/servo/components/script/dom/htmlmetaelement.rs
+@@ -17,17 +17,17 @@ use dom::htmlelement::HTMLElement;
+ use dom::htmlheadelement::HTMLHeadElement;
+ use dom::node::{Node, UnbindContext, document_from_node, window_from_node};
+ use dom::virtualmethods::VirtualMethods;
+ use dom_struct::dom_struct;
+ use html5ever::{LocalName, Prefix};
+ use parking_lot::RwLock;
+ use servo_arc::Arc;
+ use servo_config::prefs::PREFS;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::sync::atomic::AtomicBool;
+ use style::attr::AttrValue;
+ use style::media_queries::MediaList;
+ use style::str::HTML_SPACE_CHARACTERS;
+ use style::stylesheets::{Stylesheet, StylesheetContents, CssRule, CssRules, Origin, ViewportRule};
+
+ #[dom_struct]
+ pub struct HTMLMetaElement {
+diff --git a/servo/components/script/dom/htmlscriptelement.rs b/servo/components/script/dom/htmlscriptelement.rs
+--- a/servo/components/script/dom/htmlscriptelement.rs
++++ b/servo/components/script/dom/htmlscriptelement.rs
+@@ -31,17 +31,17 @@ use ipc_channel::ipc;
+ use ipc_channel::router::ROUTER;
+ use js::jsval::UndefinedValue;
+ use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
+ use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType};
+ use network_listener::{NetworkListener, PreInvoke};
+ use servo_atoms::Atom;
+ use servo_config::opts;
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::cell::Cell;
+ use std::fs::File;
+ use std::io::{Read, Write};
+ use std::path::PathBuf;
+ use std::process::{Command, Stdio};
+ use std::sync::{Arc, Mutex};
+ use style::str::{HTML_SPACE_CHARACTERS, StaticStringVec};
+ use uuid::Uuid;
+diff --git a/servo/components/script/dom/macros.rs b/servo/components/script/dom/macros.rs
+--- a/servo/components/script/dom/macros.rs
++++ b/servo/components/script/dom/macros.rs
+@@ -144,17 +144,17 @@ macro_rules! make_string_or_document_url
+ );
+
+ #[macro_export]
+ macro_rules! make_enumerated_getter(
+ ( $attr:ident, $htmlname:tt, $default:expr, $($choices: pat)|+) => (
+ fn $attr(&self) -> DOMString {
+ use dom::bindings::inheritance::Castable;
+ use dom::element::Element;
+- use std::ascii::AsciiExt;
++ #[allow(unused_imports)] use std::ascii::AsciiExt;
+ let element = self.upcast::<Element>();
+ let mut val = element.get_string_attribute(&local_name!($htmlname));
+ val.make_ascii_lowercase();
+ // https://html.spec.whatwg.org/multipage/#attr-fs-method
+ match &*val {
+ $($choices)|+ => val,
+ _ => DOMString::from($default)
+ }
+diff --git a/servo/components/script/dom/namednodemap.rs b/servo/components/script/dom/namednodemap.rs
+--- a/servo/components/script/dom/namednodemap.rs
++++ b/servo/components/script/dom/namednodemap.rs
+@@ -10,17 +10,17 @@ use dom::bindings::error::{Error, Fallib
+ use dom::bindings::js::{JS, Root};
+ use dom::bindings::reflector::{Reflector, reflect_dom_object};
+ use dom::bindings::str::DOMString;
+ use dom::bindings::xmlname::namespace_from_domstring;
+ use dom::element::Element;
+ use dom::window::Window;
+ use dom_struct::dom_struct;
+ use html5ever::LocalName;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+
+ #[dom_struct]
+ pub struct NamedNodeMap {
+ reflector_: Reflector,
+ owner: JS<Element>,
+ }
+
+ impl NamedNodeMap {
+diff --git a/servo/components/script/dom/serviceworkercontainer.rs b/servo/components/script/dom/serviceworkercontainer.rs
+--- a/servo/components/script/dom/serviceworkercontainer.rs
++++ b/servo/components/script/dom/serviceworkercontainer.rs
+@@ -11,17 +11,17 @@ use dom::bindings::str::USVString;
+ use dom::client::Client;
+ use dom::eventtarget::EventTarget;
+ use dom::globalscope::GlobalScope;
+ use dom::promise::Promise;
+ use dom::serviceworker::ServiceWorker;
+ use dom_struct::dom_struct;
+ use script_thread::ScriptThread;
+ use serviceworkerjob::{Job, JobType};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::default::Default;
+ use std::rc::Rc;
+
+ #[dom_struct]
+ pub struct ServiceWorkerContainer {
+ eventtarget: EventTarget,
+ controller: MutNullableJS<ServiceWorker>,
+ client: JS<Client>
+diff --git a/servo/components/script/dom/servoparser/async_html.rs b/servo/components/script/dom/servoparser/async_html.rs
+--- a/servo/components/script/dom/servoparser/async_html.rs
++++ b/servo/components/script/dom/servoparser/async_html.rs
+@@ -22,17 +22,17 @@ use dom::virtualmethods::vtable_for;
+ use html5ever::{Attribute as HtmlAttribute, ExpandedName, LocalName, QualName};
+ use html5ever::buffer_queue::BufferQueue;
+ use html5ever::tendril::{SendTendril, StrTendril, Tendril};
+ use html5ever::tendril::fmt::UTF8;
+ use html5ever::tokenizer::{Tokenizer as HtmlTokenizer, TokenizerOpts, TokenizerResult};
+ use html5ever::tree_builder::{ElementFlags, NodeOrText as HtmlNodeOrText, NextParserState, QuirksMode, TreeSink};
+ use html5ever::tree_builder::{TreeBuilder, TreeBuilderOpts};
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::Cow;
+ use std::cell::Cell;
+ use std::collections::HashMap;
+ use std::collections::vec_deque::VecDeque;
+ use std::sync::mpsc::{channel, Receiver, Sender};
+ use std::thread;
+ use style::context::QuirksMode as ServoQuirksMode;
+
+diff --git a/servo/components/script/dom/servoparser/mod.rs b/servo/components/script/dom/servoparser/mod.rs
+--- a/servo/components/script/dom/servoparser/mod.rs
++++ b/servo/components/script/dom/servoparser/mod.rs
+@@ -41,17 +41,17 @@ use net_traits::{FetchMetadata, FetchRes
+ use network_listener::PreInvoke;
+ use profile_traits::time::{TimerMetadata, TimerMetadataFrameType};
+ use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile};
+ use script_thread::ScriptThread;
+ use script_traits::DocumentActivity;
+ use servo_config::prefs::PREFS;
+ use servo_config::resource_files::read_resource_file;
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::Cow;
+ use std::cell::Cell;
+ use std::mem;
+ use style::context::QuirksMode as ServoQuirksMode;
+
+ mod async_html;
+ mod html;
+ mod xml;
+diff --git a/servo/components/script/dom/websocket.rs b/servo/components/script/dom/websocket.rs
+--- a/servo/components/script/dom/websocket.rs
++++ b/servo/components/script/dom/websocket.rs
+@@ -27,17 +27,17 @@ use js::jsapi::JSAutoCompartment;
+ use js::jsval::UndefinedValue;
+ use js::typedarray::{ArrayBuffer, CreateWith};
+ use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
+ use net_traits::CoreResourceMsg::WebsocketConnect;
+ use net_traits::MessageData;
+ use script_runtime::CommonScriptMsg;
+ use script_runtime::ScriptThreadEventCategory::WebSocketEvent;
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::ToOwned;
+ use std::cell::Cell;
+ use std::ptr;
+ use std::thread;
+ use task::{TaskOnce, TaskCanceller};
+ use task_source::TaskSource;
+ use task_source::networking::NetworkingTaskSource;
+
+diff --git a/servo/components/script/dom/window.rs b/servo/components/script/dom/window.rs
+--- a/servo/components/script/dom/window.rs
++++ b/servo/components/script/dom/window.rs
+@@ -82,17 +82,17 @@ use script_traits::{ConstellationControl
+ use script_traits::{ScriptToConstellationChan, ScriptMsg, ScrollState, TimerEvent, TimerEventId};
+ use script_traits::{TimerSchedulerMsg, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
+ use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
+ use selectors::attr::CaseSensitivity;
+ use servo_config::opts;
+ use servo_config::prefs::PREFS;
+ use servo_geometry::{f32_rect_to_au_rect, max_rect};
+ use servo_url::{Host, MutableOrigin, ImmutableOrigin, ServoUrl};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::ToOwned;
+ use std::cell::Cell;
+ use std::collections::{HashMap, HashSet};
+ use std::collections::hash_map::Entry;
+ use std::default::Default;
+ use std::env;
+ use std::fs;
+ use std::io::{Write, stderr, stdout};
+diff --git a/servo/components/script/dom/xmlhttprequest.rs b/servo/components/script/dom/xmlhttprequest.rs
+--- a/servo/components/script/dom/xmlhttprequest.rs
++++ b/servo/components/script/dom/xmlhttprequest.rs
+@@ -57,17 +57,17 @@ use net_traits::{FetchResponseListener,
+ use net_traits::CoreResourceMsg::Fetch;
+ use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
+ use net_traits::trim_http_whitespace;
+ use network_listener::{NetworkListener, PreInvoke};
+ use script_traits::DocumentActivity;
+ use servo_atoms::Atom;
+ use servo_config::prefs::PREFS;
+ use servo_url::ServoUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::ToOwned;
+ use std::cell::Cell;
+ use std::default::Default;
+ use std::str;
+ use std::sync::{Arc, Mutex};
+ use task_source::networking::NetworkingTaskSource;
+ use time;
+ use timers::{OneshotTimerCallback, OneshotTimerHandle};
+diff --git a/servo/components/selectors/attr.rs b/servo/components/selectors/attr.rs
+--- a/servo/components/selectors/attr.rs
++++ b/servo/components/selectors/attr.rs
+@@ -1,15 +1,15 @@
+ /* 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/. */
+
+ use cssparser::ToCss;
+ use parser::SelectorImpl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] #[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+
+ #[derive(Clone, Eq, PartialEq)]
+ pub struct AttrSelectorWithNamespace<Impl: SelectorImpl> {
+ pub namespace: NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>,
+ pub local_name: Impl::LocalName,
+ pub local_name_lower: Impl::LocalName,
+ pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
+diff --git a/servo/components/selectors/parser.rs b/servo/components/selectors/parser.rs
+--- a/servo/components/selectors/parser.rs
++++ b/servo/components/selectors/parser.rs
+@@ -8,17 +8,17 @@ use bloom::BLOOM_HASH_MASK;
+ use builder::{SelectorBuilder, SpecificityAndFlags};
+ use context::QuirksMode;
+ use cssparser::{ParseError, BasicParseError, CowRcStr, Delimiter};
+ use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
+ use precomputed_hash::PrecomputedHash;
+ use servo_arc::ThinArc;
+ use sink::Push;
+ use smallvec::SmallVec;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::{Borrow, Cow};
+ use std::fmt::{self, Display, Debug, Write};
+ use std::iter::Rev;
+ use std::slice;
+ use visitor::SelectorVisitor;
+
+ /// A trait that represents a pseudo-element.
+ pub trait PseudoElement : Sized + ToCss {
+diff --git a/servo/components/style/attr.rs b/servo/components/style/attr.rs
+--- a/servo/components/style/attr.rs
++++ b/servo/components/style/attr.rs
+@@ -11,17 +11,17 @@ use app_units::Au;
+ use cssparser::{self, Color, RGBA};
+ use euclid::num::Zero;
+ use num_traits::ToPrimitive;
+ use properties::PropertyDeclarationBlock;
+ use selectors::attr::AttrSelectorOperation;
+ use servo_arc::Arc;
+ use servo_url::ServoUrl;
+ use shared_lock::Locked;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] #[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::str::FromStr;
+ use str::{HTML_SPACE_CHARACTERS, read_exponent, read_fraction};
+ use str::{read_numbers, split_commas, split_html_space_chars};
+ use str::str_join;
+ use values::specified::Length;
+
+ // Duplicated from script::dom::values.
+ const UNSIGNED_LONG_MAX: u32 = 2147483647;
+diff --git a/servo/components/style/counter_style/mod.rs b/servo/components/style/counter_style/mod.rs
+--- a/servo/components/style/counter_style/mod.rs
++++ b/servo/components/style/counter_style/mod.rs
+@@ -10,17 +10,17 @@ use Atom;
+ use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
+ use cssparser::{Parser, Token, serialize_identifier, BasicParseError, CowRcStr};
+ use error_reporting::{ContextualParseError, ParseErrorReporter};
+ #[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors;
+ #[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSCounterDesc;
+ use parser::{ParserContext, ParserErrorContext, Parse};
+ use selectors::parser::SelectorParseError;
+ use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::Cow;
+ use std::fmt;
+ use std::ops::Range;
+ use style_traits::{Comma, OneOrMoreSeparated, ParseError, StyleParseError, ToCss};
+ use values::CustomIdent;
+
+ /// Parse the prelude of an @counter-style rule
+ pub fn parse_counter_style_name<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CustomIdent, ParseError<'i>> {
+diff --git a/servo/components/style/custom_properties.rs b/servo/components/style/custom_properties.rs
+--- a/servo/components/style/custom_properties.rs
++++ b/servo/components/style/custom_properties.rs
+@@ -9,17 +9,17 @@
+ use Atom;
+ use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
+ use parser::ParserContext;
+ use precomputed_hash::PrecomputedHash;
+ use properties::{CSSWideKeyword, DeclaredValue};
+ use selector_map::{PrecomputedHashSet, PrecomputedHashMap};
+ use selectors::parser::SelectorParseError;
+ use servo_arc::Arc;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::{Borrow, Cow};
+ use std::fmt;
+ use std::hash::Hash;
+ use style_traits::{ToCss, StyleParseError, ParseError};
+
+ /// A custom property name is just an `Atom`.
+ ///
+ /// Note that this does not include the `--` prefix
+diff --git a/servo/components/style/gecko/generated/pseudo_element_definition.rs b/servo/components/style/gecko/generated/pseudo_element_definition.rs
+--- a/servo/components/style/gecko/generated/pseudo_element_definition.rs
++++ b/servo/components/style/gecko/generated/pseudo_element_definition.rs
+@@ -1262,17 +1262,17 @@ None
+ /// user-agent stylesheet.
+ ///
+ /// If we're not in a user-agent stylesheet, we will never parse anonymous
+ /// box pseudo-elements.
+ ///
+ /// Returns `None` if the pseudo-element is not recognised.
+ #[inline]
+ pub fn from_slice(s: &str, in_ua_stylesheet: bool) -> Option<Self> {
+- use std::ascii::AsciiExt;
++ #[allow(unused_imports)] #[allow(unused_imports)] use std::ascii::AsciiExt;
+
+ // We don't need to support tree pseudos because functional
+ // pseudo-elements needs arguments, and thus should be created
+ // via other methods.
+ if in_ua_stylesheet || PseudoElement::After.exposed_in_non_ua_sheets() {
+ if s.eq_ignore_ascii_case("after") {
+ return Some(PseudoElement::After);
+ }
+@@ -1632,17 +1632,17 @@ None
+ }
+
+ /// Constructs a tree pseudo-element from the given name and arguments.
+ /// "name" must start with "-moz-tree-".
+ ///
+ /// Returns `None` if the pseudo-element is not recognized.
+ #[inline]
+ pub fn tree_pseudo_element(name: &str, args: Box<[String]>) -> Option<Self> {
+- use std::ascii::AsciiExt;
++ #[allow(unused_imports)] use std::ascii::AsciiExt;
+ debug_assert!(name.starts_with("-moz-tree-"));
+ let tree_part = &name[10..];
+ if tree_part.eq_ignore_ascii_case("column") {
+ return Some(PseudoElement::MozTreeColumn(args));
+ }
+ if tree_part.eq_ignore_ascii_case("row") {
+ return Some(PseudoElement::MozTreeRow(args));
+ }
+diff --git a/servo/components/style/gecko/pseudo_element_definition.mako.rs b/servo/components/style/gecko/pseudo_element_definition.mako.rs
+--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs
++++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs
+@@ -181,17 +181,17 @@ impl PseudoElement {
+ /// user-agent stylesheet.
+ ///
+ /// If we're not in a user-agent stylesheet, we will never parse anonymous
+ /// box pseudo-elements.
+ ///
+ /// Returns `None` if the pseudo-element is not recognised.
+ #[inline]
+ pub fn from_slice(s: &str, in_ua_stylesheet: bool) -> Option<Self> {
+- use std::ascii::AsciiExt;
++ #[allow(unused_imports)] #[allow(unused_imports)] use std::ascii::AsciiExt;
+
+ // We don't need to support tree pseudos because functional
+ // pseudo-elements needs arguments, and thus should be created
+ // via other methods.
+ % for pseudo in SIMPLE_PSEUDOS:
+ if in_ua_stylesheet || ${pseudo_element_variant(pseudo)}.exposed_in_non_ua_sheets() {
+ if s.eq_ignore_ascii_case("${pseudo.value[1:]}") {
+ return Some(${pseudo_element_variant(pseudo)});
+@@ -203,17 +203,17 @@ impl PseudoElement {
+ }
+
+ /// Constructs a tree pseudo-element from the given name and arguments.
+ /// "name" must start with "-moz-tree-".
+ ///
+ /// Returns `None` if the pseudo-element is not recognized.
+ #[inline]
+ pub fn tree_pseudo_element(name: &str, args: Box<[String]>) -> Option<Self> {
+- use std::ascii::AsciiExt;
++ #[allow(unused_imports)] use std::ascii::AsciiExt;
+ debug_assert!(name.starts_with("-moz-tree-"));
+ let tree_part = &name[10..];
+ % for pseudo in TREE_PSEUDOS:
+ if tree_part.eq_ignore_ascii_case("${pseudo.value[11:]}") {
+ return Some(${pseudo_element_variant(pseudo, "args")});
+ }
+ % endfor
+ None
+diff --git a/servo/components/style/gecko_string_cache/mod.rs b/servo/components/style/gecko_string_cache/mod.rs
+--- a/servo/components/style/gecko_string_cache/mod.rs
++++ b/servo/components/style/gecko_string_cache/mod.rs
+@@ -8,17 +8,17 @@
+
+ use gecko_bindings::bindings::Gecko_AddRefAtom;
+ use gecko_bindings::bindings::Gecko_Atomize;
+ use gecko_bindings::bindings::Gecko_Atomize16;
+ use gecko_bindings::bindings::Gecko_ReleaseAtom;
+ use gecko_bindings::structs::{nsIAtom, nsIAtom_AtomKind};
+ use nsstring::{nsAString, nsString};
+ use precomputed_hash::PrecomputedHash;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::{Cow, Borrow};
+ use std::char::{self, DecodeUtf16};
+ use std::fmt::{self, Write};
+ use std::hash::{Hash, Hasher};
+ use std::iter::Cloned;
+ use std::mem;
+ use std::ops::Deref;
+ use std::slice;
+diff --git a/servo/components/style/properties/longhand/font.mako.rs b/servo/components/style/properties/longhand/font.mako.rs
+--- a/servo/components/style/properties/longhand/font.mako.rs
++++ b/servo/components/style/properties/longhand/font.mako.rs
+@@ -2137,17 +2137,17 @@ https://drafts.csswg.org/css-fonts-4/#lo
+ SpecifiedValue::Normal
+ }
+
+ impl ToComputedValue for SpecifiedValue {
+ type ComputedValue = computed_value::T;
+
+ #[inline]
+ fn to_computed_value(&self, _context: &Context) -> computed_value::T {
+- use std::ascii::AsciiExt;
++ #[allow(unused_imports)] #[allow(unused_imports)] use std::ascii::AsciiExt;
+ match *self {
+ SpecifiedValue::Normal => computed_value::T(0),
+ SpecifiedValue::Override(ref lang) => {
+ if lang.is_empty() || lang.len() > 4 || !lang.is_ascii() {
+ return computed_value::T(0)
+ }
+ let mut computed_lang = lang.clone();
+ while computed_lang.len() < 4 {
+diff --git a/servo/components/style/properties/longhand/pointing.mako.rs b/servo/components/style/properties/longhand/pointing.mako.rs
+--- a/servo/components/style/properties/longhand/pointing.mako.rs
++++ b/servo/components/style/properties/longhand/pointing.mako.rs
+@@ -85,17 +85,17 @@
+ images: vec![],
+ keyword: computed_value::Keyword::Auto
+ }
+ }
+
+ impl Parse for computed_value::Keyword {
+ fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
+ -> Result<computed_value::Keyword, ParseError<'i>> {
+- use std::ascii::AsciiExt;
++ #[allow(unused_imports)] use std::ascii::AsciiExt;
+ use style_traits::cursor::Cursor;
+ let ident = input.expect_ident()?;
+ if ident.eq_ignore_ascii_case("auto") {
+ Ok(computed_value::Keyword::Auto)
+ } else {
+ Cursor::from_css_keyword(&ident)
+ .map(computed_value::Keyword::Cursor)
+ .map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into())
+diff --git a/servo/components/style/servo/selector_parser.rs b/servo/components/style/servo/selector_parser.rs
+--- a/servo/components/style/servo/selector_parser.rs
++++ b/servo/components/style/servo/selector_parser.rs
+@@ -16,17 +16,17 @@ use invalidation::element::element_wrapp
+ use properties::ComputedValues;
+ use properties::PropertyFlags;
+ use properties::longhands::display::computed_value as display;
+ use selector_parser::{AttrValue as SelectorAttrValue, ElementExt, PseudoElementCascadeType, SelectorParser};
+ use selectors::Element;
+ use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
+ use selectors::parser::{SelectorMethods, SelectorParseError};
+ use selectors::visitor::SelectorVisitor;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+ use std::fmt::Debug;
+ use std::mem;
+ use std::ops::{Deref, DerefMut};
+ use style_traits::{ParseError, StyleParseError};
+
+ /// A pseudo-element, both public and private.
+ ///
+diff --git a/servo/components/style/str.rs b/servo/components/style/str.rs
+--- a/servo/components/style/str.rs
++++ b/servo/components/style/str.rs
+@@ -2,17 +2,17 @@
+ * 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/. */
+
+ //! String utils for attributes and similar stuff.
+
+ #![deny(missing_docs)]
+
+ use num_traits::ToPrimitive;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] #[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::Cow;
+ use std::convert::AsRef;
+ use std::iter::{Filter, Peekable};
+ use std::str::Split;
+
+ /// A static slice of characters.
+ pub type StaticCharVec = &'static [char];
+
+diff --git a/servo/components/style/stylesheets/viewport_rule.rs b/servo/components/style/stylesheets/viewport_rule.rs
+--- a/servo/components/style/stylesheets/viewport_rule.rs
++++ b/servo/components/style/stylesheets/viewport_rule.rs
+@@ -15,17 +15,17 @@ use error_reporting::{ContextualParseErr
+ use euclid::TypedSize2D;
+ use font_metrics::get_metrics_provider_for_product;
+ use media_queries::Device;
+ use parser::{ParserContext, ParserErrorContext};
+ use properties::StyleBuilder;
+ use rule_cache::RuleCacheConditions;
+ use selectors::parser::SelectorParseError;
+ use shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::borrow::Cow;
+ use std::cell::RefCell;
+ use std::fmt;
+ use std::iter::Enumerate;
+ use std::str::Chars;
+ use style_traits::{PinchZoomFactor, ToCss, ParseError, StyleParseError};
+ use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
+ use stylesheets::{StylesheetInDocument, Origin};
+diff --git a/servo/components/style/values/mod.rs b/servo/components/style/values/mod.rs
+--- a/servo/components/style/values/mod.rs
++++ b/servo/components/style/values/mod.rs
+@@ -7,17 +7,17 @@
+ //! [values]: https://drafts.csswg.org/css-values/
+
+ #![deny(missing_docs)]
+
+ use Atom;
+ pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError, CowRcStr};
+ use parser::{Parse, ParserContext};
+ use selectors::parser::SelectorParseError;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt::{self, Debug};
+ use std::hash;
+ use style_traits::{ToCss, ParseError, StyleParseError};
+
+ pub mod animated;
+ pub mod computed;
+ pub mod distance;
+ pub mod generics;
+diff --git a/servo/components/style/values/specified/align.rs b/servo/components/style/values/specified/align.rs
+--- a/servo/components/style/values/specified/align.rs
++++ b/servo/components/style/values/specified/align.rs
+@@ -5,17 +5,17 @@
+ //! Values for CSS Box Alignment properties
+ //!
+ //! https://drafts.csswg.org/css-align/
+
+ use cssparser::Parser;
+ use gecko_bindings::structs;
+ use parser::{Parse, ParserContext};
+ use selectors::parser::SelectorParseError;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+ use style_traits::{ToCss, ParseError, StyleParseError};
+
+ bitflags! {
+ /// Constants shared by multiple CSS Box Alignment properties
+ ///
+ /// These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
+ #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
+diff --git a/servo/components/style/values/specified/angle.rs b/servo/components/style/values/specified/angle.rs
+--- a/servo/components/style/values/specified/angle.rs
++++ b/servo/components/style/values/specified/angle.rs
+@@ -1,17 +1,17 @@
+ /* 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/. */
+
+ //! Specified angles.
+
+ use cssparser::{Parser, Token, BasicParseError};
+ use parser::{ParserContext, Parse};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+ use style_traits::{ToCss, ParseError};
+ use values::CSSFloat;
+ use values::computed::{Context, ToComputedValue};
+ use values::computed::angle::Angle as ComputedAngle;
+ use values::specified::calc::CalcNode;
+
+ /// A specified angle.
+diff --git a/servo/components/style/values/specified/calc.rs b/servo/components/style/values/specified/calc.rs
+--- a/servo/components/style/values/specified/calc.rs
++++ b/servo/components/style/values/specified/calc.rs
+@@ -3,17 +3,17 @@
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ //! [Calc expressions][calc].
+ //!
+ //! [calc]: https://drafts.csswg.org/css-values/#calc-notation
+
+ use cssparser::{Parser, Token, BasicParseError};
+ use parser::ParserContext;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+ use style_traits::{ToCss, ParseError, StyleParseError};
+ use style_traits::values::specified::AllowedNumericType;
+ use values::{CSSInteger, CSSFloat};
+ use values::computed;
+ use values::specified::{Angle, Time};
+ use values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
+ use values::specified::length::ViewportPercentageLength;
+diff --git a/servo/components/style/values/specified/grid.rs b/servo/components/style/values/specified/grid.rs
+--- a/servo/components/style/values/specified/grid.rs
++++ b/servo/components/style/values/specified/grid.rs
+@@ -2,17 +2,17 @@
+ * 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/. */
+
+ //! CSS handling for the computed value of
+ //! [grids](https://drafts.csswg.org/css-grid/)
+
+ use cssparser::{Parser, Token, BasicParseError};
+ use parser::{Parse, ParserContext};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::mem;
+ use style_traits::{ParseError, StyleParseError};
+ use values::{CSSFloat, CustomIdent};
+ use values::computed::{self, Context, ToComputedValue};
+ use values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat};
+ use values::generics::grid::{LineNameList, TrackSize, TrackList, TrackListType, TrackListValue};
+ use values::specified::{LengthOrPercentage, Integer};
+
+diff --git a/servo/components/style/values/specified/length.rs b/servo/components/style/values/specified/length.rs
+--- a/servo/components/style/values/specified/length.rs
++++ b/servo/components/style/values/specified/length.rs
+@@ -7,17 +7,17 @@
+ //! [length]: https://drafts.csswg.org/css-values/#lengths
+
+ use app_units::Au;
+ use cssparser::{Parser, Token, BasicParseError};
+ use euclid::Size2D;
+ use font_metrics::FontMetricsQueryResult;
+ use parser::{Parse, ParserContext};
+ use std::{cmp, fmt, mem};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::ops::{Add, Mul};
+ use style_traits::{ToCss, ParseError, StyleParseError};
+ use style_traits::values::specified::AllowedNumericType;
+ use stylesheets::CssRuleType;
+ use super::{AllowQuirks, Number, ToComputedValue, Percentage};
+ use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, None_, Normal};
+ use values::{ExtremumLength, serialize_dimension};
+ use values::computed::{self, CSSPixelLength, Context};
+diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs
+--- a/servo/components/style/values/specified/mod.rs
++++ b/servo/components/style/values/specified/mod.rs
+@@ -6,17 +6,17 @@
+ //!
+ //! TODO(emilio): Enhance docs.
+
+ use Namespace;
+ use context::QuirksMode;
+ use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
+ use parser::{ParserContext, Parse};
+ use self::url::SpecifiedUrl;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::f32;
+ use std::fmt;
+ use style_traits::{ToCss, ParseError, StyleParseError};
+ use style_traits::values::specified::AllowedNumericType;
+ use super::{Auto, CSSFloat, CSSInteger, Either, None_};
+ use super::computed::{Context, ToComputedValue};
+ use super::generics::{GreaterThanOrEqualToOne, NonNegative};
+ use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
+diff --git a/servo/components/style/values/specified/percentage.rs b/servo/components/style/values/specified/percentage.rs
+--- a/servo/components/style/values/specified/percentage.rs
++++ b/servo/components/style/values/specified/percentage.rs
+@@ -1,17 +1,17 @@
+ /* 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/. */
+
+ //! Specified percentages.
+
+ use cssparser::{BasicParseError, Parser, Token};
+ use parser::{Parse, ParserContext};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+ use style_traits::{ParseError, ToCss};
+ use style_traits::values::specified::AllowedNumericType;
+ use values::{CSSFloat, serialize_percentage};
+ use values::computed::{Context, ToComputedValue};
+ use values::computed::percentage::Percentage as ComputedPercentage;
+ use values::specified::calc::CalcNode;
+
+diff --git a/servo/components/style/values/specified/text.rs b/servo/components/style/values/specified/text.rs
+--- a/servo/components/style/values/specified/text.rs
++++ b/servo/components/style/values/specified/text.rs
+@@ -2,17 +2,17 @@
+ * 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/. */
+
+ //! Specified types for text properties.
+
+ use cssparser::Parser;
+ use parser::{Parse, ParserContext};
+ use selectors::parser::SelectorParseError;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use style_traits::ParseError;
+ use values::computed::{Context, ToComputedValue};
+ use values::computed::text::LineHeight as ComputedLineHeight;
+ use values::generics::text::InitialLetter as GenericInitialLetter;
+ use values::generics::text::LineHeight as GenericLineHeight;
+ use values::generics::text::Spacing;
+ use values::specified::{AllowQuirks, Integer, NonNegativeNumber, Number};
+ use values::specified::length::{FontRelativeLength, Length, LengthOrPercentage, NoCalcLength};
+diff --git a/servo/components/style/values/specified/time.rs b/servo/components/style/values/specified/time.rs
+--- a/servo/components/style/values/specified/time.rs
++++ b/servo/components/style/values/specified/time.rs
+@@ -1,17 +1,17 @@
+ /* 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/. */
+
+ //! Specified time values.
+
+ use cssparser::{Parser, Token, BasicParseError};
+ use parser::{ParserContext, Parse};
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+ use style_traits::{ToCss, ParseError, StyleParseError};
+ use style_traits::values::specified::AllowedNumericType;
+ use values::CSSFloat;
+ use values::computed::{Context, ToComputedValue};
+ use values::computed::time::Time as ComputedTime;
+ use values::specified::calc::CalcNode;
+
+diff --git a/servo/components/style_traits/viewport.rs b/servo/components/style_traits/viewport.rs
+--- a/servo/components/style_traits/viewport.rs
++++ b/servo/components/style_traits/viewport.rs
+@@ -2,17 +2,17 @@
+ * 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/. */
+
+ //! Helper types for the `@viewport` rule.
+
+ use {CSSPixel, PinchZoomFactor, ParseError};
+ use cssparser::{Parser, ToCss, ParseError as CssParseError, BasicParseError};
+ use euclid::TypedSize2D;
+-use std::ascii::AsciiExt;
++#[allow(unused_imports)] use std::ascii::AsciiExt;
+ use std::fmt;
+
+ define_css_keyword_enum!(UserZoom:
+ "zoom" => Zoom,
+ "fixed" => Fixed);
+
+ define_css_keyword_enum!(Orientation:
+ "auto" => Auto,
--- a/series Sat Nov 11 10:08:36 2017 +0100
+++ b/series Wed Jan 10 22:27:13 2018 +0100
@@ -8,6 +8,9 @@
mozilla-reduce-files-per-UnifiedBindings.patch
mozilla-aarch64-startup-crash.patch
mozilla-bindgen-systemlibs.patch
+mozilla-bmo1360278.patch
+mozilla-bmo1399611-csd.patch
+mozilla-rust-1.23.patch
# Firefox patches
firefox-kde.patch